1 /*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * Main driver of the dexdump utility.
17 *
18 * This is a re-implementation of the original dexdump utility that was
19 * based on Dalvik functions in libdex into a new dexdump that is now
20 * based on Art functions in libart instead. The output is very similar to
21 * to the original for correct DEX files. Error messages may differ, however.
22 * Also, ODEX files are no longer supported.
23 */
24
25 #include <android-base/logging.h>
26 #include <base/mem_map.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <unistd.h>
30
31 #include "dexdump.h"
32
33 namespace art {
34
35 static const char* gProgName = "dexdump";
36
37 /*
38 * Shows usage.
39 */
usage()40 static void usage() {
41 LOG(ERROR) << "Copyright (C) 2007 The Android Open Source Project\n";
42 LOG(ERROR) << gProgName
43 << ": [-a] [-c] [-d] [-e] [-f] [-h] [-i] [-j] [-l layout] [-n]"
44 " [-s] [-o outfile] dexfile...\n";
45 LOG(ERROR) << " -a : display annotations";
46 LOG(ERROR) << " -c : verify checksum and exit";
47 LOG(ERROR) << " -d : disassemble code sections";
48 LOG(ERROR) << " -e : display exported items only";
49 LOG(ERROR) << " -f : display dex file header";
50 LOG(ERROR) << " -g : display CFG for dex";
51 LOG(ERROR) << " -h : display all sections header";
52 LOG(ERROR) << " -i : ignore checksum failures";
53 LOG(ERROR) << " -j : disable dex file verification";
54 LOG(ERROR) << " -l : output layout, either 'plain' or 'xml'";
55 LOG(ERROR) << " -n : don't display debug information";
56 LOG(ERROR) << " -o : output file name (defaults to stdout)";
57 LOG(ERROR) << " -s : display all strings from string_ids header section";
58 }
59
60 /*
61 * Main driver of the dexdump utility.
62 */
dexdumpDriver(int argc,char ** argv)63 int dexdumpDriver(int argc, char** argv) {
64 // Reset options.
65 bool wantUsage = false;
66 memset(&gOptions, 0, sizeof(gOptions));
67 gOptions.verbose = true;
68 gOptions.showDebugInfo = true;
69
70 // Parse all arguments.
71 while (true) {
72 const int ic = getopt(argc, argv, "acdefghijl:no:s");
73 if (ic < 0) {
74 break; // done
75 }
76 switch (ic) {
77 case 'a': // display annotations
78 gOptions.showAnnotations = true;
79 break;
80 case 'c': // verify the checksum then exit
81 gOptions.checksumOnly = true;
82 break;
83 case 'd': // disassemble Dalvik instructions
84 gOptions.disassemble = true;
85 break;
86 case 'e': // exported items only
87 gOptions.exportsOnly = true;
88 break;
89 case 'f': // display dex file header
90 gOptions.showFileHeaders = true;
91 break;
92 case 'g': // display cfg
93 gOptions.showCfg = true;
94 break;
95 case 'h': // display section headers, i.e. all meta-data
96 gOptions.showSectionHeaders = true;
97 break;
98 case 'i': // continue even if checksum is bad
99 gOptions.ignoreBadChecksum = true;
100 break;
101 case 'j': // disable dex file verification
102 gOptions.disableVerifier = true;
103 break;
104 case 'l': // layout
105 if (strcmp(optarg, "plain") == 0) {
106 gOptions.outputFormat = OUTPUT_PLAIN;
107 } else if (strcmp(optarg, "xml") == 0) {
108 gOptions.outputFormat = OUTPUT_XML;
109 gOptions.verbose = false;
110 } else {
111 wantUsage = true;
112 }
113 break;
114 case 'n': // don't display debug information
115 gOptions.showDebugInfo = false;
116 break;
117 case 'o': // output file
118 gOptions.outputFileName = optarg;
119 break;
120 case 's': // display all strings
121 gOptions.showAllStrings = true;
122 break;
123 default:
124 wantUsage = true;
125 break;
126 } // switch
127 } // while
128
129 // Detect early problems.
130 if (optind == argc) {
131 LOG(ERROR) << "No file specified";
132 wantUsage = true;
133 }
134 if (gOptions.checksumOnly && gOptions.ignoreBadChecksum) {
135 LOG(ERROR) << "Can't specify both -c and -i";
136 wantUsage = true;
137 }
138 if (wantUsage) {
139 usage();
140 return 2;
141 }
142
143 // Open alternative output file.
144 if (gOptions.outputFileName) {
145 gOutFile = fopen(gOptions.outputFileName, "we");
146 if (!gOutFile) {
147 PLOG(ERROR) << "Can't open " << gOptions.outputFileName;
148 return 1;
149 }
150 }
151
152 // Process all files supplied on command line.
153 int result = 0;
154 while (optind < argc) {
155 result |= processFile(argv[optind++]);
156 } // while
157 return result != 0 ? 1 : 0;
158 }
159
160 } // namespace art
161
main(int argc,char ** argv)162 int main(int argc, char** argv) {
163 // Output all logging to stderr.
164 android::base::SetLogger(android::base::StderrLogger);
165 art::MemMap::Init();
166
167 return art::dexdumpDriver(argc, argv);
168 }
169