main.cc 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665
  1. /*
  2. * Copyright (C) 2024 Xiaomi Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include <cstdio>
  6. #include <cstdlib>
  7. #include <cstring>
  8. #include "aot_file.h"
  9. #include "common.h"
  10. #include "option_parser.h"
  11. #include "wasm_file.h"
  12. using namespace analyzer;
  13. static const char s_description[] =
  14. R"( Print information about the contents of AoT binaries.
  15. examples:
  16. $ aot-analyzer example.aot
  17. )";
  18. struct func_info {
  19. uint32_t idx;
  20. void *ptr;
  21. };
  22. static int
  23. compare_func_ptrs(const void *f1, const void *f2)
  24. {
  25. return (intptr_t)((struct func_info *)f1)->ptr
  26. - (intptr_t)((struct func_info *)f2)->ptr;
  27. }
  28. static struct func_info *
  29. sort_func_ptrs(const AOTModule *module)
  30. {
  31. uint64_t content_len;
  32. struct func_info *sorted_func_ptrs;
  33. unsigned i;
  34. content_len = (uint64_t)sizeof(struct func_info) * module->func_count;
  35. sorted_func_ptrs = (struct func_info *)wasm_runtime_malloc(content_len);
  36. if (!sorted_func_ptrs) {
  37. return NULL;
  38. }
  39. for (i = 0; i < module->func_count; i++) {
  40. sorted_func_ptrs[i].idx = i;
  41. sorted_func_ptrs[i].ptr = module->func_ptrs[i];
  42. }
  43. qsort(sorted_func_ptrs, module->func_count, sizeof(struct func_info),
  44. compare_func_ptrs);
  45. return sorted_func_ptrs;
  46. }
  47. static ObjdumpOptions s_objdump_options;
  48. static std::vector<const char *> s_infiles;
  49. static void
  50. ParseOptions(int argc, char **argv)
  51. {
  52. OptionParser parser("aot-analyzer", s_description);
  53. parser.AddOption('i', "info", "Print basic information about AoT",
  54. []() { s_objdump_options.info = true; });
  55. parser.AddOption('t', "text-size", "Print text size",
  56. []() { s_objdump_options.text_size = true; });
  57. parser.AddOption('x', "details", "Show AoT details",
  58. []() { s_objdump_options.details = true; });
  59. parser.AddOption('c', "compare",
  60. "Show the differences between AoT and WASM",
  61. []() { s_objdump_options.compare = true; });
  62. parser.AddArgument(
  63. "filename", OptionParser::ArgumentCount::OneOrMore,
  64. [](const char *argument) { s_infiles.push_back(argument); });
  65. parser.Parse(argc, argv);
  66. }
  67. void
  68. InitStdio()
  69. {
  70. #if COMPILER_IS_MSVC
  71. int result = _setmode(_fileno(stdout), _O_BINARY);
  72. if (result == -1) {
  73. perror("Cannot set mode binary to stdout");
  74. }
  75. result = _setmode(_fileno(stderr), _O_BINARY);
  76. if (result == -1) {
  77. perror("Cannot set mode binary to stderr");
  78. }
  79. #endif
  80. }
  81. void
  82. dump_value_type(uint8 type)
  83. {
  84. switch (type) {
  85. case VALUE_TYPE_I32:
  86. printf("i32");
  87. break;
  88. case VALUE_TYPE_I64:
  89. printf("i64");
  90. break;
  91. case VALUE_TYPE_F32:
  92. printf("f32");
  93. break;
  94. case VALUE_TYPE_F64:
  95. printf("f64");
  96. break;
  97. case VALUE_TYPE_V128:
  98. printf("v128");
  99. break;
  100. case PACKED_TYPE_I8:
  101. printf("i8");
  102. break;
  103. case PACKED_TYPE_I16:
  104. printf("i16");
  105. break;
  106. case REF_TYPE_FUNCREF:
  107. printf("funcref");
  108. break;
  109. case REF_TYPE_EXTERNREF:
  110. printf("externref");
  111. break;
  112. case REF_TYPE_ANYREF:
  113. printf("anyref");
  114. break;
  115. case REF_TYPE_EQREF:
  116. printf("eqref");
  117. break;
  118. case REF_TYPE_I31REF:
  119. printf("i31ref");
  120. break;
  121. case REF_TYPE_STRUCTREF:
  122. printf("structref");
  123. break;
  124. case REF_TYPE_ARRAYREF:
  125. printf("arrayref");
  126. break;
  127. case REF_TYPE_NULLREF:
  128. printf("nullref");
  129. break;
  130. case REF_TYPE_NULLFUNCREF:
  131. printf("nullfuncref");
  132. break;
  133. case REF_TYPE_NULLEXTERNREF:
  134. printf("nullexternref");
  135. break;
  136. default:
  137. printf("unknown");
  138. }
  139. }
  140. void
  141. DumpInfo(AoTFile *aot)
  142. {
  143. const AOTTargetInfo target_info = aot->GetTargetInfo();
  144. printf("AOT File Information:\n\n");
  145. printf("Binary type: %s\n",
  146. aot->GetBinTypeName(target_info.bin_type).c_str());
  147. printf("ABI type: %d\n", target_info.abi_type);
  148. printf("Execution type: %s\n",
  149. aot->GetExectuionTypeName(target_info.e_type).c_str());
  150. printf("Execution machine: %s\n",
  151. aot->GetExectuionMachineName(target_info.e_machine).c_str());
  152. printf("Execution version: %u\n", target_info.e_version);
  153. printf("Execution flags: %u\n", target_info.e_flags);
  154. printf("Feature flags: %" PRId64 "\n", target_info.feature_flags);
  155. printf("Reserved: %" PRId64 "\n", target_info.reserved);
  156. printf("Arch: %s\n", target_info.arch);
  157. }
  158. void
  159. DumpTextSize(AoTFile *aot)
  160. {
  161. const AOTTargetInfo target_info = aot->GetTargetInfo();
  162. printf("%s: file format <%s>\n\n", aot->GetFileName(),
  163. aot->GetBinTypeName(target_info.bin_type).c_str());
  164. printf("Text size:\n");
  165. const uint32_t literal_size =
  166. ((AOTModule *)(aot->GetModule()))->literal_size;
  167. const uint32_t code_size = ((AOTModule *)(aot->GetModule()))->code_size;
  168. printf(" literal size= %u Bytes\n", literal_size);
  169. printf(" code size= %u Bytes\n", code_size);
  170. }
  171. void
  172. DumpDetails(AoTFile *aot)
  173. {
  174. const AOTTargetInfo target_info = aot->GetTargetInfo();
  175. printf("%s: file format <%s>\n\n", aot->GetFileName(),
  176. aot->GetBinTypeName(target_info.bin_type).c_str());
  177. printf("Details:\n\n");
  178. // Types
  179. const uint32_t type_count = ((AOTModule *)(aot->GetModule()))->type_count;
  180. AOTType **types = ((AOTModule *)(aot->GetModule()))->types;
  181. printf("Types[%u]\n", type_count);
  182. #if WASM_ENABLE_GC != 0
  183. const char *wasm_type[] = { "function", "struct", "array" };
  184. for (uint32_t index = 0; index < type_count; index++) {
  185. AOTType *type = types[index];
  186. const uint16_t type_flag = type->type_flag;
  187. printf(" -[%u] ", index);
  188. if (type_flag == WASM_TYPE_FUNC) {
  189. wasm_dump_func_type(((AOTFuncType *)type));
  190. }
  191. else if (type_flag == WASM_TYPE_STRUCT) {
  192. wasm_dump_struct_type(((AOTStructType *)type));
  193. }
  194. else if (type_flag == WASM_TYPE_ARRAY) {
  195. wasm_dump_array_type(((AOTArrayType *)type));
  196. }
  197. else {
  198. printf(" -[%u] unknown type\n", index);
  199. }
  200. }
  201. #else
  202. for (uint32_t index = 0; index < type_count; index++) {
  203. printf(" -[%u] ", index);
  204. AOTType *type = types[index];
  205. uint32_t i = 0;
  206. printf("func [");
  207. for (i = 0; i < type->param_count; i++) {
  208. dump_value_type(type->types[i]);
  209. if (i < (uint32)type->param_count - 1)
  210. printf(" ");
  211. }
  212. printf("] -> [");
  213. for (; i < (uint32)(type->param_count + type->result_count); i++) {
  214. dump_value_type(type->types[i]);
  215. if (i < (uint32)type->param_count + type->result_count - 1)
  216. printf(" ");
  217. }
  218. printf("]\n");
  219. }
  220. #endif
  221. printf("\n\n");
  222. // Imports
  223. const uint32_t import_memory_count =
  224. ((AOTModule *)(aot->GetModule()))->import_memory_count;
  225. AOTImportMemory *import_memories =
  226. ((AOTModule *)(aot->GetModule()))->import_memories;
  227. const uint32_t import_table_count =
  228. ((AOTModule *)(aot->GetModule()))->import_table_count;
  229. AOTImportTable *import_tables =
  230. ((AOTModule *)(aot->GetModule()))->import_tables;
  231. const uint32_t import_global_count =
  232. ((AOTModule *)(aot->GetModule()))->import_global_count;
  233. AOTImportGlobal *import_globals =
  234. ((AOTModule *)(aot->GetModule()))->import_globals;
  235. const uint32_t import_func_count =
  236. ((AOTModule *)(aot->GetModule()))->import_func_count;
  237. AOTImportFunc *import_funcs =
  238. ((AOTModule *)(aot->GetModule()))->import_funcs;
  239. printf("Imports[%u]\n", import_memory_count + import_table_count
  240. + import_global_count + import_func_count);
  241. // import memories
  242. printf(" -import_memories[%u]\n", import_memory_count);
  243. for (uint32_t index = 0; index < import_memory_count; index++) {
  244. AOTImportMemory memory = import_memories[index];
  245. printf(" -[%u] num_bytes_per_page:%5u init_page_count:%5u "
  246. "max_page_count:%5u module_name: %s memory_name: %s\n",
  247. index, memory.mem_type.num_bytes_per_page,
  248. memory.mem_type.init_page_count, memory.mem_type.max_page_count,
  249. memory.module_name, memory.memory_name);
  250. }
  251. printf("\n");
  252. // import tables
  253. printf(" -import_tables[%u]\n", import_table_count);
  254. for (uint32_t index = 0; index < import_table_count; index++) {
  255. AOTImportTable table = import_tables[index];
  256. printf(" -[%u] ", index);
  257. printf("elem_type: ");
  258. #if WASM_ENABLE_GC != 0
  259. wasm_dump_value_type(table.table_type.elem_type,
  260. table.table_type.elem_ref_type);
  261. #else
  262. dump_value_type(table.table_type.elem_type);
  263. #endif
  264. printf(" init_size:%5u max_size:%5u "
  265. "module_name: %s table_name: %s\n",
  266. table.table_type.init_size, table.table_type.max_size,
  267. table.module_name, table.table_name);
  268. }
  269. printf("\n");
  270. // import globals
  271. printf(" -import_globals[%u]\n", import_global_count);
  272. for (uint32_t index = 0; index < import_global_count; index++) {
  273. AOTImportGlobal global = import_globals[index];
  274. printf(" -[%u] ", index);
  275. printf("type: ");
  276. dump_value_type(global.type.val_type);
  277. printf(" module_name: %s global_name: %s\n", global.module_name,
  278. global.global_name);
  279. }
  280. printf("\n");
  281. // import functions
  282. printf(" -import_functions[%u]\n", import_func_count);
  283. for (uint32_t index = 0; index < import_func_count; index++) {
  284. AOTImportFunc func = import_funcs[index];
  285. printf(" -[%u] module_name: %s function_name: %s\n", index,
  286. func.module_name, func.func_name);
  287. }
  288. printf("\n\n");
  289. // Functions
  290. const uint32_t func_count = ((AOTModule *)(aot->GetModule()))->func_count;
  291. const uint32_t code_size = ((AOTModule *)(aot->GetModule()))->code_size;
  292. struct func_info *sorted_func_ptrs = NULL;
  293. sorted_func_ptrs = sort_func_ptrs(((AOTModule *)(aot->GetModule())));
  294. if (sorted_func_ptrs) {
  295. printf("Function[%u]\n", func_count);
  296. for (uint32_t index = 0; index < func_count; index++) {
  297. const uint32_t func_size =
  298. index + 1 < func_count
  299. ? (uintptr_t)(sorted_func_ptrs[index + 1].ptr)
  300. - (uintptr_t)(sorted_func_ptrs[index].ptr)
  301. : code_size
  302. + (uintptr_t)(((AOTModule *)(aot->GetModule()))->code)
  303. - (uintptr_t)(sorted_func_ptrs[index].ptr);
  304. printf(" -[%u] code_size= %u Bytes\n", index, func_size);
  305. }
  306. wasm_runtime_free(sorted_func_ptrs);
  307. printf("\n\n");
  308. }
  309. // Tables
  310. const uint32_t table_count = ((AOTModule *)(aot->GetModule()))->table_count;
  311. AOTTable *tables = ((AOTModule *)(aot->GetModule()))->tables;
  312. printf("Tables[%u]\n", table_count);
  313. for (uint32_t index = 0; index < table_count; index++) {
  314. AOTTable table = tables[index];
  315. printf(" -[%u] ", index);
  316. printf("elem_type: ");
  317. #if WASM_ENABLE_GC != 0
  318. wasm_dump_value_type(table.table_type.elem_type,
  319. table.table_type.elem_ref_type);
  320. #else
  321. dump_value_type(table.table_type.elem_type);
  322. #endif
  323. printf(" init_size:%5u max_size:%5u\n",
  324. table.table_type.init_size, table.table_type.max_size);
  325. }
  326. printf("\n\n");
  327. // Memories
  328. const uint32_t memory_count =
  329. ((AOTModule *)(aot->GetModule()))->memory_count;
  330. AOTMemory *memories = ((AOTModule *)(aot->GetModule()))->memories;
  331. printf("Memories[%u]\n", memory_count);
  332. for (uint32_t index = 0; index < memory_count; index++) {
  333. AOTMemory memory = memories[index];
  334. printf(" -[%u] flags:%5u bytes_per_page:%5u "
  335. "init_page_count:%5u max_page_count:%5u\n",
  336. index, memory.flags, memory.num_bytes_per_page,
  337. memory.init_page_count, memory.max_page_count);
  338. }
  339. printf("\n\n");
  340. // Globals
  341. const uint32_t global_count =
  342. ((AOTModule *)(aot->GetModule()))->global_count;
  343. AOTGlobal *globals = ((AOTModule *)(aot->GetModule()))->globals;
  344. printf("Globals[%u]\n", global_count);
  345. for (uint32_t index = 0; index < global_count; index++) {
  346. AOTGlobal global = globals[index];
  347. printf(" -[%u] ", index);
  348. printf("type: ");
  349. dump_value_type(global.type.val_type);
  350. printf(" is_mutable: %d size: %u data_offset: %u\n",
  351. global.type.is_mutable, global.size, global.data_offset);
  352. }
  353. printf("\n\n");
  354. // Exports
  355. const uint32_t export_count =
  356. ((AOTModule *)(aot->GetModule()))->export_count;
  357. AOTExport *exports = ((AOTModule *)(aot->GetModule()))->exports;
  358. printf("Exports[%u]\n", export_count);
  359. for (uint32_t index = 0; index < export_count; index++) {
  360. AOTExport expt = exports[index];
  361. printf(" -[%u] kind:%5d index:%5u name: %s\n", index, expt.kind,
  362. expt.index, expt.name);
  363. }
  364. printf("\n\n");
  365. // Code
  366. const uint32_t aot_code_size = (aot->GetMemConsumption()).aot_code_size;
  367. const uint32_t literal_size =
  368. ((AOTModule *)(aot->GetModule()))->literal_size;
  369. const uint32_t data_section_count =
  370. ((AOTModule *)(aot->GetModule()))->data_section_count;
  371. printf("Codes[%u]\n", aot_code_size);
  372. printf(" -code\n");
  373. printf(" -code_size: %u Bytes\n", code_size);
  374. printf("\n");
  375. printf(" -literal\n");
  376. printf(" -literal_size: %u Bytes\n", literal_size);
  377. printf("\n");
  378. printf(" -data section\n");
  379. for (uint32_t index = 0; index < data_section_count; index++) {
  380. AOTObjectDataSection *obj_data =
  381. ((AOTModule *)(aot->GetModule()))->data_sections + index;
  382. printf(" -[%u] code_size:%5u Bytes name: %s\n", index,
  383. obj_data->size, obj_data->name);
  384. }
  385. printf("\n\n");
  386. }
  387. void
  388. DumpCompare(AoTFile *aot, WasmFile *wasm)
  389. {
  390. const AOTTargetInfo target_info = aot->GetTargetInfo();
  391. AOTModule *aot_module = (AOTModule *)(aot->GetModule());
  392. WASMModuleMemConsumption aot_mem_conspn = aot->GetMemConsumption();
  393. WASMModule *wasm_module = (WASMModule *)(wasm->GetModule());
  394. const uint32_t aot_func_count = aot_module->func_count;
  395. const uint32_t aot_code_size = aot_module->code_size;
  396. struct func_info *sorted_func_ptrs = NULL;
  397. sorted_func_ptrs = sort_func_ptrs(((AOTModule *)(aot->GetModule())));
  398. if (!sorted_func_ptrs) {
  399. printf("sort AoT functions failed.\n");
  400. return;
  401. }
  402. const uint32_t wasm_func_count = wasm_module->function_count;
  403. WASMFunction **wasm_functions = wasm_module->functions;
  404. if (aot_func_count != wasm_func_count) {
  405. printf("The number of AoT functions does not match the number of Wasm "
  406. "functions.\n");
  407. wasm_runtime_free(sorted_func_ptrs);
  408. return;
  409. }
  410. uint32_t wasm_code_size = 0;
  411. // print function Comparison Details
  412. printf(
  413. "|--------------------------------------------------------------------"
  414. "-------------------|\n");
  415. printf(
  416. "| Function Code Size Compare "
  417. " |\n");
  418. printf(
  419. "|--------------------------------------------------------------------"
  420. "-------------------|\n");
  421. printf(
  422. "| ID | AoT Function Code Size | Wasm Function Code Size | "
  423. "expansion multiple |\n");
  424. printf(
  425. "|--------------------------------------------------------------------"
  426. "-------------------|\n");
  427. for (uint32_t index = 0; index < aot_func_count; index++) {
  428. const uint32_t aot_func_size =
  429. index + 1 < aot_func_count
  430. ? (uintptr_t)(sorted_func_ptrs[index + 1].ptr)
  431. - (uintptr_t)(sorted_func_ptrs[index].ptr)
  432. : aot_code_size + (uintptr_t)(aot_module->code)
  433. - (uintptr_t)(sorted_func_ptrs[index].ptr);
  434. const uint32_t wasm_func_size = wasm_functions[index]->code_size;
  435. wasm_code_size += wasm_func_size;
  436. printf(
  437. "| %4d | %10d Bytes | %10d Bytes | %10.2f "
  438. " "
  439. " |\n",
  440. index, aot_func_size, wasm_func_size,
  441. (aot_func_size * 1.0) / wasm_func_size);
  442. printf(
  443. "|-----------------------------------------------------------------"
  444. "-"
  445. "---------------------|\n");
  446. }
  447. wasm_runtime_free(sorted_func_ptrs);
  448. printf("\n\n");
  449. printf(
  450. "|--------------------------------------------------------------------"
  451. "---|\n");
  452. printf(
  453. "| Total Code Size Compare "
  454. " |\n");
  455. printf(
  456. "|--------------------------------------------------------------------"
  457. "---|\n");
  458. printf("| AoT code size= %10d Bytes | Wasm code size= %10d Bytes |\n",
  459. aot_code_size, wasm_code_size);
  460. printf(
  461. "|--------------------------------------------------------------------"
  462. "---|\n");
  463. }
  464. int
  465. ProgramMain(int argc, char **argv)
  466. {
  467. InitStdio();
  468. ParseOptions(argc, argv);
  469. if (!s_objdump_options.info && !s_objdump_options.text_size
  470. && !s_objdump_options.details && !s_objdump_options.compare) {
  471. fprintf(stderr,
  472. "At least one of the following switches must be given:\n");
  473. fprintf(stderr, " -i/ --info\n");
  474. fprintf(stderr, " -t/ --text-size\n");
  475. fprintf(stderr, " -x/ --details\n");
  476. fprintf(stderr, " -c/ --compare\n");
  477. return 1;
  478. }
  479. std::vector<BinaryFile *> readers;
  480. for (const char *filename : s_infiles) {
  481. BinaryFile *reader = NULL;
  482. const char *dot = strrchr(filename, '.');
  483. if (!dot) {
  484. printf("bad file name: %s\n", filename);
  485. continue;
  486. }
  487. if (strncmp(dot, ".aot", 4) == 0) {
  488. reader = new AoTFile(filename);
  489. }
  490. else if (strncmp(dot, ".wasm", 4) == 0) {
  491. reader = new WasmFile(filename);
  492. }
  493. else {
  494. printf("unknown file extension: %s\n", dot);
  495. continue;
  496. }
  497. if (reader && reader->ReadModule() == Result::Error) {
  498. printf("read module failed.\n");
  499. continue;
  500. }
  501. CHECK_RESULT(reader->Scan());
  502. readers.push_back(reader);
  503. }
  504. // -i/ --info
  505. if (s_objdump_options.info == 1) {
  506. for (size_t i = 0; i < readers.size(); ++i) {
  507. printf("\n");
  508. BinaryFile *reader = readers[i];
  509. const uint32_t module_type = reader->GetModule()->module_type;
  510. if (module_type == Wasm_Module_AoT) {
  511. AoTFile *aot = dynamic_cast<AoTFile *>(reader);
  512. if (!aot) {
  513. printf("[DumpInfo]: Reader cast failed.\n");
  514. continue;
  515. }
  516. DumpInfo(aot);
  517. }
  518. else {
  519. printf("[DumpInfo]: Wrong file format, not an AoT file.\n");
  520. }
  521. }
  522. }
  523. // -t/ --text-size
  524. if (s_objdump_options.text_size == 1) {
  525. for (size_t i = 0; i < readers.size(); ++i) {
  526. printf("\n");
  527. BinaryFile *reader = readers[i];
  528. const uint32_t module_type = reader->GetModule()->module_type;
  529. if (module_type == Wasm_Module_AoT) {
  530. AoTFile *aot = dynamic_cast<AoTFile *>(reader);
  531. if (!aot) {
  532. printf("[DumpTextSize]: Reader cast failed.\n");
  533. continue;
  534. }
  535. DumpTextSize(aot);
  536. }
  537. else {
  538. printf("[DumpTextSize]: Wrong file format, not an AoT file.\n");
  539. }
  540. }
  541. }
  542. // -x/ --details
  543. if (s_objdump_options.details == 1) {
  544. for (size_t i = 0; i < readers.size(); ++i) {
  545. printf("\n");
  546. BinaryFile *reader = readers[i];
  547. const uint32_t module_type = reader->GetModule()->module_type;
  548. if (module_type == Wasm_Module_AoT) {
  549. AoTFile *aot = dynamic_cast<AoTFile *>(reader);
  550. if (!aot) {
  551. printf("[DumpDetails]: Reader cast failed.\n");
  552. continue;
  553. }
  554. DumpDetails(aot);
  555. }
  556. else {
  557. printf("[DumpDetails]: Wrong file format, not an AoT file.\n");
  558. }
  559. }
  560. }
  561. // -c/ --compare
  562. if (s_objdump_options.compare == 1) {
  563. printf("\n");
  564. if (readers.size() != 2) {
  565. printf("[DumpCompare]: Illegal number of file parameters.\n");
  566. return 1;
  567. }
  568. AoTFile *aot = NULL;
  569. WasmFile *wasm = NULL;
  570. for (size_t i = 0; i < readers.size(); ++i) {
  571. BinaryFile *reader = readers[i];
  572. const uint32_t module_type = reader->GetModule()->module_type;
  573. if (module_type == Wasm_Module_AoT) {
  574. aot = dynamic_cast<AoTFile *>(reader);
  575. }
  576. else if (module_type == Wasm_Module_Bytecode) {
  577. wasm = dynamic_cast<WasmFile *>(reader);
  578. }
  579. }
  580. if (!aot) {
  581. printf("[DumpCompare]: an aot file is required for comparison.\n");
  582. return 1;
  583. }
  584. if (!wasm) {
  585. printf("[DumpCompare]: a wasm file is required for comparison.\n");
  586. return 1;
  587. }
  588. DumpCompare(aot, wasm);
  589. }
  590. return 0;
  591. }
  592. int
  593. main(int argc, char **argv)
  594. {
  595. ANALYZER_TRY
  596. return ProgramMain(argc, argv);
  597. ANALYZER_CATCH_BAD_ALLOC_AND_EXIT
  598. }