mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-07 17:29:36 +00:00
1
This commit is contained in:
@@ -0,0 +1,583 @@
|
||||
//--------------------
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
// MakePtr is a macro that allows you to easily add to values (including
|
||||
// pointers) together without dealing with C's pointer arithmetic. It
|
||||
// essentially treats the last two parameters as DWORDs. The first
|
||||
// parameter is used to typecast the result to the appropriate pointer type.
|
||||
#define MakePtr( cast, ptr, addValue ) (cast)( (DWORD)(ptr) + (addValue) )
|
||||
|
||||
void DumpHeader(PIMAGE_FILE_HEADER pImageFileHeader);
|
||||
void DumpOptionalHeader(PIMAGE_OPTIONAL_HEADER pImageOptionalHeader);
|
||||
void DumpSectionTable(PIMAGE_SECTION_HEADER section,
|
||||
unsigned cSections,
|
||||
BOOL IsEXE);
|
||||
BOOL LookupSymbolName(DWORD index, PSTR buffer, UINT length);
|
||||
void DumpSymbolTable(PIMAGE_SYMBOL pSymbolTable, unsigned cSymbols);
|
||||
LPVOID GetSectionPtr(PSTR name, PIMAGE_NT_HEADERS pNTHeader, DWORD imageBase);
|
||||
PIMAGE_SECTION_HEADER GetSectionHeader(PSTR name, PIMAGE_NT_HEADERS pNTHeader);
|
||||
void DumpRawSectionData(PIMAGE_SECTION_HEADER section,
|
||||
PVOID base,
|
||||
unsigned cSections);
|
||||
void DumpLineNumbers(PIMAGE_LINENUMBER pln, DWORD count);
|
||||
void HexDump(PBYTE ptr, DWORD length);
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
void DumpExeFile( PIMAGE_DOS_HEADER dosHeader );
|
||||
@@ -0,0 +1,16 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
// EXTRNVAR.H holds the "extern" definitions for global variables used
|
||||
// through the program.
|
||||
|
||||
extern BOOL fShowRelocations;
|
||||
extern BOOL fShowRawSectionData;
|
||||
extern BOOL fShowSymbolTable;
|
||||
extern BOOL fShowLineNumbers;
|
||||
extern PIMAGE_SYMBOL PCOFFSymbolTable;
|
||||
extern DWORD COFFSymbolCount;
|
||||
@@ -0,0 +1,132 @@
|
||||
//--------------------
|
||||
// PROGRAM: PEDUMP
|
||||
// FILE: OBJDUMP.C
|
||||
// AUTHOR: Matt Pietrek - 1993
|
||||
//--------------------
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include "common.h"
|
||||
#include "extrnvar.h"
|
||||
|
||||
typedef struct _i386RelocTypes
|
||||
{
|
||||
WORD type;
|
||||
PSTR name;
|
||||
} i386RelocTypes;
|
||||
|
||||
// ASCII names for the various relocations used in i386 COFF OBJs
|
||||
i386RelocTypes i386Relocations[] =
|
||||
{
|
||||
{ IMAGE_REL_I386_ABSOLUTE, "ABSOLUTE" },
|
||||
{ IMAGE_REL_I386_DIR16, "DIR16" },
|
||||
{ IMAGE_REL_I386_REL16, "REL16" },
|
||||
{ IMAGE_REL_I386_DIR32, "DIR32" },
|
||||
{ IMAGE_REL_I386_DIR32NB, "DIR32NB" },
|
||||
{ IMAGE_REL_I386_SEG12, "SEG12" },
|
||||
{ IMAGE_REL_I386_SECTION, "SECTION" },
|
||||
{ IMAGE_REL_I386_SECREL, "SECREL" },
|
||||
{ IMAGE_REL_I386_REL32, "REL32" }
|
||||
};
|
||||
#define I386RELOCTYPECOUNT (sizeof(i386Relocations) / sizeof(i386RelocTypes))
|
||||
|
||||
//
|
||||
// Given an i386 OBJ relocation type, return its ASCII name in a buffer
|
||||
//
|
||||
void GetObjRelocationName(WORD type, PSTR buffer, DWORD cBytes)
|
||||
{
|
||||
DWORD i;
|
||||
|
||||
for ( i=0; i < I386RELOCTYPECOUNT; i++ )
|
||||
if ( type == i386Relocations[i].type )
|
||||
{
|
||||
strncpy(buffer, i386Relocations[i].name, cBytes);
|
||||
return;
|
||||
}
|
||||
|
||||
wsprintf( buffer, "???_%X", type);
|
||||
}
|
||||
|
||||
//
|
||||
// Dump the relocation table for one COFF section
|
||||
//
|
||||
void DumpObjRelocations(PIMAGE_RELOCATION pRelocs, DWORD count)
|
||||
{
|
||||
DWORD i;
|
||||
char szTypeName[32];
|
||||
|
||||
for ( i=0; i < count; i++ )
|
||||
{
|
||||
GetObjRelocationName(pRelocs->Type, szTypeName, sizeof(szTypeName));
|
||||
printf(" Address: %08X SymIndex: %08X Type: %s\n",
|
||||
pRelocs->VirtualAddress, pRelocs->SymbolTableIndex,
|
||||
szTypeName);
|
||||
pRelocs++;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// top level routine called from PEDUMP.C to dump the components of a
|
||||
// COFF OBJ file.
|
||||
//
|
||||
void DumpObjFile( PIMAGE_FILE_HEADER pImageFileHeader )
|
||||
{
|
||||
unsigned i;
|
||||
PIMAGE_SECTION_HEADER pSections;
|
||||
|
||||
DumpHeader(pImageFileHeader);
|
||||
printf("\n");
|
||||
|
||||
pSections = (PIMAGE_SECTION_HEADER)(pImageFileHeader+1);
|
||||
|
||||
DumpSectionTable(pSections, pImageFileHeader->NumberOfSections, FALSE);
|
||||
printf("\n");
|
||||
|
||||
if ( fShowRelocations )
|
||||
{
|
||||
for ( i=0; i < pImageFileHeader->NumberOfSections; i++ )
|
||||
{
|
||||
if ( pSections[i].PointerToRelocations == 0 )
|
||||
continue;
|
||||
|
||||
printf("Section %02X (%.8s) relocations\n", i, pSections[i].Name);
|
||||
DumpObjRelocations( MakePtr(PIMAGE_RELOCATION, pImageFileHeader,
|
||||
pSections[i].PointerToRelocations),
|
||||
pSections[i].NumberOfRelocations );
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
PCOFFSymbolTable = MakePtr(PIMAGE_SYMBOL, pImageFileHeader,
|
||||
pImageFileHeader->PointerToSymbolTable);
|
||||
COFFSymbolCount = pImageFileHeader->NumberOfSymbols;
|
||||
|
||||
if ( fShowLineNumbers )
|
||||
{
|
||||
// Walk through the section table...
|
||||
for (i=0; i < pImageFileHeader->NumberOfSections; i++)
|
||||
{
|
||||
// if there's any line numbers for this section, dump'em
|
||||
if ( pSections->NumberOfLinenumbers )
|
||||
{
|
||||
DumpLineNumbers( MakePtr(PIMAGE_LINENUMBER, pImageFileHeader,
|
||||
pSections->PointerToLinenumbers),
|
||||
pSections->NumberOfLinenumbers );
|
||||
printf("\n");
|
||||
}
|
||||
pSections++;
|
||||
}
|
||||
}
|
||||
|
||||
if ( fShowSymbolTable )
|
||||
{
|
||||
DumpSymbolTable(PCOFFSymbolTable, COFFSymbolCount);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if ( fShowRawSectionData )
|
||||
{
|
||||
DumpRawSectionData( (PIMAGE_SECTION_HEADER)(pImageFileHeader+1),
|
||||
pImageFileHeader,
|
||||
pImageFileHeader->NumberOfSections);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
void DumpObjFile( PIMAGE_FILE_HEADER pImageFileHeader );
|
||||
@@ -0,0 +1,139 @@
|
||||
//--------------------
|
||||
// PROGRAM: PEDUMP
|
||||
// FILE: PEDUMP.C
|
||||
// AUTHOR: Matt Pietrek - 1993
|
||||
//--------------------
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include "objdump.h"
|
||||
#include "exedump.h"
|
||||
#include "extrnvar.h"
|
||||
|
||||
// Global variables set here, and used in EXEDUMP.C and OBJDUMP.C
|
||||
BOOL fShowRelocations = FALSE;
|
||||
BOOL fShowRawSectionData = FALSE;
|
||||
BOOL fShowSymbolTable = FALSE;
|
||||
BOOL fShowLineNumbers = FALSE;
|
||||
|
||||
char HelpText[] =
|
||||
"PEDUMP - Win32/COFF .EXE/.OBJ file dumper - 1993 Matt Pietrek\n\n"
|
||||
"Syntax: PEDUMP [switches] filename\n\n"
|
||||
" /A include everything in dump\n"
|
||||
" /H include hex dump of sections\n"
|
||||
" /L include line number information\n"
|
||||
" /R show base relocations\n"
|
||||
" /S show symbol table\n";
|
||||
|
||||
//
|
||||
// Open up a file, memory map it, and call the appropriate dumping routine
|
||||
//
|
||||
void DumpFile(LPSTR filename)
|
||||
{
|
||||
HANDLE hFile;
|
||||
HANDLE hFileMapping;
|
||||
LPVOID lpFileBase;
|
||||
PIMAGE_DOS_HEADER dosHeader;
|
||||
|
||||
hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
|
||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
|
||||
if ( hFile == INVALID_HANDLE_VALUE )
|
||||
{
|
||||
printf("Couldn't open file with CreateFile()\n");
|
||||
return;
|
||||
}
|
||||
|
||||
hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||
if ( hFileMapping == 0 )
|
||||
{
|
||||
CloseHandle(hFile);
|
||||
printf("Couldn't open file mapping with CreateFileMapping()\n");
|
||||
return;
|
||||
}
|
||||
|
||||
lpFileBase = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
|
||||
if ( lpFileBase == 0 )
|
||||
{
|
||||
CloseHandle(hFileMapping);
|
||||
CloseHandle(hFile);
|
||||
printf("Couldn't map view of file with MapViewOfFile()\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("Dump of file %s\n\n", filename);
|
||||
|
||||
dosHeader = (PIMAGE_DOS_HEADER)lpFileBase;
|
||||
if ( dosHeader->e_magic == IMAGE_DOS_SIGNATURE )
|
||||
{
|
||||
DumpExeFile( dosHeader );
|
||||
}
|
||||
else if ( (dosHeader->e_magic == 0x014C) // Does it look like a i386
|
||||
&& (dosHeader->e_sp == 0) ) // COFF OBJ file???
|
||||
{
|
||||
// The two tests above aren't what they look like. They're
|
||||
// really checking for IMAGE_FILE_HEADER.Machine == i386 (0x14C)
|
||||
// and IMAGE_FILE_HEADER.SizeOfOptionalHeader == 0;
|
||||
|
||||
DumpObjFile( (PIMAGE_FILE_HEADER)lpFileBase );
|
||||
}
|
||||
else
|
||||
printf("unrecognized file format\n");
|
||||
UnmapViewOfFile(lpFileBase);
|
||||
CloseHandle(hFileMapping);
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
|
||||
//
|
||||
// process all the command line arguments and return a pointer to
|
||||
// the filename argument.
|
||||
//
|
||||
PSTR ProcessCommandLine(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
for ( i=1; i < argc; i++ )
|
||||
{
|
||||
strupr(argv[i]);
|
||||
|
||||
// Is it a switch character?
|
||||
if ( (argv[i][0] == '-') || (argv[i][0] == '/') )
|
||||
{
|
||||
if ( argv[i][1] == 'A' )
|
||||
{
|
||||
fShowRelocations = TRUE;
|
||||
fShowRawSectionData = TRUE;
|
||||
fShowSymbolTable = TRUE;
|
||||
fShowLineNumbers = TRUE;
|
||||
}
|
||||
else if ( argv[i][1] == 'H' )
|
||||
fShowRawSectionData = TRUE;
|
||||
else if ( argv[i][1] == 'L' )
|
||||
fShowLineNumbers = TRUE;
|
||||
else if ( argv[i][1] == 'R' )
|
||||
fShowRelocations = TRUE;
|
||||
else if ( argv[i][1] == 'S' )
|
||||
fShowSymbolTable = TRUE;
|
||||
}
|
||||
else // Not a switch character. Must be the filename
|
||||
{
|
||||
return argv[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
PSTR filename;
|
||||
|
||||
if ( argc == 1 )
|
||||
{
|
||||
printf( HelpText );
|
||||
return 1;
|
||||
}
|
||||
|
||||
filename = ProcessCommandLine(argc, argv);
|
||||
if ( filename )
|
||||
DumpFile( filename );
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
// test_binaries.cpp : test for debug section
|
||||
//
|
||||
// Adapted from PEDUMP, AUTHOR: Matt Pietrek - 1993
|
||||
//--------------------
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include "common.h"
|
||||
#include "strtools.h"
|
||||
|
||||
bool HasSection( PIMAGE_SECTION_HEADER section, int numSections, const char *pSectionName )
|
||||
{
|
||||
for ( int i = 0; i < numSections; i++ )
|
||||
{
|
||||
if ( !strnicmp( (char *)section[i].Name, pSectionName, 8 ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void TestExeFile( const char *pFilename, PIMAGE_DOS_HEADER dosHeader )
|
||||
{
|
||||
PIMAGE_NT_HEADERS pNTHeader;
|
||||
|
||||
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 (%s)\n", pFilename);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( HasSection( (PIMAGE_SECTION_HEADER)(pNTHeader+1), pNTHeader->FileHeader.NumberOfSections, "ValveDBG" ) )
|
||||
{
|
||||
printf("%s is a debug build\n", pFilename);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Open up a file, memory map it, and call the appropriate dumping routine
|
||||
//
|
||||
void TestFile(const char *pFilename)
|
||||
{
|
||||
HANDLE hFile;
|
||||
HANDLE hFileMapping;
|
||||
LPVOID lpFileBase;
|
||||
PIMAGE_DOS_HEADER dosHeader;
|
||||
|
||||
hFile = CreateFile(pFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
|
||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
|
||||
if ( hFile == INVALID_HANDLE_VALUE )
|
||||
{
|
||||
printf("Couldn't open file %s with CreateFile()\n", pFilename );
|
||||
return;
|
||||
}
|
||||
|
||||
hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||
if ( hFileMapping == 0 )
|
||||
{
|
||||
CloseHandle(hFile);
|
||||
printf("Couldn't open file mapping with CreateFileMapping()\n");
|
||||
return;
|
||||
}
|
||||
|
||||
lpFileBase = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
|
||||
if ( lpFileBase == 0 )
|
||||
{
|
||||
CloseHandle(hFileMapping);
|
||||
CloseHandle(hFile);
|
||||
printf("Couldn't map view of file with MapViewOfFile()\n");
|
||||
return;
|
||||
}
|
||||
|
||||
dosHeader = (PIMAGE_DOS_HEADER)lpFileBase;
|
||||
if ( dosHeader->e_magic == IMAGE_DOS_SIGNATURE )
|
||||
{
|
||||
TestExeFile( pFilename, dosHeader );
|
||||
}
|
||||
#if 0
|
||||
else if ( (dosHeader->e_magic == 0x014C) // Does it look like a i386
|
||||
&& (dosHeader->e_sp == 0) ) // COFF OBJ file???
|
||||
{
|
||||
// The two tests above aren't what they look like. They're
|
||||
// really checking for IMAGE_FILE_HEADER.Machine == i386 (0x14C)
|
||||
// and IMAGE_FILE_HEADER.SizeOfOptionalHeader == 0;
|
||||
|
||||
DumpObjFile( (PIMAGE_FILE_HEADER)lpFileBase );
|
||||
}
|
||||
#endif
|
||||
else
|
||||
printf("unrecognized file format\n");
|
||||
UnmapViewOfFile(lpFileBase);
|
||||
CloseHandle(hFileMapping);
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
if ( argc < 2 )
|
||||
{
|
||||
printf("Usage: test_binaries <FILENAME>\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
char fileName[2048], dir[2048];
|
||||
if ( !Q_ExtractFilePath( argv[1], dir, sizeof( dir ) ) )
|
||||
{
|
||||
strcpy( dir, "" );
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_FixSlashes( dir, '/' );
|
||||
int len = strlen(dir);
|
||||
if ( len && dir[len-1] !='/' )
|
||||
{
|
||||
strcat( dir, "/" );
|
||||
}
|
||||
}
|
||||
|
||||
WIN32_FIND_DATA findData;
|
||||
HANDLE hFind = FindFirstFile( argv[1], &findData );
|
||||
if ( hFind == INVALID_HANDLE_VALUE )
|
||||
{
|
||||
printf("Can't find %s\n", argv[1] );
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
sprintf( fileName, "%s%s", dir, findData.cFileName );
|
||||
TestFile( fileName );
|
||||
} while ( FindNextFile( hFind, &findData ) );
|
||||
FindClose( hFind );
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// TEST_BINARIES.VPC
|
||||
//
|
||||
// Project Script
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
$Macro SRCDIR "..\.."
|
||||
$Macro OUTBINDIR "$SRCDIR\..\game\bin"
|
||||
|
||||
$Include "$SRCDIR\vpc_scripts\source_exe_con_base.vpc"
|
||||
|
||||
$Project "Test_binaries"
|
||||
{
|
||||
$Folder "Source Files"
|
||||
{
|
||||
$File "test_binaries.cpp"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user