1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License.
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The "dexdump" tool is intended to mimic "objdump".  When possible, use
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * similar command-line arguments.
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
21a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden * TODO: rework the "plain" output format to be more regexp-friendly
22a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden *
23a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden * Differences between XML output and the "current.xml" file:
24a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden * - classes in same package are not all grouped together; generally speaking
25a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden *   nothing is sorted
26a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden * - no "deprecated" on fields and methods
27a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden * - no "value" on fields
28a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden * - no parameter names
29a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden * - no generic signatures on parameters, e.g. type="java.lang.Class<?>"
30a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden * - class shows declared fields and methods; does not show inherited fields
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
329ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "libdex/DexFile.h"
349ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein
359ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein#include "libdex/CmdUtils.h"
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "libdex/DexCatch.h"
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "libdex/DexClass.h"
389ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2Dan Bornstein#include "libdex/DexDebugInfo.h"
39df4daaf8f41e3dcaa8221f54273338160dd43138Dan Bornstein#include "libdex/DexOpcodes.h"
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "libdex/DexProto.h"
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "libdex/InstrUtils.h"
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "libdex/SysUtil.h"
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdlib.h>
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdio.h>
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <fcntl.h>
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <string.h>
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <unistd.h>
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <getopt.h>
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <errno.h>
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <assert.h>
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic const char* gProgName = "dexdump";
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
55bfc9799b1a53fd6f6136d07e6278d4538cf70f13Carl Shapiroenum OutputFormat {
56a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    OUTPUT_PLAIN = 0,               /* default */
57a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    OUTPUT_XML,                     /* fancy */
58bfc9799b1a53fd6f6136d07e6278d4538cf70f13Carl Shapiro};
59a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* command-line options */
61bfc9799b1a53fd6f6136d07e6278d4538cf70f13Carl Shapirostruct Options {
620198b1443707d575d30c2b20f1bc3766a9221e96Andy McFadden    bool checksumOnly;
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool disassemble;
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool showFileHeaders;
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool showSectionHeaders;
662124cb83c3d46542d6bbc7a5da5b2288f4d6401bAndy McFadden    bool ignoreBadChecksum;
6799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    bool dumpRegisterMaps;
68a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    OutputFormat outputFormat;
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* tempFileName;
70a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    bool exportsOnly;
71a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    bool verbose;
72bfc9799b1a53fd6f6136d07e6278d4538cf70f13Carl Shapiro};
73bfc9799b1a53fd6f6136d07e6278d4538cf70f13Carl Shapiro
74bfc9799b1a53fd6f6136d07e6278d4538cf70f13Carl Shapirostruct Options gOptions;
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* basic info about a field or method */
77bfc9799b1a53fd6f6136d07e6278d4538cf70f13Carl Shapirostruct FieldMethodInfo {
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* classDescriptor;
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* name;
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* signature;
81bfc9799b1a53fd6f6136d07e6278d4538cf70f13Carl Shapiro};
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
84de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * Get 2 little-endian bytes.
85de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro */
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic inline u2 get2LE(unsigned char const* pSrc)
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return pSrc[0] | (pSrc[1] << 8);
89de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro}
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
92de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * Get 4 little-endian bytes.
93de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro */
9499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Projectstatic inline u4 get4LE(unsigned char const* pSrc)
9599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project{
9699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    return pSrc[0] | (pSrc[1] << 8) | (pSrc[2] << 16) | (pSrc[3] << 24);
97de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro}
9899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
9999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project/*
100a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden * Converts a single-character primitive type into its human-readable
101a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden * equivalent.
102a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden */
103a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFaddenstatic const char* primitiveTypeLabel(char typeChar)
104a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden{
105a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    switch (typeChar) {
106a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    case 'B':   return "byte";
107a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    case 'C':   return "char";
108a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    case 'D':   return "double";
109a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    case 'F':   return "float";
110a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    case 'I':   return "int";
111a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    case 'J':   return "long";
112a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    case 'S':   return "short";
113a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    case 'V':   return "void";
114a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    case 'Z':   return "boolean";
115a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    default:
116a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden                return "UNKNOWN";
117a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    }
118a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden}
119a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
120a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden/*
121a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden * Converts a type descriptor to human-readable "dotted" form.  For
122a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden * example, "Ljava/lang/String;" becomes "java.lang.String", and
123a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden * "[I" becomes "int[]".  Also converts '$' to '.', which means this
124a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden * form can't be converted back to a descriptor.
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic char* descriptorToDot(const char* str)
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
128a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    int targetLen = strlen(str);
129a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    int offset = 0;
130a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    int arrayDepth = 0;
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* newStr;
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
133a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    /* strip leading [s; will be added to end */
134a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    while (targetLen > 1 && str[offset] == '[') {
135a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        offset++;
136a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        targetLen--;
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
138a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    arrayDepth = offset;
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
140a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    if (targetLen == 1) {
141a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        /* primitive type */
142a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        str = primitiveTypeLabel(str[offset]);
143a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        offset = 0;
144a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        targetLen = strlen(str);
145a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    } else {
146a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        /* account for leading 'L' and trailing ';' */
147a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        if (targetLen >= 2 && str[offset] == 'L' &&
148a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            str[offset+targetLen-1] == ';')
149a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        {
150a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            targetLen -= 2;
151a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            offset++;
152a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        }
153a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    }
154a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
155bfc9799b1a53fd6f6136d07e6278d4538cf70f13Carl Shapiro    newStr = (char*)malloc(targetLen + arrayDepth * 2 +1);
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
157a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    /* copy class name over */
158a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    int i;
159a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    for (i = 0; i < targetLen; i++) {
160a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        char ch = str[offset + i];
161a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        newStr[i] = (ch == '/' || ch == '$') ? '.' : ch;
162a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    }
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
164a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    /* add the appropriate number of brackets for arrays */
165a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    while (arrayDepth-- > 0) {
166a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        newStr[i++] = '[';
167a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        newStr[i++] = ']';
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
169a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    newStr[i] = '\0';
170a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    assert(i == targetLen + arrayDepth * 2);
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return newStr;
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
176a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden * Converts the class name portion of a type descriptor to human-readable
177a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden * "dotted" form.
178a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden *
179a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden * Returns a newly-allocated string.
180a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden */
181a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFaddenstatic char* descriptorClassToDot(const char* str)
182a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden{
183a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    const char* lastSlash;
184a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    char* newStr;
185a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    char* cp;
186a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
187a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    /* reduce to just the class name, trimming trailing ';' */
188a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    lastSlash = strrchr(str, '/');
189a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    if (lastSlash == NULL)
190a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        lastSlash = str + 1;        /* start past 'L' */
191a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    else
192a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        lastSlash++;                /* start past '/' */
193a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
194a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    newStr = strdup(lastSlash);
195a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    newStr[strlen(lastSlash)-1] = '\0';
196a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    for (cp = newStr; *cp != '\0'; cp++) {
197a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        if (*cp == '$')
198a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            *cp = '.';
199a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    }
200a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
201a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    return newStr;
202a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden}
203a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
204a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden/*
205a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden * Returns a quoted string representing the boolean value.
206a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden */
207a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFaddenstatic const char* quotedBool(bool val)
208a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden{
209a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    if (val)
210a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        return "\"true\"";
211a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    else
212a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        return "\"false\"";
213a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden}
214a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
215a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFaddenstatic const char* quotedVisibility(u4 accessFlags)
216a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden{
217a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    if ((accessFlags & ACC_PUBLIC) != 0)
218a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        return "\"public\"";
219a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    else if ((accessFlags & ACC_PROTECTED) != 0)
220a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        return "\"protected\"";
221a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    else if ((accessFlags & ACC_PRIVATE) != 0)
222a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        return "\"private\"";
223a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    else
224a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        return "\"package\"";
225a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden}
226a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
227a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden/*
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Count the number of '1' bits in a word.
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int countOnes(u4 val)
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int count = 0;
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
234e339343c9c698a887681771372ba6cc58a79c707Cosmin Cojocar    val = val - ((val >> 1) & 0x55555555);
235e339343c9c698a887681771372ba6cc58a79c707Cosmin Cojocar    val = (val & 0x33333333) + ((val >> 2) & 0x33333333);
236e339343c9c698a887681771372ba6cc58a79c707Cosmin Cojocar    count = (((val + (val >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return count;
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Flag for use with createAccessFlagStr().
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
244d862faa2ceae186da5518607505eb942d634ced9Carl Shapiroenum AccessFor {
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    kAccessForClass = 0, kAccessForMethod = 1, kAccessForField = 2,
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    kAccessForMAX
247d862faa2ceae186da5518607505eb942d634ced9Carl Shapiro};
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create a new string with human-readable access flags.
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * In the base language the access_flags fields are type u2; in Dalvik
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * they're u4.
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic char* createAccessFlagStr(u4 flags, AccessFor forWhat)
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define NUM_FLAGS   18
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static const char* kAccessStrings[kAccessForMAX][NUM_FLAGS] = {
259de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro        {
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* class, inner class */
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "PUBLIC",           /* 0x0001 */
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "PRIVATE",          /* 0x0002 */
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "PROTECTED",        /* 0x0004 */
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "STATIC",           /* 0x0008 */
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "FINAL",            /* 0x0010 */
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "?",                /* 0x0020 */
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "?",                /* 0x0040 */
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "?",                /* 0x0080 */
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "?",                /* 0x0100 */
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "INTERFACE",        /* 0x0200 */
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "ABSTRACT",         /* 0x0400 */
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "?",                /* 0x0800 */
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "SYNTHETIC",        /* 0x1000 */
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "ANNOTATION",       /* 0x2000 */
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "ENUM",             /* 0x4000 */
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "?",                /* 0x8000 */
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "VERIFIED",         /* 0x10000 */
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "OPTIMIZED",        /* 0x20000 */
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        },
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* method */
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "PUBLIC",           /* 0x0001 */
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "PRIVATE",          /* 0x0002 */
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "PROTECTED",        /* 0x0004 */
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "STATIC",           /* 0x0008 */
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "FINAL",            /* 0x0010 */
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "SYNCHRONIZED",     /* 0x0020 */
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "BRIDGE",           /* 0x0040 */
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "VARARGS",          /* 0x0080 */
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "NATIVE",           /* 0x0100 */
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "?",                /* 0x0200 */
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "ABSTRACT",         /* 0x0400 */
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "STRICT",           /* 0x0800 */
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "SYNTHETIC",        /* 0x1000 */
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "?",                /* 0x2000 */
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "?",                /* 0x4000 */
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "MIRANDA",          /* 0x8000 */
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "CONSTRUCTOR",      /* 0x10000 */
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "DECLARED_SYNCHRONIZED", /* 0x20000 */
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        },
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* field */
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "PUBLIC",           /* 0x0001 */
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "PRIVATE",          /* 0x0002 */
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "PROTECTED",        /* 0x0004 */
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "STATIC",           /* 0x0008 */
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "FINAL",            /* 0x0010 */
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "?",                /* 0x0020 */
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "VOLATILE",         /* 0x0040 */
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "TRANSIENT",        /* 0x0080 */
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "?",                /* 0x0100 */
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "?",                /* 0x0200 */
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "?",                /* 0x0400 */
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "?",                /* 0x0800 */
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "SYNTHETIC",        /* 0x1000 */
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "?",                /* 0x2000 */
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "ENUM",             /* 0x4000 */
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "?",                /* 0x8000 */
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "?",                /* 0x10000 */
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "?",                /* 0x20000 */
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        },
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    };
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const int kLongest = 21;        /* strlen of longest string above */
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i, count;
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* str;
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* cp;
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Allocate enough storage to hold the expected number of strings,
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * plus a space between each.  We over-allocate, using the longest
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * string above as the base metric.
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    count = countOnes(flags);
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    cp = str = (char*) malloc(count * (kLongest+1) +1);
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < NUM_FLAGS; i++) {
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (flags & 0x01) {
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            const char* accessStr = kAccessStrings[forWhat][i];
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int len = strlen(accessStr);
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (cp != str)
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *cp++ = ' ';
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            memcpy(cp, accessStr, len);
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cp += len;
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        flags >>= 1;
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *cp = '\0';
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return str;
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3550ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden * Copy character data from "data" to "out", converting non-ASCII values
3560ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden * to printf format chars or an ASCII filler ('.' or '?').
3570ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden *
3580ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden * The output buffer must be able to hold (2*len)+1 bytes.  The result is
3590ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden * NUL-terminated.
3600ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden */
3610ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFaddenstatic void asciify(char* out, const unsigned char* data, size_t len)
3620ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden{
3630ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden    while (len--) {
3640ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden        if (*data < 0x20) {
3650ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden            /* could do more here, but we don't need them yet */
3660ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden            switch (*data) {
3670ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden            case '\0':
3680ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden                *out++ = '\\';
3690ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden                *out++ = '0';
3700ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden                break;
3710ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden            case '\n':
3720ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden                *out++ = '\\';
3730ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden                *out++ = 'n';
3740ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden                break;
3750ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden            default:
3760ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden                *out++ = '.';
3770ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden                break;
3780ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden            }
3790ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden        } else if (*data >= 0x80) {
3800ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden            *out++ = '?';
3810ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden        } else {
3820ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden            *out++ = *data;
3830ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden        }
3840ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden        data++;
3850ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden    }
3860ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden    *out = '\0';
3870ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden}
3880ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden
3890ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden/*
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the file header.
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dumpFileHeader(const DexFile* pDexFile)
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3940ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden    const DexOptHeader* pOptHeader = pDexFile->pOptHeader;
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexHeader* pHeader = pDexFile->pHeader;
3960ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden    char sanitized[sizeof(pHeader->magic)*2 +1];
3970ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden
3980ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden    assert(sizeof(pHeader->magic) == sizeof(pOptHeader->magic));
3990ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden
4000ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden    if (pOptHeader != NULL) {
4010ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden        printf("Optimized DEX file header:\n");
4020ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden
4030ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden        asciify(sanitized, pOptHeader->magic, sizeof(pOptHeader->magic));
4040ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden        printf("magic               : '%s'\n", sanitized);
4050ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden        printf("dex_offset          : %d (0x%06x)\n",
4060ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden            pOptHeader->dexOffset, pOptHeader->dexOffset);
4070ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden        printf("dex_length          : %d\n", pOptHeader->dexLength);
4080ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden        printf("deps_offset         : %d (0x%06x)\n",
4090ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden            pOptHeader->depsOffset, pOptHeader->depsOffset);
4100ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden        printf("deps_length         : %d\n", pOptHeader->depsLength);
411e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        printf("opt_offset          : %d (0x%06x)\n",
412e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            pOptHeader->optOffset, pOptHeader->optOffset);
413e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        printf("opt_length          : %d\n", pOptHeader->optLength);
4140ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden        printf("flags               : %08x\n", pOptHeader->flags);
4150ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden        printf("checksum            : %08x\n", pOptHeader->checksum);
4160ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden        printf("\n");
4170ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden    }
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("DEX file header:\n");
4200ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden    asciify(sanitized, pHeader->magic, sizeof(pHeader->magic));
4210ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden    printf("magic               : '%s'\n", sanitized);
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("checksum            : %08x\n", pHeader->checksum);
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("signature           : %02x%02x...%02x%02x\n",
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pHeader->signature[0], pHeader->signature[1],
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pHeader->signature[kSHA1DigestLen-2],
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pHeader->signature[kSHA1DigestLen-1]);
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("file_size           : %d\n", pHeader->fileSize);
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("header_size         : %d\n", pHeader->headerSize);
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("link_size           : %d\n", pHeader->linkSize);
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("link_off            : %d (0x%06x)\n",
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pHeader->linkOff, pHeader->linkOff);
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("string_ids_size     : %d\n", pHeader->stringIdsSize);
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("string_ids_off      : %d (0x%06x)\n",
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pHeader->stringIdsOff, pHeader->stringIdsOff);
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("type_ids_size       : %d\n", pHeader->typeIdsSize);
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("type_ids_off        : %d (0x%06x)\n",
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pHeader->typeIdsOff, pHeader->typeIdsOff);
438da4a0999bdffd2f73154d25768de32183db35967Carl Shapiro    printf("proto_ids_size       : %d\n", pHeader->protoIdsSize);
439da4a0999bdffd2f73154d25768de32183db35967Carl Shapiro    printf("proto_ids_off        : %d (0x%06x)\n",
440da4a0999bdffd2f73154d25768de32183db35967Carl Shapiro        pHeader->protoIdsOff, pHeader->protoIdsOff);
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("field_ids_size      : %d\n", pHeader->fieldIdsSize);
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("field_ids_off       : %d (0x%06x)\n",
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pHeader->fieldIdsOff, pHeader->fieldIdsOff);
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("method_ids_size     : %d\n", pHeader->methodIdsSize);
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("method_ids_off      : %d (0x%06x)\n",
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pHeader->methodIdsOff, pHeader->methodIdsOff);
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("class_defs_size     : %d\n", pHeader->classDefsSize);
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("class_defs_off      : %d (0x%06x)\n",
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pHeader->classDefsOff, pHeader->classDefsOff);
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("data_size           : %d\n", pHeader->dataSize);
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("data_off            : %d (0x%06x)\n",
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pHeader->dataOff, pHeader->dataOff);
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("\n");
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
457e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein * Dump the "table of contents" for the opt area.
4580ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden */
459e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornsteinvoid dumpOptDirectory(const DexFile* pDexFile)
4600ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden{
4610ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden    const DexOptHeader* pOptHeader = pDexFile->pOptHeader;
4620ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden    if (pOptHeader == NULL)
4630ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden        return;
4640ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden
465e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    printf("OPT section contents:\n");
4660ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden
467e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    const u4* pOpt = (const u4*) ((u1*) pOptHeader + pOptHeader->optOffset);
4680ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden
469e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    if (*pOpt == 0) {
4700ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden        printf("(1.0 format, only class lookup table is present)\n\n");
4710ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden        return;
4720ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden    }
4730ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden
4740ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden    /*
475e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein     * The "opt" section is in "chunk" format: a 32-bit identifier, a 32-bit
4760ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden     * length, then the data.  Chunks start on 64-bit boundaries.
4770ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden     */
478e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein    while (*pOpt != kDexChunkEnd) {
4790ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden        const char* verboseStr;
4800ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden
481e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        u4 size = *(pOpt+1);
4820ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden
483e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        switch (*pOpt) {
4840ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden        case kDexChunkClassLookup:
4850ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden            verboseStr = "class lookup hash table";
4860ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden            break;
4870ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden        case kDexChunkRegisterMaps:
4880ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden            verboseStr = "register maps";
4890ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden            break;
4900ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden        default:
4910ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden            verboseStr = "(unknown chunk type)";
4920ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden            break;
4930ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden        }
4940ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden
495e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        printf("Chunk %08x (%c%c%c%c) - %s (%d bytes)\n", *pOpt,
496e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein            *pOpt >> 24, (char)(*pOpt >> 16), (char)(*pOpt >> 8), (char)*pOpt,
4970ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden            verboseStr, size);
4980ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden
4990ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden        size = (size + 8 + 7) & ~7;
500e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        pOpt += size / sizeof(u4);
5010ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden    }
5020ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden    printf("\n");
5030ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden}
5040ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden
5050ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden/*
506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump a class_def_item.
507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dumpClassDef(DexFile* pDexFile, int idx)
509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexClassDef* pClassDef;
511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const u1* pEncodedData;
512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexClassData* pClassData;
513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pClassDef = dexGetClassDef(pDexFile, idx);
515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pEncodedData = dexGetClassData(pDexFile, pClassDef);
516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pClassData = dexReadAndVerifyClassData(&pEncodedData, NULL);
517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pClassData == NULL) {
519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fprintf(stderr, "Trouble reading class data\n");
520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("Class #%d header:\n", idx);
524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("class_idx           : %d\n", pClassDef->classIdx);
525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("access_flags        : %d (0x%04x)\n",
526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pClassDef->accessFlags, pClassDef->accessFlags);
527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("superclass_idx      : %d\n", pClassDef->superclassIdx);
528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("interfaces_off      : %d (0x%06x)\n",
529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pClassDef->interfacesOff, pClassDef->interfacesOff);
530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("source_file_idx     : %d\n", pClassDef->sourceFileIdx);
531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("annotations_off     : %d (0x%06x)\n",
532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pClassDef->annotationsOff, pClassDef->annotationsOff);
533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("class_data_off      : %d (0x%06x)\n",
534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pClassDef->classDataOff, pClassDef->classDataOff);
535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("static_fields_size  : %d\n", pClassData->header.staticFieldsSize);
536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("instance_fields_size: %d\n",
537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pClassData->header.instanceFieldsSize);
538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("direct_methods_size : %d\n", pClassData->header.directMethodsSize);
539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("virtual_methods_size: %d\n",
540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pClassData->header.virtualMethodsSize);
541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("\n");
542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(pClassData);
544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
547a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden * Dump an interface that a class declares to implement.
548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dumpInterface(const DexFile* pDexFile, const DexTypeItem* pTypeItem,
550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i)
551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* interfaceName =
553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dexStringByTypeIdx(pDexFile, pTypeItem->typeIdx);
554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
555a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    if (gOptions.outputFormat == OUTPUT_PLAIN) {
556a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf("    #%d              : '%s'\n", i, interfaceName);
557a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    } else {
558a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        char* dotted = descriptorToDot(interfaceName);
559a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf("<implements name=\"%s\">\n</implements>\n", dotted);
560a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        free(dotted);
561a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    }
562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the catches table associated with the code.
566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dumpCatches(DexFile* pDexFile, const DexCode* pCode)
568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 triesSize = pCode->triesSize;
570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (triesSize == 0) {
572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("      catches       : (none)\n");
573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
574de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro    }
575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("      catches       : %d\n", triesSize);
577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexTry* pTries = dexGetTries(pCode);
579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 i;
580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < triesSize; i++) {
582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const DexTry* pTry = &pTries[i];
583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u4 start = pTry->startAddr;
584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u4 end = start + pTry->insnCount;
585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DexCatchIterator iterator;
586de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf("        0x%04x - 0x%04x\n", start, end);
588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dexCatchIteratorInit(&iterator, pCode, pTry->handlerOff);
590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (;;) {
592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            DexCatchHandler* handler = dexCatchIteratorNext(&iterator);
593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            const char* descriptor;
594de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (handler == NULL) {
596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
598de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
599de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro            descriptor = (handler->typeIdx == kDexNoIndex) ? "<any>" :
600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dexStringByTypeIdx(pDexFile, handler->typeIdx);
601de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("          %s -> 0x%04x\n", descriptor,
603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    handler->address);
604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int dumpPositionsCb(void *cnxt, u4 address, u4 lineNum)
609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("        0x%04x line=%d\n", address, lineNum);
611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the positions list.
616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
617de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapirovoid dumpPositions(DexFile* pDexFile, const DexCode* pCode,
618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const DexMethod *pDexMethod)
619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("      positions     : \n");
621de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro    const DexMethodId *pMethodId
622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            = dexGetMethodId(pDexFile, pDexMethod->methodIdx);
623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char *classDescriptor
624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            = dexStringByTypeIdx(pDexFile, pMethodId->classIdx);
625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dexDecodeDebugInfo(pDexFile, pCode, classDescriptor, pMethodId->protoIdx,
627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pDexMethod->accessFlags, dumpPositionsCb, NULL, NULL);
628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void dumpLocalsCb(void *cnxt, u2 reg, u4 startAddress,
631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u4 endAddress, const char *name, const char *descriptor,
632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const char *signature)
633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("        0x%04x - 0x%04x reg=%d %s %s %s\n",
635de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro            startAddress, endAddress, reg, name, descriptor,
636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            signature);
637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the locals list.
641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dumpLocals(DexFile* pDexFile, const DexCode* pCode,
643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const DexMethod *pDexMethod)
644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("      locals        : \n");
646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
647de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro    const DexMethodId *pMethodId
648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            = dexGetMethodId(pDexFile, pDexMethod->methodIdx);
649de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro    const char *classDescriptor
650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            = dexStringByTypeIdx(pDexFile, pMethodId->classIdx);
651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dexDecodeDebugInfo(pDexFile, pCode, classDescriptor, pMethodId->protoIdx,
653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pDexMethod->accessFlags, NULL, dumpLocalsCb, NULL);
654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get information about a method.
658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool getMethodInfo(DexFile* pDexFile, u4 methodIdx, FieldMethodInfo* pMethInfo)
660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexMethodId* pMethodId;
662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (methodIdx >= pDexFile->pHeader->methodIdsSize)
664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pMethodId = dexGetMethodId(pDexFile, methodIdx);
667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pMethInfo->name = dexStringById(pDexFile, pMethodId->nameIdx);
668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pMethInfo->signature = dexCopyDescriptorFromMethodId(pDexFile, pMethodId);
669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
670de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro    pMethInfo->classDescriptor =
671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dexStringByTypeIdx(pDexFile, pMethodId->classIdx);
672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get information about a field.
677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool getFieldInfo(DexFile* pDexFile, u4 fieldIdx, FieldMethodInfo* pFieldInfo)
679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexFieldId* pFieldId;
681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (fieldIdx >= pDexFile->pHeader->fieldIdsSize)
683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pFieldId = dexGetFieldId(pDexFile, fieldIdx);
686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pFieldInfo->name = dexStringById(pDexFile, pFieldId->nameIdx);
687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pFieldInfo->signature = dexStringByTypeIdx(pDexFile, pFieldId->typeIdx);
688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pFieldInfo->classDescriptor =
689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dexStringByTypeIdx(pDexFile, pFieldId->classIdx);
690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Look up a class' descriptor.
696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectconst char* getClassDescriptor(DexFile* pDexFile, u4 classIdx)
698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return dexStringByTypeIdx(pDexFile, classIdx);
700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
7034a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein * Helper for dumpInstruction(), which builds the string
7044a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein * representation for the index in the given instruction. This will
7054a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein * first try to use the given buffer, but if the result won't fit,
7064a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein * then this will allocate a new buffer to hold the result. A pointer
7074a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein * to the buffer which holds the full result is always returned, and
7084a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein * this can be compared with the one passed in, to see if the result
7094a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein * needs to be free()d.
7104a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein */
7114a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornsteinstatic char* indexString(DexFile* pDexFile,
7124a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    const DecodedInstruction* pDecInsn, char* buf, size_t bufSize)
7134a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein{
7144a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    int outSize;
7154a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    u4 index;
7164a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    u4 width;
7174a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein
7184a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    /* TODO: Make the index *always* be in field B, to simplify this code. */
719e485276c6ba778cafa373b3b5c867f84e91b0bfdDan Bornstein    switch (dexGetFormatFromOpcode(pDecInsn->opcode)) {
7204a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    case kFmt20bc:
7214a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    case kFmt21c:
7224a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    case kFmt35c:
7234a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    case kFmt35ms:
7244a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    case kFmt3rc:
7254a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    case kFmt3rms:
7264a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    case kFmt35mi:
7274a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    case kFmt3rmi:
7284a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        index = pDecInsn->vB;
7294a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        width = 4;
7304a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        break;
7314a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    case kFmt31c:
7324a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        index = pDecInsn->vB;
7334a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        width = 8;
7344a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        break;
7354a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    case kFmt22c:
7364a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    case kFmt22cs:
7374a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        index = pDecInsn->vC;
7384a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        width = 4;
7394a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        break;
7404a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    default:
7414a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        index = 0;
7424a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        width = 4;
7434a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        break;
7444a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    }
7454a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein
7464a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    switch (pDecInsn->indexType) {
7474a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    case kIndexUnknown:
7484a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        /*
7494a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein         * This function shouldn't ever get called for this type, but do
7504a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein         * something sensible here, just to help with debugging.
7514a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein         */
7524a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        outSize = snprintf(buf, bufSize, "<unknown-index>");
7534a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        break;
7544a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    case kIndexNone:
7554a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        /*
7564a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein         * This function shouldn't ever get called for this type, but do
7574a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein         * something sensible here, just to help with debugging.
7584a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein         */
7594a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        outSize = snprintf(buf, bufSize, "<no-index>");
7604a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        break;
7614a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    case kIndexVaries:
7624a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        /*
7634a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein         * This one should never show up in a dexdump, so no need to try
7644a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein         * to get fancy here.
7654a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein         */
7664a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        outSize = snprintf(buf, bufSize, "<index-varies> // thing@%0*x",
7674a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein                width, index);
7684a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        break;
7691530c3e6952581aa20ac1e06562a49b9d70bc2b6Dan Bornstein    case kIndexTypeRef:
77035ecedd8eacfd38b833135170a38221b54476c86Elliott Hughes        if (index < pDexFile->pHeader->typeIdsSize) {
77135ecedd8eacfd38b833135170a38221b54476c86Elliott Hughes            outSize = snprintf(buf, bufSize, "%s // type@%0*x",
77235ecedd8eacfd38b833135170a38221b54476c86Elliott Hughes                               getClassDescriptor(pDexFile, index), width, index);
77335ecedd8eacfd38b833135170a38221b54476c86Elliott Hughes        } else {
77435ecedd8eacfd38b833135170a38221b54476c86Elliott Hughes            outSize = snprintf(buf, bufSize, "<type?> // type@%0*x", width, index);
77535ecedd8eacfd38b833135170a38221b54476c86Elliott Hughes        }
7764a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        break;
7774a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    case kIndexStringRef:
77835ecedd8eacfd38b833135170a38221b54476c86Elliott Hughes        if (index < pDexFile->pHeader->stringIdsSize) {
77935ecedd8eacfd38b833135170a38221b54476c86Elliott Hughes            outSize = snprintf(buf, bufSize, "\"%s\" // string@%0*x",
78035ecedd8eacfd38b833135170a38221b54476c86Elliott Hughes                               dexStringById(pDexFile, index), width, index);
78135ecedd8eacfd38b833135170a38221b54476c86Elliott Hughes        } else {
78235ecedd8eacfd38b833135170a38221b54476c86Elliott Hughes            outSize = snprintf(buf, bufSize, "<string?> // string@%0*x",
78335ecedd8eacfd38b833135170a38221b54476c86Elliott Hughes                               width, index);
78435ecedd8eacfd38b833135170a38221b54476c86Elliott Hughes        }
7854a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        break;
7864a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    case kIndexMethodRef:
7874a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        {
7884a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein            FieldMethodInfo methInfo;
7894a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein            if (getMethodInfo(pDexFile, index, &methInfo)) {
7904a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein                outSize = snprintf(buf, bufSize, "%s.%s:%s // method@%0*x",
7914a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein                        methInfo.classDescriptor, methInfo.name,
7924a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein                        methInfo.signature, width, index);
793f1aa871d4d39dc7f6bcbd8cb77a9f54c6cbd2ae9You Kim                free((void *) methInfo.signature);
7944a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein            } else {
7954a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein                outSize = snprintf(buf, bufSize, "<method?> // method@%0*x",
7964a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein                        width, index);
7974a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein            }
7984a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        }
7994a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        break;
8004a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    case kIndexFieldRef:
8014a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        {
8024a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein            FieldMethodInfo fieldInfo;
8034a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein            if (getFieldInfo(pDexFile, index, &fieldInfo)) {
8044a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein                outSize = snprintf(buf, bufSize, "%s.%s:%s // field@%0*x",
8054a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein                        fieldInfo.classDescriptor, fieldInfo.name,
8064a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein                        fieldInfo.signature, width, index);
8074a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein            } else {
8084a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein                outSize = snprintf(buf, bufSize, "<field?> // field@%0*x",
8094a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein                        width, index);
8104a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein            }
8114a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        }
8124a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        break;
8134a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    case kIndexInlineMethod:
8144a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        outSize = snprintf(buf, bufSize, "[%0*x] // inline #%0*x",
8154a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein                width, index, width, index);
8164a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        break;
8174a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    case kIndexVtableOffset:
8184a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        outSize = snprintf(buf, bufSize, "[%0*x] // vtable #%0*x",
8194a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein                width, index, width, index);
8204a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        break;
8214a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    case kIndexFieldOffset:
8224a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        outSize = snprintf(buf, bufSize, "[obj+%0*x]", width, index);
8234a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        break;
8244a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    default:
8254a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        outSize = snprintf(buf, bufSize, "<?>");
8264a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        break;
8274a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    }
8284a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein
8294a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    if (outSize >= (int) bufSize) {
8304a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        /*
8314a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein         * The buffer wasn't big enough; allocate and retry. Note:
8324a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein         * snprintf() doesn't count the '\0' as part of its returned
8334a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein         * size, so we add explicit space for it here.
8344a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein         */
8354a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        outSize++;
836bfc9799b1a53fd6f6136d07e6278d4538cf70f13Carl Shapiro        buf = (char*)malloc(outSize);
8374a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        if (buf == NULL) {
8384a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein            return NULL;
8394a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        }
8404a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        return indexString(pDexFile, pDecInsn, buf, outSize);
8414a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    } else {
8424a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        return buf;
8434a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    }
8444a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein}
8454a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein
8464a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein/*
847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump a single instruction.
848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dumpInstruction(DexFile* pDexFile, const DexCode* pCode, int insnIdx,
850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int insnWidth, const DecodedInstruction* pDecInsn)
851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
8524a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    char indexBufChars[200];
8534a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    char *indexBuf = indexBufChars;
854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const u2* insns = pCode->insns;
855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("%06x:", ((u1*)insns - pDexFile->baseAddr) + insnIdx*2);
858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < 8; i++) {
859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (i < insnWidth) {
860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (i == 7) {
861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf(" ... ");
862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* print 16-bit value in little-endian order */
864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                const u1* bytePtr = (const u1*) &insns[insnIdx+i];
865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                printf(" %02x%02x", bytePtr[0], bytePtr[1]);
866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fputs("     ", stdout);
869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
8729a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    if (pDecInsn->opcode == OP_NOP) {
873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u2 instr = get2LE((const u1*) &insns[insnIdx]);
874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (instr == kPackedSwitchSignature) {
875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("|%04x: packed-switch-data (%d units)",
876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                insnIdx, insnWidth);
877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (instr == kSparseSwitchSignature) {
878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("|%04x: sparse-switch-data (%d units)",
879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                insnIdx, insnWidth);
880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (instr == kArrayDataSignature) {
881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("|%04x: array-data (%d units)",
882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                insnIdx, insnWidth);
883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf("|%04x: nop // spacer", insnIdx);
885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
8879a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        printf("|%04x: %s", insnIdx, dexGetOpcodeName(pDecInsn->opcode));
888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
8904a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    if (pDecInsn->indexType != kIndexNone) {
8914a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        indexBuf = indexString(pDexFile, pDecInsn,
8924a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein                indexBufChars, sizeof(indexBufChars));
8934a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    }
8944a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein
895e485276c6ba778cafa373b3b5c867f84e91b0bfdDan Bornstein    switch (dexGetFormatFromOpcode(pDecInsn->opcode)) {
896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kFmt10x:        // op
897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kFmt12x:        // op vA, vB
899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf(" v%d, v%d", pDecInsn->vA, pDecInsn->vB);
900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kFmt11n:        // op vA, #+B
902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf(" v%d, #int %d // #%x",
903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pDecInsn->vA, (s4)pDecInsn->vB, (u1)pDecInsn->vB);
904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kFmt11x:        // op vAA
906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf(" v%d", pDecInsn->vA);
907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kFmt10t:        // op +AA
909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kFmt20t:        // op +AAAA
910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            s4 targ = (s4) pDecInsn->vA;
912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf(" %04x // %c%04x",
913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                insnIdx + targ,
914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                (targ < 0) ? '-' : '+',
915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                (targ < 0) ? -targ : targ);
916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kFmt22x:        // op vAA, vBBBB
919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf(" v%d, v%d", pDecInsn->vA, pDecInsn->vB);
920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kFmt21t:        // op vAA, +BBBB
922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            s4 targ = (s4) pDecInsn->vB;
924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf(" v%d, %04x // %c%04x", pDecInsn->vA,
925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                insnIdx + targ,
926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                (targ < 0) ? '-' : '+',
927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                (targ < 0) ? -targ : targ);
928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kFmt21s:        // op vAA, #+BBBB
931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf(" v%d, #int %d // #%x",
932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pDecInsn->vA, (s4)pDecInsn->vB, (u2)pDecInsn->vB);
933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kFmt21h:        // op vAA, #+BBBB0000[00000000]
935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // The printed format varies a bit based on the actual opcode.
9369a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        if (pDecInsn->opcode == OP_CONST_HIGH16) {
937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            s4 value = pDecInsn->vB << 16;
938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf(" v%d, #int %d // #%x",
939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pDecInsn->vA, value, (u2)pDecInsn->vB);
940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            s8 value = ((s8) pDecInsn->vB) << 48;
942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf(" v%d, #long %lld // #%x",
943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pDecInsn->vA, value, (u2)pDecInsn->vB);
944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kFmt21c:        // op vAA, thing@BBBB
9474a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    case kFmt31c:        // op vAA, thing@BBBBBBBB
9484a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        printf(" v%d, %s", pDecInsn->vA, indexBuf);
949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kFmt23x:        // op vAA, vBB, vCC
951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf(" v%d, v%d, v%d", pDecInsn->vA, pDecInsn->vB, pDecInsn->vC);
952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kFmt22b:        // op vAA, vBB, #+CC
954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf(" v%d, v%d, #int %d // #%02x",
955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pDecInsn->vA, pDecInsn->vB, (s4)pDecInsn->vC, (u1)pDecInsn->vC);
956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kFmt22t:        // op vA, vB, +CCCC
958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            s4 targ = (s4) pDecInsn->vC;
960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf(" v%d, v%d, %04x // %c%04x", pDecInsn->vA, pDecInsn->vB,
961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                insnIdx + targ,
962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                (targ < 0) ? '-' : '+',
963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                (targ < 0) ? -targ : targ);
964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kFmt22s:        // op vA, vB, #+CCCC
967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf(" v%d, v%d, #int %d // #%04x",
968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pDecInsn->vA, pDecInsn->vB, (s4)pDecInsn->vC, (u2)pDecInsn->vC);
969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kFmt22c:        // op vA, vB, thing@CCCC
971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kFmt22cs:       // [opt] op vA, vB, field offset CCCC
9724a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        printf(" v%d, v%d, %s", pDecInsn->vA, pDecInsn->vB, indexBuf);
973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kFmt30t:
975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf(" #%08x", pDecInsn->vA);
976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kFmt31i:        // op vAA, #+BBBBBBBB
978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* this is often, but not always, a float */
980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            union {
981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                float f;
982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                u4 i;
983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } conv;
984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            conv.i = pDecInsn->vB;
985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf(" v%d, #float %f // #%08x",
986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pDecInsn->vA, conv.f, pDecInsn->vB);
987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kFmt31t:       // op vAA, offset +BBBBBBBB
990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf(" v%d, %08x // +%08x",
991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pDecInsn->vA, insnIdx + pDecInsn->vB, pDecInsn->vB);
992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kFmt32x:        // op vAAAA, vBBBB
994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf(" v%d, v%d", pDecInsn->vA, pDecInsn->vB);
995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
9967b3e9b0886f2b716b004f0377866988ae39a136eDan Bornstein    case kFmt35c:        // op {vC, vD, vE, vF, vG}, thing@BBBB
997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kFmt35ms:       // [opt] invoke-virtual+super
9984a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    case kFmt35mi:       // [opt] inline invoke
999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
1000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fputs(" {", stdout);
1001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (i = 0; i < (int) pDecInsn->vA; i++) {
1002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (i == 0)
1003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    printf("v%d", pDecInsn->arg[i]);
1004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                else
1005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    printf(", v%d", pDecInsn->arg[i]);
1006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
10074a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein            printf("}, %s", indexBuf);
1008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
10104a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    case kFmt3rc:        // op {vCCCC .. v(CCCC+AA-1)}, thing@BBBB
1011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kFmt3rms:       // [opt] invoke-virtual+super/range
10124a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    case kFmt3rmi:       // [opt] execute-inline/range
1013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
1014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
1015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * This doesn't match the "dx" output when some of the args are
1016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * 64-bit values -- dx only shows the first register.
1017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fputs(" {", stdout);
1019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (i = 0; i < (int) pDecInsn->vA; i++) {
1020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (i == 0)
1021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    printf("v%d", pDecInsn->vC + i);
1022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                else
1023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    printf(", v%d", pDecInsn->vC + i);
1024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
10254a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein            printf("}, %s", indexBuf);
1026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
1028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kFmt51l:        // op vAA, #+BBBBBBBBBBBBBBBB
1029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
1030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* this is often, but not always, a double */
1031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            union {
1032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                double d;
1033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                u8 j;
1034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } conv;
1035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            conv.j = pDecInsn->vB_wide;
1036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            printf(" v%d, #double %f // #%016llx",
1037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pDecInsn->vA, conv.d, pDecInsn->vB_wide);
1038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
10408424432a87c784547e4510bca538eaedc312e40dDan Bornstein    case kFmt00x:        // unknown op or breakpoint
1041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
1042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    default:
1043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        printf(" ???");
1044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
1045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    putchar('\n');
1048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
10494a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    if (indexBuf != indexBufChars) {
10504a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein        free(indexBuf);
10514a6b4825a5d3ac267e359897a5fb4d132a82c935Dan Bornstein    }
1052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump a bytecode disassembly.
1056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dumpBytecodes(DexFile* pDexFile, const DexMethod* pDexMethod)
1058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexCode* pCode = dexGetCode(pDexFile, pDexMethod);
1060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const u2* insns;
1061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int insnIdx;
1062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    FieldMethodInfo methInfo;
1063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int startAddr;
1064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* className = NULL;
1065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(pCode->insnsSize > 0);
1067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    insns = pCode->insns;
1068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    getMethodInfo(pDexFile, pDexMethod->methodIdx, &methInfo);
1070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    startAddr = ((u1*)pCode - pDexFile->baseAddr);
1071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    className = descriptorToDot(methInfo.classDescriptor);
1072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("%06x:                                        |[%06x] %s.%s:%s\n",
1074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        startAddr, startAddr,
1075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        className, methInfo.name, methInfo.signature);
1076f1aa871d4d39dc7f6bcbd8cb77a9f54c6cbd2ae9You Kim    free((void *) methInfo.signature);
1077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    insnIdx = 0;
1079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (insnIdx < (int) pCode->insnsSize) {
1080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int insnWidth;
1081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DecodedInstruction decInsn;
1082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u2 instr;
1083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1084111221644c5b7b1d4f426d02786aeebf1addc8f6Dan Bornstein        /*
1085111221644c5b7b1d4f426d02786aeebf1addc8f6Dan Bornstein         * Note: This code parallels the function
1086e485276c6ba778cafa373b3b5c867f84e91b0bfdDan Bornstein         * dexGetWidthFromInstruction() in InstrUtils.c, but this version
1087111221644c5b7b1d4f426d02786aeebf1addc8f6Dan Bornstein         * can deal with data in either endianness.
1088111221644c5b7b1d4f426d02786aeebf1addc8f6Dan Bornstein         *
1089111221644c5b7b1d4f426d02786aeebf1addc8f6Dan Bornstein         * TODO: Figure out if this really matters, and possibly change
1090e485276c6ba778cafa373b3b5c867f84e91b0bfdDan Bornstein         * this to just use dexGetWidthFromInstruction().
1091111221644c5b7b1d4f426d02786aeebf1addc8f6Dan Bornstein         */
1092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        instr = get2LE((const u1*)insns);
1093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (instr == kPackedSwitchSignature) {
1094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            insnWidth = 4 + get2LE((const u1*)(insns+1)) * 2;
1095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (instr == kSparseSwitchSignature) {
1096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            insnWidth = 2 + get2LE((const u1*)(insns+1)) * 4;
1097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (instr == kArrayDataSignature) {
1098f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int width = get2LE((const u1*)(insns+1));
1099de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro            int size = get2LE((const u1*)(insns+2)) |
1100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                       (get2LE((const u1*)(insns+3))<<16);
1101111221644c5b7b1d4f426d02786aeebf1addc8f6Dan Bornstein            // The plus 1 is to round up for odd size and width.
1102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            insnWidth = 4 + ((size * width) + 1) / 2;
1103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
11049a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            Opcode opcode = dexOpcodeFromCodeUnit(instr);
1105e485276c6ba778cafa373b3b5c867f84e91b0bfdDan Bornstein            insnWidth = dexGetWidthFromOpcode(opcode);
1106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (insnWidth == 0) {
1107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                fprintf(stderr,
1108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "GLITCH: zero-width instruction at idx=0x%04x\n", insnIdx);
1109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
1110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1113543223954993a19fa96670692bc7aa55d851966bDan Bornstein        dexDecodeInstruction(insns, &decInsn);
1114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dumpInstruction(pDexFile, pCode, insnIdx, insnWidth, &decInsn);
1115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        insns += insnWidth;
1117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        insnIdx += insnWidth;
1118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(className);
1121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump a "code" struct.
1125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dumpCode(DexFile* pDexFile, const DexMethod* pDexMethod)
1127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexCode* pCode = dexGetCode(pDexFile, pDexMethod);
1129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("      registers     : %d\n", pCode->registersSize);
1131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("      ins           : %d\n", pCode->insSize);
1132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("      outs          : %d\n", pCode->outsSize);
1133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("      insns size    : %d 16-bit code units\n", pCode->insnsSize);
1134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gOptions.disassemble)
1136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dumpBytecodes(pDexFile, pDexMethod);
1137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dumpCatches(pDexFile, pCode);
1139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* both of these are encoded in debug info */
1140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dumpPositions(pDexFile, pCode, pDexMethod);
1141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dumpLocals(pDexFile, pCode, pDexMethod);
1142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump a method.
1146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dumpMethod(DexFile* pDexFile, const DexMethod* pDexMethod, int i)
1148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexMethodId* pMethodId;
1150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* backDescriptor;
1151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* name;
1152a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    char* typeDescriptor = NULL;
1153a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    char* accessStr = NULL;
1154a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1155a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    if (gOptions.exportsOnly &&
1156a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        (pDexMethod->accessFlags & (ACC_PUBLIC | ACC_PROTECTED)) == 0)
1157a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    {
1158a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        return;
1159a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    }
1160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pMethodId = dexGetMethodId(pDexFile, pDexMethod->methodIdx);
1162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    name = dexStringById(pDexFile, pMethodId->nameIdx);
1163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    typeDescriptor = dexCopyDescriptorFromMethodId(pDexFile, pMethodId);
1164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    backDescriptor = dexStringByTypeIdx(pDexFile, pMethodId->classIdx);
1166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    accessStr = createAccessFlagStr(pDexMethod->accessFlags,
1168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    kAccessForMethod);
1169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1170a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    if (gOptions.outputFormat == OUTPUT_PLAIN) {
1171a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf("    #%d              : (in %s)\n", i, backDescriptor);
1172a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf("      name          : '%s'\n", name);
1173a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf("      type          : '%s'\n", typeDescriptor);
1174a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf("      access        : 0x%04x (%s)\n",
1175a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            pDexMethod->accessFlags, accessStr);
1176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1177a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        if (pDexMethod->codeOff == 0) {
1178a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            printf("      code          : (none)\n");
1179a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        } else {
1180a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            printf("      code          -\n");
1181a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            dumpCode(pDexFile, pDexMethod);
1182a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        }
1183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1184a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        if (gOptions.disassemble)
1185a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            putchar('\n');
1186a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    } else if (gOptions.outputFormat == OUTPUT_XML) {
1187a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        bool constructor = (name[0] == '<');
1188a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1189a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        if (constructor) {
1190a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            char* tmp;
1191a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1192a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            tmp = descriptorClassToDot(backDescriptor);
1193a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            printf("<constructor name=\"%s\"\n", tmp);
1194a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            free(tmp);
1195a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1196a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            tmp = descriptorToDot(backDescriptor);
1197a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            printf(" type=\"%s\"\n", tmp);
1198a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            free(tmp);
1199a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        } else {
1200a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            printf("<method name=\"%s\"\n", name);
1201a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1202a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            const char* returnType = strrchr(typeDescriptor, ')');
1203a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            if (returnType == NULL) {
1204a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden                fprintf(stderr, "bad method type descriptor '%s'\n",
1205a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden                    typeDescriptor);
1206a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden                goto bail;
1207a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            }
1208a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1209a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            char* tmp = descriptorToDot(returnType+1);
1210a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            printf(" return=\"%s\"\n", tmp);
1211a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            free(tmp);
1212a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1213a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            printf(" abstract=%s\n",
1214a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden                quotedBool((pDexMethod->accessFlags & ACC_ABSTRACT) != 0));
1215a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            printf(" native=%s\n",
1216a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden                quotedBool((pDexMethod->accessFlags & ACC_NATIVE) != 0));
1217a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1218a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            bool isSync =
1219a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden                (pDexMethod->accessFlags & ACC_SYNCHRONIZED) != 0 ||
1220a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden                (pDexMethod->accessFlags & ACC_DECLARED_SYNCHRONIZED) != 0;
1221a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            printf(" synchronized=%s\n", quotedBool(isSync));
1222a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        }
1223a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1224a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf(" static=%s\n",
1225a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            quotedBool((pDexMethod->accessFlags & ACC_STATIC) != 0));
1226a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf(" final=%s\n",
1227a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            quotedBool((pDexMethod->accessFlags & ACC_FINAL) != 0));
1228a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        // "deprecated=" not knowable w/o parsing annotations
1229a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf(" visibility=%s\n",
1230a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            quotedVisibility(pDexMethod->accessFlags));
1231a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1232a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf(">\n");
1233a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1234a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        /*
1235a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden         * Parameters.
1236a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden         */
1237a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        if (typeDescriptor[0] != '(') {
1238a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            fprintf(stderr, "ERROR: bad descriptor '%s'\n", typeDescriptor);
1239a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            goto bail;
1240a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        }
1241a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1242a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        char tmpBuf[strlen(typeDescriptor)+1];      /* more than big enough */
1243a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        int argNum = 0;
1244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1245a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        const char* base = typeDescriptor+1;
1246a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1247a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        while (*base != ')') {
1248a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            char* cp = tmpBuf;
1249a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1250a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            while (*base == '[')
1251a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden                *cp++ = *base++;
1252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1253a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            if (*base == 'L') {
1254a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden                /* copy through ';' */
1255a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden                do {
1256a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden                    *cp = *base++;
1257a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden                } while (*cp++ != ';');
1258a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            } else {
1259a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden                /* primitive char, copy it */
1260a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden                if (strchr("ZBCSIFJD", *base) == NULL) {
1261a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden                    fprintf(stderr, "ERROR: bad method signature '%s'\n", base);
1262a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden                    goto bail;
1263a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden                }
1264a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden                *cp++ = *base++;
1265a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            }
1266a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1267a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            /* null terminate and display */
1268a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            *cp++ = '\0';
1269a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1270a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            char* tmp = descriptorToDot(tmpBuf);
1271a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            printf("<parameter name=\"arg%d\" type=\"%s\">\n</parameter>\n",
1272a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden                argNum++, tmp);
1273a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            free(tmp);
1274a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        }
1275a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1276a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        if (constructor)
1277a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            printf("</constructor>\n");
1278a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        else
1279a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            printf("</method>\n");
1280a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    }
1281a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1282a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFaddenbail:
1283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(typeDescriptor);
1284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(accessStr);
1285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump a static (class) field.
1289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dumpSField(const DexFile* pDexFile, const DexField* pSField, int i)
1291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexFieldId* pFieldId;
1293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* backDescriptor;
1294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* name;
1295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* typeDescriptor;
1296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* accessStr;
1297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1298a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    if (gOptions.exportsOnly &&
1299a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        (pSField->accessFlags & (ACC_PUBLIC | ACC_PROTECTED)) == 0)
1300a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    {
1301a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        return;
1302a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    }
1303a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pFieldId = dexGetFieldId(pDexFile, pSField->fieldIdx);
1305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    name = dexStringById(pDexFile, pFieldId->nameIdx);
1306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    typeDescriptor = dexStringByTypeIdx(pDexFile, pFieldId->typeIdx);
1307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    backDescriptor = dexStringByTypeIdx(pDexFile, pFieldId->classIdx);
1308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    accessStr = createAccessFlagStr(pSField->accessFlags, kAccessForField);
1310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1311a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    if (gOptions.outputFormat == OUTPUT_PLAIN) {
1312a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf("    #%d              : (in %s)\n", i, backDescriptor);
1313a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf("      name          : '%s'\n", name);
1314a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf("      type          : '%s'\n", typeDescriptor);
1315a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf("      access        : 0x%04x (%s)\n",
1316a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            pSField->accessFlags, accessStr);
1317a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    } else if (gOptions.outputFormat == OUTPUT_XML) {
1318a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        char* tmp;
1319a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1320a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf("<field name=\"%s\"\n", name);
1321a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1322a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        tmp = descriptorToDot(typeDescriptor);
1323a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf(" type=\"%s\"\n", tmp);
1324a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        free(tmp);
1325a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1326a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf(" transient=%s\n",
1327a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            quotedBool((pSField->accessFlags & ACC_TRANSIENT) != 0));
1328a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf(" volatile=%s\n",
1329a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            quotedBool((pSField->accessFlags & ACC_VOLATILE) != 0));
1330a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        // "value=" not knowable w/o parsing annotations
1331a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf(" static=%s\n",
1332a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            quotedBool((pSField->accessFlags & ACC_STATIC) != 0));
1333a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf(" final=%s\n",
1334a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            quotedBool((pSField->accessFlags & ACC_FINAL) != 0));
1335a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        // "deprecated=" not knowable w/o parsing annotations
1336a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf(" visibility=%s\n",
1337a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            quotedVisibility(pSField->accessFlags));
1338a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf(">\n</field>\n");
1339a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    }
1340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(accessStr);
1342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump an instance field.
1346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dumpIField(const DexFile* pDexFile, const DexField* pIField, int i)
1348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1349a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    dumpSField(pDexFile, pIField, i);
1350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the class.
135499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project *
135599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * Note "idx" is a DexClassDef index, not a DexTypeId index.
1356d18aff3e3ef753a0b6725f1b0a9cd47faa5989e0Andy McFadden *
1357a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden * If "*pLastPackage" is NULL or does not match the current class' package,
1358a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden * the value will be replaced with a newly-allocated string.
1359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1360a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFaddenvoid dumpClass(DexFile* pDexFile, int idx, char** pLastPackage)
1361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexTypeList* pInterfaces;
1363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexClassDef* pClassDef;
1364a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    DexClassData* pClassData = NULL;
1365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const u1* pEncodedData;
1366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* fileName;
1367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* classDescriptor;
1368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* superclassDescriptor;
1369a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    char* accessStr = NULL;
1370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pClassDef = dexGetClassDef(pDexFile, idx);
1373a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1374a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    if (gOptions.exportsOnly && (pClassDef->accessFlags & ACC_PUBLIC) == 0) {
1375a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        //printf("<!-- omitting non-public class %s -->\n",
1376a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        //    classDescriptor);
1377a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        goto bail;
1378a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    }
1379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pEncodedData = dexGetClassData(pDexFile, pClassDef);
1381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pClassData = dexReadAndVerifyClassData(&pEncodedData, NULL);
1382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pClassData == NULL) {
1384a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf("Trouble reading class data (#%d)\n", idx);
1385a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        goto bail;
1386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1387de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
1388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    classDescriptor = dexStringByTypeIdx(pDexFile, pClassDef->classIdx);
1389a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1390a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    /*
1391a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden     * For the XML output, show the package name.  Ideally we'd gather
1392a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden     * up the classes, sort them, and dump them alphabetically so the
1393a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden     * package name wouldn't jump around, but that's not a great plan
1394a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden     * for something that needs to run on the device.
1395a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden     */
1396a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    if (!(classDescriptor[0] == 'L' &&
1397a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden          classDescriptor[strlen(classDescriptor)-1] == ';'))
1398a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    {
1399a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        /* arrays and primitives should not be defined explicitly */
1400a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        fprintf(stderr, "Malformed class name '%s'\n", classDescriptor);
1401a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        /* keep going? */
1402a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    } else if (gOptions.outputFormat == OUTPUT_XML) {
1403a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        char* mangle;
1404a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        char* lastSlash;
1405a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        char* cp;
1406a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1407a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        mangle = strdup(classDescriptor + 1);
1408a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        mangle[strlen(mangle)-1] = '\0';
1409a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1410a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        /* reduce to just the package name */
1411a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        lastSlash = strrchr(mangle, '/');
1412a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        if (lastSlash != NULL) {
1413a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            *lastSlash = '\0';
1414a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        } else {
1415a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            *mangle = '\0';
1416a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        }
1417a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1418a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        for (cp = mangle; *cp != '\0'; cp++) {
1419a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            if (*cp == '/')
1420a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden                *cp = '.';
1421a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        }
1422a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1423a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        if (*pLastPackage == NULL || strcmp(mangle, *pLastPackage) != 0) {
1424a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            /* start of a new package */
1425a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            if (*pLastPackage != NULL)
1426a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden                printf("</package>\n");
1427a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            printf("<package name=\"%s\"\n>\n", mangle);
1428a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            free(*pLastPackage);
1429a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            *pLastPackage = mangle;
1430a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        } else {
1431a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            free(mangle);
1432a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        }
1433a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    }
1434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    accessStr = createAccessFlagStr(pClassDef->accessFlags, kAccessForClass);
1436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1437a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    if (pClassDef->superclassIdx == kDexNoIndex) {
1438a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        superclassDescriptor = NULL;
1439a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    } else {
1440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        superclassDescriptor =
1441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dexStringByTypeIdx(pDexFile, pClassDef->superclassIdx);
1442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1444a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    if (gOptions.outputFormat == OUTPUT_PLAIN) {
1445a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf("Class #%d            -\n", idx);
1446a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf("  Class descriptor  : '%s'\n", classDescriptor);
1447a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf("  Access flags      : 0x%04x (%s)\n",
1448a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            pClassDef->accessFlags, accessStr);
1449a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1450a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        if (superclassDescriptor != NULL)
1451a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            printf("  Superclass        : '%s'\n", superclassDescriptor);
1452a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1453a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf("  Interfaces        -\n");
1454a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    } else {
1455a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        char* tmp;
1456a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1457a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        tmp = descriptorClassToDot(classDescriptor);
1458a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf("<class name=\"%s\"\n", tmp);
1459a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        free(tmp);
1460a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1461a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        if (superclassDescriptor != NULL) {
1462a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            tmp = descriptorToDot(superclassDescriptor);
1463a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            printf(" extends=\"%s\"\n", tmp);
1464a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            free(tmp);
1465a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        }
1466a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf(" abstract=%s\n",
1467a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            quotedBool((pClassDef->accessFlags & ACC_ABSTRACT) != 0));
1468a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf(" static=%s\n",
1469a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            quotedBool((pClassDef->accessFlags & ACC_STATIC) != 0));
1470a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf(" final=%s\n",
1471a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            quotedBool((pClassDef->accessFlags & ACC_FINAL) != 0));
1472a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        // "deprecated=" not knowable w/o parsing annotations
1473a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf(" visibility=%s\n",
1474a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            quotedVisibility(pClassDef->accessFlags));
1475a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf(">\n");
1476a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    }
1477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pInterfaces = dexGetInterfacesList(pDexFile, pClassDef);
1478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pInterfaces != NULL) {
1479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0; i < (int) pInterfaces->size; i++)
1480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dumpInterface(pDexFile, dexGetTypeItem(pInterfaces, i), i);
1481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1483a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    if (gOptions.outputFormat == OUTPUT_PLAIN)
1484a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf("  Static fields     -\n");
1485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < (int) pClassData->header.staticFieldsSize; i++) {
1486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dumpSField(pDexFile, &pClassData->staticFields[i], i);
1487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1489a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    if (gOptions.outputFormat == OUTPUT_PLAIN)
1490a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf("  Instance fields   -\n");
1491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < (int) pClassData->header.instanceFieldsSize; i++) {
1492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dumpIField(pDexFile, &pClassData->instanceFields[i], i);
1493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1495a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    if (gOptions.outputFormat == OUTPUT_PLAIN)
1496a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf("  Direct methods    -\n");
1497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < (int) pClassData->header.directMethodsSize; i++) {
1498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dumpMethod(pDexFile, &pClassData->directMethods[i], i);
1499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1501a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    if (gOptions.outputFormat == OUTPUT_PLAIN)
1502a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf("  Virtual methods   -\n");
1503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < (int) pClassData->header.virtualMethodsSize; i++) {
1504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dumpMethod(pDexFile, &pClassData->virtualMethods[i], i);
1505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // TODO: Annotations.
1508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pClassDef->sourceFileIdx != kDexNoIndex)
1510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fileName = dexStringById(pDexFile, pClassDef->sourceFileIdx);
1511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
1512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fileName = "unknown";
1513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1514a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    if (gOptions.outputFormat == OUTPUT_PLAIN) {
1515a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf("  source_file_idx   : %d (%s)\n",
1516a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            pClassDef->sourceFileIdx, fileName);
1517a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf("\n");
1518a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    }
1519a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1520a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    if (gOptions.outputFormat == OUTPUT_XML) {
1521a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf("</class>\n");
1522a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    }
1523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1524a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFaddenbail:
1525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(pClassData);
1526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(accessStr);
1527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
152999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
153099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project/*
153199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * Advance "ptr" to ensure 32-bit alignment.
153299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project */
153399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Projectstatic inline const u1* align32(const u1* ptr)
153499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project{
1535b210a9f9c7ae17e2028a86d9a4e9a3b35472862aSangWook Han    return (u1*) (((uintptr_t) ptr + 3) & ~0x03);
153699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project}
153799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
15381035127f783b84befca34f1afe2a5bff64546902Andy McFadden
15391035127f783b84befca34f1afe2a5bff64546902Andy McFadden/*
15401035127f783b84befca34f1afe2a5bff64546902Andy McFadden * Dump a map in the "differential" format.
15411035127f783b84befca34f1afe2a5bff64546902Andy McFadden *
15421035127f783b84befca34f1afe2a5bff64546902Andy McFadden * TODO: show a hex dump of the compressed data.  (We can show the
15431035127f783b84befca34f1afe2a5bff64546902Andy McFadden * uncompressed data if we move the compression code to libdex; otherwise
15441035127f783b84befca34f1afe2a5bff64546902Andy McFadden * it's too complex to merit a fast & fragile implementation here.)
15451035127f783b84befca34f1afe2a5bff64546902Andy McFadden */
15461035127f783b84befca34f1afe2a5bff64546902Andy McFaddenvoid dumpDifferentialCompressedMap(const u1** pData)
15471035127f783b84befca34f1afe2a5bff64546902Andy McFadden{
15481035127f783b84befca34f1afe2a5bff64546902Andy McFadden    const u1* data = *pData;
15491035127f783b84befca34f1afe2a5bff64546902Andy McFadden    const u1* dataStart = data -1;      // format byte already removed
15501035127f783b84befca34f1afe2a5bff64546902Andy McFadden    u1 regWidth;
15511035127f783b84befca34f1afe2a5bff64546902Andy McFadden    u2 numEntries;
15521035127f783b84befca34f1afe2a5bff64546902Andy McFadden
15531035127f783b84befca34f1afe2a5bff64546902Andy McFadden    /* standard header */
15541035127f783b84befca34f1afe2a5bff64546902Andy McFadden    regWidth = *data++;
15551035127f783b84befca34f1afe2a5bff64546902Andy McFadden    numEntries = *data++;
15561035127f783b84befca34f1afe2a5bff64546902Andy McFadden    numEntries |= (*data++) << 8;
15571035127f783b84befca34f1afe2a5bff64546902Andy McFadden
15581035127f783b84befca34f1afe2a5bff64546902Andy McFadden    /* compressed data begins with the compressed data length */
15591035127f783b84befca34f1afe2a5bff64546902Andy McFadden    int compressedLen = readUnsignedLeb128(&data);
15601035127f783b84befca34f1afe2a5bff64546902Andy McFadden    int addrWidth = 1;
15611035127f783b84befca34f1afe2a5bff64546902Andy McFadden    if ((*data & 0x80) != 0)
15621035127f783b84befca34f1afe2a5bff64546902Andy McFadden        addrWidth++;
15631035127f783b84befca34f1afe2a5bff64546902Andy McFadden
15641035127f783b84befca34f1afe2a5bff64546902Andy McFadden    int origLen = 4 + (addrWidth + regWidth) * numEntries;
15651035127f783b84befca34f1afe2a5bff64546902Andy McFadden    int compLen = (data - dataStart) + compressedLen;
15661035127f783b84befca34f1afe2a5bff64546902Andy McFadden
15671035127f783b84befca34f1afe2a5bff64546902Andy McFadden    printf("        (differential compression %d -> %d [%d -> %d])\n",
15681035127f783b84befca34f1afe2a5bff64546902Andy McFadden        origLen, compLen,
15691035127f783b84befca34f1afe2a5bff64546902Andy McFadden        (addrWidth + regWidth) * numEntries, compressedLen);
15701035127f783b84befca34f1afe2a5bff64546902Andy McFadden
15711035127f783b84befca34f1afe2a5bff64546902Andy McFadden    /* skip past end of entry */
15721035127f783b84befca34f1afe2a5bff64546902Andy McFadden    data += compressedLen;
15731035127f783b84befca34f1afe2a5bff64546902Andy McFadden
15741035127f783b84befca34f1afe2a5bff64546902Andy McFadden    *pData = data;
15751035127f783b84befca34f1afe2a5bff64546902Andy McFadden}
15761035127f783b84befca34f1afe2a5bff64546902Andy McFadden
157799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project/*
157899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * Dump register map contents of the current method.
157999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project *
158099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * "*pData" should point to the start of the register map data.  Advances
158199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * "*pData" to the start of the next map.
158299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project */
158399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Projectvoid dumpMethodMap(DexFile* pDexFile, const DexMethod* pDexMethod, int idx,
158499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    const u1** pData)
158599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project{
158699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    const u1* data = *pData;
158799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    const DexMethodId* pMethodId;
158899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    const char* name;
158999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    int offset = data - (u1*) pDexFile->pOptHeader;
159099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
159199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    pMethodId = dexGetMethodId(pDexFile, pDexMethod->methodIdx);
159299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    name = dexStringById(pDexFile, pMethodId->nameIdx);
159399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    printf("      #%d: 0x%08x %s\n", idx, offset, name);
159499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
159599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    u1 format;
159699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    int addrWidth;
159799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
159899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    format = *data++;
159999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    if (format == 1) {              /* kRegMapFormatNone */
160099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        /* no map */
160199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        printf("        (no map)\n");
160299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        addrWidth = 0;
160399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    } else if (format == 2) {       /* kRegMapFormatCompact8 */
160499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        addrWidth = 1;
160599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    } else if (format == 3) {       /* kRegMapFormatCompact16 */
160699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        addrWidth = 2;
16071035127f783b84befca34f1afe2a5bff64546902Andy McFadden    } else if (format == 4) {       /* kRegMapFormatDifferential */
16081035127f783b84befca34f1afe2a5bff64546902Andy McFadden        dumpDifferentialCompressedMap(&data);
16091035127f783b84befca34f1afe2a5bff64546902Andy McFadden        goto bail;
161099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    } else {
161199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        printf("        (unknown format %d!)\n", format);
16121035127f783b84befca34f1afe2a5bff64546902Andy McFadden        /* don't know how to skip data; failure will cascade to end of class */
16131035127f783b84befca34f1afe2a5bff64546902Andy McFadden        goto bail;
161499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    }
161599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
161699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    if (addrWidth > 0) {
161799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        u1 regWidth;
161899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        u2 numEntries;
161999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        int idx, addr, byte;
162099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
162199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        regWidth = *data++;
162299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        numEntries = *data++;
162399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        numEntries |= (*data++) << 8;
162499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
162599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        for (idx = 0; idx < numEntries; idx++) {
162699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            addr = *data++;
162799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            if (addrWidth > 1)
162899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project                addr |= (*data++) << 8;
162999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
163099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            printf("        %4x:", addr);
163199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            for (byte = 0; byte < regWidth; byte++) {
163299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project                printf(" %02x", *data++);
163399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            }
163499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            printf("\n");
163599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        }
163699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    }
163799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
16381035127f783b84befca34f1afe2a5bff64546902Andy McFaddenbail:
163999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    //if (addrWidth >= 0)
164099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    //    *pData = align32(data);
164199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    *pData = data;
164299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project}
164399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
164499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project/*
164599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * Dump the contents of the register map area.
164699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project *
164799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * These are only present in optimized DEX files, and the structure is
164899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * not really exposed to other parts of the VM itself.  We're going to
164999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * dig through them here, but this is pretty fragile.  DO NOT rely on
165099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * this or derive other code from it.
165199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project */
165299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Projectvoid dumpRegisterMaps(DexFile* pDexFile)
165399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project{
1654bfc9799b1a53fd6f6136d07e6278d4538cf70f13Carl Shapiro    const u1* pClassPool = (const u1*)pDexFile->pRegisterMapPool;
165599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    const u4* classOffsets;
165699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    const u1* ptr;
165799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    u4 numClasses;
165899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    int baseFileOffset = (u1*) pClassPool - (u1*) pDexFile->pOptHeader;
165999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    int idx;
166099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
166199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    if (pClassPool == NULL) {
166299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        printf("No register maps found\n");
166399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        return;
166499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    }
166599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
166699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    ptr = pClassPool;
166799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    numClasses = get4LE(ptr);
166899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    ptr += sizeof(u4);
166999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    classOffsets = (const u4*) ptr;
167099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
167199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    printf("RMAP begins at offset 0x%07x\n", baseFileOffset);
167299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    printf("Maps for %d classes\n", numClasses);
167399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    for (idx = 0; idx < (int) numClasses; idx++) {
167499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        const DexClassDef* pClassDef;
167599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        const char* classDescriptor;
167699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
167799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        pClassDef = dexGetClassDef(pDexFile, idx);
167899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        classDescriptor = dexStringByTypeIdx(pDexFile, pClassDef->classIdx);
167999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
168099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        printf("%4d: +%d (0x%08x) %s\n", idx, classOffsets[idx],
168199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            baseFileOffset + classOffsets[idx], classDescriptor);
168299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
168399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        if (classOffsets[idx] == 0)
168499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            continue;
168599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
168699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        /*
168799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * What follows is a series of RegisterMap entries, one for every
168899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * direct method, then one for every virtual method.
168999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         */
169099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        DexClassData* pClassData;
169199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        const u1* pEncodedData;
169299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        const u1* data = (u1*) pClassPool + classOffsets[idx];
169399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        u2 methodCount;
169499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        int i;
169599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
169699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        pEncodedData = dexGetClassData(pDexFile, pClassDef);
169799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        pClassData = dexReadAndVerifyClassData(&pEncodedData, NULL);
169899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        if (pClassData == NULL) {
169999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            fprintf(stderr, "Trouble reading class data\n");
170099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            continue;
170199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        }
170299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
170399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        methodCount = *data++;
170499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        methodCount |= (*data++) << 8;
170599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        data += 2;      /* two pad bytes follow methodCount */
170699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        if (methodCount != pClassData->header.directMethodsSize
170799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project                            + pClassData->header.virtualMethodsSize)
170899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        {
170999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            printf("NOTE: method count discrepancy (%d != %d + %d)\n",
171099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project                methodCount, pClassData->header.directMethodsSize,
171199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project                pClassData->header.virtualMethodsSize);
171299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            /* this is bad, but keep going anyway */
171399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        }
171499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
171599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        printf("    direct methods: %d\n",
171699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            pClassData->header.directMethodsSize);
171799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        for (i = 0; i < (int) pClassData->header.directMethodsSize; i++) {
171899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            dumpMethodMap(pDexFile, &pClassData->directMethods[i], i, &data);
171999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        }
172099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
172199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        printf("    virtual methods: %d\n",
172299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            pClassData->header.virtualMethodsSize);
172399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        for (i = 0; i < (int) pClassData->header.virtualMethodsSize; i++) {
172499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            dumpMethodMap(pDexFile, &pClassData->virtualMethods[i], i, &data);
172599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        }
172699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
172799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        free(pClassData);
172899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    }
172999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project}
173099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
1731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the requested sections of the file.
1733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid processDexFile(const char* fileName, DexFile* pDexFile)
1735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1736a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    char* package = NULL;
1737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1739a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    if (gOptions.verbose) {
1740a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf("Opened '%s', DEX version '%.3s'\n", fileName,
1741a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            pDexFile->pHeader->magic +4);
1742a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    }
1743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
174499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    if (gOptions.dumpRegisterMaps) {
174599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        dumpRegisterMaps(pDexFile);
174699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        return;
174799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    }
174899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
17490ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden    if (gOptions.showFileHeaders) {
1750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dumpFileHeader(pDexFile);
1751e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein        dumpOptDirectory(pDexFile);
17520ea77b9be67b3491d878ed0f9314f6ecf6f79d61Andy McFadden    }
1753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1754a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    if (gOptions.outputFormat == OUTPUT_XML)
1755a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf("<api>\n");
1756a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < (int) pDexFile->pHeader->classDefsSize; i++) {
1758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (gOptions.showSectionHeaders)
1759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dumpClassDef(pDexFile, i);
1760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1761a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        dumpClass(pDexFile, i, &package);
1762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1763a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1764a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    /* free the last one allocated */
1765a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    if (package != NULL) {
1766a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf("</package>\n");
1767a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        free(package);
1768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1769a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden
1770a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    if (gOptions.outputFormat == OUTPUT_XML)
1771a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf("</api>\n");
1772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Process one file.
1777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint process(const char* fileName)
1779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexFile* pDexFile = NULL;
1781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    MemMapping map;
1782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool mapped = false;
1783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result = -1;
1784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1785a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    if (gOptions.verbose)
1786a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        printf("Processing '%s'...\n", fileName);
1787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1788bfc9799b1a53fd6f6136d07e6278d4538cf70f13Carl Shapiro    if (dexOpenAndMap(fileName, gOptions.tempFileName, &map, false) != 0) {
1789bfc9799b1a53fd6f6136d07e6278d4538cf70f13Carl Shapiro        return result;
1790bfc9799b1a53fd6f6136d07e6278d4538cf70f13Carl Shapiro    }
1791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mapped = true;
1792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
17932124cb83c3d46542d6bbc7a5da5b2288f4d6401bAndy McFadden    int flags = kDexParseVerifyChecksum;
17942124cb83c3d46542d6bbc7a5da5b2288f4d6401bAndy McFadden    if (gOptions.ignoreBadChecksum)
17952124cb83c3d46542d6bbc7a5da5b2288f4d6401bAndy McFadden        flags |= kDexParseContinueOnError;
17962124cb83c3d46542d6bbc7a5da5b2288f4d6401bAndy McFadden
1797bfc9799b1a53fd6f6136d07e6278d4538cf70f13Carl Shapiro    pDexFile = dexFileParse((u1*)map.addr, map.length, flags);
1798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pDexFile == NULL) {
1799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fprintf(stderr, "ERROR: DEX parse failed\n");
1800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
1801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
18030198b1443707d575d30c2b20f1bc3766a9221e96Andy McFadden    if (gOptions.checksumOnly) {
18040198b1443707d575d30c2b20f1bc3766a9221e96Andy McFadden        printf("Checksum verified\n");
18050198b1443707d575d30c2b20f1bc3766a9221e96Andy McFadden    } else {
18060198b1443707d575d30c2b20f1bc3766a9221e96Andy McFadden        processDexFile(fileName, pDexFile);
18070198b1443707d575d30c2b20f1bc3766a9221e96Andy McFadden    }
1808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = 0;
1810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
1812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mapped)
1813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sysReleaseShmem(&map);
1814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pDexFile != NULL)
1815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dexFileFree(pDexFile);
1816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
1817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Show usage.
1822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid usage(void)
1824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fprintf(stderr, "Copyright (C) 2007 The Android Open Source Project\n\n");
18260198b1443707d575d30c2b20f1bc3766a9221e96Andy McFadden    fprintf(stderr,
1827d18aff3e3ef753a0b6725f1b0a9cd47faa5989e0Andy McFadden        "%s: [-c] [-d] [-f] [-h] [-i] [-l layout] [-m] [-t tempfile] dexfile...\n",
182899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        gProgName);
1829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fprintf(stderr, "\n");
18300198b1443707d575d30c2b20f1bc3766a9221e96Andy McFadden    fprintf(stderr, " -c : verify checksum and exit\n");
1831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fprintf(stderr, " -d : disassemble code sections\n");
1832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fprintf(stderr, " -f : display summary information from file header\n");
1833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fprintf(stderr, " -h : display file header details\n");
18342124cb83c3d46542d6bbc7a5da5b2288f4d6401bAndy McFadden    fprintf(stderr, " -i : ignore checksum failures\n");
1835a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    fprintf(stderr, " -l : output layout, either 'plain' or 'xml'\n");
183699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    fprintf(stderr, " -m : dump register maps (and nothing else)\n");
1837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fprintf(stderr, " -t : temp file name (defaults to /sdcard/dex-temp-*)\n");
1838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Parse args.
1842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * I'm not using getopt_long() because we may not have it in libc.
1844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint main(int argc, char* const argv[])
1846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool wantUsage = false;
1848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int ic;
1849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memset(&gOptions, 0, sizeof(gOptions));
1851a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden    gOptions.verbose = true;
1852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (1) {
1854d18aff3e3ef753a0b6725f1b0a9cd47faa5989e0Andy McFadden        ic = getopt(argc, argv, "cdfhil:mt:");
1855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (ic < 0)
1856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (ic) {
18590198b1443707d575d30c2b20f1bc3766a9221e96Andy McFadden        case 'c':       // verify the checksum then exit
18600198b1443707d575d30c2b20f1bc3766a9221e96Andy McFadden            gOptions.checksumOnly = true;
18610198b1443707d575d30c2b20f1bc3766a9221e96Andy McFadden            break;
1862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case 'd':       // disassemble Dalvik instructions
1863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            gOptions.disassemble = true;
1864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case 'f':       // dump outer file header
1866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            gOptions.showFileHeaders = true;
1867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case 'h':       // dump section headers, i.e. all meta-data
1869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            gOptions.showSectionHeaders = true;
1870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
18712124cb83c3d46542d6bbc7a5da5b2288f4d6401bAndy McFadden        case 'i':       // continue even if checksum is bad
18722124cb83c3d46542d6bbc7a5da5b2288f4d6401bAndy McFadden            gOptions.ignoreBadChecksum = true;
18732124cb83c3d46542d6bbc7a5da5b2288f4d6401bAndy McFadden            break;
1874a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden        case 'l':       // layout
1875a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            if (strcmp(optarg, "plain") == 0) {
1876a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden                gOptions.outputFormat = OUTPUT_PLAIN;
1877a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            } else if (strcmp(optarg, "xml") == 0) {
1878a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden                gOptions.outputFormat = OUTPUT_XML;
1879a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden                gOptions.verbose = false;
1880a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden                gOptions.exportsOnly = true;
1881a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            } else {
1882a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden                wantUsage = true;
1883a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            }
1884a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            break;
188599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        case 'm':       // dump register maps only
188699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            gOptions.dumpRegisterMaps = true;
188799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            break;
1888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        case 't':       // temp file, used when opening compressed Jar
1889a2ee53bac4db4c77aa2bb31bad8a9d177fd09301Andy McFadden            gOptions.tempFileName = optarg;
1890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        default:
1892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            wantUsage = true;
1893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (optind == argc) {
1898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fprintf(stderr, "%s: no file specified\n", gProgName);
1899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        wantUsage = true;
1900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
19020198b1443707d575d30c2b20f1bc3766a9221e96Andy McFadden    if (gOptions.checksumOnly && gOptions.ignoreBadChecksum) {
19030198b1443707d575d30c2b20f1bc3766a9221e96Andy McFadden        fprintf(stderr, "Can't specify both -c and -i\n");
19040198b1443707d575d30c2b20f1bc3766a9221e96Andy McFadden        wantUsage = true;
19050198b1443707d575d30c2b20f1bc3766a9221e96Andy McFadden    }
19060198b1443707d575d30c2b20f1bc3766a9221e96Andy McFadden
1907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (wantUsage) {
1908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        usage();
1909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 2;
1910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
19120198b1443707d575d30c2b20f1bc3766a9221e96Andy McFadden    int result = 0;
19130198b1443707d575d30c2b20f1bc3766a9221e96Andy McFadden    while (optind < argc) {
19140198b1443707d575d30c2b20f1bc3766a9221e96Andy McFadden        result |= process(argv[optind++]);
19150198b1443707d575d30c2b20f1bc3766a9221e96Andy McFadden    }
1916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
19170198b1443707d575d30c2b20f1bc3766a9221e96Andy McFadden    return (result != 0);
1918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1919