diff options
author | Andy McFadden <fadden@android.com> | 2010-04-20 14:18:59 -0700 |
---|---|---|
committer | Andy McFadden <fadden@android.com> | 2010-04-20 15:30:37 -0700 |
commit | 0ea77b9be67b3491d878ed0f9314f6ecf6f79d61 (patch) | |
tree | 1138bd06810aa9ad1d7e7ad76e5c7521027d6dd3 /dexdump | |
parent | 0d90503b1b0e29ec0060938341457f8548ca4ac8 (diff) | |
download | android_dalvik-0ea77b9be67b3491d878ed0f9314f6ecf6f79d61.tar.gz android_dalvik-0ea77b9be67b3491d878ed0f9314f6ecf6f79d61.tar.bz2 android_dalvik-0ea77b9be67b3491d878ed0f9314f6ecf6f79d61.zip |
Add some .odex info to dexdump output.
"dexdump -f" will now show the contents of the optimized DEX header if
one is present. A "table of contents" for the auxillary data is also
displayed.
As an added bonus, stop being lazy and sanitize the DEX magic before
printing it (it has an embedded newline and \0).
Change-Id: If9c5278785062cd0f44fc3d3ea0725ef0009932a
Diffstat (limited to 'dexdump')
-rw-r--r-- | dexdump/DexDump.c | 120 |
1 files changed, 118 insertions, 2 deletions
diff --git a/dexdump/DexDump.c b/dexdump/DexDump.c index b3b0839f7..09b072efb 100644 --- a/dexdump/DexDump.c +++ b/dexdump/DexDump.c @@ -357,14 +357,73 @@ static char* createAccessFlagStr(u4 flags, AccessFor forWhat) /* + * Copy character data from "data" to "out", converting non-ASCII values + * to printf format chars or an ASCII filler ('.' or '?'). + * + * The output buffer must be able to hold (2*len)+1 bytes. The result is + * NUL-terminated. + */ +static void asciify(char* out, const unsigned char* data, size_t len) +{ + while (len--) { + if (*data < 0x20) { + /* could do more here, but we don't need them yet */ + switch (*data) { + case '\0': + *out++ = '\\'; + *out++ = '0'; + break; + case '\n': + *out++ = '\\'; + *out++ = 'n'; + break; + default: + *out++ = '.'; + break; + } + } else if (*data >= 0x80) { + *out++ = '?'; + } else { + *out++ = *data; + } + data++; + } + *out = '\0'; +} + +/* * Dump the file header. */ void dumpFileHeader(const DexFile* pDexFile) { + const DexOptHeader* pOptHeader = pDexFile->pOptHeader; const DexHeader* pHeader = pDexFile->pHeader; + char sanitized[sizeof(pHeader->magic)*2 +1]; + + assert(sizeof(pHeader->magic) == sizeof(pOptHeader->magic)); + + if (pOptHeader != NULL) { + printf("Optimized DEX file header:\n"); + + asciify(sanitized, pOptHeader->magic, sizeof(pOptHeader->magic)); + printf("magic : '%s'\n", sanitized); + printf("dex_offset : %d (0x%06x)\n", + pOptHeader->dexOffset, pOptHeader->dexOffset); + printf("dex_length : %d\n", pOptHeader->dexLength); + printf("deps_offset : %d (0x%06x)\n", + pOptHeader->depsOffset, pOptHeader->depsOffset); + printf("deps_length : %d\n", pOptHeader->depsLength); + printf("aux_offset : %d (0x%06x)\n", + pOptHeader->auxOffset, pOptHeader->auxOffset); + printf("aux_length : %d\n", pOptHeader->auxLength); + printf("flags : %08x\n", pOptHeader->flags); + printf("checksum : %08x\n", pOptHeader->checksum); + printf("\n"); + } printf("DEX file header:\n"); - printf("magic : '%.8s'\n", pHeader->magic); + asciify(sanitized, pHeader->magic, sizeof(pHeader->magic)); + printf("magic : '%s'\n", sanitized); printf("checksum : %08x\n", pHeader->checksum); printf("signature : %02x%02x...%02x%02x\n", pHeader->signature[0], pHeader->signature[1], @@ -397,6 +456,61 @@ void dumpFileHeader(const DexFile* pDexFile) } /* + * Dump the "table of contents" for the aux area. + */ +void dumpAuxDirectory(const DexFile* pDexFile) +{ + const DexOptHeader* pOptHeader = pDexFile->pOptHeader; + if (pOptHeader == NULL) + return; + + printf("AUX section contents:\n"); + + const u4* pAux = (const u4*) ((u1*) pOptHeader + pOptHeader->auxOffset); + + if (*pAux == 0) { + printf("(1.0 format, only class lookup table is present)\n\n"); + return; + } + + /* + * The "aux" section is in "chunk" format: a 32-bit identifier, a 32-bit + * length, then the data. Chunks start on 64-bit boundaries. + */ + while (*pAux != kDexChunkEnd) { + const char* verboseStr; + + u4 size = *(pAux+1); + + switch (*pAux) { + case kDexChunkClassLookup: + verboseStr = "class lookup hash table"; + break; + case kDexChunkRegisterMaps: + verboseStr = "register maps"; + break; + case kDexChunkReducingIndexMap: + verboseStr = "'reducing' index map"; + break; + case kDexChunkExpandingIndexMap: + verboseStr = "'expanding' index map"; + break; + default: + verboseStr = "(unknown chunk type)"; + break; + } + + printf("Chunk %08x (%c%c%c%c) - %s (%d bytes)\n", *pAux, + *pAux >> 24, (char)(*pAux >> 16), (char)(*pAux >> 8), (char)*pAux, + verboseStr, size); + + size = (size + 8 + 7) & ~7; + pAux += size / sizeof(u4); + } + printf("\n"); +} + +/* * Dump a class_def_item. */ void dumpClassDef(DexFile* pDexFile, int idx) @@ -1609,8 +1723,10 @@ void processDexFile(const char* fileName, DexFile* pDexFile) return; } - if (gOptions.showFileHeaders) + if (gOptions.showFileHeaders) { dumpFileHeader(pDexFile); + dumpAuxDirectory(pDexFile); + } if (gOptions.outputFormat == OUTPUT_XML) printf("<api>\n"); |