De-duplicate symbols listed in generated module definition files

MS tools have a limit on the number of symbols that can be listed
in a `.def` file.  If multiple `.obj` files provide a symbol then
avoid listing it more than once in the generated `.def` file to
avoid counting toward the limit.
This commit is contained in:
Bill Hoffman 2015-11-16 15:31:10 -05:00 committed by Brad King
parent 30b0db7bb5
commit 1c1ace2db0
3 changed files with 75 additions and 23 deletions

View File

@ -70,7 +70,7 @@
* Author: Valery Fine 16/09/96 (E-mail: fine@vxcern.cern.ch) * Author: Valery Fine 16/09/96 (E-mail: fine@vxcern.cern.ch)
*---------------------------------------------------------------------- *----------------------------------------------------------------------
*/ */
#include "bindexplib.h"
#include <cmsys/Encoding.hxx> #include <cmsys/Encoding.hxx>
#include <windows.h> #include <windows.h>
#include <stdio.h> #include <stdio.h>
@ -173,15 +173,17 @@ public:
*/ */
DumpSymbols(ObjectHeaderType* ih, DumpSymbols(ObjectHeaderType* ih,
FILE* fout, bool is64) { std::set<std::string>& symbols,
std::set<std::string>& dataSymbols,
bool is64)
:Symbols(symbols), DataSymbols(dataSymbols)
{
this->ObjectImageHeader = ih; this->ObjectImageHeader = ih;
this->SymbolTable = (SymbolTableType*) this->SymbolTable = (SymbolTableType*)
((DWORD_PTR)this->ObjectImageHeader ((DWORD_PTR)this->ObjectImageHeader
+ this->ObjectImageHeader->PointerToSymbolTable); + this->ObjectImageHeader->PointerToSymbolTable);
this->FileOut = fout;
this->SectionHeaders = this->SectionHeaders =
GetSectionHeaderOffset(this->ObjectImageHeader); GetSectionHeaderOffset(this->ObjectImageHeader);
this->ImportFlag = true;
this->SymbolCount = this->ObjectImageHeader->NumberOfSymbols; this->SymbolCount = this->ObjectImageHeader->NumberOfSymbols;
this->Is64Bit = is64; this->Is64Bit = is64;
} }
@ -296,10 +298,6 @@ public:
symbol.erase(0,1); symbol.erase(0,1);
} }
} }
if (this->ImportFlag) {
this->ImportFlag = false;
fprintf(this->FileOut,"EXPORTS \n");
}
/* /*
Check whether it is "Scalar deleting destructor" and Check whether it is "Scalar deleting destructor" and
"Vector deleting destructor" "Vector deleting destructor"
@ -319,11 +317,11 @@ public:
SectionHeaders[pSymbolTable->SectionNumber-1].Characteristics; 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(this->FileOut, "\t%s \t DATA\n", symbol.c_str()); this->DataSymbols.insert(symbol);
} else { } else {
if ( pSymbolTable->Type || if ( pSymbolTable->Type ||
!(SectChar & IMAGE_SCN_MEM_READ)) { !(SectChar & IMAGE_SCN_MEM_READ)) {
fprintf(this->FileOut, "\t%s\n", symbol.c_str()); this->Symbols.insert(symbol);
} else { } else {
// printf(" strange symbol: %s \n",symbol.c_str()); // printf(" strange symbol: %s \n",symbol.c_str());
} }
@ -340,11 +338,7 @@ public:
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 (!this->ImportFlag) { this->DataSymbols.insert(symbol);
this->ImportFlag = true;
fprintf(this->FileOut,"IMPORTS \n");
}
fprintf(this->FileOut, "\t%s DATA \n", symbol.c_str()+1);
} }
} }
@ -357,8 +351,8 @@ public:
} }
} }
private: private:
bool ImportFlag; std::set<std::string>& Symbols;
FILE* FileOut; std::set<std::string>& DataSymbols;
DWORD_PTR SymbolCount; DWORD_PTR SymbolCount;
PIMAGE_SECTION_HEADER SectionHeaders; PIMAGE_SECTION_HEADER SectionHeaders;
ObjectHeaderType* ObjectImageHeader; ObjectHeaderType* ObjectImageHeader;
@ -367,7 +361,9 @@ private:
}; };
bool bool
DumpFile(const char* filename, FILE *fout) DumpFile(const char* filename,
std::set<std::string>& symbols,
std::set<std::string>& dataSymbols)
{ {
HANDLE hFile; HANDLE hFile;
HANDLE hFileMapping; HANDLE hFileMapping;
@ -415,7 +411,7 @@ DumpFile(const char* filename, FILE *fout)
* and IMAGE_FILE_HEADER.SizeOfOptionalHeader == 0; * and IMAGE_FILE_HEADER.SizeOfOptionalHeader == 0;
*/ */
DumpSymbols<IMAGE_FILE_HEADER, IMAGE_SYMBOL> DumpSymbols<IMAGE_FILE_HEADER, IMAGE_SYMBOL>
symbolDumper((PIMAGE_FILE_HEADER) lpFileBase, fout, symbolDumper((PIMAGE_FILE_HEADER) lpFileBase, symbols, dataSymbols,
(dosHeader->e_magic == IMAGE_FILE_MACHINE_AMD64)); (dosHeader->e_magic == IMAGE_FILE_MACHINE_AMD64));
symbolDumper.DumpObjFile(); symbolDumper.DumpObjFile();
} else { } else {
@ -424,7 +420,8 @@ DumpFile(const char* filename, FILE *fout)
(cmANON_OBJECT_HEADER_BIGOBJ*) lpFileBase; (cmANON_OBJECT_HEADER_BIGOBJ*) lpFileBase;
if(h->Sig1 == 0x0 && h->Sig2 == 0xffff) { if(h->Sig1 == 0x0 && h->Sig2 == 0xffff) {
DumpSymbols<cmANON_OBJECT_HEADER_BIGOBJ, cmIMAGE_SYMBOL_EX> DumpSymbols<cmANON_OBJECT_HEADER_BIGOBJ, cmIMAGE_SYMBOL_EX>
symbolDumper((cmANON_OBJECT_HEADER_BIGOBJ*) lpFileBase, fout, symbolDumper((cmANON_OBJECT_HEADER_BIGOBJ*) lpFileBase, symbols,
dataSymbols,
(dosHeader->e_magic == IMAGE_FILE_MACHINE_AMD64)); (dosHeader->e_magic == IMAGE_FILE_MACHINE_AMD64));
symbolDumper.DumpObjFile(); symbolDumper.DumpObjFile();
} else { } else {
@ -437,3 +434,27 @@ DumpFile(const char* filename, FILE *fout)
CloseHandle(hFile); CloseHandle(hFile);
return true; return true;
} }
bool bindexplib::AddObjectFile(const char* filename)
{
if(!DumpFile(filename, this->Symbols, this->DataSymbols))
{
return false;
}
return true;
}
void bindexplib::WriteFile(FILE* file)
{
fprintf(file,"EXPORTS \n");
for(std::set<std::string>::const_iterator i = this->DataSymbols.begin();
i!= this->DataSymbols.end(); ++i)
{
fprintf(file, "\t%s \t DATA\n", i->c_str());
}
for(std::set<std::string>::const_iterator i = this->Symbols.begin();
i!= this->Symbols.end(); ++i)
{
fprintf(file, "\t%s\n", i->c_str());
}
}

29
Source/bindexplib.h Normal file
View File

@ -0,0 +1,29 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
#ifndef bindexplib_h
#define bindexplib_h
#include "cmStandardIncludes.h"
class bindexplib
{
public:
bindexplib() {}
bool AddObjectFile(const char* filename);
void WriteFile(FILE* file);
private:
std::set<std::string> Symbols;
std::set<std::string> DataSymbols;
};
#endif

View File

@ -35,8 +35,7 @@
#include <stdlib.h> // required for atoi #include <stdlib.h> // required for atoi
#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE) #if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE)
// defined in binexplib.cxx #include "bindexplib.h"
bool DumpFile(const char* filename, FILE *fout);
#endif #endif
void CMakeCommandUsage(const char* program) void CMakeCommandUsage(const char* program)
@ -240,13 +239,16 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
return 1; return 1;
} }
std::string objfile; std::string objfile;
bindexplib deffile;
while(cmSystemTools::GetLineFromStream(fin, objfile)) while(cmSystemTools::GetLineFromStream(fin, objfile))
{ {
if (!DumpFile(objfile.c_str(), fout)) if( !deffile.AddObjectFile(objfile.c_str()))
{ {
return 1; return 1;
} }
} }
deffile.WriteFile(fout);
fclose(fout);
return 0; return 0;
} }
#endif #endif