From 069aa93b555293679f4b8c07623133ba62a74ee4 Mon Sep 17 00:00:00 2001 From: Bill Hoffman Date: Thu, 2 Jul 2015 17:46:25 -0400 Subject: [PATCH] bindexplib: Add support for "/bigobj" format objects --- Source/bindexplib.cxx | 290 +++++++++++++++++++++++++----------------- 1 file changed, 174 insertions(+), 116 deletions(-) diff --git a/Source/bindexplib.cxx b/Source/bindexplib.cxx index 6a63279a0..11e3f3400 100644 --- a/Source/bindexplib.cxx +++ b/Source/bindexplib.cxx @@ -78,6 +78,59 @@ #include #include +typedef struct cmANON_OBJECT_HEADER_BIGOBJ { + /* same as ANON_OBJECT_HEADER_V2 */ + WORD Sig1; // Must be IMAGE_FILE_MACHINE_UNKNOWN + WORD Sig2; // Must be 0xffff + WORD Version; // >= 2 (implies the Flags field is present) + WORD Machine; // Actual machine - IMAGE_FILE_MACHINE_xxx + DWORD TimeDateStamp; + CLSID ClassID; // {D1BAA1C7-BAEE-4ba9-AF20-FAF66AA4DCB8} + DWORD SizeOfData; // Size of data that follows the header + DWORD Flags; // 0x1 -> contains metadata + DWORD MetaDataSize; // Size of CLR metadata + DWORD MetaDataOffset; // Offset of CLR metadata + + /* bigobj specifics */ + DWORD NumberOfSections; // extended from WORD + DWORD PointerToSymbolTable; + DWORD NumberOfSymbols; +} cmANON_OBJECT_HEADER_BIGOBJ; + +typedef struct _cmIMAGE_SYMBOL_EX { + union { + BYTE ShortName[8]; + struct { + DWORD Short; // if 0, use LongName + DWORD Long; // offset into string table + } Name; + DWORD LongName[2]; // PBYTE [2] + } N; + DWORD Value; + LONG SectionNumber; + WORD Type; + BYTE StorageClass; + BYTE NumberOfAuxSymbols; +} cmIMAGE_SYMBOL_EX; +typedef cmIMAGE_SYMBOL_EX UNALIGNED *cmPIMAGE_SYMBOL_EX; + +PIMAGE_SECTION_HEADER GetSectionHeaderOffset(PIMAGE_FILE_HEADER + pImageFileHeader) +{ + return (PIMAGE_SECTION_HEADER) + ((DWORD_PTR)pImageFileHeader + + IMAGE_SIZEOF_FILE_HEADER + + pImageFileHeader->SizeOfOptionalHeader); +} + +PIMAGE_SECTION_HEADER GetSectionHeaderOffset(cmANON_OBJECT_HEADER_BIGOBJ* + pImageFileHeader) +{ + return (PIMAGE_SECTION_HEADER) + ((DWORD_PTR)pImageFileHeader + + sizeof(cmANON_OBJECT_HEADER_BIGOBJ)); +} + /* + * Utility func, strstr with size + */ @@ -102,44 +155,64 @@ const char* StrNStr(const char* start, const char* find, size_t &size) { return 0; } -/* - *---------------------------------------------------------------------- - * HaveExportedObjects -- - * - * Returns >0 if export directives (declspec(dllexport)) exist. - * - *---------------------------------------------------------------------- - */ -int -HaveExportedObjects(PIMAGE_FILE_HEADER pImageFileHeader, - PIMAGE_SECTION_HEADER pSectionHeaders) +template < + // cmANON_OBJECT_HEADER_BIGOBJ or IMAGE_FILE_HEADER + class ObjectHeaderType, + // cmPIMAGE_SYMBOL_EX or PIMAGE_SYMBOL + class SymbolTableType> +class DumpSymbols { - static int fImportFlag = 0; /* The status is nor defined yet */ - WORD i; - size_t size; - char foundExports; - const char * rawdata; +public: + /* + *---------------------------------------------------------------------- + * Constructor -- + * + * Initialize variables from pointer to object header. + * + *---------------------------------------------------------------------- + */ - PIMAGE_SECTION_HEADER pDirectivesSectionHeader; + DumpSymbols(ObjectHeaderType* ih, + FILE* fout) { + this->ObjectImageHeader = ih; + this->SymbolTable = (SymbolTableType*) + ((DWORD_PTR)this->ObjectImageHeader + + this->ObjectImageHeader->PointerToSymbolTable); + this->FileOut = fout; + this->SectionHeaders = + GetSectionHeaderOffset(this->ObjectImageHeader); + this->ImportFlag = true; + this->SymbolCount = this->ObjectImageHeader->NumberOfSymbols; + } - if (fImportFlag) return 1; + /* + *---------------------------------------------------------------------- + * HaveExportedObjects -- + * + * Returns true if export directives (declspec(dllexport)) exist. + * + *---------------------------------------------------------------------- + */ - i = 0; - foundExports = 0; - pDirectivesSectionHeader = 0; - for(i = 0; (i < pImageFileHeader->NumberOfSections && - !pDirectivesSectionHeader); i++) + bool HaveExportedObjects() { + WORD i = 0; + size_t size = 0; + const char * rawdata = 0; + PIMAGE_SECTION_HEADER pDirectivesSectionHeader = 0; + PIMAGE_SECTION_HEADER pSectionHeaders = this->SectionHeaders; + for(i = 0; (i < this->ObjectImageHeader->NumberOfSections && + !pDirectivesSectionHeader); i++) if (!strncmp((const char*)&pSectionHeaders[i].Name[0], ".drectve",8)) - pDirectivesSectionHeader = &pSectionHeaders[i]; - if (!pDirectivesSectionHeader) return 0; + pDirectivesSectionHeader = &pSectionHeaders[i]; + if (!pDirectivesSectionHeader) return 0; - rawdata=(const char*) - pImageFileHeader+pDirectivesSectionHeader->PointerToRawData; - if (!pDirectivesSectionHeader->PointerToRawData || !rawdata) return 0; + rawdata=(const char*) + this->ObjectImageHeader+pDirectivesSectionHeader->PointerToRawData; + if (!pDirectivesSectionHeader->PointerToRawData || !rawdata) return 0; - size = pDirectivesSectionHeader->SizeOfRawData; - const char* posImportFlag = rawdata; - while ((posImportFlag = StrNStr(posImportFlag, " /EXPORT:", size))) { + size = pDirectivesSectionHeader->SizeOfRawData; + const char* posImportFlag = rawdata; + while ((posImportFlag = StrNStr(posImportFlag, " /EXPORT:", size))) { const char* lookingForDict = posImportFlag + 9; if (!strncmp(lookingForDict, "_G__cpp_",8) || !strncmp(lookingForDict, "_G__set_cpp_",12)) { @@ -153,38 +226,44 @@ HaveExportedObjects(PIMAGE_FILE_HEADER pImageFileHeader, // ignore DATA exports if (strncmp(lookingForDATA, ",DATA", 5)) break; posImportFlag = lookingForDATA + 5; - } - fImportFlag = (int)posImportFlag; - return fImportFlag; -} + } + if(posImportFlag) { + return true; + } + return false; + } - - -/* - *---------------------------------------------------------------------- -* DumpExternalsObjects -- -* -* Dumps a COFF symbol table from an EXE or OBJ. We only use -* it to dump tables from OBJs. -*---------------------------------------------------------------------- -*/ -void -DumpExternalsObjects(PIMAGE_SYMBOL pSymbolTable, - PIMAGE_SECTION_HEADER pSectionHeaders, - FILE *fout, DWORD_PTR cSymbols) -{ - unsigned i; - PSTR stringTable; - std::string symbol; - DWORD SectChar; - static int fImportFlag = -1; /* The status is nor defined yet */ - - /* - * The string table apparently starts right after the symbol table + /* + *---------------------------------------------------------------------- + * DumpObjFile -- + * + * Dump an object file's exported symbols. + *---------------------------------------------------------------------- */ - stringTable = (PSTR)&pSymbolTable[cSymbols]; + void DumpObjFile() { + if(!HaveExportedObjects()) { + this->DumpExternalsObjects(); + } + } - for ( i=0; i < cSymbols; i++ ) { + /* + *---------------------------------------------------------------------- + * DumpExternalsObjects -- + * + * Dumps a COFF symbol table from an OBJ. + *---------------------------------------------------------------------- + */ + void DumpExternalsObjects() { + unsigned i; + PSTR stringTable; + std::string symbol; + DWORD SectChar; + /* + * The string table apparently starts right after the symbol table + */ + stringTable = (PSTR)&this->SymbolTable[this->SymbolCount]; + SymbolTableType* pSymbolTable = this->SymbolTable; + for ( i=0; i < this->SymbolCount; i++ ) { if (pSymbolTable->SectionNumber > 0 && ( pSymbolTable->Type == 0x20 || pSymbolTable->Type == 0x0)) { if (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) { @@ -209,9 +288,9 @@ DumpExternalsObjects(PIMAGE_SYMBOL pSymbolTable, } } if (symbol[0] == '_') symbol.erase(0,1); - if (fImportFlag) { - fImportFlag = 0; - fprintf(fout,"EXPORTS \n"); + if (this->ImportFlag) { + this->ImportFlag = false; + fprintf(this->FileOut,"EXPORTS \n"); } /* Check whether it is "Scalar deleting destructor" and @@ -228,14 +307,15 @@ DumpExternalsObjects(PIMAGE_SYMBOL pSymbolTable, symbol.compare(0, 4, vectorPrefix) ) { SectChar = - pSectionHeaders[pSymbolTable->SectionNumber-1].Characteristics; + this-> + SectionHeaders[pSymbolTable->SectionNumber-1].Characteristics; if (!pSymbolTable->Type && (SectChar & IMAGE_SCN_MEM_WRITE)) { // Read only (i.e. constants) must be excluded - fprintf(fout, "\t%s \t DATA\n", symbol.c_str()); + fprintf(this->FileOut, "\t%s \t DATA\n", symbol.c_str()); } else { if ( pSymbolTable->Type || !(SectChar & IMAGE_SCN_MEM_READ)) { - fprintf(fout, "\t%s\n", symbol.c_str()); + fprintf(this->FileOut, "\t%s\n", symbol.c_str()); } else { // printf(" strange symbol: %s \n",symbol.c_str()); } @@ -252,11 +332,11 @@ DumpExternalsObjects(PIMAGE_SYMBOL pSymbolTable, symbol = stringTable + pSymbolTable->N.Name.Long; while (isspace(symbol[0])) symbol.erase(0,1); if (symbol[0] == '_') symbol.erase(0,1); - if (!fImportFlag) { - fImportFlag = 1; - fprintf(fout,"IMPORTS \n"); + if (!this->ImportFlag) { + this->ImportFlag = true; + fprintf(this->FileOut,"IMPORTS \n"); } - fprintf(fout, "\t%s DATA \n", symbol.c_str()+1); + fprintf(this->FileOut, "\t%s DATA \n", symbol.c_str()+1); } } @@ -266,49 +346,16 @@ DumpExternalsObjects(PIMAGE_SYMBOL pSymbolTable, i += pSymbolTable->NumberOfAuxSymbols; pSymbolTable += pSymbolTable->NumberOfAuxSymbols; pSymbolTable++; - } -} - -/* -*---------------------------------------------------------------------- -* DumpObjFile -- -* -* Dump an object file--either a full listing or just the exported -* symbols. -*---------------------------------------------------------------------- -*/ -void -DumpObjFile(PIMAGE_FILE_HEADER pImageFileHeader, FILE *fout) -{ - PIMAGE_SYMBOL PCOFFSymbolTable; - PIMAGE_SECTION_HEADER PCOFFSectionHeaders; - DWORD_PTR COFFSymbolCount; - - PCOFFSymbolTable = (PIMAGE_SYMBOL) - ((DWORD_PTR)pImageFileHeader + pImageFileHeader->PointerToSymbolTable); - COFFSymbolCount = pImageFileHeader->NumberOfSymbols; - - PCOFFSectionHeaders = (PIMAGE_SECTION_HEADER) - ((DWORD_PTR)pImageFileHeader + - IMAGE_SIZEOF_FILE_HEADER + - pImageFileHeader->SizeOfOptionalHeader); - - - int haveExports = HaveExportedObjects(pImageFileHeader, - PCOFFSectionHeaders); - if (!haveExports) - DumpExternalsObjects(PCOFFSymbolTable, PCOFFSectionHeaders, - fout, COFFSymbolCount); -} - -/* -*---------------------------------------------------------------------- -* DumpFile -- -* -* Open up a file, memory map it, and call the appropriate -* dumping routine -*---------------------------------------------------------------------- -*/ + } + } +private: + bool ImportFlag; + FILE* FileOut; + DWORD_PTR SymbolCount; + PIMAGE_SECTION_HEADER SectionHeaders; + ObjectHeaderType* ObjectImageHeader; + SymbolTableType* SymbolTable; +}; bool DumpFile(const char* filename, FILE *fout) @@ -358,10 +405,21 @@ DumpFile(const char* filename, FILE *fout) * really checking for IMAGE_FILE_HEADER.Machine == i386 (0x14C) * and IMAGE_FILE_HEADER.SizeOfOptionalHeader == 0; */ - DumpObjFile((PIMAGE_FILE_HEADER) lpFileBase, fout); + DumpSymbols + symbolDumper((PIMAGE_FILE_HEADER) lpFileBase, fout); + symbolDumper.DumpObjFile(); } else { - printf("unrecognized file format in '%s'\n", filename); - return false; + // check for /bigobj format + cmANON_OBJECT_HEADER_BIGOBJ* h = + (cmANON_OBJECT_HEADER_BIGOBJ*) lpFileBase; + if(h->Sig1 == 0x0 && h->Sig2 == 0xffff) { + DumpSymbols + symbolDumper((cmANON_OBJECT_HEADER_BIGOBJ*) lpFileBase, fout); + symbolDumper.DumpObjFile(); + } else { + printf("unrecognized file format in '%s'\n", filename); + return false; + } } UnmapViewOfFile(lpFileBase); CloseHandle(hFileMapping);