mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-08 01:39:36 +00:00
1
This commit is contained in:
@@ -0,0 +1,532 @@
|
||||
//--------------------
|
||||
// PROGRAM: PEDUMP
|
||||
// FILE: EXEDUMP.C
|
||||
// AUTHOR: Matt Pietrek - 1993
|
||||
//--------------------
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include "common.h"
|
||||
#include "extrnvar.h"
|
||||
|
||||
typedef PIMAGE_COFF_SYMBOLS_HEADER PIMAGE_DEBUG_INFO;
|
||||
|
||||
PIMAGE_DEBUG_INFO PCOFFDebugInfo = 0;
|
||||
|
||||
char *SzDebugFormats[] = {
|
||||
"UNKNOWN/BORLAND","COFF","CODEVIEW","FPO","MISC","EXCEPTION","FIXUP" };
|
||||
|
||||
//
|
||||
// Dump the debug directory in a PE file.
|
||||
//
|
||||
void DumpDebugDirectory(DWORD base, PIMAGE_NT_HEADERS pNTHeader)
|
||||
{
|
||||
PIMAGE_DEBUG_DIRECTORY debugDir;
|
||||
PIMAGE_SECTION_HEADER header;
|
||||
unsigned cDebugFormats, i;
|
||||
DWORD offsetInto_rdata;
|
||||
DWORD va_debug_dir;
|
||||
PSTR szDebugFormat;
|
||||
|
||||
// This line was so long that we had to break it up
|
||||
va_debug_dir = pNTHeader->OptionalHeader.
|
||||
DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].
|
||||
VirtualAddress;
|
||||
if ( va_debug_dir == 0 )
|
||||
return;
|
||||
|
||||
// If we found a .debug section, and the debug directory is at the
|
||||
// beginning of this section, it looks like a Borland file
|
||||
header = GetSectionHeader(".debug", pNTHeader);
|
||||
if ( header && (header->VirtualAddress == va_debug_dir) )
|
||||
{
|
||||
debugDir = (PIMAGE_DEBUG_DIRECTORY)(header->PointerToRawData+base);
|
||||
cDebugFormats = pNTHeader->OptionalHeader.
|
||||
DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
|
||||
}
|
||||
else // Look for microsoft debug directory in the .rdata section
|
||||
{
|
||||
header = GetSectionHeader(".rdata", pNTHeader);
|
||||
if ( !header )
|
||||
return;
|
||||
|
||||
// See if there's even any debug directories to speak of...
|
||||
cDebugFormats = pNTHeader->OptionalHeader.
|
||||
DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size
|
||||
/ sizeof(IMAGE_DEBUG_DIRECTORY);
|
||||
if ( cDebugFormats == 0 )
|
||||
return;
|
||||
|
||||
offsetInto_rdata = va_debug_dir - header->VirtualAddress;
|
||||
debugDir = MakePtr(PIMAGE_DEBUG_DIRECTORY, base,
|
||||
header->PointerToRawData + offsetInto_rdata);
|
||||
}
|
||||
|
||||
printf(
|
||||
"Debug Formats in File\n"
|
||||
" Type Size Address FilePtr Charactr TimeData Version\n"
|
||||
" --------------- -------- -------- -------- -------- -------- --------\n"
|
||||
);
|
||||
|
||||
for ( i=0; i < cDebugFormats; i++ )
|
||||
{
|
||||
szDebugFormat = (debugDir->Type <= 6)
|
||||
? SzDebugFormats[debugDir->Type] : "???";
|
||||
|
||||
printf(" %-15s %08X %08X %08X %08X %08X %u.%02u\n",
|
||||
szDebugFormat, debugDir->SizeOfData, debugDir->AddressOfRawData,
|
||||
debugDir->PointerToRawData, debugDir->Characteristics,
|
||||
debugDir->TimeDateStamp, debugDir->MajorVersion,
|
||||
debugDir->MinorVersion);
|
||||
|
||||
// If COFF debug info, save its address away for later. We
|
||||
// do the check for "PointerToSymbolTable" because some files
|
||||
// have bogus values for the COFF header offset.
|
||||
if ( (debugDir->Type == IMAGE_DEBUG_TYPE_COFF) &&
|
||||
pNTHeader->FileHeader.PointerToSymbolTable )
|
||||
{
|
||||
PCOFFDebugInfo =
|
||||
(PIMAGE_DEBUG_INFO)(base+ debugDir->PointerToRawData);
|
||||
}
|
||||
|
||||
debugDir++;
|
||||
}
|
||||
}
|
||||
|
||||
// Function prototype (necessary because two functions recurse)
|
||||
void DumpResourceDirectory
|
||||
(
|
||||
PIMAGE_RESOURCE_DIRECTORY resDir, DWORD resourceBase,
|
||||
DWORD level, DWORD resourceType
|
||||
);
|
||||
|
||||
// The predefined resource types
|
||||
char *SzResourceTypes[] = {
|
||||
"???_0", "CURSOR", "BITMAP", "ICON", "MENU", "DIALOG", "STRING", "FONTDIR",
|
||||
"FONT", "ACCELERATORS", "RCDATA", "MESSAGETABLE", "GROUP_CURSOR",
|
||||
"???_13", "GROUP_ICON", "???_15", "VERSION"
|
||||
};
|
||||
|
||||
// Get an ASCII string representing a resource type
|
||||
void GetResourceTypeName(DWORD type, PSTR buffer, UINT cBytes)
|
||||
{
|
||||
if ( type <= 16 )
|
||||
strncpy(buffer, SzResourceTypes[type], cBytes);
|
||||
else
|
||||
wsprintf(buffer, "%X", type);
|
||||
}
|
||||
|
||||
//
|
||||
// If a resource entry has a string name (rather than an ID), go find
|
||||
// the string and convert it from unicode to ascii.
|
||||
//
|
||||
void GetResourceNameFromId
|
||||
(
|
||||
DWORD id, DWORD resourceBase, PSTR buffer, UINT cBytes
|
||||
)
|
||||
{
|
||||
PIMAGE_RESOURCE_DIR_STRING_U prdsu;
|
||||
|
||||
// If it's a regular ID, just format it.
|
||||
if ( !(id & IMAGE_RESOURCE_NAME_IS_STRING) )
|
||||
{
|
||||
wsprintf(buffer, "%X", id);
|
||||
return;
|
||||
}
|
||||
|
||||
id &= 0x7FFFFFFF;
|
||||
prdsu = (PIMAGE_RESOURCE_DIR_STRING_U)(resourceBase + id);
|
||||
|
||||
// prdsu->Length is the number of unicode characters
|
||||
WideCharToMultiByte(CP_ACP, 0, prdsu->NameString, prdsu->Length,
|
||||
buffer, cBytes, 0, 0);
|
||||
buffer[ min(cBytes-1,prdsu->Length) ] = 0; // Null terminate it!!!
|
||||
}
|
||||
|
||||
//
|
||||
// Dump the information about one resource directory entry. If the
|
||||
// entry is for a subdirectory, call the directory dumping routine
|
||||
// instead of printing information in this routine.
|
||||
//
|
||||
void DumpResourceEntry
|
||||
(
|
||||
PIMAGE_RESOURCE_DIRECTORY_ENTRY resDirEntry,
|
||||
DWORD resourceBase,
|
||||
DWORD level
|
||||
)
|
||||
{
|
||||
UINT i;
|
||||
char nameBuffer[128];
|
||||
|
||||
if ( resDirEntry->OffsetToData & IMAGE_RESOURCE_DATA_IS_DIRECTORY )
|
||||
{
|
||||
DumpResourceDirectory( (PIMAGE_RESOURCE_DIRECTORY)
|
||||
((resDirEntry->OffsetToData & 0x7FFFFFFF) + resourceBase),
|
||||
resourceBase, level, resDirEntry->Name);
|
||||
return;
|
||||
}
|
||||
|
||||
// Spit out the spacing for the level indentation
|
||||
for ( i=0; i < level; i++ )
|
||||
printf(" ");
|
||||
|
||||
if ( resDirEntry->Name & IMAGE_RESOURCE_NAME_IS_STRING )
|
||||
{
|
||||
GetResourceNameFromId(resDirEntry->Name, resourceBase, nameBuffer,
|
||||
sizeof(nameBuffer));
|
||||
printf("Name: %s Offset: %08X\n",
|
||||
nameBuffer, resDirEntry->OffsetToData);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("ID: %08X Offset: %08X\n",
|
||||
resDirEntry->Name, resDirEntry->OffsetToData);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Dump the information about one resource directory.
|
||||
//
|
||||
void DumpResourceDirectory
|
||||
(
|
||||
PIMAGE_RESOURCE_DIRECTORY resDir,
|
||||
DWORD resourceBase,
|
||||
DWORD level,
|
||||
DWORD resourceType
|
||||
)
|
||||
{
|
||||
PIMAGE_RESOURCE_DIRECTORY_ENTRY resDirEntry;
|
||||
char szType[64];
|
||||
UINT i;
|
||||
|
||||
// Spit out the spacing for the level indentation
|
||||
for ( i=0; i < level; i++ )
|
||||
printf(" ");
|
||||
|
||||
// Level 1 resources are the resource types
|
||||
if ( level == 1 && !(resourceType & IMAGE_RESOURCE_NAME_IS_STRING) )
|
||||
{
|
||||
GetResourceTypeName( resourceType, szType, sizeof(szType) );
|
||||
}
|
||||
else // Just print out the regular id or name
|
||||
{
|
||||
GetResourceNameFromId( resourceType, resourceBase, szType,
|
||||
sizeof(szType) );
|
||||
}
|
||||
|
||||
printf(
|
||||
"ResDir (%s) Named:%02X ID:%02X TimeDate:%08X Vers:%u.%02u Char:%X\n",
|
||||
szType, resDir->NumberOfNamedEntries, resDir->NumberOfIdEntries,
|
||||
resDir->TimeDateStamp, resDir->MajorVersion,
|
||||
resDir->MinorVersion,resDir->Characteristics);
|
||||
|
||||
resDirEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resDir+1);
|
||||
|
||||
for ( i=0; i < resDir->NumberOfNamedEntries; i++, resDirEntry++ )
|
||||
DumpResourceEntry(resDirEntry, resourceBase, level+1);
|
||||
|
||||
for ( i=0; i < resDir->NumberOfIdEntries; i++, resDirEntry++ )
|
||||
DumpResourceEntry(resDirEntry, resourceBase, level+1);
|
||||
}
|
||||
|
||||
//
|
||||
// Top level routine called to dump out the entire resource hierarchy
|
||||
//
|
||||
void DumpResourceSection(DWORD base, PIMAGE_NT_HEADERS pNTHeader)
|
||||
{
|
||||
PIMAGE_RESOURCE_DIRECTORY resDir;
|
||||
|
||||
resDir = GetSectionPtr(".rsrc", pNTHeader, (DWORD)base);
|
||||
if ( !resDir )
|
||||
return;
|
||||
|
||||
printf("Resources\n");
|
||||
DumpResourceDirectory(resDir, (DWORD)resDir, 0, 0);
|
||||
}
|
||||
|
||||
//
|
||||
// Dump the imports table (the .idata section) of a PE file
|
||||
//
|
||||
void DumpImportsSection(DWORD base, PIMAGE_NT_HEADERS pNTHeader)
|
||||
{
|
||||
PIMAGE_IMPORT_DESCRIPTOR importDesc;
|
||||
PIMAGE_SECTION_HEADER header;
|
||||
PIMAGE_THUNK_DATA thunk;
|
||||
PIMAGE_IMPORT_BY_NAME pOrdinalName;
|
||||
DWORD exportsStartRVA, exportsEndRVA;
|
||||
|
||||
INT delta;
|
||||
|
||||
header = GetSectionHeader(".idata", pNTHeader);
|
||||
if ( !header )
|
||||
return;
|
||||
importDesc = MakePtr(PIMAGE_IMPORT_DESCRIPTOR, base,
|
||||
header->PointerToRawData);
|
||||
delta = (INT)(header->VirtualAddress - header->PointerToRawData);
|
||||
|
||||
printf("Imports Table:\n");
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
// See if we've reached an empty IMAGE_IMPORT_DESCRIPTOR
|
||||
if ( (importDesc->TimeDateStamp==0 ) && (importDesc->Name==0) )
|
||||
break;
|
||||
|
||||
printf(" %s\n", (PBYTE)(importDesc->Name) - delta + base);
|
||||
|
||||
printf(" Hint/Name Table: %08X\n", importDesc->Characteristics);
|
||||
printf(" TimeDateStamp: %08X\n", importDesc->TimeDateStamp);
|
||||
printf(" ForwarderChain: %08X\n", importDesc->ForwarderChain);
|
||||
printf(" First thunk RVA: %08X\n", importDesc->FirstThunk);
|
||||
|
||||
thunk = (PIMAGE_THUNK_DATA)importDesc->FirstThunk;
|
||||
thunk = (PIMAGE_THUNK_DATA)( (PBYTE)thunk - delta + base);
|
||||
|
||||
// If the pointer that thunk points to is outside of the .idata
|
||||
// section, it looks like this file is "pre-fixed up" with regards
|
||||
// to the thunk table. In this situation, we'll need to fall back
|
||||
// to the hint-name (aka, the "Characteristics") table.
|
||||
exportsStartRVA = header->VirtualAddress;
|
||||
exportsEndRVA= exportsStartRVA + header->SizeOfRawData;
|
||||
if ( (*(PDWORD)thunk <= exportsStartRVA) ||
|
||||
(*(PDWORD)thunk >= exportsEndRVA) )
|
||||
{
|
||||
if ( importDesc->Characteristics == 0 ) // Borland doesn't have
|
||||
return; // this table!!!
|
||||
|
||||
thunk = (PIMAGE_THUNK_DATA)importDesc->Characteristics;
|
||||
if ( ((DWORD)thunk <= exportsStartRVA) ||
|
||||
((DWORD)thunk >= exportsEndRVA) )
|
||||
return;
|
||||
|
||||
thunk = (PIMAGE_THUNK_DATA)( (PBYTE)thunk - delta + base);
|
||||
}
|
||||
|
||||
printf(" Ordn Name\n");
|
||||
|
||||
while ( 1 ) // Loop forever (or until we break out)
|
||||
{
|
||||
if ( thunk->u1.AddressOfData == 0 )
|
||||
break;
|
||||
|
||||
if ( thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG )
|
||||
{
|
||||
printf(" %4u\n", thunk->u1.Ordinal & 0xFFFF);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
pOrdinalName = thunk->u1.AddressOfData;
|
||||
pOrdinalName = (PIMAGE_IMPORT_BY_NAME)
|
||||
((PBYTE)pOrdinalName - delta + base);
|
||||
|
||||
printf(" %4u %s\n", pOrdinalName->Hint, pOrdinalName->Name);
|
||||
}
|
||||
|
||||
thunk++; // Advance to next thunk
|
||||
}
|
||||
|
||||
importDesc++; // advance to next IMAGE_IMPORT_DESCRIPTOR
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Dump the exports table (the .edata section) of a PE file
|
||||
//
|
||||
void DumpExportsSection(DWORD base, PIMAGE_NT_HEADERS pNTHeader)
|
||||
{
|
||||
PIMAGE_EXPORT_DIRECTORY exportDir;
|
||||
PIMAGE_SECTION_HEADER header;
|
||||
INT delta;
|
||||
PSTR filename;
|
||||
DWORD i;
|
||||
PDWORD functions;
|
||||
PWORD ordinals;
|
||||
PSTR *name;
|
||||
|
||||
header = GetSectionHeader(".edata", pNTHeader);
|
||||
if ( !header )
|
||||
return;
|
||||
exportDir = MakePtr(PIMAGE_EXPORT_DIRECTORY, base,
|
||||
header->PointerToRawData);
|
||||
delta = (INT)(header->VirtualAddress - header->PointerToRawData);
|
||||
|
||||
filename = (PSTR)(exportDir->Name - delta + base);
|
||||
|
||||
printf("exports table:\n\n");
|
||||
printf(" Name: %s\n", filename);
|
||||
printf(" Characteristics: %08X\n", exportDir->Characteristics);
|
||||
printf(" TimeDateStamp: %08X\n", exportDir->TimeDateStamp);
|
||||
printf(" Version: %u.%02u\n", exportDir->MajorVersion,
|
||||
exportDir->MinorVersion);
|
||||
printf(" Ordinal base: %08X\n", exportDir->Base);
|
||||
printf(" # of functions: %08X\n", exportDir->NumberOfFunctions);
|
||||
printf(" # of Names: %08X\n", exportDir->NumberOfNames);
|
||||
|
||||
functions = (PDWORD)((DWORD)exportDir->AddressOfFunctions - delta + base);
|
||||
ordinals = (PWORD)((DWORD)exportDir->AddressOfNameOrdinals - delta + base);
|
||||
name = (PSTR *)((DWORD)exportDir->AddressOfNames - delta + base);
|
||||
|
||||
printf("\n Entry Pt Ordn Name\n");
|
||||
for ( i=0; i < exportDir->NumberOfNames; i++ )
|
||||
{
|
||||
printf(" %08X %4u %s\n", *functions,
|
||||
*ordinals + exportDir->Base,
|
||||
(*name - delta + base));
|
||||
name++; // Bump each pointer to the next array element
|
||||
ordinals++;
|
||||
functions++;
|
||||
}
|
||||
}
|
||||
|
||||
// The names of the available base relocations
|
||||
char *SzRelocTypes[] = {
|
||||
"ABSOLUTE","HIGH","LOW","HIGHLOW","HIGHADJ","MIPS_JMPADDR",
|
||||
"I860_BRADDR","I860_SPLIT" };
|
||||
|
||||
//
|
||||
// Dump the base relocation table of a PE file
|
||||
//
|
||||
void DumpBaseRelocationsSection(DWORD base, PIMAGE_NT_HEADERS pNTHeader)
|
||||
{
|
||||
PIMAGE_BASE_RELOCATION baseReloc;
|
||||
|
||||
baseReloc = GetSectionPtr(".reloc", pNTHeader, base);
|
||||
if ( !baseReloc )
|
||||
return;
|
||||
|
||||
printf("base relocations:\n\n");
|
||||
|
||||
while ( baseReloc->SizeOfBlock != 0 )
|
||||
{
|
||||
unsigned i,cEntries;
|
||||
PWORD pEntry;
|
||||
char *szRelocType;
|
||||
WORD relocType;
|
||||
|
||||
cEntries = (baseReloc->SizeOfBlock-sizeof(*baseReloc))/sizeof(WORD);
|
||||
pEntry = MakePtr( PWORD, baseReloc, sizeof(*baseReloc) );
|
||||
|
||||
printf("Virtual Address: %08X size: %08X\n",
|
||||
baseReloc->VirtualAddress, baseReloc->SizeOfBlock);
|
||||
|
||||
for ( i=0; i < cEntries; i++ )
|
||||
{
|
||||
// Extract the top 4 bits of the relocation entry. Turn those 4
|
||||
// bits into an appropriate descriptive string (szRelocType)
|
||||
relocType = (*pEntry & 0xF000) >> 12;
|
||||
szRelocType = relocType < 8 ? SzRelocTypes[relocType] : "unknown";
|
||||
|
||||
printf(" %08X %s\n",
|
||||
(*pEntry & 0x0FFF) + baseReloc->VirtualAddress,
|
||||
szRelocType);
|
||||
pEntry++; // Advance to next relocation entry
|
||||
}
|
||||
|
||||
baseReloc = MakePtr( PIMAGE_BASE_RELOCATION, baseReloc,
|
||||
baseReloc->SizeOfBlock);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Dump the COFF debug information header
|
||||
//
|
||||
void DumpCOFFHeader(PIMAGE_DEBUG_INFO pDbgInfo)
|
||||
{
|
||||
printf("COFF Debug Info Header\n");
|
||||
printf(" NumberOfSymbols: %08X\n", pDbgInfo->NumberOfSymbols);
|
||||
printf(" LvaToFirstSymbol: %08X\n", pDbgInfo->LvaToFirstSymbol);
|
||||
printf(" NumberOfLinenumbers: %08X\n", pDbgInfo->NumberOfLinenumbers);
|
||||
printf(" LvaToFirstLinenumber: %08X\n", pDbgInfo->LvaToFirstLinenumber);
|
||||
printf(" RvaToFirstByteOfCode: %08X\n", pDbgInfo->RvaToFirstByteOfCode);
|
||||
printf(" RvaToLastByteOfCode: %08X\n", pDbgInfo->RvaToLastByteOfCode);
|
||||
printf(" RvaToFirstByteOfData: %08X\n", pDbgInfo->RvaToFirstByteOfData);
|
||||
printf(" RvaToLastByteOfData: %08X\n", pDbgInfo->RvaToLastByteOfData);
|
||||
}
|
||||
|
||||
//
|
||||
// top level routine called from PEDUMP.C to dump the components of a PE file
|
||||
//
|
||||
void DumpExeFile( PIMAGE_DOS_HEADER dosHeader )
|
||||
{
|
||||
PIMAGE_NT_HEADERS pNTHeader;
|
||||
DWORD base = (DWORD)dosHeader;
|
||||
|
||||
pNTHeader = MakePtr( PIMAGE_NT_HEADERS, dosHeader,
|
||||
dosHeader->e_lfanew );
|
||||
|
||||
// First, verify that the e_lfanew field gave us a reasonable
|
||||
// pointer, then verify the PE signature.
|
||||
if ( IsBadReadPtr(pNTHeader, sizeof(IMAGE_NT_HEADERS)) ||
|
||||
pNTHeader->Signature != IMAGE_NT_SIGNATURE )
|
||||
{
|
||||
printf("Unhandled EXE type, or invalid .EXE\n");
|
||||
return;
|
||||
}
|
||||
|
||||
DumpHeader((PIMAGE_FILE_HEADER)&pNTHeader->FileHeader);
|
||||
printf("\n");
|
||||
|
||||
DumpOptionalHeader((PIMAGE_OPTIONAL_HEADER)&pNTHeader->OptionalHeader);
|
||||
printf("\n");
|
||||
|
||||
DumpSectionTable( (PIMAGE_SECTION_HEADER)(pNTHeader+1),
|
||||
pNTHeader->FileHeader.NumberOfSections, TRUE);
|
||||
printf("\n");
|
||||
|
||||
DumpDebugDirectory(base, pNTHeader);
|
||||
printf("\n");
|
||||
|
||||
DumpResourceSection(base, pNTHeader);
|
||||
printf("\n");
|
||||
|
||||
DumpImportsSection(base, pNTHeader);
|
||||
printf("\n");
|
||||
|
||||
DumpExportsSection(base, pNTHeader);
|
||||
printf("\n");
|
||||
|
||||
if ( fShowRelocations )
|
||||
{
|
||||
DumpBaseRelocationsSection(base, pNTHeader);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize these vars here since we'll need them in DumpLineNumbers
|
||||
//
|
||||
PCOFFSymbolTable = MakePtr(PIMAGE_SYMBOL, base,
|
||||
pNTHeader->FileHeader.PointerToSymbolTable);
|
||||
COFFSymbolCount = pNTHeader->FileHeader.NumberOfSymbols;
|
||||
|
||||
if ( fShowSymbolTable && PCOFFDebugInfo )
|
||||
{
|
||||
DumpCOFFHeader( PCOFFDebugInfo );
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if ( fShowLineNumbers && PCOFFDebugInfo )
|
||||
{
|
||||
DumpLineNumbers( MakePtr(PIMAGE_LINENUMBER, PCOFFDebugInfo,
|
||||
PCOFFDebugInfo->LvaToFirstLinenumber),
|
||||
PCOFFDebugInfo->NumberOfLinenumbers);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if ( fShowSymbolTable )
|
||||
{
|
||||
if ( pNTHeader->FileHeader.NumberOfSymbols
|
||||
&& pNTHeader->FileHeader.PointerToSymbolTable)
|
||||
{
|
||||
DumpSymbolTable(PCOFFSymbolTable, COFFSymbolCount);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
if ( fShowRawSectionData )
|
||||
{
|
||||
DumpRawSectionData( (PIMAGE_SECTION_HEADER)(pNTHeader+1),
|
||||
dosHeader,
|
||||
pNTHeader->FileHeader.NumberOfSections);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user