tools/redexdump/RedexDump.cpp (207 lines of code) (raw):

/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #include "RedexDump.h" #include <getopt.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "Formatters.h" #include "PrintUtil.h" static const char ddump_usage_string[] = "ReDex, DEX Dump tool\n" "\nredexdump pretty prints content of a dexfile. " "By default only prints the header\n" "\n" "Usage:\n" "\tredump [-h | --all | [[-string] [-type] [-proto] [-field] [-meth] " "[-clsdef] [-clsdata] [-code] [-enarr] [-anno]] [-clean]" " <classes.dex>...\n" "\n<classes.dex>: path to a dex file (not an APK!)\n" "\noptions:\n" "--h: help summary\n" "\nsections to print:\n" "-a, --all: print all items in all sections\n" "-s, --string: print items in the string id section\n" "-S, --stringdata: print string section (pointee of string ids)\n" "-t, --type: print items in the type id section\n" "-p, --proto: print items in the proto id section\n" "-f, --field: print items in the field id section\n" "-m, --meth: print items in the method id section\n" "-h, --methodhandle: print items in the methodhandle section\n" "-k, --callsite: print items in the callsite section\n" "-c, --clsdef: print items in the class def id section\n" "-C, --clsdata: print items in the class data section\n" "-x, --code: print items in the code data section\n" "-e, --enarr: print items in the encoded array section\n" "-A, --anno: print items in the annotation section\n" "-d, --debug: print debug info items in the data section\n" "-D, --ddebug=<addr>: disassemble debug info item at <addr>\n" "\n" "printing options:\n" "--clean: suppress indices and offsets\n" "--no-headers: suppress headers\n" "--raw: print all bytes, even control characters\n"; int main(int argc, char* argv[]) { bool all = false; bool string = false; bool stringdata = false; bool type = false; bool proto = false; bool field = false; bool meth = false; bool methodhandle = false; bool callsite = false; bool clsdef = false; bool clsdata = false; bool code = false; bool enarr = false; bool anno = false; bool redexdump_debug = false; uint32_t ddebug_offset = 0; int no_headers = 0; char c; static const struct option options[] = { {"all", no_argument, nullptr, 'a'}, {"string", no_argument, nullptr, 's'}, {"stringdata", no_argument, nullptr, 'S'}, {"type", no_argument, nullptr, 't'}, {"proto", no_argument, nullptr, 'p'}, {"field", no_argument, nullptr, 'f'}, {"meth", no_argument, nullptr, 'm'}, {"callsite", no_argument, nullptr, 'k'}, {"methodhandle", no_argument, nullptr, 'H'}, {"clsdef", no_argument, nullptr, 'c'}, {"clsdata", no_argument, nullptr, 'C'}, {"code", no_argument, nullptr, 'x'}, {"enarr", no_argument, nullptr, 'e'}, {"anno", no_argument, nullptr, 'A'}, {"debug", no_argument, nullptr, 'd'}, {"ddebug", required_argument, nullptr, 'D'}, {"clean", no_argument, (int*)&clean, 1}, {"raw", no_argument, (int*)&raw, 1}, {"escape", no_argument, (int*)&escape, 1}, {"no-headers", no_argument, &no_headers, 1}, {"help", no_argument, nullptr, 'h'}, {nullptr, 0, nullptr, 0}, }; while ((c = getopt_long(argc, argv, "asStpfmcCxeAdDh", &options[0], nullptr)) != -1) { switch (c) { case 'a': all = true; break; case 's': string = true; break; case 'S': stringdata = true; break; case 't': type = true; break; case 'p': proto = true; break; case 'f': field = true; break; case 'm': meth = true; break; case 'H': methodhandle = true; break; case 'k': callsite = true; break; case 'c': clsdef = true; break; case 'C': clsdata = true; break; case 'x': code = true; break; case 'e': enarr = true; break; case 'A': anno = true; break; case 'd': redexdump_debug = true; break; case 'D': sscanf(optarg, "%x", &ddebug_offset); break; case 'h': puts(ddump_usage_string); return 0; case '?': return 1; // getopt_long has printed an error case 0: // we're handling a long-only option break; default: abort(); } } if (optind == argc) { fprintf(stderr, "%s: no dex files given; use -h for help\n", argv[0]); return 1; } while (optind < argc) { const char* dexfile = argv[optind++]; ddump_data rd; open_dex_file(dexfile, &rd); if (!no_headers) { redump(format_map(&rd).c_str()); } if (string || all) { dump_strings(&rd, !no_headers); } if (stringdata || all) { dump_stringdata(&rd, !no_headers); } if (type || all) { dump_types(&rd); } if (proto || all) { dump_protos(&rd, !no_headers); } if (field || all) { dump_fields(&rd, !no_headers); } if (meth || all) { dump_methods(&rd, !no_headers); } if (methodhandle || all) { dump_methodhandles(&rd, !no_headers); } if (callsite || all) { dump_callsites(&rd, !no_headers); } if (clsdef || all) { dump_clsdefs(&rd, !no_headers); } if (clsdata || all) { dump_clsdata(&rd, !no_headers); } if (code || all) { dump_code(&rd); } if (enarr || all) { dump_enarr(&rd); } if (anno || all) { dump_anno(&rd); } if (redexdump_debug || all) { dump_debug(&rd); } if (ddebug_offset != 0) { disassemble_debug(&rd, ddebug_offset); } fprintf(stdout, "\n"); fflush(stdout); } return 0; }