diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /devtools/test_binaries | |
| download | archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.tar.xz archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.zip | |
Diffstat (limited to 'devtools/test_binaries')
| -rw-r--r-- | devtools/test_binaries/COMMON.C | 583 | ||||
| -rw-r--r-- | devtools/test_binaries/COMMON.H | 27 | ||||
| -rw-r--r-- | devtools/test_binaries/EXEDUMP.C | 532 | ||||
| -rw-r--r-- | devtools/test_binaries/EXEDUMP.H | 8 | ||||
| -rw-r--r-- | devtools/test_binaries/EXTRNVAR.H | 16 | ||||
| -rw-r--r-- | devtools/test_binaries/OBJDUMP.C | 132 | ||||
| -rw-r--r-- | devtools/test_binaries/OBJDUMP.H | 8 | ||||
| -rw-r--r-- | devtools/test_binaries/PEDUMP.C | 139 | ||||
| -rw-r--r-- | devtools/test_binaries/test_binaries.cpp | 149 | ||||
| -rw-r--r-- | devtools/test_binaries/test_binaries.vpc | 18 |
10 files changed, 1612 insertions, 0 deletions
diff --git a/devtools/test_binaries/COMMON.C b/devtools/test_binaries/COMMON.C new file mode 100644 index 0000000..61821d7 --- /dev/null +++ b/devtools/test_binaries/COMMON.C @@ -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; + } +} diff --git a/devtools/test_binaries/COMMON.H b/devtools/test_binaries/COMMON.H new file mode 100644 index 0000000..6ead1b7 --- /dev/null +++ b/devtools/test_binaries/COMMON.H @@ -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); diff --git a/devtools/test_binaries/EXEDUMP.C b/devtools/test_binaries/EXEDUMP.C new file mode 100644 index 0000000..a34cea0 --- /dev/null +++ b/devtools/test_binaries/EXEDUMP.C @@ -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); + } +} diff --git a/devtools/test_binaries/EXEDUMP.H b/devtools/test_binaries/EXEDUMP.H new file mode 100644 index 0000000..deaa6d8 --- /dev/null +++ b/devtools/test_binaries/EXEDUMP.H @@ -0,0 +1,8 @@ +//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +void DumpExeFile( PIMAGE_DOS_HEADER dosHeader ); diff --git a/devtools/test_binaries/EXTRNVAR.H b/devtools/test_binaries/EXTRNVAR.H new file mode 100644 index 0000000..e54ec49 --- /dev/null +++ b/devtools/test_binaries/EXTRNVAR.H @@ -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; diff --git a/devtools/test_binaries/OBJDUMP.C b/devtools/test_binaries/OBJDUMP.C new file mode 100644 index 0000000..e9481cc --- /dev/null +++ b/devtools/test_binaries/OBJDUMP.C @@ -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); + } +} diff --git a/devtools/test_binaries/OBJDUMP.H b/devtools/test_binaries/OBJDUMP.H new file mode 100644 index 0000000..74e0695 --- /dev/null +++ b/devtools/test_binaries/OBJDUMP.H @@ -0,0 +1,8 @@ +//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +void DumpObjFile( PIMAGE_FILE_HEADER pImageFileHeader ); diff --git a/devtools/test_binaries/PEDUMP.C b/devtools/test_binaries/PEDUMP.C new file mode 100644 index 0000000..dd47ff4 --- /dev/null +++ b/devtools/test_binaries/PEDUMP.C @@ -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; +} diff --git a/devtools/test_binaries/test_binaries.cpp b/devtools/test_binaries/test_binaries.cpp new file mode 100644 index 0000000..818cd3d --- /dev/null +++ b/devtools/test_binaries/test_binaries.cpp @@ -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; +} diff --git a/devtools/test_binaries/test_binaries.vpc b/devtools/test_binaries/test_binaries.vpc new file mode 100644 index 0000000..70b8df6 --- /dev/null +++ b/devtools/test_binaries/test_binaries.vpc @@ -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" + } +} |