blob: bec8d106693ec2286f0ea56d9140406219a0be69 [file] [log] [blame]
Brian Carlstrom78128a62011-09-15 17:21:19 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
3#include <stdio.h>
4#include <stdlib.h>
5
Brian Carlstrom27ec9612011-09-19 20:20:38 -07006#include <fstream>
7#include <iostream>
Brian Carlstrom78128a62011-09-15 17:21:19 -07008#include <string>
9#include <vector>
10
11#include "class_linker.h"
Brian Carlstrom916e74e2011-09-23 11:42:01 -070012#include "file.h"
Brian Carlstrom78128a62011-09-15 17:21:19 -070013#include "image.h"
Brian Carlstrom916e74e2011-09-23 11:42:01 -070014#include "os.h"
Brian Carlstrom78128a62011-09-15 17:21:19 -070015#include "runtime.h"
16#include "space.h"
17#include "stringpiece.h"
Brian Carlstrom916e74e2011-09-23 11:42:01 -070018#include "unordered_map.h"
Brian Carlstrom78128a62011-09-15 17:21:19 -070019
20namespace art {
21
22static void usage() {
23 fprintf(stderr,
24 "Usage: oatdump [options] ...\n"
Brian Carlstrome24fa612011-09-29 00:53:55 -070025 " Example: oatdump --dex-file=$ANDROID_PRODUCT_OUT/system/framework/core.jar --oat=$ANDROID_PRODUCT_OUT/system/framework/boot.oat --image=$ANDROID_PRODUCT_OUT/system/framework/boot.art --strip-prefix=$ANDROID_PRODUCT_OUT\n"
26 " Example: adb shell oatdump --dex-file=/system/framework/core.jar --oat=/system/framework/boot.oat --image=/system/framework/boot.art\n"
Brian Carlstrom78128a62011-09-15 17:21:19 -070027 "\n");
Brian Carlstrome24fa612011-09-29 00:53:55 -070028 // TODO: remove this by inferring from --image or --oat
Brian Carlstrom78128a62011-09-15 17:21:19 -070029 fprintf(stderr,
30 " --dex-file=<dex-file>: specifies a .dex file location. At least one .dex\n"
31 " file must be specified. \n"
32 " Example: --dex-file=/system/framework/core.jar\n"
33 "\n");
34 fprintf(stderr,
Brian Carlstrome24fa612011-09-29 00:53:55 -070035 " --image=<file.art>: specifies the required input image filename.\n"
36 " Example: --image=/system/framework/boot.art\n"
37 "\n");
38 // TODO: remove this by inferring from --image
39 fprintf(stderr,
40 " --oat=<file.oat>: specifies the required input oat filename.\n"
Brian Carlstrom78128a62011-09-15 17:21:19 -070041 " Example: --image=/system/framework/boot.oat\n"
42 "\n");
43 fprintf(stderr,
Brian Carlstrome24fa612011-09-29 00:53:55 -070044 " --boot-image=<file.art>: provide the image file for the boot class path.\n"
45 " Example: --boot-image=/system/framework/boot.art\n"
Brian Carlstrom78128a62011-09-15 17:21:19 -070046 "\n");
Brian Carlstrome24fa612011-09-29 00:53:55 -070047 // TODO: remove this by inferring from --boot-image
48 fprintf(stderr,
49 " --boot-oat=<file.oat>: provide the oat file for the boot class path.\n"
50 " Example: --boot-oat=/system/framework/boot.oat\n"
51 "\n");
52 // TODO: remove this by inderring from --boot-image or --boot-oat
Brian Carlstrom78128a62011-09-15 17:21:19 -070053 fprintf(stderr,
54 " --boot-dex-file=<dex-file>: specifies a .dex file that is part of the boot\n"
55 " image specified with --boot. \n"
56 " Example: --boot-dex-file=/system/framework/core.jar\n"
57 "\n");
58 fprintf(stderr,
59 " --strip-prefix may be used to strip a path prefix from dex file names in the\n"
60 " the generated image to match the target file system layout.\n"
61 " Example: --strip-prefix=out/target/product/crespo\n"
62 "\n");
Brian Carlstrom27ec9612011-09-19 20:20:38 -070063 fprintf(stderr,
64 " --output=<file> may be used to send the output to a file.\n"
65 " Example: --output=/tmp/oatdump.txt\n"
66 "\n");
Brian Carlstrom78128a62011-09-15 17:21:19 -070067 exit(EXIT_FAILURE);
68}
69
Ian Rogersff1ed472011-09-20 13:46:24 -070070const char* image_roots_descriptions_[] = {
Brian Carlstrom78128a62011-09-15 17:21:19 -070071 "kJniStubArray",
Brian Carlstrome24fa612011-09-29 00:53:55 -070072 "kAbstractMethodErrorStubArray",
73 "kCalleeSaveMethod",
74 "kOatLocation",
Brian Carlstrom78128a62011-09-15 17:21:19 -070075};
76
Brian Carlstrom27ec9612011-09-19 20:20:38 -070077class OatDump {
Brian Carlstrom78128a62011-09-15 17:21:19 -070078
Brian Carlstrom27ec9612011-09-19 20:20:38 -070079 public:
Brian Carlstrom916e74e2011-09-23 11:42:01 -070080 static void Dump(const std::string& image_filename,
81 std::ostream& os,
82 Space& image_space,
83 const ImageHeader& image_header) {
Brian Carlstrom27ec9612011-09-19 20:20:38 -070084 os << "MAGIC:\n";
85 os << image_header.GetMagic() << "\n\n";
86
Brian Carlstrome24fa612011-09-29 00:53:55 -070087 os << "IMAGE BASE:\n";
88 os << reinterpret_cast<void*>(image_header.GetImageBaseAddr()) << "\n\n";
89
90 os << "OAT BASE:\n";
91 os << reinterpret_cast<void*>(image_header.GetOatBaseAddr()) << "\n\n";
Brian Carlstrom916e74e2011-09-23 11:42:01 -070092
Brian Carlstrom27ec9612011-09-19 20:20:38 -070093 os << "ROOTS:\n";
Elliott Hughes418d20f2011-09-22 14:00:39 -070094 CHECK_EQ(arraysize(image_roots_descriptions_), size_t(ImageHeader::kImageRootsMax));
Brian Carlstrom27ec9612011-09-19 20:20:38 -070095 for (int i = 0; i < ImageHeader::kImageRootsMax; i++) {
96 ImageHeader::ImageRoot image_root = static_cast<ImageHeader::ImageRoot>(i);
97 os << StringPrintf("%s: %p\n",
98 image_roots_descriptions_[i], image_header.GetImageRoot(image_root));
99 }
100 os << "\n";
101
102 os << "OBJECTS:\n" << std::flush;
103 OatDump state(image_space, os);
104 HeapBitmap* heap_bitmap = Heap::GetLiveBits();
105 DCHECK(heap_bitmap != NULL);
106 heap_bitmap->Walk(OatDump::Callback, &state);
Brian Carlstrom916e74e2011-09-23 11:42:01 -0700107 os << "\n";
108
109 os << "STATS:\n" << std::flush;
110 UniquePtr<File> file(OS::OpenFile(image_filename.c_str(), false));
111 state.stats_.file_bytes = file->Length();
Brian Carlstrome24fa612011-09-29 00:53:55 -0700112 size_t header_bytes = sizeof(ImageHeader);
113 state.stats_.header_bytes = header_bytes;
114 size_t alignment_bytes = RoundUp(header_bytes, kObjectAlignment) - header_bytes;
115 state.stats_.alignment_bytes += alignment_bytes;
Brian Carlstrom916e74e2011-09-23 11:42:01 -0700116 state.stats_.Dump(os);
117
118 os << std::flush;
Brian Carlstrom78128a62011-09-15 17:21:19 -0700119 }
120
Brian Carlstrom27ec9612011-09-19 20:20:38 -0700121 private:
122
Elliott Hughesd1bb4f62011-09-23 14:09:45 -0700123 OatDump(const Space& dump_space, std::ostream& os) : dump_space_(dump_space), os_(os) {
124 }
125
126 ~OatDump() {
127 }
Brian Carlstrom27ec9612011-09-19 20:20:38 -0700128
Brian Carlstrom78128a62011-09-15 17:21:19 -0700129 static void Callback(Object* obj, void* arg) {
130 DCHECK(obj != NULL);
131 DCHECK(arg != NULL);
132 OatDump* state = reinterpret_cast<OatDump*>(arg);
133 if (!state->InDumpSpace(obj)) {
134 return;
135 }
Brian Carlstrom916e74e2011-09-23 11:42:01 -0700136
137 size_t object_bytes = obj->SizeOf();
138 size_t alignment_bytes = RoundUp(object_bytes, kObjectAlignment) - object_bytes;
139 state->stats_.object_bytes += object_bytes;
140 state->stats_.alignment_bytes += alignment_bytes;
141
Brian Carlstrom78128a62011-09-15 17:21:19 -0700142 std::string summary;
143 StringAppendF(&summary, "%p: ", obj);
144 if (obj->IsClass()) {
145 Class* klass = obj->AsClass();
146 StringAppendF(&summary, "CLASS %s", klass->GetDescriptor()->ToModifiedUtf8().c_str());
Brian Carlstrome10b6972011-09-26 13:49:03 -0700147 std::stringstream ss;
148 ss << " (" << klass->GetStatus() << ")";
149 summary += ss.str();
Brian Carlstrom78128a62011-09-15 17:21:19 -0700150 } else if (obj->IsMethod()) {
151 Method* method = obj->AsMethod();
152 StringAppendF(&summary, "METHOD %s", PrettyMethod(method).c_str());
153 } else if (obj->IsField()) {
154 Field* field = obj->AsField();
155 Class* type = field->GetType();
156 std::string type_string;
157 type_string += (type == NULL) ? "<UNKNOWN>" : type->GetDescriptor()->ToModifiedUtf8();
158 StringAppendF(&summary, "FIELD %s", PrettyField(field).c_str());
159 } else if (obj->IsArrayInstance()) {
160 StringAppendF(&summary, "ARRAY %d", obj->AsArray()->GetLength());
161 } else if (obj->IsString()) {
162 StringAppendF(&summary, "STRING %s", obj->AsString()->ToModifiedUtf8().c_str());
163 } else {
164 StringAppendF(&summary, "OBJECT");
165 }
166 StringAppendF(&summary, "\n");
Brian Carlstrom916e74e2011-09-23 11:42:01 -0700167 std::string descriptor = obj->GetClass()->GetDescriptor()->ToModifiedUtf8();
168 StringAppendF(&summary, "\tclass %p: %s\n", obj->GetClass(), descriptor.c_str());
169 state->stats_.descriptor_to_bytes[descriptor] += object_bytes;
170 state->stats_.descriptor_to_count[descriptor] += 1;
171 // StringAppendF(&summary, "\tsize %d (alignment padding %d)\n",
172 // object_bytes, RoundUp(object_bytes, kObjectAlignment) - object_bytes);
Brian Carlstrom78128a62011-09-15 17:21:19 -0700173 if (obj->IsMethod()) {
174 Method* method = obj->AsMethod();
Brian Carlstrom916e74e2011-09-23 11:42:01 -0700175 if (!method->IsPhony()) {
Brian Carlstrome10b6972011-09-26 13:49:03 -0700176 const ByteArray* code = method->GetCodeArray();
177 const int8_t* code_base = NULL;
178 const int8_t* code_limit = NULL;
179 if (code != NULL) {
180 size_t code_bytes = code->GetLength();
181 code_base = code->GetData();
182 code_limit = code_base + code_bytes;
183 if (method->IsNative()) {
184 state->stats_.managed_to_native_code_bytes += code_bytes;
185 } else {
186 state->stats_.managed_code_bytes += code_bytes;
187 }
Brian Carlstrome24fa612011-09-29 00:53:55 -0700188 } else {
189 code_base = reinterpret_cast<const int8_t*>(method->GetCode());
Brian Carlstrom916e74e2011-09-23 11:42:01 -0700190 }
Brian Carlstrome10b6972011-09-26 13:49:03 -0700191 StringAppendF(&summary, "\tCODE %p-%p\n", code_base, code_limit);
Brian Carlstrom916e74e2011-09-23 11:42:01 -0700192
Ian Rogersff1ed472011-09-20 13:46:24 -0700193 const ByteArray* invoke = method->GetInvokeStubArray();
Brian Carlstrome10b6972011-09-26 13:49:03 -0700194 const int8_t* invoke_base = NULL;
195 const int8_t* invoke_limit = NULL;
196 if (invoke != NULL) {
197 size_t native_to_managed_code_bytes = invoke->GetLength();
198 invoke_base = invoke->GetData();
199 invoke_limit = invoke_base + native_to_managed_code_bytes;
200 state->stats_.native_to_managed_code_bytes += native_to_managed_code_bytes;
201 StringAppendF(&summary, "\tJNI STUB %p-%p\n", invoke_base, invoke_limit);
202 }
Ian Rogersff1ed472011-09-20 13:46:24 -0700203 }
Brian Carlstrom78128a62011-09-15 17:21:19 -0700204 if (method->IsNative()) {
205 if (method->IsRegistered()) {
Brian Carlstrom916e74e2011-09-23 11:42:01 -0700206 StringAppendF(&summary, "\tNATIVE REGISTERED %p\n", method->GetNativeMethod());
Brian Carlstrom78128a62011-09-15 17:21:19 -0700207 } else {
208 StringAppendF(&summary, "\tNATIVE UNREGISTERED\n");
209 }
Brian Carlstrom916e74e2011-09-23 11:42:01 -0700210 DCHECK(method->GetRegisterMapHeader() == NULL);
211 DCHECK(method->GetRegisterMapData() == NULL);
212 DCHECK(method->GetMappingTable() == NULL);
213 } else if (method->IsAbstract()) {
214 StringAppendF(&summary, "\tABSTRACT\n");
215 DCHECK(method->GetRegisterMapHeader() == NULL);
216 DCHECK(method->GetRegisterMapData() == NULL);
217 DCHECK(method->GetMappingTable() == NULL);
218 } else if (method->IsPhony()) {
219 StringAppendF(&summary, "\tPHONY\n");
220 DCHECK(method->GetRegisterMapHeader() == NULL);
221 DCHECK(method->GetRegisterMapData() == NULL);
222 DCHECK(method->GetMappingTable() == NULL);
223 } else {
224 size_t register_map_bytes = (method->GetRegisterMapHeader()->GetLength() +
225 method->GetRegisterMapData()->GetLength());
226 state->stats_.register_map_bytes += register_map_bytes;
227
Brian Carlstrome10b6972011-09-26 13:49:03 -0700228 if (method->GetMappingTable() != NULL) {
229 size_t pc_mapping_table_bytes = method->GetMappingTable()->GetLength();
230 state->stats_.pc_mapping_table_bytes += pc_mapping_table_bytes;
231 }
Brian Carlstrom916e74e2011-09-23 11:42:01 -0700232
233 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
234 class DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
235 const DexFile& dex_file = class_linker->FindDexFile(dex_cache);
236 const DexFile::CodeItem* code_item = dex_file.GetCodeItem(method->GetCodeItemOffset());
237 size_t dex_instruction_bytes = code_item->insns_size_ * 2;
238 state->stats_.dex_instruction_bytes += dex_instruction_bytes;
Brian Carlstrom78128a62011-09-15 17:21:19 -0700239 }
240 }
Brian Carlstrom27ec9612011-09-19 20:20:38 -0700241 state->os_ << summary << std::flush;
Brian Carlstrom78128a62011-09-15 17:21:19 -0700242 }
Brian Carlstrom27ec9612011-09-19 20:20:38 -0700243
244 bool InDumpSpace(const Object* object) {
245 const byte* o = reinterpret_cast<const byte*>(object);
246 return (o >= dump_space_.GetBase() && o < dump_space_.GetLimit());
247 }
Brian Carlstrom916e74e2011-09-23 11:42:01 -0700248
249 public:
250 struct Stats {
251 size_t file_bytes;
252
253 size_t header_bytes;
254 size_t object_bytes;
255 size_t alignment_bytes;
256
257 size_t managed_code_bytes;
258 size_t managed_to_native_code_bytes;
259 size_t native_to_managed_code_bytes;
260
261 size_t register_map_bytes;
262 size_t pc_mapping_table_bytes;
263
264 size_t dex_instruction_bytes;
265
266 Stats()
267 : file_bytes(0),
268 header_bytes(0),
269 object_bytes(0),
270 alignment_bytes(0),
271 managed_code_bytes(0),
272 managed_to_native_code_bytes(0),
273 native_to_managed_code_bytes(0),
274 register_map_bytes(0),
275 pc_mapping_table_bytes(0),
276 dex_instruction_bytes(0) {}
277
278 typedef std::tr1::unordered_map<std::string,size_t> TableBytes;
279 TableBytes descriptor_to_bytes;
280
281 typedef std::tr1::unordered_map<std::string,size_t> TableCount;
282 TableCount descriptor_to_count;
283
284 double PercentOfFileBytes(size_t size) {
285 return (static_cast<double>(size) / static_cast<double>(file_bytes)) * 100;
286 }
287
288 double PercentOfObjectBytes(size_t size) {
289 return (static_cast<double>(size) / static_cast<double>(object_bytes)) * 100;
290 }
291
292 void Dump(std::ostream& os) {
293 os << StringPrintf("\tfile_bytes = %d\n", file_bytes);
294 os << "\n";
295
296 os << "\tfile_bytes = header_bytes + object_bytes + alignment_bytes\n";
297 os << StringPrintf("\theader_bytes = %10d (%2.0f%% of file_bytes)\n",
298 header_bytes, PercentOfFileBytes(header_bytes));
299 os << StringPrintf("\tobject_bytes = %10d (%2.0f%% of file_bytes)\n",
300 object_bytes, PercentOfFileBytes(object_bytes));
301 os << StringPrintf("\talignment_bytes = %10d (%2.0f%% of file_bytes)\n",
302 alignment_bytes, PercentOfFileBytes(alignment_bytes));
303 os << "\n";
304 os << std::flush;
305 CHECK_EQ(file_bytes, header_bytes + object_bytes + alignment_bytes);
306
307 os << "\tobject_bytes = sum of descriptor_to_bytes values below:\n";
308 size_t object_bytes_total = 0;
309 typedef TableBytes::const_iterator It; // TODO: C++0x auto
310 for (It it = descriptor_to_bytes.begin(), end = descriptor_to_bytes.end(); it != end; ++it) {
311 const std::string& descriptor = it->first;
312 size_t bytes = it->second;
313 size_t count = descriptor_to_count[descriptor];
314 double average = static_cast<double>(bytes) / static_cast<double>(count);
315 double percent = PercentOfObjectBytes(bytes);
Brian Carlstromf153fe12011-09-27 16:27:12 -0700316 os << StringPrintf("\t%32s %8d bytes %6d instances "
Brian Carlstrom916e74e2011-09-23 11:42:01 -0700317 "(%3.0f bytes/instance) %2.0f%% of object_bytes\n",
318 descriptor.c_str(), bytes, count,
319 average, percent);
320
321 object_bytes_total += bytes;
322 }
323 os << "\n";
324 os << std::flush;
325 CHECK_EQ(object_bytes, object_bytes_total);
326
327 os << StringPrintf("\tmanaged_code_bytes = %8d (%2.0f%% of object_bytes)\n",
328 managed_code_bytes, PercentOfObjectBytes(managed_code_bytes));
329 os << StringPrintf("\tmanaged_to_native_code_bytes = %8d (%2.0f%% of object_bytes)\n",
330 managed_to_native_code_bytes,
331 PercentOfObjectBytes(managed_to_native_code_bytes));
332 os << StringPrintf("\tnative_to_managed_code_bytes = %8d (%2.0f%% of object_bytes)\n",
333 native_to_managed_code_bytes,
334 PercentOfObjectBytes(native_to_managed_code_bytes));
335 os << "\n";
336 os << std::flush;
337
338 os << StringPrintf("\tregister_map_bytes = %7d (%2.0f%% of object_bytes)\n",
339 register_map_bytes, PercentOfObjectBytes(register_map_bytes));
340 os << StringPrintf("\tpc_mapping_table_bytes = %7d (%2.0f%% of object_bytes)\n",
341 pc_mapping_table_bytes, PercentOfObjectBytes(pc_mapping_table_bytes));
342 os << "\n";
343 os << std::flush;
344
345 os << StringPrintf("\tdex_instruction_bytes = %d\n", dex_instruction_bytes);
346 os << StringPrintf("\tmanaged_code_bytes expansion = %.2f\n",
347 static_cast<double>(managed_code_bytes)
348 / static_cast<double>(dex_instruction_bytes));
349 os << "\n";
350 os << std::flush;
351
352 }
353 } stats_;
354
355 private:
Brian Carlstrom27ec9612011-09-19 20:20:38 -0700356 const Space& dump_space_;
357 std::ostream& os_;
Elliott Hughesd1bb4f62011-09-23 14:09:45 -0700358
359 DISALLOW_COPY_AND_ASSIGN(OatDump);
Brian Carlstrom78128a62011-09-15 17:21:19 -0700360};
361
362int oatdump(int argc, char** argv) {
363 // Skip over argv[0].
364 argv++;
365 argc--;
366
367 if (argc == 0) {
368 fprintf(stderr, "no arguments specified\n");
369 usage();
370 }
371
372 std::vector<const char*> dex_filenames;
373 const char* image_filename = NULL;
Brian Carlstrome24fa612011-09-29 00:53:55 -0700374 const char* oat_filename = NULL;
Brian Carlstrom78128a62011-09-15 17:21:19 -0700375 const char* boot_image_filename = NULL;
Brian Carlstrome24fa612011-09-29 00:53:55 -0700376 const char* boot_oat_filename = NULL;
Brian Carlstrom78128a62011-09-15 17:21:19 -0700377 std::vector<const char*> boot_dex_filenames;
378 std::string strip_location_prefix;
Brian Carlstrom27ec9612011-09-19 20:20:38 -0700379 std::ostream* os = &std::cout;
380 UniquePtr<std::ofstream> out;
Brian Carlstrom78128a62011-09-15 17:21:19 -0700381
382 for (int i = 0; i < argc; i++) {
383 const StringPiece option(argv[i]);
384 if (option.starts_with("--dex-file=")) {
385 dex_filenames.push_back(option.substr(strlen("--dex-file=")).data());
386 } else if (option.starts_with("--image=")) {
387 image_filename = option.substr(strlen("--image=")).data();
Brian Carlstrome24fa612011-09-29 00:53:55 -0700388 } else if (option.starts_with("--oat=")) {
389 oat_filename = option.substr(strlen("--oat=")).data();
390 } else if (option.starts_with("--boot-image=")) {
391 boot_image_filename = option.substr(strlen("--boot-image=")).data();
392 } else if (option.starts_with("--boot-oat=")) {
393 boot_oat_filename = option.substr(strlen("--boot-oat=")).data();
Brian Carlstrom78128a62011-09-15 17:21:19 -0700394 } else if (option.starts_with("--boot-dex-file=")) {
395 boot_dex_filenames.push_back(option.substr(strlen("--boot-dex-file=")).data());
396 } else if (option.starts_with("--strip-prefix=")) {
397 strip_location_prefix = option.substr(strlen("--strip-prefix=")).data();
Brian Carlstrom27ec9612011-09-19 20:20:38 -0700398 } else if (option.starts_with("--output=")) {
399 const char* filename = option.substr(strlen("--output=")).data();
400 out.reset(new std::ofstream(filename));
401 if (!out->good()) {
402 fprintf(stderr, "failed to open output filename %s\n", filename);
403 usage();
404 }
405 os = out.get();
Brian Carlstrom78128a62011-09-15 17:21:19 -0700406 } else {
407 fprintf(stderr, "unknown argument %s\n", option.data());
408 usage();
409 }
410 }
411
412 if (image_filename == NULL) {
413 fprintf(stderr, "--image file name not specified\n");
414 return EXIT_FAILURE;
415 }
416
Brian Carlstrome24fa612011-09-29 00:53:55 -0700417 if (oat_filename == NULL) {
418 fprintf(stderr, "--oat file name not specified\n");
419 return EXIT_FAILURE;
420 }
421
Brian Carlstrom78128a62011-09-15 17:21:19 -0700422 if (dex_filenames.empty()) {
423 fprintf(stderr, "no --dex-file values specified\n");
424 return EXIT_FAILURE;
425 }
426
Brian Carlstrome24fa612011-09-29 00:53:55 -0700427 if ((boot_image_filename != NULL) != (boot_oat_filename != NULL)) {
428 fprintf(stderr, "--boot-image and --boat-oat must be specified together or not at all\n");
429 return EXIT_FAILURE;
430 }
431
Brian Carlstrom78128a62011-09-15 17:21:19 -0700432 if (boot_image_filename != NULL && boot_dex_filenames.empty()) {
433 fprintf(stderr, "no --boot-dex-file values specified with --boot\n");
434 return EXIT_FAILURE;
435 }
436
437 std::vector<const DexFile*> dex_files;
438 DexFile::OpenDexFiles(dex_filenames, dex_files, strip_location_prefix);
439
440 std::vector<const DexFile*> boot_dex_files;
441 DexFile::OpenDexFiles(boot_dex_filenames, boot_dex_files, strip_location_prefix);
442
443 Runtime::Options options;
444 std::string image_option;
Brian Carlstrome24fa612011-09-29 00:53:55 -0700445 std::string oat_option;
Brian Carlstrom78128a62011-09-15 17:21:19 -0700446 std::string boot_image_option;
Brian Carlstrome24fa612011-09-29 00:53:55 -0700447 std::string boot_oat_option;
Brian Carlstrom78128a62011-09-15 17:21:19 -0700448 if (boot_image_filename == NULL) {
449 // if we don't have multiple images, pass the main one as the boot to match dex2oat
450 boot_image_filename = image_filename;
Brian Carlstrome24fa612011-09-29 00:53:55 -0700451 boot_oat_filename = oat_filename;
Brian Carlstrom78128a62011-09-15 17:21:19 -0700452 boot_dex_files = dex_files;
Brian Carlstrom78128a62011-09-15 17:21:19 -0700453 dex_files.clear();
454 } else {
455 image_option += "-Ximage:";
456 image_option += image_filename;
Brian Carlstrome24fa612011-09-29 00:53:55 -0700457 oat_option += "-Xoat:";
458 oat_option += oat_filename;
Brian Carlstrom78128a62011-09-15 17:21:19 -0700459 options.push_back(std::make_pair("classpath", &dex_files));
460 options.push_back(std::make_pair(image_option.c_str(), reinterpret_cast<void*>(NULL)));
Brian Carlstrome24fa612011-09-29 00:53:55 -0700461 options.push_back(std::make_pair(oat_option.c_str(), reinterpret_cast<void*>(NULL)));
Brian Carlstrom78128a62011-09-15 17:21:19 -0700462 }
463 boot_image_option += "-Xbootimage:";
464 boot_image_option += boot_image_filename;
Brian Carlstrome24fa612011-09-29 00:53:55 -0700465 boot_oat_option += "-Xbootoat:";
466 boot_oat_option += boot_oat_filename;
Brian Carlstrom78128a62011-09-15 17:21:19 -0700467 options.push_back(std::make_pair("bootclasspath", &boot_dex_files));
468 options.push_back(std::make_pair(boot_image_option.c_str(), reinterpret_cast<void*>(NULL)));
Brian Carlstrome24fa612011-09-29 00:53:55 -0700469 options.push_back(std::make_pair(boot_oat_option.c_str(), reinterpret_cast<void*>(NULL)));
Brian Carlstrom78128a62011-09-15 17:21:19 -0700470
471 UniquePtr<Runtime> runtime(Runtime::Create(options, false));
472 if (runtime.get() == NULL) {
473 fprintf(stderr, "could not create runtime\n");
474 return EXIT_FAILURE;
475 }
476 ClassLinker* class_linker = runtime->GetClassLinker();
477 for (size_t i = 0; i < dex_files.size(); i++) {
478 class_linker->RegisterDexFile(*dex_files[i]);
479 }
480
481 Space* image_space = Heap::GetSpaces()[Heap::GetSpaces().size()-2];
482 CHECK(image_space != NULL);
483 const ImageHeader& image_header = image_space->GetImageHeader();
484 if (!image_header.IsValid()) {
485 fprintf(stderr, "invalid image header %s\n", image_filename);
486 return EXIT_FAILURE;
487 }
Brian Carlstrom916e74e2011-09-23 11:42:01 -0700488 OatDump::Dump(image_filename, *os, *image_space, image_header);
Brian Carlstrom78128a62011-09-15 17:21:19 -0700489 return EXIT_SUCCESS;
490}
491
492} // namespace art
493
494int main(int argc, char** argv) {
495 return art::oatdump(argc, argv);
496}