/*++ Copyright (c) 1990 Microsoft Corporation Module Name: peext.c Abstract: This module contains the PE dump extensions Author: Kent Forschmiedt (kentf) 10-May-1995 Revision History: --*/ #include "precomp.h" #pragma hdrstop #include // STYP_ flags values for MIPS ROM images #define STYP_REG 0x00000000 #define STYP_TEXT 0x00000020 #define STYP_INIT 0x80000000 #define STYP_RDATA 0x00000100 #define STYP_DATA 0x00000040 #define STYP_LIT8 0x08000000 #define STYP_LIT4 0x10000000 #define STYP_SDATA 0x00000200 #define STYP_SBSS 0x00000080 #define STYP_BSS 0x00000400 #define STYP_LIB 0x40000000 #define STYP_UCODE 0x00000800 #define S_NRELOC_OVFL 0x20000000 #define IMAGE_SCN_MEM_SYSHEAP 0x00010000 // Obsolete #define IMAGE_SCN_MEM_PROTECTED 0x00004000 // Obsolete const static char * const MachineName[] = { "Unknown", "i386", "Alpha AXP", "Alpha AXP64", "Intel IA64", }; const static char * const SubsystemName[] = { "Unknown", "Native", "Windows GUI", "Windows CUI", "Posix CUI", }; const static char * const DirectoryEntryName[] = { "Export", "Import", "Resource", "Exception", "Security", "Base Relocation", "Debug", "Description", "Special", "Thread Storage", "Load Configuration", "Bound Import", "Import Address Table", "Reserved", "Reserved", "Reserved", 0 }; typedef enum DFT { dftUnknown, dftObject, dftPE, dftROM, dftDBG, dftPEF, } DFT; typedef struct NB10I // NB10 debug info { DWORD nb10; // NB10 DWORD off; // offset, always 0 DWORD sig; DWORD age; } NB10I; IMAGE_NT_HEADERS ImageNtHeaders; PIMAGE_FILE_HEADER ImageFileHdr; PIMAGE_OPTIONAL_HEADER ImageOptionalHdr; PIMAGE_SECTION_HEADER SectionHdrs; ULONG64 Base; ULONG64 ImageNtHeadersAddr, ImageFileHdrAddr, ImageOptionalHdrAddr, SectionHdrsAddr; DFT dft; VOID DumpHeaders ( VOID ); VOID DumpSections( VOID ); BOOL TranslateFilePointerToVirtualAddress( IN ULONG64 FilePointer, OUT PULONG64 VirtualAddress ); VOID DumpImage( ULONG64 xBase, BOOL DoHeaders, BOOL DoSections ); VOID ImageExtension( IN PSTR lpArgs ); DECLARE_API( dh ) { INIT_API(); ImageExtension( (PSTR)args ); EXIT_API(); return S_OK; } VOID ImageExtension( IN PSTR lpArgs ) { BOOL DoAll; BOOL DoSections; BOOL DoHeaders; CHAR c; PCHAR p; ULONG64 xBase; // // Evaluate the argument string to get the address of the // image to dump. // DoAll = TRUE; DoHeaders = FALSE; DoSections = FALSE; xBase = 0; while (*lpArgs) { while (isspace(*lpArgs)) { lpArgs++; } if (*lpArgs == '/' || *lpArgs == '-') { // process switch switch (*++lpArgs) { case 'a': // dump everything we can case 'A': ++lpArgs; DoAll = TRUE; break; default: // invalid switch case 'h': // help case 'H': case '?': dprintf("Usage: dh [options] address\n"); dprintf("\n"); dprintf("Dumps headers from an image based at address.\n"); dprintf("\n"); dprintf("Options:\n"); dprintf("\n"); dprintf(" -a Dump everything\n"); dprintf(" -f Dump file headers\n"); dprintf(" -s Dump section headers\n"); dprintf("\n"); return; case 'f': case 'F': ++lpArgs; DoAll = FALSE; DoHeaders = TRUE; break; case 's': case 'S': ++lpArgs; DoAll = FALSE; DoSections = TRUE; break; } } else if (*lpArgs) { if (xBase != 0) { dprintf("Invalid extra argument\n"); return; } p = lpArgs; while (*p && !isspace(*p)) { p++; } c = *p; *p = 0; xBase = GetExpression(lpArgs); *p = c; lpArgs=p; } } if ( !xBase ) { return; } DumpImage(xBase, DoAll || DoHeaders, DoAll || DoSections); } VOID DumpImage( ULONG64 xBase, BOOL DoHeaders, BOOL DoSections ) { IMAGE_DOS_HEADER DosHeader; ULONG cb; ULONG64 Offset; BOOL Ok; Base = xBase; Ok = ReadMemory(Base, &DosHeader, sizeof(DosHeader), &cb); if (!Ok) { dprintf("Can't read file header: error == %d\n", GetLastError()); return; } if (cb != sizeof(DosHeader) || DosHeader.e_magic != IMAGE_DOS_SIGNATURE) { dprintf("No file header.\n"); return; } Offset = Base + DosHeader.e_lfanew; Ok = ReadMemory(Offset, &ImageNtHeaders, sizeof(ImageNtHeaders), &cb); ImageNtHeadersAddr = Offset; if (!Ok) { dprintf("Can't read optional header: error == %d\n", GetLastError()); return; } if (InitTypeRead(ImageNtHeadersAddr, IMAGE_NT_HEADERS)) { dprintf("Bad file header.\n"); return; } ImageFileHdr = &ImageNtHeaders.FileHeader; ImageFileHdrAddr = ReadField(FileHeader); ImageOptionalHdr = &ImageNtHeaders.OptionalHeader; ImageOptionalHdrAddr = ReadField(OptionalHeader); if ((ULONG) ReadField(FileHeader.SizeOfOptionalHeader) == GetTypeSize("IMAGE_ROM_OPTIONAL_HEADER")) { dft = dftROM; } else if (ImageFileHdr->Characteristics & IMAGE_FILE_DLL) { dft = dftPE; } else if (ImageFileHdr->Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) { dft = dftPE; } else if (ImageFileHdr->SizeOfOptionalHeader == 0) { dft = dftObject; } else { dft = dftUnknown; } if (DoHeaders) { DumpHeaders(); } if (DoSections) { ULONG SectSize, NumSections; SectSize = GetTypeSize("IMAGE_SECTION_HEADER"); InitTypeRead(ImageFileHdrAddr, IMAGE_FILE_HEADER); SectionHdrs = (PIMAGE_SECTION_HEADER) malloc((NumSections =(ULONG) ReadField(NumberOfSections) )* SectSize); try { SectionHdrsAddr = Offset + GetTypeSize("IMAGE_NT_HEADERS") + ReadField(SizeOfOptionalHeader) - GetTypeSize("IMAGE_OPTIONAL_HEADER"); Ok = ReadMemory( SectionHdrsAddr, SectionHdrs, (NumSections) * SectSize, &cb); if (!Ok) { dprintf("Can't read section headers.\n"); } else { if (cb != NumSections * SectSize) { dprintf("\n***\n*** Some section headers may be missing ***\n***\n\n"); NumSections = (USHORT)(cb / SectSize); } DumpSections( ); } } finally { if (SectionHdrs) { free(SectionHdrs); SectionHdrs = 0; } } } } VOID DumpHeaders ( VOID ) /*++ Routine Description: Formats the file header and optional header. Arguments: None. Return Value: None. --*/ { int i, j; const char *time; const char *name; DWORD dw; ULONG TimeDateStamp, SizeOfOptionalHeader, DirOff, DirSize; InitTypeRead(ImageFileHdrAddr, IMAGE_FILE_HEADER); // Print out file type switch (dft) { case dftObject : dprintf("\nFile Type: COFF OBJECT\n"); break; case dftPE : if (ReadField(Characteristics) & IMAGE_FILE_DLL) { dprintf("\nFile Type: DLL\n"); } else { dprintf("\nFile Type: EXECUTABLE IMAGE\n"); } break; case dftROM : dprintf("\nFile Type: ROM IMAGE\n"); break; default : dprintf("\nFile Type: UNKNOWN\n"); break; } switch (ReadField(Machine)) { case IMAGE_FILE_MACHINE_I386 : i = 1; break; case IMAGE_FILE_MACHINE_ALPHA : i = 2; break; case IMAGE_FILE_MACHINE_ALPHA64 : i = 3; break; case IMAGE_FILE_MACHINE_IA64 : i = 4; break; default : i = 0; } dprintf( "FILE HEADER VALUES\n" "%8hX machine (%s)\n" "%8hX number of sections\n" "%8lX time date stamp", (ULONG) ReadField(Machine), MachineName[i], (ULONG) ReadField(NumberOfSections), TimeDateStamp = (ULONG) ReadField(TimeDateStamp)); if ((time = ctime((time_t *) &TimeDateStamp)) != NULL) { dprintf( " %s", time); } dprintf("\n"); dprintf( "%8lX file pointer to symbol table\n" "%8lX number of symbols\n" "%8hX size of optional header\n" "%8hX characteristics\n", (ULONG) ReadField(PointerToSymbolTable), (ULONG) ReadField(NumberOfSymbols), SizeOfOptionalHeader = (ULONG) ReadField(SizeOfOptionalHeader), (ULONG) ReadField(Characteristics)); for (dw = (ULONG) ReadField(Characteristics), j = 0; dw; dw >>= 1, j++) { if (dw & 1) { switch (1 << j) { case IMAGE_FILE_RELOCS_STRIPPED : name = "Relocations stripped"; break; case IMAGE_FILE_EXECUTABLE_IMAGE : name = "Executable"; break; case IMAGE_FILE_LINE_NUMS_STRIPPED : name = "Line numbers stripped"; break; case IMAGE_FILE_LOCAL_SYMS_STRIPPED : name = "Symbols stripped"; break; case IMAGE_FILE_BYTES_REVERSED_LO : name = "Bytes reversed"; break; case IMAGE_FILE_32BIT_MACHINE : name = "32 bit word machine"; break; case IMAGE_FILE_DEBUG_STRIPPED : name = "Debug information stripped"; break; case IMAGE_FILE_SYSTEM : name = "System"; break; case IMAGE_FILE_DLL : name = "DLL"; break; case IMAGE_FILE_BYTES_REVERSED_HI : name = ""; break; default : name = "RESERVED - UNKNOWN"; } if (*name) { dprintf( " %s\n", name); } } } if (SizeOfOptionalHeader != 0) { char szLinkerVersion[30]; ULONG Ptr64 = IsPtr64(); InitTypeRead(ImageOptionalHdrAddr, IMAGE_OPTIONAL_HEADER); sprintf(szLinkerVersion, "%u.%02u", (ULONG) ReadField(MajorLinkerVersion), (ULONG) ReadField(MinorLinkerVersion)); dprintf( "\n" "OPTIONAL HEADER VALUES\n" "%8hX magic #\n" "%8s linker version\n" "%8lX size of code\n" "%8lX size of initialized data\n" "%8lX size of uninitialized data\n" "%8P address of entry point\n" "%8P base of code\n" , (ULONG) ReadField(Magic), szLinkerVersion, (ULONG) ReadField(SizeOfCode), (ULONG) ReadField(SizeOfInitializedData), (ULONG) ReadField(SizeOfUninitializedData), ReadField(AddressOfEntryPoint), ReadField(BaseOfCode) ); if (Ptr64) { dprintf("%8P base of data\n", ReadField(BaseOfData)); } } if (dft == dftROM) { PIMAGE_ROM_OPTIONAL_HEADER romOptionalHdr; InitTypeRead(ImageOptionalHdrAddr, IMAGE_ROM_OPTIONAL_HEADER); // romOptionalHdr = (PIMAGE_ROM_OPTIONAL_HEADER) &ImageOptionalHdr; dprintf( " ----- rom -----\n" "%8lX base of bss\n" "%8lX gpr mask\n" " cpr mask\n" " %08lX %08lX %08lX %08lX\n" "%8hX gp value\n", (ULONG) ReadField(BaseOfBss), (ULONG) ReadField(GprMask), (ULONG) ReadField(CprMask[0]), (ULONG) ReadField(CprMask[1]), (ULONG) ReadField(CprMask[2]), (ULONG) ReadField(CprMask[3]), (ULONG) ReadField(GpValue)); } if (SizeOfOptionalHeader == GetTypeSize("IMAGE_OPTIONAL_HEADER")) { char szOSVersion[30]; char szImageVersion[30]; char szSubsystemVersion[30]; InitTypeRead(ImageOptionalHdrAddr, IMAGE_OPTIONAL_HEADER); switch ((ULONG) ReadField(Subsystem)) { case IMAGE_SUBSYSTEM_POSIX_CUI : i = 4; break; case IMAGE_SUBSYSTEM_WINDOWS_CUI : i = 3; break; case IMAGE_SUBSYSTEM_WINDOWS_GUI : i = 2; break; case IMAGE_SUBSYSTEM_NATIVE : i = 1; break; default : i = 0; } sprintf(szOSVersion, "%hu.%02hu", (USHORT) ReadField(MajorOperatingSystemVersion), (USHORT) ReadField(MinorOperatingSystemVersion)); sprintf(szImageVersion, "%hu.%02hu", (USHORT) ReadField(MajorImageVersion), (USHORT) ReadField(MinorImageVersion)); sprintf(szSubsystemVersion, "%hu.%02hu", (USHORT) ReadField(MajorSubsystemVersion), (USHORT) ReadField(MinorSubsystemVersion)); dprintf( " ----- new -----\n" "%p image base\n" "%8lX section alignment\n" "%8lX file alignment\n" "%8hX subsystem (%s)\n" "%8s operating system version\n" "%8s image version\n" "%8s subsystem version\n", ReadField(ImageBase), (ULONG) ReadField(SectionAlignment), (ULONG) ReadField(FileAlignment), (USHORT) ReadField(Subsystem), SubsystemName[i], szOSVersion, szImageVersion, szSubsystemVersion); dprintf( "%8lX size of image\n" "%8lX size of headers\n" "%8lX checksum\n" "%p size of stack reserve\n" "%p size of stack commit\n" "%p size of heap reserve\n" "%p size of heap commit\n", (ULONG) ReadField(SizeOfImage), (ULONG) ReadField(SizeOfHeaders), (ULONG) ReadField(CheckSum), ReadField(SizeOfStackReserve), ReadField(SizeOfStackCommit), ReadField(SizeOfHeapReserve), ReadField(SizeOfHeapCommit)); dprintf("%p Opt Hdr\n", ImageOptionalHdrAddr); GetFieldOffset("IMAGE_OPTIONAL_HEADER", "DataDirectory", &DirOff); DirSize = GetTypeSize("IMAGE_DATA_DIRECTORY"); for (i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++) { if (!DirectoryEntryName[i]) { break; } InitTypeRead(ImageOptionalHdrAddr + DirOff + i*DirSize, IMAGE_DATA_DIRECTORY); dprintf( "%8P [%8lX] address [size] of %s Directory\n", ReadField(VirtualAddress), (ULONG) ReadField(Size), DirectoryEntryName[i] ); } dprintf( "\n" ); } } VOID DumpSectionHeader ( IN DWORD i, IN ULONG64 Sh ) { const char *name; char *szUnDName; DWORD li, lj; WORD memFlags; CHAR Name[40]; InitTypeRead(Sh, IMAGE_SECTION_HEADER); GetFieldValue(Sh, "IMAGE_SECTION_HEADER", "Name", Name); dprintf("\nSECTION HEADER #%hX\n%8.8s name", i, Name); #if 0 if (Sh->Name[0] == '/') { name = SzObjSectionName((char *) Sh->Name, (char *) DumpStringTable); dprintf(" (%s)", name); } #endif dprintf( "\n"); dprintf( "%8P %s\n" "%8lX virtual address\n" "%8lX size of raw data\n" "%8lX file pointer to raw data\n" "%8lX file pointer to relocation table\n", ReadField(Misc.PhysicalAddress), (dft == dftObject) ? "physical address" : "virtual size", (ULONG) ReadField(VirtualAddress), (ULONG) ReadField(SizeOfRawData), (ULONG) ReadField(PointerToRawData), (ULONG) ReadField(PointerToRelocations)); dprintf( "%8lX file pointer to line numbers\n" "%8hX number of relocations\n" "%8hX number of line numbers\n" "%8lX flags\n", (ULONG) ReadField(PointerToLinenumbers), (ULONG) ReadField(NumberOfRelocations), (ULONG) ReadField(NumberOfLinenumbers), (ULONG) ReadField(Characteristics)); memFlags = 0; li = (ULONG) ReadField(Characteristics); if (dft == dftROM) { for (lj = 0L; li; li = li >> 1, lj++) { if (li & 1) { switch ((li & 1) << lj) { case STYP_REG : name = "Regular"; break; case STYP_TEXT : name = "Text"; memFlags = 1; break; case STYP_INIT : name = "Init Code"; memFlags = 1; break; case STYP_RDATA : name = "Data"; memFlags = 2; break; case STYP_DATA : name = "Data"; memFlags = 6; break; case STYP_LIT8 : name = "Literal 8"; break; case STYP_LIT4 : name = "Literal 4"; break; case STYP_SDATA : name = "GP Init Data"; memFlags = 6; break; case STYP_SBSS : name = "GP Uninit Data"; memFlags = 6; break; case STYP_BSS : name = "Uninit Data"; memFlags = 6; break; case STYP_LIB : name = "Library"; break; case STYP_UCODE : name = "UCode"; break; case S_NRELOC_OVFL : name = "Non-Relocatable overlay"; memFlags = 1; break; default : name = "RESERVED - UNKNOWN"; } dprintf( " %s\n", name); } } } else { // Clear the padding bits li &= ~0x00700000; for (lj = 0L; li; li = li >> 1, lj++) { if (li & 1) { switch ((li & 1) << lj) { case IMAGE_SCN_TYPE_NO_PAD : name = "No Pad"; break; case IMAGE_SCN_CNT_CODE : name = "Code"; break; case IMAGE_SCN_CNT_INITIALIZED_DATA : name = "Initialized Data"; break; case IMAGE_SCN_CNT_UNINITIALIZED_DATA : name = "Uninitialized Data"; break; case IMAGE_SCN_LNK_OTHER : name = "Other"; break; case IMAGE_SCN_LNK_INFO : name = "Info"; break; case IMAGE_SCN_LNK_REMOVE : name = "Remove"; break; case IMAGE_SCN_LNK_COMDAT : name = "Communal"; break; case IMAGE_SCN_MEM_DISCARDABLE: name = "Discardable"; break; case IMAGE_SCN_MEM_NOT_CACHED: name = "Not Cached"; break; case IMAGE_SCN_MEM_NOT_PAGED: name = "Not Paged"; break; case IMAGE_SCN_MEM_SHARED : name = "Shared"; break; case IMAGE_SCN_MEM_EXECUTE : name = ""; memFlags |= 1; break; case IMAGE_SCN_MEM_READ : name = ""; memFlags |= 2; break; case IMAGE_SCN_MEM_WRITE : name = ""; memFlags |= 4; break; case IMAGE_SCN_MEM_FARDATA : name = "Far Data"; break; case IMAGE_SCN_MEM_SYSHEAP : name = "Sys Heap"; break; case IMAGE_SCN_MEM_PURGEABLE: name = "Purgeable or 16-Bit"; break; case IMAGE_SCN_MEM_LOCKED : name = "Locked"; break; case IMAGE_SCN_MEM_PRELOAD : name = "Preload"; break; case IMAGE_SCN_MEM_PROTECTED: name = "Protected"; break; default : name = "RESERVED - UNKNOWN"; } if (*name) { dprintf( " %s\n", name); } } } // print alignment switch ((ULONG) ReadField(Characteristics) & 0x00700000) { default: name = "(no align specified)"; break; case IMAGE_SCN_ALIGN_1BYTES: name = "1 byte align"; break; case IMAGE_SCN_ALIGN_2BYTES: name = "2 byte align"; break; case IMAGE_SCN_ALIGN_4BYTES: name = "4 byte align"; break; case IMAGE_SCN_ALIGN_8BYTES: name = "8 byte align"; break; case IMAGE_SCN_ALIGN_16BYTES: name = "16 byte align"; break; case IMAGE_SCN_ALIGN_32BYTES: name = "32 byte align"; break; case IMAGE_SCN_ALIGN_64BYTES: name = "64 byte align"; break; } dprintf( " %s\n", name); } if (memFlags) { switch(memFlags) { case 1 : name = "Execute Only"; break; case 2 : name = "Read Only"; break; case 3 : name = "Execute Read"; break; case 4 : name = "Write Only"; break; case 5 : name = "Execute Write"; break; case 6 : name = "Read Write"; break; case 7 : name = "Execute Read Write"; break; default : name = "Unknown Memory Flags"; break; } dprintf( " %s\n", name); } } VOID DumpDebugDirectory ( IN ULONG64 DebugDir ) { BOOL Ok; DWORD cb; NB10I nb10i; PIMAGE_DEBUG_MISC miscData; PIMAGE_DEBUG_MISC miscDataCur; ULONG64 VirtualAddress; DWORD len; InitTypeRead(DebugDir, IMAGE_DEBUG_DIRECTORY ); switch ((ULONG) ReadField(Type)){ case IMAGE_DEBUG_TYPE_COFF: dprintf( "\tcoff "); break; case IMAGE_DEBUG_TYPE_CODEVIEW: dprintf( "\tcv "); break; case IMAGE_DEBUG_TYPE_FPO: dprintf( "\tfpo "); break; case IMAGE_DEBUG_TYPE_MISC: dprintf( "\tmisc "); break; case IMAGE_DEBUG_TYPE_FIXUP: dprintf( "\tfixup "); break; case IMAGE_DEBUG_TYPE_OMAP_TO_SRC: dprintf( "\t-> src "); break; case IMAGE_DEBUG_TYPE_OMAP_FROM_SRC: dprintf( "\tsrc -> "); break; case IMAGE_DEBUG_TYPE_EXCEPTION: dprintf( "\tpdata "); break; default: dprintf( "\t(%6lu)", (ULONG) ReadField(Type)); break; } dprintf( "%8x %8x %8x", (ULONG) ReadField(SizeOfData), (ULONG) ReadField(AddressOfRawData), (ULONG) ReadField(PointerToRawData)); if ((ULONG) ReadField(PointerToRawData) && (ULONG) ReadField(Type) == IMAGE_DEBUG_TYPE_MISC) { if (!TranslateFilePointerToVirtualAddress(ReadField(PointerToRawData), &VirtualAddress)) { dprintf(" [Debug data not mapped]\n"); } else { len = (ULONG) ReadField(SizeOfData); miscData = (PIMAGE_DEBUG_MISC) malloc(len); try { Ok = ReadMemory(Base + VirtualAddress, miscData, len, &cb); if (!Ok || cb != len) { dprintf("Can't read debug data\n"); } else { miscDataCur = miscData; do { if (miscDataCur->DataType == IMAGE_DEBUG_MISC_EXENAME) { if (ImageOptionalHdr->MajorLinkerVersion == 2 && ImageOptionalHdr->MinorLinkerVersion < 37) { dprintf( "\tImage Name: %s", miscDataCur->Reserved); } else { dprintf( "\tImage Name: %s", miscDataCur->Data); } break; } len -= miscDataCur->Length; miscDataCur = (PIMAGE_DEBUG_MISC) ((PCHAR) miscDataCur + miscData->Length); } while (len > 0); } } finally { if (miscData) { free(miscData); } } } } if ((ULONG) ReadField(PointerToRawData) && (ULONG) ReadField(Type) == IMAGE_DEBUG_TYPE_CODEVIEW) { if (!TranslateFilePointerToVirtualAddress((ULONG) ReadField(PointerToRawData), &VirtualAddress)) { dprintf(" [Debug data not mapped]\n"); } else { len = (ULONG) ReadField(SizeOfData); Ok = ReadMemory(Base + VirtualAddress, &nb10i, sizeof(nb10i), &cb); if (!Ok || cb != sizeof(nb10i)) { dprintf("Can't read debug data\n"); } else { dprintf( "\tFormat: %4.4s", &nb10i.nb10); if (nb10i.nb10 == '01BN') { CHAR PdbName[MAX_PATH]; if ((len - sizeof(nb10i) > MAX_PATH)) len = MAX_PATH; Ok = ReadMemory(Base + VirtualAddress + sizeof(nb10i), PdbName, len-sizeof(nb10i), &cb); if (!Ok || cb != len-sizeof(nb10i)) { strcpy(PdbName, ""); } dprintf( ", %x, %x, %s", nb10i.sig, nb10i.age, PdbName); } } } } dprintf( "\n"); } VOID DumpDebugDirectories ( ULONG64 sh ) /*++ Routine Description: Print out the contents of all debug directories Arguments: sh - Section header for section that contains debug dirs Return Value: None. --*/ { int numDebugDirs; IMAGE_DEBUG_DIRECTORY debugDir; ULONG64 DebugDirAddr; ULONG64 pc; ULONG64 VA; DWORD cb, Sz, DebugDirSize; BOOL Ok; Sz = GetTypeSize("IMAGE_DATA_DIRECTORY"); DebugDirSize = GetTypeSize("IMAGE_DEBUG_DIRECTORY"); if (dft == dftROM) { GetFieldValue(sh, "IMAGE_SECTION_HEADER", "VirtualAddress", VA); DebugDirAddr = Base + VA; pc = DebugDirAddr; if (InitTypeRead(pc, IMAGE_DEBUG_DIRECTORY)) { dprintf("Can't read debug dir @%p\n", pc); return; } numDebugDirs = 0; while (ReadField(Type) != 0) { numDebugDirs++; pc += DebugDirSize; if (InitTypeRead(pc, IMAGE_DEBUG_DIRECTORY)) { break; } } } else { ULONG Off, DirSize; GetFieldOffset("IMAGE_OPTIONAL_HEADER", "DataDirectory", &Off); GetFieldValue(ImageOptionalHdrAddr + Off + Sz*IMAGE_DIRECTORY_ENTRY_DEBUG, "IMAGE_DATA_DIRECTORY", "VirtualAddress", VA); GetFieldValue(ImageOptionalHdrAddr + Off + Sz*IMAGE_DIRECTORY_ENTRY_DEBUG, "IMAGE_DATA_DIRECTORY", "Size", DirSize); DebugDirAddr = Base + VA; // ImageOptionalHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress; numDebugDirs = DirSize / DebugDirSize; // dprintf(" DD @%p, DD addr %p\n", ImageOptionalHdrAddr + Off + Sz*IMAGE_DIRECTORY_ENTRY_DEBUG, // DebugDirAddr); // ImageOptionalHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size / sizeof(IMAGE_DEBUG_DIRECTORY); } dprintf("\n\nDebug Directories(%d)\n",numDebugDirs); dprintf("\tType Size Address Pointer\n\n"); pc = DebugDirAddr; while (numDebugDirs) { if (InitTypeRead(pc, IMAGE_DEBUG_DIRECTORY)) { dprintf("Can't read debug dir @%p\n", pc); break; } DumpDebugDirectory(pc); pc += Sz; numDebugDirs--; } } VOID DumpSections( VOID ) { ULONG64 sh; const char *p; DWORD64 li; DWORD cb; BOOL Ok; ULONG i, j; CHAR szName[IMAGE_SIZEOF_SHORT_NAME + 1]; ULONG NumberOfSections, SectSize, Characteristics; GetFieldValue(ImageFileHdrAddr, "IMAGE_FILE_HEADER", "NumberOfSections", NumberOfSections); GetFieldValue(ImageFileHdrAddr, "IMAGE_FILE_HEADER", "Characteristics", Characteristics); SectSize = GetTypeSize("IMAGE_SECTION_HEADER"); for (i = 1; i <= NumberOfSections; i++) { sh = SectionHdrsAddr + (i-1)*SectSize; //szName = SzObjSectionName((char *) sh.Name, (char *) DumpStringTable); GetFieldValue(sh, "IMAGE_SECTION_HEADER", "Name", szName); // strncpy(szName, (char *) sh.Name, IMAGE_SIZEOF_SHORT_NAME); szName[IMAGE_SIZEOF_SHORT_NAME] = 0; DumpSectionHeader(i, sh); if (dft == dftROM) { if (!(Characteristics & IMAGE_FILE_DEBUG_STRIPPED)) { // If we're looking at the .rdata section and the symbols // aren't stripped, the debug directory must be here. if (!strcmp(szName, ".rdata")) { DumpDebugDirectories(sh); //DumpDebugData(&sh); } } } else if (dft == dftPE) { UCHAR tmp[40]; ULONG64 VA; sprintf(tmp, "DataDirectory[%d].VirtualAddress", IMAGE_DIRECTORY_ENTRY_DEBUG); GetFieldValue(ImageOptionalHdrAddr, "IMAGE_OPTIONAL_HEADER", tmp, li); // dprintf("Opt Hdr %p, %s = %p", ImageOptionalHdrAddr, tmp, li); if (li != 0) { InitTypeRead(sh, IMAGE_SECTION_HEADER); VA = ReadField(VirtualAddress); if (li >= VA && li < (VA + ReadField(SizeOfRawData))) { DumpDebugDirectories(sh); //DumpDebugData(&sh); } } #if 0 if (Switch.Dump.PData) { li = ImageOptionalHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress; if ((li != 0) && (li >= sh.VirtualAddress) && (li < sh.VirtualAddress+sh.SizeOfRawData)) { DumpFunctionTable(pimage, rgsym, (char *) DumpStringTable, &sh); } } if (Switch.Dump.Imports) { li = ImageOptionalHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; if ((li != 0) && (li >= sh.VirtualAddress) && (li < sh.VirtualAddress+sh.SizeOfRawData)) { DumpImports(&sh); } } if (Switch.Dump.Exports) { li = ImageOptionalHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; if ((li != 0) && (li >= sh.VirtualAddress) && (li < sh.VirtualAddress+sh.SizeOfRawData)) { // UNDONE: Is this check really necessary? if (ImageFileHdr->Machine != IMAGE_FILE_MACHINE_MPPC_601) { DumpExports(&sh); } } } #endif } } } BOOL TranslateFilePointerToVirtualAddress( IN ULONG64 FilePointer, OUT PULONG64 VirtualAddress ) { ULONG i; ULONG64 sh; ULONG NumberOfSections, SectSize, Characteristics; GetFieldValue(ImageFileHdrAddr, "IMAGE_FILE_HEADER", "NumberOfSections", NumberOfSections); GetFieldValue(ImageFileHdrAddr, "IMAGE_FILE_HEADER", "Characteristics", Characteristics); SectSize = GetTypeSize("IMAGE_SECTION_HEADER"); for (i = 1; i <= NumberOfSections; i++) { sh = SectionHdrsAddr + (i-1)*SectSize; InitTypeRead(sh, IMAGE_SECTION_HEADER); if (ReadField(PointerToRawData) <= FilePointer && FilePointer < ReadField(PointerToRawData) + ReadField(SizeOfRawData)) { *VirtualAddress = FilePointer - ReadField(PointerToRawData) + ReadField(VirtualAddress); return TRUE; } } return FALSE; }