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