You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
583 lines
17 KiB
583 lines
17 KiB
//-------------------- |
|
// PROGRAM: PEDUMP |
|
// FILE: COMMON.C |
|
// AUTHOR: Matt Pietrek - 1993 |
|
//-------------------- |
|
#include <windows.h> |
|
#include <stdio.h> |
|
#include <string.h> |
|
#include "common.h" |
|
|
|
PIMAGE_SYMBOL PCOFFSymbolTable = 0; // RVA to COFF symbol table (if present) |
|
DWORD COFFSymbolCount = 0; // Number of symbols in COFF symbol table |
|
|
|
typedef struct |
|
{ |
|
WORD flag; |
|
PSTR name; |
|
} WORD_FLAG_DESCRIPTIONS; |
|
|
|
typedef struct |
|
{ |
|
DWORD flag; |
|
PSTR name; |
|
} DWORD_FLAG_DESCRIPTIONS; |
|
|
|
// Bitfield values and names for the IMAGE_FILE_HEADER flags |
|
WORD_FLAG_DESCRIPTIONS ImageFileHeaderCharacteristics[] = |
|
{ |
|
{ IMAGE_FILE_RELOCS_STRIPPED, "RELOCS_STRIPPED" }, |
|
{ IMAGE_FILE_EXECUTABLE_IMAGE, "EXECUTABLE_IMAGE" }, |
|
{ IMAGE_FILE_LINE_NUMS_STRIPPED, "LINE_NUMS_STRIPPED" }, |
|
{ IMAGE_FILE_LOCAL_SYMS_STRIPPED, "LOCAL_SYMS_STRIPPED" }, |
|
{ IMAGE_FILE_MINIMAL_OBJECT, "MINIMAL_OBJECT" }, |
|
{ IMAGE_FILE_UPDATE_OBJECT, "UPDATE_OBJECT" }, |
|
{ IMAGE_FILE_16BIT_MACHINE, "16BIT_MACHINE" }, |
|
{ IMAGE_FILE_BYTES_REVERSED_LO, "BYTES_REVERSED_LO" }, |
|
{ IMAGE_FILE_32BIT_MACHINE, "32BIT_MACHINE" }, |
|
{ IMAGE_FILE_PATCH, "PATCH" }, |
|
{ IMAGE_FILE_SYSTEM, "SYSTEM" }, |
|
{ IMAGE_FILE_DLL, "DLL" }, |
|
{ IMAGE_FILE_BYTES_REVERSED_HI, "BYTES_REVERSED_HI" } |
|
}; |
|
|
|
#define NUMBER_IMAGE_HEADER_FLAGS \ |
|
(sizeof(ImageFileHeaderCharacteristics) / sizeof(WORD_FLAG_DESCRIPTIONS)) |
|
|
|
// |
|
// Dump the IMAGE_FILE_HEADER for a PE file or an OBJ |
|
// |
|
void DumpHeader(PIMAGE_FILE_HEADER pImageFileHeader) |
|
{ |
|
UINT headerFieldWidth = 30; |
|
UINT i; |
|
char *szMachine; |
|
|
|
printf("File Header\n"); |
|
|
|
switch( pImageFileHeader->Machine ) |
|
{ |
|
case IMAGE_FILE_MACHINE_I386: szMachine = "i386"; break; |
|
case IMAGE_FILE_MACHINE_I860: szMachine = "i860"; break; |
|
case IMAGE_FILE_MACHINE_R3000: szMachine = "R3000"; break; |
|
case IMAGE_FILE_MACHINE_R4000: szMachine = "R4000"; break; |
|
case IMAGE_FILE_MACHINE_ALPHA: szMachine = "alpha"; break; |
|
default: szMachine = "unknown"; break; |
|
} |
|
|
|
printf(" %-*s%04X (%s)\n", headerFieldWidth, "Machine:", |
|
pImageFileHeader->Machine, szMachine); |
|
printf(" %-*s%04X\n", headerFieldWidth, "Number of Sections:", |
|
pImageFileHeader->NumberOfSections); |
|
printf(" %-*s%08X\n", headerFieldWidth, "TimeDateStamp:", |
|
pImageFileHeader->TimeDateStamp); |
|
printf(" %-*s%08X\n", headerFieldWidth, "PointerToSymbolTable:", |
|
pImageFileHeader->PointerToSymbolTable); |
|
printf(" %-*s%08X\n", headerFieldWidth, "NumberOfSymbols:", |
|
pImageFileHeader->NumberOfSymbols); |
|
printf(" %-*s%04X\n", headerFieldWidth, "SizeOfOptionalHeader:", |
|
pImageFileHeader->SizeOfOptionalHeader); |
|
printf(" %-*s%04X\n", headerFieldWidth, "Characteristics:", |
|
pImageFileHeader->Characteristics); |
|
for ( i=0; i < NUMBER_IMAGE_HEADER_FLAGS; i++ ) |
|
{ |
|
if ( pImageFileHeader->Characteristics & |
|
ImageFileHeaderCharacteristics[i].flag ) |
|
printf( " %s\n", ImageFileHeaderCharacteristics[i].name ); |
|
} |
|
} |
|
|
|
// Bitfield values and names for the DllCharacteritics flags |
|
WORD_FLAG_DESCRIPTIONS DllCharacteristics[] = |
|
{ |
|
{ IMAGE_LIBRARY_PROCESS_INIT, "PROCESS_INIT" }, |
|
{ IMAGE_LIBRARY_PROCESS_TERM, "PROCESS_TERM" }, |
|
{ IMAGE_LIBRARY_THREAD_INIT, "THREAD_INIT" }, |
|
{ IMAGE_LIBRARY_THREAD_TERM, "THREAD_TERM" }, |
|
}; |
|
#define NUMBER_DLL_CHARACTERISTICS \ |
|
(sizeof(DllCharacteristics) / sizeof(WORD_FLAG_DESCRIPTIONS)) |
|
|
|
// Bitfield values and names for the LoaderFlags flags |
|
DWORD_FLAG_DESCRIPTIONS LoaderFlags[] = |
|
{ |
|
{ IMAGE_LOADER_FLAGS_BREAK_ON_LOAD, "BREAK_ON_LOAD" }, |
|
{ IMAGE_LOADER_FLAGS_DEBUG_ON_LOAD, "DEBUG_ON_LOAD" } |
|
}; |
|
#define NUMBER_LOADER_FLAGS \ |
|
(sizeof(LoaderFlags) / sizeof(DWORD_FLAG_DESCRIPTIONS)) |
|
|
|
// Names of the data directory elements that are defined |
|
char *ImageDirectoryNames[] = { |
|
"EXPORT", "IMPORT", "RESOURCE", "EXCEPTION", "SECURITY", "BASERELOC", |
|
"DEBUG", "COPYRIGHT", "GLOBALPTR", "TLS", "LOAD_CONFIG" }; |
|
|
|
#define NUMBER_IMAGE_DIRECTORY_ENTRYS \ |
|
(sizeof(ImageDirectoryNames)/sizeof(char *)) |
|
|
|
// |
|
// Dump the IMAGE_OPTIONAL_HEADER from a PE file |
|
// |
|
void DumpOptionalHeader(PIMAGE_OPTIONAL_HEADER optionalHeader) |
|
{ |
|
UINT width = 30; |
|
char *s; |
|
UINT i; |
|
|
|
printf("Optional Header\n"); |
|
|
|
printf(" %-*s%04X\n", width, "Magic", optionalHeader->Magic); |
|
printf(" %-*s%u.%02u\n", width, "linker version", |
|
optionalHeader->MajorLinkerVersion, |
|
optionalHeader->MinorLinkerVersion); |
|
printf(" %-*s%X\n", width, "size of code", optionalHeader->SizeOfCode); |
|
printf(" %-*s%X\n", width, "size of initialized data", |
|
optionalHeader->SizeOfInitializedData); |
|
printf(" %-*s%X\n", width, "size of uninitialized data", |
|
optionalHeader->SizeOfUninitializedData); |
|
printf(" %-*s%X\n", width, "entrypoint RVA", |
|
optionalHeader->AddressOfEntryPoint); |
|
printf(" %-*s%X\n", width, "base of code", optionalHeader->BaseOfCode); |
|
printf(" %-*s%X\n", width, "base of data", optionalHeader->BaseOfData); |
|
printf(" %-*s%X\n", width, "image base", optionalHeader->ImageBase); |
|
|
|
printf(" %-*s%X\n", width, "section align", |
|
optionalHeader->SectionAlignment); |
|
printf(" %-*s%X\n", width, "file align", optionalHeader->FileAlignment); |
|
printf(" %-*s%u.%02u\n", width, "required OS version", |
|
optionalHeader->MajorOperatingSystemVersion, |
|
optionalHeader->MinorOperatingSystemVersion); |
|
printf(" %-*s%u.%02u\n", width, "image version", |
|
optionalHeader->MajorImageVersion, |
|
optionalHeader->MinorImageVersion); |
|
printf(" %-*s%u.%02u\n", width, "subsystem version", |
|
optionalHeader->MajorSubsystemVersion, |
|
optionalHeader->MinorSubsystemVersion); |
|
printf(" %-*s%X\n", width, "Reserved1", optionalHeader->Reserved1); |
|
printf(" %-*s%X\n", width, "size of image", optionalHeader->SizeOfImage); |
|
printf(" %-*s%X\n", width, "size of headers", |
|
optionalHeader->SizeOfHeaders); |
|
printf(" %-*s%X\n", width, "checksum", optionalHeader->CheckSum); |
|
switch( optionalHeader->Subsystem ) |
|
{ |
|
case IMAGE_SUBSYSTEM_NATIVE: s = "Native"; break; |
|
case IMAGE_SUBSYSTEM_WINDOWS_GUI: s = "Windows GUI"; break; |
|
case IMAGE_SUBSYSTEM_WINDOWS_CUI: s = "Windows character"; break; |
|
case IMAGE_SUBSYSTEM_OS2_CUI: s = "OS/2 character"; break; |
|
case IMAGE_SUBSYSTEM_POSIX_CUI: s = "Posix character"; break; |
|
default: s = "unknown"; |
|
} |
|
printf(" %-*s%04X (%s)\n", width, "Subsystem", |
|
optionalHeader->Subsystem, s); |
|
|
|
printf(" %-*s%04X\n", width, "DLL flags", |
|
optionalHeader->DllCharacteristics); |
|
for ( i=0; i < NUMBER_DLL_CHARACTERISTICS; i++ ) |
|
{ |
|
if ( optionalHeader->DllCharacteristics & |
|
DllCharacteristics[i].flag ) |
|
printf( " %s", DllCharacteristics[i].name ); |
|
} |
|
if ( optionalHeader->DllCharacteristics ) |
|
printf("\n"); |
|
|
|
printf(" %-*s%X\n", width, "stack reserve size", |
|
optionalHeader->SizeOfStackReserve); |
|
printf(" %-*s%X\n", width, "stack commit size", |
|
optionalHeader->SizeOfStackCommit); |
|
printf(" %-*s%X\n", width, "heap reserve size", |
|
optionalHeader->SizeOfHeapReserve); |
|
printf(" %-*s%X\n", width, "heap commit size", |
|
optionalHeader->SizeOfHeapCommit); |
|
|
|
printf(" %-*s%08X\n", width, "loader flags", |
|
optionalHeader->LoaderFlags); |
|
|
|
for ( i=0; i < NUMBER_LOADER_FLAGS; i++ ) |
|
{ |
|
if ( optionalHeader->LoaderFlags & |
|
LoaderFlags[i].flag ) |
|
printf( " %s", LoaderFlags[i].name ); |
|
} |
|
if ( optionalHeader->LoaderFlags ) |
|
printf("\n"); |
|
|
|
printf(" %-*s%X\n", width, "RVAs & sizes", |
|
optionalHeader->NumberOfRvaAndSizes); |
|
|
|
printf("\nData Directory\n"); |
|
for ( i=0; i < optionalHeader->NumberOfRvaAndSizes; i++) |
|
{ |
|
printf( " %-12s rva: %08X size: %08X\n", |
|
(i >= NUMBER_IMAGE_DIRECTORY_ENTRYS) |
|
? "unused" : ImageDirectoryNames[i], |
|
optionalHeader->DataDirectory[i].VirtualAddress, |
|
optionalHeader->DataDirectory[i].Size); |
|
} |
|
} |
|
|
|
// Bitfield values and names for the IMAGE_SECTION_HEADER flags |
|
DWORD_FLAG_DESCRIPTIONS SectionCharacteristics[] = |
|
{ |
|
{ IMAGE_SCN_CNT_CODE, "CODE" }, |
|
{ IMAGE_SCN_CNT_INITIALIZED_DATA, "INITIALIZED_DATA" }, |
|
{ IMAGE_SCN_CNT_UNINITIALIZED_DATA, "UNINITIALIZED_DATA" }, |
|
{ IMAGE_SCN_LNK_INFO, "LNK_INFO" }, |
|
{ IMAGE_SCN_LNK_OVERLAY, "LNK_OVERLAY" }, |
|
{ IMAGE_SCN_LNK_REMOVE, "LNK_REMOVE" }, |
|
{ IMAGE_SCN_LNK_COMDAT, "LNK_COMDAT" }, |
|
{ IMAGE_SCN_MEM_DISCARDABLE, "MEM_DISCARDABLE" }, |
|
{ IMAGE_SCN_MEM_NOT_CACHED, "MEM_NOT_CACHED" }, |
|
{ IMAGE_SCN_MEM_NOT_PAGED, "MEM_NOT_PAGED" }, |
|
{ IMAGE_SCN_MEM_SHARED, "MEM_SHARED" }, |
|
{ IMAGE_SCN_MEM_EXECUTE, "MEM_EXECUTE" }, |
|
{ IMAGE_SCN_MEM_READ, "MEM_READ" }, |
|
{ IMAGE_SCN_MEM_WRITE, "MEM_WRITE" }, |
|
}; |
|
|
|
#define NUMBER_SECTION_CHARACTERISTICS \ |
|
(sizeof(SectionCharacteristics) / sizeof(DWORD_FLAG_DESCRIPTIONS)) |
|
|
|
// |
|
// Dump the section table from a PE file or an OBJ |
|
// |
|
void DumpSectionTable(PIMAGE_SECTION_HEADER section, |
|
unsigned cSections, |
|
BOOL IsEXE) |
|
{ |
|
unsigned i, j; |
|
|
|
printf("Section Table\n"); |
|
|
|
for ( i=1; i <= cSections; i++, section++ ) |
|
{ |
|
printf( " %02X %-8.8s %s: %08X VirtAddr: %08X\n", |
|
i, section->Name, |
|
IsEXE ? "VirtSize" : "PhysAddr", |
|
section->Misc.VirtualSize, section->VirtualAddress); |
|
printf( " raw data offs: %08X raw data size: %08X\n", |
|
section->PointerToRawData, section->SizeOfRawData ); |
|
printf( " relocation offs: %08X relocations: %08X\n", |
|
section->PointerToRelocations, section->NumberOfRelocations ); |
|
printf( " line # offs: %08X line #'s: %08X\n", |
|
section->PointerToLinenumbers, section->NumberOfLinenumbers ); |
|
printf( " characteristics: %08X\n", section->Characteristics); |
|
|
|
printf(" "); |
|
for ( j=0; j < NUMBER_SECTION_CHARACTERISTICS; j++ ) |
|
{ |
|
if ( section->Characteristics & |
|
SectionCharacteristics[j].flag ) |
|
printf( " %s", SectionCharacteristics[j].name ); |
|
} |
|
printf("\n\n"); |
|
} |
|
} |
|
|
|
// |
|
// Used by the DumpSymbolTable() routine. It purpose is to filter out |
|
// the non-normal section numbers and give them meaningful names. |
|
// |
|
void GetSectionName(WORD section, PSTR buffer, unsigned cbBuffer) |
|
{ |
|
char tempbuffer[10]; |
|
|
|
switch ( (SHORT)section ) |
|
{ |
|
case IMAGE_SYM_UNDEFINED: strcpy(tempbuffer, "UNDEF"); break; |
|
case IMAGE_SYM_ABSOLUTE: strcpy(tempbuffer, "ABS "); break; |
|
case IMAGE_SYM_DEBUG: strcpy(tempbuffer, "DEBUG"); break; |
|
default: wsprintf(tempbuffer, "%-5X", section); |
|
} |
|
|
|
strncpy(buffer, tempbuffer, cbBuffer-1); |
|
} |
|
|
|
// The names of the first group of possible symbol table storage classes |
|
char * SzStorageClass1[] = { |
|
"NULL","AUTOMATIC","EXTERNAL","STATIC","REGISTER","EXTERNAL_DEF","LABEL", |
|
"UNDEFINED_LABEL","MEMBER_OF_STRUCT","ARGUMENT","STRUCT_TAG", |
|
"MEMBER_OF_UNION","UNION_TAG","TYPE_DEFINITION","UNDEFINED_STATIC", |
|
"ENUM_TAG","MEMBER_OF_ENUM","REGISTER_PARAM","BIT_FIELD" |
|
}; |
|
|
|
// The names of the second group of possible symbol table storage classes |
|
char * SzStorageClass2[] = { |
|
"BLOCK","FUNCTION","END_OF_STRUCT","FILE","SECTION","WEAK_EXTERNAL" |
|
}; |
|
|
|
// |
|
// Given a symbol storage class value, return a descriptive ASCII string |
|
// |
|
PSTR GetSZStorageClass(BYTE storageClass) |
|
{ |
|
if ( storageClass <= IMAGE_SYM_CLASS_BIT_FIELD ) |
|
return SzStorageClass1[storageClass]; |
|
else if ( (storageClass >= IMAGE_SYM_CLASS_BLOCK) |
|
&& (storageClass <= IMAGE_SYM_CLASS_WEAK_EXTERNAL) ) |
|
return SzStorageClass2[storageClass-IMAGE_SYM_CLASS_BLOCK]; |
|
else |
|
return "???"; |
|
} |
|
|
|
// |
|
// Dumps the auxillary symbol for a regular symbol. It takes a pointer |
|
// to the regular symbol, since the routine needs the information in |
|
// that record. |
|
// |
|
void DumpAuxSymbols(PIMAGE_SYMBOL pSymbolTable) |
|
{ |
|
PIMAGE_AUX_SYMBOL auxSym; |
|
|
|
auxSym = (PIMAGE_AUX_SYMBOL)(pSymbolTable+1); |
|
|
|
if ( pSymbolTable->StorageClass == IMAGE_SYM_CLASS_FILE ) |
|
printf(" * %s\n", auxSym); |
|
else if ( (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) ) |
|
{ |
|
if ( (pSymbolTable->Type & 0xF0) == (IMAGE_SYM_DTYPE_FUNCTION << 4)) |
|
{ |
|
printf(" * tag: %04X size: %04X Line #'s: %08X next fn: %04X\n", |
|
auxSym->Sym.TagIndex, auxSym->Sym.Misc.TotalSize, |
|
auxSym->Sym.FcnAry.Function.PointerToLinenumber, |
|
auxSym->Sym.FcnAry.Function.PointerToNextFunction); |
|
} |
|
} |
|
else if ( (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_STATIC) ) |
|
{ |
|
printf( |
|
" * Section: %04X Len: %05X Relocs: %04X LineNums: %04X\n", |
|
auxSym->Section.Number, auxSym->Section.Length, |
|
auxSym->Section.NumberOfRelocations, |
|
auxSym->Section.NumberOfLinenumbers); |
|
} |
|
} |
|
|
|
// |
|
// Given a COFF symbol table index, look up its name. This function assumes |
|
// that the COFFSymbolCount and PCOFFSymbolTable variables have been already |
|
// set up. |
|
// |
|
BOOL LookupSymbolName(DWORD index, PSTR buffer, UINT length) |
|
{ |
|
PSTR stringTable; |
|
|
|
if ( index >= COFFSymbolCount ) |
|
return FALSE; |
|
|
|
if ( PCOFFSymbolTable == 0 ) |
|
return FALSE; |
|
|
|
if ( PCOFFSymbolTable[index].N.Name.Short != 0 ) |
|
{ |
|
strncpy(buffer, PCOFFSymbolTable[index].N.ShortName, min(8,length)); |
|
buffer[8] = 0; |
|
} |
|
else |
|
{ |
|
stringTable = (PSTR)&PCOFFSymbolTable[COFFSymbolCount]; |
|
strncpy(buffer, |
|
stringTable + PCOFFSymbolTable[index].N.Name.Long, length); |
|
buffer[length-1] = 0; |
|
} |
|
|
|
return TRUE; |
|
} |
|
|
|
// |
|
// Dumps a COFF symbol table from an EXE or OBJ |
|
// |
|
void DumpSymbolTable(PIMAGE_SYMBOL pSymbolTable, unsigned cSymbols) |
|
{ |
|
unsigned i; |
|
PSTR stringTable; |
|
char sectionName[10]; |
|
|
|
printf("Symbol Table - %X entries (* = auxillary symbol)\n", cSymbols); |
|
|
|
printf( |
|
"Indx Name Value Section cAux Type Storage\n" |
|
"---- -------------------- -------- ---------- ----- ------- --------\n"); |
|
|
|
// The string table apparently starts right after the symbol table |
|
stringTable = (PSTR)&pSymbolTable[cSymbols]; |
|
|
|
for ( i=0; i < cSymbols; i++ ) |
|
{ |
|
printf("%04X ", i); |
|
|
|
if ( pSymbolTable->N.Name.Short != 0 ) |
|
printf("%-20.8s", pSymbolTable->N.ShortName); |
|
else |
|
printf("%-20s", stringTable + pSymbolTable->N.Name.Long); |
|
|
|
printf(" %08X", pSymbolTable->Value); |
|
|
|
GetSectionName(pSymbolTable->SectionNumber, sectionName, |
|
sizeof(sectionName)); |
|
printf(" sect:%s aux:%X type:%02X st:%s\n", |
|
sectionName, |
|
pSymbolTable->NumberOfAuxSymbols, |
|
pSymbolTable->Type, |
|
GetSZStorageClass(pSymbolTable->StorageClass) ); |
|
|
|
if ( pSymbolTable->NumberOfAuxSymbols ) |
|
DumpAuxSymbols(pSymbolTable); |
|
|
|
// Take into account any aux symbols |
|
i += pSymbolTable->NumberOfAuxSymbols; |
|
pSymbolTable += pSymbolTable->NumberOfAuxSymbols; |
|
pSymbolTable++; |
|
} |
|
} |
|
|
|
// |
|
// Given a section name, look it up in the section table and return a |
|
// pointer to the start of its raw data area. |
|
// |
|
LPVOID GetSectionPtr(PSTR name, PIMAGE_NT_HEADERS pNTHeader, DWORD imageBase) |
|
{ |
|
PIMAGE_SECTION_HEADER section; |
|
unsigned i; |
|
|
|
section = (PIMAGE_SECTION_HEADER)(pNTHeader+1); |
|
|
|
for ( i=0; i < pNTHeader->FileHeader.NumberOfSections; i++, section++ ) |
|
{ |
|
if ( strnicmp(section->Name, name, IMAGE_SIZEOF_SHORT_NAME) == 0 ) |
|
return (LPVOID)(section->PointerToRawData + imageBase); |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
// |
|
// Given a section name, look it up in the section table and return a |
|
// pointer to its IMAGE_SECTION_HEADER |
|
// |
|
PIMAGE_SECTION_HEADER GetSectionHeader(PSTR name, PIMAGE_NT_HEADERS pNTHeader) |
|
{ |
|
PIMAGE_SECTION_HEADER section; |
|
unsigned i; |
|
|
|
section = (PIMAGE_SECTION_HEADER)(pNTHeader+1); |
|
|
|
for ( i=0; i < pNTHeader->FileHeader.NumberOfSections; i++, section++ ) |
|
{ |
|
if ( strnicmp(section->Name, name, IMAGE_SIZEOF_SHORT_NAME) == 0 ) |
|
return section; |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
// |
|
// Do a hexadecimal dump of the raw data for all the sections. You |
|
// could just dump one section by adjusting the PIMAGE_SECTION_HEADER |
|
// and cSections parameters |
|
// |
|
void DumpRawSectionData(PIMAGE_SECTION_HEADER section, |
|
PVOID base, |
|
unsigned cSections) |
|
{ |
|
unsigned i; |
|
char name[IMAGE_SIZEOF_SHORT_NAME + 1]; |
|
|
|
printf("Section Hex Dumps\n"); |
|
|
|
for ( i=0; i < cSections; i++, section++ ) |
|
{ |
|
// Make a copy of the section name so that we can ensure that |
|
// it's null-terminated |
|
memcpy(name, section->Name, IMAGE_SIZEOF_SHORT_NAME); |
|
name[IMAGE_SIZEOF_SHORT_NAME] = 0; |
|
|
|
// Don't dump sections that don't exist in the file! |
|
if ( section->PointerToRawData == 0 ) |
|
continue; |
|
|
|
printf( "section %02X (%s) size: %08X file offs: %08X\n", |
|
i, name, section->SizeOfRawData, section->PointerToRawData); |
|
|
|
HexDump( MakePtr(PBYTE, base, section->PointerToRawData), |
|
section->SizeOfRawData ); |
|
printf("\n"); |
|
} |
|
} |
|
|
|
// |
|
// Dump a range of line numbers from the COFF debug information |
|
// |
|
void DumpLineNumbers(PIMAGE_LINENUMBER pln, DWORD count) |
|
{ |
|
char buffer[64]; |
|
DWORD i; |
|
|
|
printf("Line Numbers\n"); |
|
|
|
for (i=0; i < count; i++) |
|
{ |
|
if ( pln->Linenumber == 0 ) // A symbol table index |
|
{ |
|
buffer[0] = 0; |
|
LookupSymbolName(pln->Type.SymbolTableIndex, buffer, |
|
sizeof(buffer)); |
|
printf("SymIndex: %X (%s)\n", pln->Type.SymbolTableIndex, |
|
buffer); |
|
} |
|
else // A regular line number |
|
printf(" Addr: %05X Line: %04X\n", |
|
pln->Type.VirtualAddress, pln->Linenumber); |
|
pln++; |
|
} |
|
} |
|
|
|
// Number of hex values displayed per line |
|
#define HEX_DUMP_WIDTH 16 |
|
|
|
// |
|
// Dump a region of memory in a hexadecimal format |
|
// |
|
void HexDump(PBYTE ptr, DWORD length) |
|
{ |
|
char buffer[256]; |
|
PSTR buffPtr; |
|
unsigned cOutput, i; |
|
DWORD bytesToGo=length; |
|
|
|
while ( bytesToGo ) |
|
{ |
|
cOutput = bytesToGo >= HEX_DUMP_WIDTH ? HEX_DUMP_WIDTH : bytesToGo; |
|
|
|
buffPtr = buffer; |
|
buffPtr += wsprintf(buffPtr, "%08X: ", length-bytesToGo ); |
|
|
|
for ( i=0; i < HEX_DUMP_WIDTH; i++ ) |
|
{ |
|
buffPtr += wsprintf(buffPtr, |
|
i < cOutput ? "%02X " : " ", |
|
*(ptr+i) ); |
|
|
|
// Put an extra space between the 1st and 2nd half of the bytes |
|
// on each line. |
|
if ( i == (HEX_DUMP_WIDTH/2)-1 ) |
|
buffPtr += wsprintf(buffPtr, " "); |
|
} |
|
|
|
for ( i=0; i < cOutput; i++ ) |
|
{ |
|
char c; |
|
|
|
c = '.'; |
|
if ( isascii(*(ptr + i)) ) |
|
c = isprint(*(ptr + i)) ? *(ptr + i) : '.'; |
|
|
|
buffPtr += wsprintf(buffPtr, "%c", c); |
|
} |
|
puts(buffer); // Can't use printf(), since there may be a '%' |
|
// in the string. |
|
|
|
bytesToGo -= cOutput; |
|
ptr += HEX_DUMP_WIDTH; |
|
} |
|
}
|
|
|