mirror of
https://github.com/nillerusr/source-engine.git
synced 2024-12-23 06:36:54 +00:00
584 lines
17 KiB
C
584 lines
17 KiB
C
//--------------------
|
|
// 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;
|
|
}
|
|
}
|