bindexplib: Add support for "/bigobj" format objects

This commit is contained in:
Bill Hoffman 2015-07-02 17:46:25 -04:00 committed by Brad King
parent 61bbbdcf9c
commit 069aa93b55
1 changed files with 174 additions and 116 deletions

View File

@ -78,6 +78,59 @@
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
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 + * Utility func, strstr with size
+ */ + */
@ -102,39 +155,59 @@ const char* StrNStr(const char* start, const char* find, size_t &size) {
return 0; return 0;
} }
/* template <
// cmANON_OBJECT_HEADER_BIGOBJ or IMAGE_FILE_HEADER
class ObjectHeaderType,
// cmPIMAGE_SYMBOL_EX or PIMAGE_SYMBOL
class SymbolTableType>
class DumpSymbols
{
public:
/*
*---------------------------------------------------------------------- *----------------------------------------------------------------------
* HaveExportedObjects -- * Constructor --
* *
* Returns >0 if export directives (declspec(dllexport)) exist. * Initialize variables from pointer to object header.
* *
*---------------------------------------------------------------------- *----------------------------------------------------------------------
*/ */
int
HaveExportedObjects(PIMAGE_FILE_HEADER pImageFileHeader,
PIMAGE_SECTION_HEADER pSectionHeaders)
{
static int fImportFlag = 0; /* The status is nor defined yet */
WORD i;
size_t size;
char foundExports;
const char * rawdata;
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; bool HaveExportedObjects() {
foundExports = 0; WORD i = 0;
pDirectivesSectionHeader = 0; size_t size = 0;
for(i = 0; (i < pImageFileHeader->NumberOfSections && const char * rawdata = 0;
PIMAGE_SECTION_HEADER pDirectivesSectionHeader = 0;
PIMAGE_SECTION_HEADER pSectionHeaders = this->SectionHeaders;
for(i = 0; (i < this->ObjectImageHeader->NumberOfSections &&
!pDirectivesSectionHeader); i++) !pDirectivesSectionHeader); i++)
if (!strncmp((const char*)&pSectionHeaders[i].Name[0], ".drectve",8)) if (!strncmp((const char*)&pSectionHeaders[i].Name[0], ".drectve",8))
pDirectivesSectionHeader = &pSectionHeaders[i]; pDirectivesSectionHeader = &pSectionHeaders[i];
if (!pDirectivesSectionHeader) return 0; if (!pDirectivesSectionHeader) return 0;
rawdata=(const char*) rawdata=(const char*)
pImageFileHeader+pDirectivesSectionHeader->PointerToRawData; this->ObjectImageHeader+pDirectivesSectionHeader->PointerToRawData;
if (!pDirectivesSectionHeader->PointerToRawData || !rawdata) return 0; if (!pDirectivesSectionHeader->PointerToRawData || !rawdata) return 0;
size = pDirectivesSectionHeader->SizeOfRawData; size = pDirectivesSectionHeader->SizeOfRawData;
@ -154,37 +227,43 @@ HaveExportedObjects(PIMAGE_FILE_HEADER pImageFileHeader,
if (strncmp(lookingForDATA, ",DATA", 5)) break; if (strncmp(lookingForDATA, ",DATA", 5)) break;
posImportFlag = lookingForDATA + 5; posImportFlag = lookingForDATA + 5;
} }
fImportFlag = (int)posImportFlag; if(posImportFlag) {
return fImportFlag; return true;
} }
return false;
}
/*
/*
*---------------------------------------------------------------------- *----------------------------------------------------------------------
* DumpExternalsObjects -- * DumpObjFile --
* *
* Dumps a COFF symbol table from an EXE or OBJ. We only use * Dump an object file's exported symbols.
* it to dump tables from OBJs. *----------------------------------------------------------------------
*---------------------------------------------------------------------- */
*/ void DumpObjFile() {
void if(!HaveExportedObjects()) {
DumpExternalsObjects(PIMAGE_SYMBOL pSymbolTable, this->DumpExternalsObjects();
PIMAGE_SECTION_HEADER pSectionHeaders, }
FILE *fout, DWORD_PTR cSymbols) }
{
/*
*----------------------------------------------------------------------
* DumpExternalsObjects --
*
* Dumps a COFF symbol table from an OBJ.
*----------------------------------------------------------------------
*/
void DumpExternalsObjects() {
unsigned i; unsigned i;
PSTR stringTable; PSTR stringTable;
std::string symbol; std::string symbol;
DWORD SectChar; DWORD SectChar;
static int fImportFlag = -1; /* The status is nor defined yet */
/* /*
* The string table apparently starts right after the symbol table * The string table apparently starts right after the symbol table
*/ */
stringTable = (PSTR)&pSymbolTable[cSymbols]; stringTable = (PSTR)&this->SymbolTable[this->SymbolCount];
SymbolTableType* pSymbolTable = this->SymbolTable;
for ( i=0; i < cSymbols; i++ ) { for ( i=0; i < this->SymbolCount; i++ ) {
if (pSymbolTable->SectionNumber > 0 && if (pSymbolTable->SectionNumber > 0 &&
( pSymbolTable->Type == 0x20 || pSymbolTable->Type == 0x0)) { ( pSymbolTable->Type == 0x20 || pSymbolTable->Type == 0x0)) {
if (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) { if (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) {
@ -209,9 +288,9 @@ DumpExternalsObjects(PIMAGE_SYMBOL pSymbolTable,
} }
} }
if (symbol[0] == '_') symbol.erase(0,1); if (symbol[0] == '_') symbol.erase(0,1);
if (fImportFlag) { if (this->ImportFlag) {
fImportFlag = 0; this->ImportFlag = false;
fprintf(fout,"EXPORTS \n"); fprintf(this->FileOut,"EXPORTS \n");
} }
/* /*
Check whether it is "Scalar deleting destructor" and Check whether it is "Scalar deleting destructor" and
@ -228,14 +307,15 @@ DumpExternalsObjects(PIMAGE_SYMBOL pSymbolTable,
symbol.compare(0, 4, vectorPrefix) ) symbol.compare(0, 4, vectorPrefix) )
{ {
SectChar = SectChar =
pSectionHeaders[pSymbolTable->SectionNumber-1].Characteristics; this->
SectionHeaders[pSymbolTable->SectionNumber-1].Characteristics;
if (!pSymbolTable->Type && (SectChar & IMAGE_SCN_MEM_WRITE)) { if (!pSymbolTable->Type && (SectChar & IMAGE_SCN_MEM_WRITE)) {
// Read only (i.e. constants) must be excluded // 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 { } else {
if ( pSymbolTable->Type || if ( pSymbolTable->Type ||
!(SectChar & IMAGE_SCN_MEM_READ)) { !(SectChar & IMAGE_SCN_MEM_READ)) {
fprintf(fout, "\t%s\n", symbol.c_str()); fprintf(this->FileOut, "\t%s\n", symbol.c_str());
} else { } else {
// printf(" strange symbol: %s \n",symbol.c_str()); // printf(" strange symbol: %s \n",symbol.c_str());
} }
@ -252,11 +332,11 @@ DumpExternalsObjects(PIMAGE_SYMBOL pSymbolTable,
symbol = stringTable + pSymbolTable->N.Name.Long; symbol = stringTable + pSymbolTable->N.Name.Long;
while (isspace(symbol[0])) symbol.erase(0,1); while (isspace(symbol[0])) symbol.erase(0,1);
if (symbol[0] == '_') symbol.erase(0,1); if (symbol[0] == '_') symbol.erase(0,1);
if (!fImportFlag) { if (!this->ImportFlag) {
fImportFlag = 1; this->ImportFlag = true;
fprintf(fout,"IMPORTS \n"); 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);
} }
} }
@ -267,48 +347,15 @@ DumpExternalsObjects(PIMAGE_SYMBOL pSymbolTable,
pSymbolTable += pSymbolTable->NumberOfAuxSymbols; pSymbolTable += pSymbolTable->NumberOfAuxSymbols;
pSymbolTable++; pSymbolTable++;
} }
} }
private:
/* bool ImportFlag;
*---------------------------------------------------------------------- FILE* FileOut;
* DumpObjFile -- DWORD_PTR SymbolCount;
* PIMAGE_SECTION_HEADER SectionHeaders;
* Dump an object file--either a full listing or just the exported ObjectHeaderType* ObjectImageHeader;
* symbols. SymbolTableType* SymbolTable;
*---------------------------------------------------------------------- };
*/
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
*----------------------------------------------------------------------
*/
bool bool
DumpFile(const char* filename, FILE *fout) DumpFile(const char* filename, FILE *fout)
@ -358,11 +405,22 @@ DumpFile(const char* filename, FILE *fout)
* really checking for IMAGE_FILE_HEADER.Machine == i386 (0x14C) * really checking for IMAGE_FILE_HEADER.Machine == i386 (0x14C)
* and IMAGE_FILE_HEADER.SizeOfOptionalHeader == 0; * and IMAGE_FILE_HEADER.SizeOfOptionalHeader == 0;
*/ */
DumpObjFile((PIMAGE_FILE_HEADER) lpFileBase, fout); DumpSymbols<IMAGE_FILE_HEADER, IMAGE_SYMBOL>
symbolDumper((PIMAGE_FILE_HEADER) lpFileBase, fout);
symbolDumper.DumpObjFile();
} else {
// check for /bigobj format
cmANON_OBJECT_HEADER_BIGOBJ* h =
(cmANON_OBJECT_HEADER_BIGOBJ*) lpFileBase;
if(h->Sig1 == 0x0 && h->Sig2 == 0xffff) {
DumpSymbols<cmANON_OBJECT_HEADER_BIGOBJ, cmIMAGE_SYMBOL_EX>
symbolDumper((cmANON_OBJECT_HEADER_BIGOBJ*) lpFileBase, fout);
symbolDumper.DumpObjFile();
} else { } else {
printf("unrecognized file format in '%s'\n", filename); printf("unrecognized file format in '%s'\n", filename);
return false; return false;
} }
}
UnmapViewOfFile(lpFileBase); UnmapViewOfFile(lpFileBase);
CloseHandle(hFileMapping); CloseHandle(hFileMapping);
CloseHandle(hFile); CloseHandle(hFile);