summaryrefslogtreecommitdiff
path: root/devtools/test_binaries
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /devtools/test_binaries
downloadarchived-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.C583
-rw-r--r--devtools/test_binaries/COMMON.H27
-rw-r--r--devtools/test_binaries/EXEDUMP.C532
-rw-r--r--devtools/test_binaries/EXEDUMP.H8
-rw-r--r--devtools/test_binaries/EXTRNVAR.H16
-rw-r--r--devtools/test_binaries/OBJDUMP.C132
-rw-r--r--devtools/test_binaries/OBJDUMP.H8
-rw-r--r--devtools/test_binaries/PEDUMP.C139
-rw-r--r--devtools/test_binaries/test_binaries.cpp149
-rw-r--r--devtools/test_binaries/test_binaries.vpc18
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"
+ }
+}