windows-nt/Source/XPSP1/NT/sdktools/debuggers/exts/extsdll/image.c

1103 lines
32 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
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 <time.h>
// 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, "<pdb name unavailable>");
}
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;
}