diff options
Diffstat (limited to 'devtools/test_binaries/COMMON.C')
| -rw-r--r-- | devtools/test_binaries/COMMON.C | 583 |
1 files changed, 583 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; + } +} |