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