From 65086ad778b5d8312e4168fc5ed670e545be7d4b Mon Sep 17 00:00:00 2001 From: Bill Hoffman Date: Fri, 19 Jun 2015 16:12:43 -0400 Subject: bindexplib: Import original implementation from CERN Download the original implementation provided by root.cern.ch with the following session: $ wget https://raw.githubusercontent.com/gordonwatts/root-vc-port/f0ee59af/build/win/bindexplib/bindexplib.cxx $ sha1sum bindexplib.cxx fa6efafb2c58a0644bd0f6a56fe02ee0d55c7fcd bindexplib.cxx $ sed -i 's/ *$//;s/'$'\t''/ /' bindexplib.cxx --- Source/bindexplib.cxx | 739 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 739 insertions(+) create mode 100644 Source/bindexplib.cxx diff --git a/Source/bindexplib.cxx b/Source/bindexplib.cxx new file mode 100644 index 0000000..6f9605c --- /dev/null +++ b/Source/bindexplib.cxx @@ -0,0 +1,739 @@ +/* +*---------------------------------------------------------------------- +* Program: dumpexts.exe +* Author: Gordon Chaffee +* +* History: The real functionality of this file was written by +* Matt Pietrek in 1993 in his pedump utility. I've +* modified it to dump the externals in a bunch of object +* files to create a .def file. +* +* Notes: Visual C++ puts an underscore before each exported symbol. +* This file removes them. I don't know if this is a problem +* this other compilers. If _MSC_VER is defined, +* the underscore is removed. If not, it isn't. To get a +* full dump of an object file, use the -f option. This can +* help determine the something that may be different with a +* compiler other than Visual C++. +* ====================================== +* Corrections (Axel 2006-04-04): +* Conversion to C++. Mostly. +* + * Extension (Axel 2006-03-15) + * As soon as an object file contains an /EXPORT directive (which + * is generated by the compiler when a symbol is declared as + * declspec(dllexport)) no to-be-exported symbols are printed, + * as the linker will see these directives, and if those directives + * are present we only export selectively (i.e. we trust the + * programmer). + * + * ====================================== +* ====================================== +* Corrections (Valery Fine 23/02/98): +* +* The "(vector) deleting destructor" MUST not be exported +* To recognize it the following test are introduced: +* "@@UAEPAXI@Z" scalar deleting dtor +* "@@QAEPAXI@Z" vector deleting dtor +* "AEPAXI@Z" vector deleting dtor with thunk adjustor +* ====================================== +* Corrections (Valery Fine 12/02/97): +* +* It created a wrong EXPORTS for the global pointers and constants. +* The Section Header has been involved to discover the missing information +* Now the pointers are correctly supplied supplied with "DATA" descriptor +* the constants with no extra descriptor. +* +* Corrections (Valery Fine 16/09/96): +* +* It didn't work for C++ code with global variables and class definitons +* The DumpExternalObject function has been introduced to generate .DEF file +* +* Author: Valery Fine 16/09/96 (E-mail: fine@vxcern.cern.ch) +*---------------------------------------------------------------------- +*/ + +static char sccsid[] = "@(#) winDumpExts.c 1.2 95/10/03 15:27:34"; + +#include +#include +#include +#include + +/* +*---------------------------------------------------------------------- +* GetArgcArgv -- +* +* Break up a line into argc argv +*---------------------------------------------------------------------- +*/ +int +GetArgcArgv(std::string &s, char **argv) +{ + int quote = 0; + int argc = 0; + std::string::iterator bp = s.begin(); + + while (1) { + while (isspace(*bp)) { + bp++; + } + if (*bp == '\n' || *bp == '\0') { + *bp = '\0'; + return argc; + } + if (*bp == '\"') { + quote = 1; + bp++; + } + argv[argc++] = &(*bp); + + while (*bp != '\0') { + if (quote) { + if (*bp == '\"') { + quote = 0; + *bp = '\0'; + bp++; + break; + } + bp++; + continue; + } + if (isspace(*bp)) { + *bp = '\0'; + bp++; + break; + } + bp++; + } + } +} + +/* +* 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" +}; + +/* +*---------------------------------------------------------------------- +* GetSZStorageClass -- +* +* 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 "???"; +} + +void AddHex(std::string& buf, long val, bool caps=false) +{ + buf += "0x"; + size_t len=buf.length(); + while (val) { + char hex = (char)(val & 16); + val = val >> 4; + if (hex<10) hex+='0'; + else if (caps) hex+='A'-10; + else hex+='a'-10; + buf.insert(len, hex, 1); + } +} + +/* +*---------------------------------------------------------------------- +* GetSectionName -- +* +* Used by DumpSymbolTable, it gives meaningful names to +* the non-normal section number. +* +* Results: +* A name is returned in buffer +*---------------------------------------------------------------------- +*/ +void +GetSectionName(PIMAGE_SYMBOL pSymbolTable, std::string& buffer) +{ + DWORD section; + + section = pSymbolTable->SectionNumber; + + switch ( (SHORT)section ) + { + case IMAGE_SYM_UNDEFINED: if (pSymbolTable->Value) buffer += "COMM"; else buffer += "UNDEF"; break; + case IMAGE_SYM_ABSOLUTE: buffer += "ABS "; break; + case IMAGE_SYM_DEBUG: buffer += "DEBUG"; break; + default: AddHex(buffer, section, true); + } +} + +/* +*---------------------------------------------------------------------- +* GetSectionCharacteristics -- +* +* Converts the Characteristics field of IMAGE_SECTION_HEADER +* to print. +* +* Results: +* A definiton of the section symbol type +*---------------------------------------------------------------------- +*/ +void +GetSectionCharacteristics(PIMAGE_SECTION_HEADER pSectionHeaders, int nSectNum, std::string &buffer) +{ + DWORD SectChar; + std::string TempBuf; + buffer.clear(); + if (nSectNum > 0) { + SectChar = pSectionHeaders[nSectNum-1].Characteristics; + + buffer = " "; + AddHex(buffer, SectChar); + if (SectChar & IMAGE_SCN_CNT_CODE) buffer += " Code"; + else if (SectChar & IMAGE_SCN_CNT_INITIALIZED_DATA) buffer += " Init. data"; + else if (SectChar & IMAGE_SCN_CNT_UNINITIALIZED_DATA ) buffer += " UnInit data"; + else buffer += " Unknow type"; + + if (SectChar & IMAGE_SCN_MEM_READ) { + buffer += " Read"; + if (SectChar & IMAGE_SCN_MEM_WRITE) + buffer += " and Write"; + else buffer += " only"; + } + else if (SectChar & IMAGE_SCN_MEM_WRITE) + buffer +=" Write only"; + + } +} + +/* +*---------------------------------------------------------------------- +* DumpSymbolTable -- +* +* Dumps a COFF symbol table from an EXE or OBJ. We only use +* it to dump tables from OBJs. +*---------------------------------------------------------------------- +*/ +void +DumpSymbolTable(PIMAGE_SYMBOL pSymbolTable, PIMAGE_SECTION_HEADER pSectionHeaders, FILE *fout, unsigned cSymbols) +{ + unsigned i; + PSTR stringTable; + std::string sectionName; + std::string sectionCharacter; + int iSectNum; + + fprintf(fout, "Symbol Table - %X entries (* = auxillary symbol)\n", + cSymbols); + + fprintf(fout, + "Indx Name Value Section cAux Type Storage Character\n" + "---- -------------------- -------- ---------- ----- ------- -------- ---------\n"); + + /* + * The string table apparently starts right after the symbol table + */ + stringTable = (PSTR)&pSymbolTable[cSymbols]; + + for ( i=0; i < cSymbols; i++ ) { + fprintf(fout, "%04X ", i); + if ( pSymbolTable->N.Name.Short != 0 ) + fprintf(fout, "%-20.8s", pSymbolTable->N.ShortName); + else + fprintf(fout, "%-20s", stringTable + pSymbolTable->N.Name.Long); + + fprintf(fout, " %08X", pSymbolTable->Value); + + iSectNum = pSymbolTable->SectionNumber; + GetSectionName(pSymbolTable, sectionName); + fprintf(fout, " sect:%s aux:%X type:%02X st:%s", + sectionName.c_str(), + pSymbolTable->NumberOfAuxSymbols, + pSymbolTable->Type, + GetSZStorageClass(pSymbolTable->StorageClass) ); + + GetSectionCharacteristics(pSectionHeaders,iSectNum,sectionCharacter); + fprintf(fout," hc: %s \n",sectionCharacter.c_str()); +#if 0 + if ( pSymbolTable->NumberOfAuxSymbols ) + DumpAuxSymbols(pSymbolTable); +#endif + + /* + * Take into account any aux symbols + */ + i += pSymbolTable->NumberOfAuxSymbols; + pSymbolTable += pSymbolTable->NumberOfAuxSymbols; + pSymbolTable++; + } +} + +/* +*---------------------------------------------------------------------- +* DumpExternals -- +* +* Dumps a COFF symbol table from an EXE or OBJ. We only use +* it to dump tables from OBJs. +*---------------------------------------------------------------------- +*/ +void +DumpExternals(PIMAGE_SYMBOL pSymbolTable, FILE *fout, unsigned cSymbols) +{ + unsigned i; + PSTR stringTable; + std::string symbol; + + /* + * The string table apparently starts right after the symbol table + */ + stringTable = (PSTR)&pSymbolTable[cSymbols]; + + for ( i=0; i < cSymbols; i++ ) { + if (pSymbolTable->SectionNumber > 0 && pSymbolTable->Type == 0x20) { + if (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) { + if (pSymbolTable->N.Name.Short != 0) { + symbol = ""; + symbol.insert(0, (const char *)(pSymbolTable->N.ShortName), 8); + } else { + symbol = stringTable + pSymbolTable->N.Name.Long; + } + std::string::size_type posAt = symbol.find('@'); + if (posAt != std::string::npos) symbol.erase(posAt); +#ifndef _MSC_VER + fprintf(fout, "\t%s\n", symbol.c_str()); +#else + fprintf(fout, "\t%s\n", symbol.c_str()+1); +#endif + } + } + + /* + * Take into account any aux symbols + */ + i += pSymbolTable->NumberOfAuxSymbols; + pSymbolTable += pSymbolTable->NumberOfAuxSymbols; + pSymbolTable++; + } +} + +/* ++ * Utility func, strstr with size ++ */ +const char* StrNStr(const char* start, const char* find, size_t &size) { + size_t len; + const char* hint; + + if (!start || !find || !size) { + size = 0; + return 0; + } + len = strlen(find); + + while (hint = (const char*) memchr(start, find[0], size-len+1)) { + size -= (hint - start); + if (!strncmp(hint, find, len)) + return hint; + start = hint + 1; + } + + size = 0; + return 0; +} + +/* + *---------------------------------------------------------------------- + * HaveExportedObjects -- + * + * Returns >0 if export directives (declspec(dllexport)) exist. + * + *---------------------------------------------------------------------- + */ +int +HaveExportedObjects(PIMAGE_FILE_HEADER pImageFileHeader, PIMAGE_SECTION_HEADER pSectionHeaders, FILE *fout) +{ + static int fImportFlag = 0; /* The status is nor defined yet */ + WORD i; + size_t size; + char foundExports; + const char * rawdata; + + PIMAGE_SECTION_HEADER pDirectivesSectionHeader; + + if (fImportFlag) return 1; + + i = 0; + foundExports = 0; + pDirectivesSectionHeader = 0; + for(i = 0; i < pImageFileHeader->NumberOfSections && !pDirectivesSectionHeader; i++) + if (!strncmp((const char*)&pSectionHeaders[i].Name[0], ".drectve",8)) + pDirectivesSectionHeader = &pSectionHeaders[i]; + if (!pDirectivesSectionHeader) return 0; + + rawdata=(const char*)pImageFileHeader+pDirectivesSectionHeader->PointerToRawData; + if (!pDirectivesSectionHeader->PointerToRawData || !rawdata) return 0; + + 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)) { + posImportFlag = lookingForDict; + continue; + } + + const char* lookingForDATA = posImportFlag + 9; + while (*(++lookingForDATA) && *lookingForDATA != ' '); + lookingForDATA -= 5; + // ignore DATA exports + if (strncmp(lookingForDATA, ",DATA", 5)) break; + posImportFlag = lookingForDATA + 5; + } + fImportFlag = (int)posImportFlag; + return fImportFlag; +} + + + +/* + *---------------------------------------------------------------------- +* 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, unsigned cSymbols, int fort) +{ + 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 + */ + stringTable = (PSTR)&pSymbolTable[cSymbols]; + + for ( i=0; i < cSymbols; i++ ) { + if (pSymbolTable->SectionNumber > 0 && ( pSymbolTable->Type == 0x20 || pSymbolTable->Type == 0x0)) { + if (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) { + /* + * The name of the Function entry points + */ + if (pSymbolTable->N.Name.Short != 0) { + symbol = ""; + symbol.insert(0, (const char *)pSymbolTable->N.ShortName, 8); + } else { + symbol = stringTable + pSymbolTable->N.Name.Long; + } + + while (isspace(symbol[0])) symbol.erase(0,1); +#ifdef _MSC_VER + if (symbol[0] == '_') symbol.erase(0,1); + if (fort) { + std::string::size_type posAt = symbol.find('@'); + if (posAt != std::string::npos) symbol.erase(posAt); + } +#endif + if (fImportFlag) { + fImportFlag = 0; + fprintf(fout,"EXPORTS \n"); + } + /* + Check whether it is "Scalar deleting destructor" and + "Vector deleting destructor" + */ + /* + if (!strstr(s,"@@UAEPAXI@Z") && !strstr(s,"@@QAEPAXI@Z") && + !strstr(s,"@AEPAXI@Z") && !strstr(s,"AEPAXI@Z") && + !strstr(s,"real@")) + */ + const char *scalarPrefix = "??_G"; + const char *vectorPrefix = "??_E"; + if (symbol.compare(0, 4, scalarPrefix) && + symbol.compare(0, 4, vectorPrefix) && + symbol.find("real@") == std::string::npos) + { + SectChar = pSectionHeaders[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()); + } else { + if ( pSymbolTable->Type || !(SectChar & IMAGE_SCN_MEM_READ)) { + fprintf(fout, "\t%s\n", symbol.c_str()); + } else { + // printf(" strange symbol: %s \n",s); + } + } + } + } + } + else if (pSymbolTable->SectionNumber == IMAGE_SYM_UNDEFINED && !pSymbolTable->Type && 0){ + /* + * The IMPORT global variable entry points + */ + if (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) { + 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"); + } + fprintf(fout, "\t%s DATA \n", symbol.c_str()+1); + } + } + + /* + * Take into account any aux symbols + */ + 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, int full, int fort) +{ + 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); + + + if (full) { + DumpSymbolTable(PCOFFSymbolTable, PCOFFSectionHeaders, fout, COFFSymbolCount); + } else { + int haveExports = HaveExportedObjects(pImageFileHeader, PCOFFSectionHeaders, fout); + if (!haveExports) + DumpExternalsObjects(PCOFFSymbolTable, PCOFFSectionHeaders, fout, COFFSymbolCount, fort); + } +} + +/* +*---------------------------------------------------------------------- +* DumpFile -- +* +* Open up a file, memory map it, and call the appropriate +* dumping routine +*---------------------------------------------------------------------- +*/ +void +DumpFile(LPSTR filename, FILE *fout, int full, int fort) +{ + 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) { + fprintf(stderr, "Couldn't open file with CreateFile()\n"); + return; + } + + hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); + if (hFileMapping == 0) { + CloseHandle(hFile); + fprintf(stderr, "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); + fprintf(stderr, "Couldn't map view of file with MapViewOfFile()\n"); + return; + } + + dosHeader = (PIMAGE_DOS_HEADER)lpFileBase; + if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE) { +#if 0 + DumpExeFile( dosHeader ); +#else + fprintf(stderr, "File is an executable. I don't dump those.\n"); + return; +#endif + } + /* Does it look like a i386 COFF OBJ file??? */ + else if ( + ((dosHeader->e_magic == IMAGE_FILE_MACHINE_I386) || (dosHeader->e_magic == IMAGE_FILE_MACHINE_AMD64)) + && (dosHeader->e_sp == 0) + ) { + /* + * 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, fout, full, fort); + } else { + printf("unrecognized file format\n"); + } + UnmapViewOfFile(lpFileBase); + CloseHandle(hFileMapping); + CloseHandle(hFile); +} + +void +main(int argc, char **argv) +{ + std::string cmdline; + int i, arg; + FILE *fout; + int full = 0; + int fort = 0; + char *dllname = ""; + char *outfile = NULL; + + if (argc < 3) { +Usage: + fprintf(stderr, "Usage: %s ?-o outfile? ?-f(ull)? ..\n", argv[0]); + exit(1); + } + + arg = 1; + while (argv[arg][0] == '-') { + if (strcmp(argv[arg], "--") == 0) { + arg++; + break; + } else if (strcmp(argv[arg], "-f") == 0) { + full = 1; + } else if (strcmp(argv[arg], "-x") == 0) { + fort = 1; + } else if (strcmp(argv[arg], "-o") == 0) { + arg++; + if (arg == argc) { + goto Usage; + } + outfile = argv[arg]; + } + arg++; + } + if (arg == argc) { + goto Usage; + } + + if (outfile) { + fout = fopen(outfile, "w+"); + if (fout == NULL) { + fprintf(stderr, "Unable to open \'%s\' for writing:\n", + argv[arg]); + perror(""); + exit(1); + } + } else { + fout = stdout; + } + + if (! full) { + dllname = argv[arg]; + arg++; + if (arg == argc) { + goto Usage; + } + fprintf(fout, "LIBRARY %s\n", dllname); +#ifndef _X86_ + fprintf(fout, "CODE PRELOAD MOVEABLE DISCARDABLE\n"); + fprintf(fout, "DATA PRELOAD MOVEABLE MULTIPLE\n\n"); +#endif + } + + for (; arg < argc; arg++) { + WIN32_FIND_DATA FindFileData; + HANDLE SearchFile; + if (argv[arg][0] == '@') { + std::ifstream fargs(&argv[arg][1]); + if (!fargs) { + fprintf(stderr, "Unable to open \'%s\' for reading:\n", + argv[arg]); + perror(""); + exit(1); + } + char *fargv[1000]; + for (i = 0; i < arg; i++) { + cmdline += argv[i]; + fargv[i] = argv[i]; + } + std::string line; + std::getline(fargs, line); + cmdline += line; + fprintf(stderr, "%s\n", line.c_str()); + i += GetArgcArgv(line, &fargv[i]); + argc = i; + argv = fargv; + } + /* + * Argument can contain the wildcard names + */ + SearchFile = FindFirstFile(argv[arg],&FindFileData); + if (SearchFile == INVALID_HANDLE_VALUE){ + fprintf(stderr, "Unable to find \'%s\' for reading:\n", + argv[arg]); + exit(1); + } + else { + /* + * Since WIN32_FIND_DATA has no path information one has to extract it himself. + */ + TCHAR *filename = argv[arg]; + TCHAR path[2048]; + size_t i = strlen(filename); + i--; + while( filename[i] != '\\' && filename[i] != '/' && i >=0) i--; + do + { + if (i >= 0) strncpy( path, filename, i+1); /* Generate the 'path' info */ + path[i+1] = '\0'; + DumpFile(strcat(path, FindFileData.cFileName), fout, full, fort); + } while (FindNextFile(SearchFile,&FindFileData)); + + + FindClose(SearchFile); + } + } + exit(0); +} -- cgit v0.12 From 7de8276ca92db0630009eeab865afc445a30e1b8 Mon Sep 17 00:00:00 2001 From: Bill Hoffman Date: Fri, 19 Jun 2015 16:12:43 -0400 Subject: bindexplib: Add copyright/license notice block --- Source/bindexplib.cxx | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Source/bindexplib.cxx b/Source/bindexplib.cxx index 6f9605c..a86318f 100644 --- a/Source/bindexplib.cxx +++ b/Source/bindexplib.cxx @@ -1,3 +1,21 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2015 Kitware, Inc. + + 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. +============================================================================*/ +/*------------------------------------------------------------------------- + Portions of this source have been derived from the 'bindexplib' tool + provided by the CERN ROOT Data Analysis Framework project (root.cern.ch). + Permission has been granted by Pere Mato to distribute + this derived work under the CMake license. +-------------------------------------------------------------------------*/ + /* *---------------------------------------------------------------------- * Program: dumpexts.exe -- cgit v0.12 From 4ff09893232b26b5c2961fb1e2a31836cad00a35 Mon Sep 17 00:00:00 2001 From: Bill Hoffman Date: Fri, 19 Jun 2015 16:12:43 -0400 Subject: bindexplib: Drop code that CMake does not need --- Source/bindexplib.cxx | 433 +------------------------------------------------- 1 file changed, 8 insertions(+), 425 deletions(-) diff --git a/Source/bindexplib.cxx b/Source/bindexplib.cxx index a86318f..33f8161 100644 --- a/Source/bindexplib.cxx +++ b/Source/bindexplib.cxx @@ -71,290 +71,12 @@ *---------------------------------------------------------------------- */ -static char sccsid[] = "@(#) winDumpExts.c 1.2 95/10/03 15:27:34"; - #include #include #include #include /* -*---------------------------------------------------------------------- -* GetArgcArgv -- -* -* Break up a line into argc argv -*---------------------------------------------------------------------- -*/ -int -GetArgcArgv(std::string &s, char **argv) -{ - int quote = 0; - int argc = 0; - std::string::iterator bp = s.begin(); - - while (1) { - while (isspace(*bp)) { - bp++; - } - if (*bp == '\n' || *bp == '\0') { - *bp = '\0'; - return argc; - } - if (*bp == '\"') { - quote = 1; - bp++; - } - argv[argc++] = &(*bp); - - while (*bp != '\0') { - if (quote) { - if (*bp == '\"') { - quote = 0; - *bp = '\0'; - bp++; - break; - } - bp++; - continue; - } - if (isspace(*bp)) { - *bp = '\0'; - bp++; - break; - } - bp++; - } - } -} - -/* -* 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" -}; - -/* -*---------------------------------------------------------------------- -* GetSZStorageClass -- -* -* 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 "???"; -} - -void AddHex(std::string& buf, long val, bool caps=false) -{ - buf += "0x"; - size_t len=buf.length(); - while (val) { - char hex = (char)(val & 16); - val = val >> 4; - if (hex<10) hex+='0'; - else if (caps) hex+='A'-10; - else hex+='a'-10; - buf.insert(len, hex, 1); - } -} - -/* -*---------------------------------------------------------------------- -* GetSectionName -- -* -* Used by DumpSymbolTable, it gives meaningful names to -* the non-normal section number. -* -* Results: -* A name is returned in buffer -*---------------------------------------------------------------------- -*/ -void -GetSectionName(PIMAGE_SYMBOL pSymbolTable, std::string& buffer) -{ - DWORD section; - - section = pSymbolTable->SectionNumber; - - switch ( (SHORT)section ) - { - case IMAGE_SYM_UNDEFINED: if (pSymbolTable->Value) buffer += "COMM"; else buffer += "UNDEF"; break; - case IMAGE_SYM_ABSOLUTE: buffer += "ABS "; break; - case IMAGE_SYM_DEBUG: buffer += "DEBUG"; break; - default: AddHex(buffer, section, true); - } -} - -/* -*---------------------------------------------------------------------- -* GetSectionCharacteristics -- -* -* Converts the Characteristics field of IMAGE_SECTION_HEADER -* to print. -* -* Results: -* A definiton of the section symbol type -*---------------------------------------------------------------------- -*/ -void -GetSectionCharacteristics(PIMAGE_SECTION_HEADER pSectionHeaders, int nSectNum, std::string &buffer) -{ - DWORD SectChar; - std::string TempBuf; - buffer.clear(); - if (nSectNum > 0) { - SectChar = pSectionHeaders[nSectNum-1].Characteristics; - - buffer = " "; - AddHex(buffer, SectChar); - if (SectChar & IMAGE_SCN_CNT_CODE) buffer += " Code"; - else if (SectChar & IMAGE_SCN_CNT_INITIALIZED_DATA) buffer += " Init. data"; - else if (SectChar & IMAGE_SCN_CNT_UNINITIALIZED_DATA ) buffer += " UnInit data"; - else buffer += " Unknow type"; - - if (SectChar & IMAGE_SCN_MEM_READ) { - buffer += " Read"; - if (SectChar & IMAGE_SCN_MEM_WRITE) - buffer += " and Write"; - else buffer += " only"; - } - else if (SectChar & IMAGE_SCN_MEM_WRITE) - buffer +=" Write only"; - - } -} - -/* -*---------------------------------------------------------------------- -* DumpSymbolTable -- -* -* Dumps a COFF symbol table from an EXE or OBJ. We only use -* it to dump tables from OBJs. -*---------------------------------------------------------------------- -*/ -void -DumpSymbolTable(PIMAGE_SYMBOL pSymbolTable, PIMAGE_SECTION_HEADER pSectionHeaders, FILE *fout, unsigned cSymbols) -{ - unsigned i; - PSTR stringTable; - std::string sectionName; - std::string sectionCharacter; - int iSectNum; - - fprintf(fout, "Symbol Table - %X entries (* = auxillary symbol)\n", - cSymbols); - - fprintf(fout, - "Indx Name Value Section cAux Type Storage Character\n" - "---- -------------------- -------- ---------- ----- ------- -------- ---------\n"); - - /* - * The string table apparently starts right after the symbol table - */ - stringTable = (PSTR)&pSymbolTable[cSymbols]; - - for ( i=0; i < cSymbols; i++ ) { - fprintf(fout, "%04X ", i); - if ( pSymbolTable->N.Name.Short != 0 ) - fprintf(fout, "%-20.8s", pSymbolTable->N.ShortName); - else - fprintf(fout, "%-20s", stringTable + pSymbolTable->N.Name.Long); - - fprintf(fout, " %08X", pSymbolTable->Value); - - iSectNum = pSymbolTable->SectionNumber; - GetSectionName(pSymbolTable, sectionName); - fprintf(fout, " sect:%s aux:%X type:%02X st:%s", - sectionName.c_str(), - pSymbolTable->NumberOfAuxSymbols, - pSymbolTable->Type, - GetSZStorageClass(pSymbolTable->StorageClass) ); - - GetSectionCharacteristics(pSectionHeaders,iSectNum,sectionCharacter); - fprintf(fout," hc: %s \n",sectionCharacter.c_str()); -#if 0 - if ( pSymbolTable->NumberOfAuxSymbols ) - DumpAuxSymbols(pSymbolTable); -#endif - - /* - * Take into account any aux symbols - */ - i += pSymbolTable->NumberOfAuxSymbols; - pSymbolTable += pSymbolTable->NumberOfAuxSymbols; - pSymbolTable++; - } -} - -/* -*---------------------------------------------------------------------- -* DumpExternals -- -* -* Dumps a COFF symbol table from an EXE or OBJ. We only use -* it to dump tables from OBJs. -*---------------------------------------------------------------------- -*/ -void -DumpExternals(PIMAGE_SYMBOL pSymbolTable, FILE *fout, unsigned cSymbols) -{ - unsigned i; - PSTR stringTable; - std::string symbol; - - /* - * The string table apparently starts right after the symbol table - */ - stringTable = (PSTR)&pSymbolTable[cSymbols]; - - for ( i=0; i < cSymbols; i++ ) { - if (pSymbolTable->SectionNumber > 0 && pSymbolTable->Type == 0x20) { - if (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) { - if (pSymbolTable->N.Name.Short != 0) { - symbol = ""; - symbol.insert(0, (const char *)(pSymbolTable->N.ShortName), 8); - } else { - symbol = stringTable + pSymbolTable->N.Name.Long; - } - std::string::size_type posAt = symbol.find('@'); - if (posAt != std::string::npos) symbol.erase(posAt); -#ifndef _MSC_VER - fprintf(fout, "\t%s\n", symbol.c_str()); -#else - fprintf(fout, "\t%s\n", symbol.c_str()+1); -#endif - } - } - - /* - * Take into account any aux symbols - */ - i += pSymbolTable->NumberOfAuxSymbols; - pSymbolTable += pSymbolTable->NumberOfAuxSymbols; - pSymbolTable++; - } -} - -/* + * Utility func, strstr with size + */ const char* StrNStr(const char* start, const char* find, size_t &size) { @@ -387,7 +109,7 @@ const char* StrNStr(const char* start, const char* find, size_t &size) { *---------------------------------------------------------------------- */ int -HaveExportedObjects(PIMAGE_FILE_HEADER pImageFileHeader, PIMAGE_SECTION_HEADER pSectionHeaders, FILE *fout) +HaveExportedObjects(PIMAGE_FILE_HEADER pImageFileHeader, PIMAGE_SECTION_HEADER pSectionHeaders) { static int fImportFlag = 0; /* The status is nor defined yet */ WORD i; @@ -443,7 +165,7 @@ HaveExportedObjects(PIMAGE_FILE_HEADER pImageFileHeader, PIMAGE_SECTION_HEADER p */ void DumpExternalsObjects(PIMAGE_SYMBOL pSymbolTable, PIMAGE_SECTION_HEADER pSectionHeaders, - FILE *fout, unsigned cSymbols, int fort) + FILE *fout, unsigned cSymbols) { unsigned i; PSTR stringTable; @@ -470,13 +192,7 @@ DumpExternalsObjects(PIMAGE_SYMBOL pSymbolTable, PIMAGE_SECTION_HEADER pSectionH } while (isspace(symbol[0])) symbol.erase(0,1); -#ifdef _MSC_VER if (symbol[0] == '_') symbol.erase(0,1); - if (fort) { - std::string::size_type posAt = symbol.find('@'); - if (posAt != std::string::npos) symbol.erase(posAt); - } -#endif if (fImportFlag) { fImportFlag = 0; fprintf(fout,"EXPORTS \n"); @@ -485,11 +201,6 @@ DumpExternalsObjects(PIMAGE_SYMBOL pSymbolTable, PIMAGE_SECTION_HEADER pSectionH Check whether it is "Scalar deleting destructor" and "Vector deleting destructor" */ - /* - if (!strstr(s,"@@UAEPAXI@Z") && !strstr(s,"@@QAEPAXI@Z") && - !strstr(s,"@AEPAXI@Z") && !strstr(s,"AEPAXI@Z") && - !strstr(s,"real@")) - */ const char *scalarPrefix = "??_G"; const char *vectorPrefix = "??_E"; if (symbol.compare(0, 4, scalarPrefix) && @@ -544,7 +255,7 @@ DumpExternalsObjects(PIMAGE_SYMBOL pSymbolTable, PIMAGE_SECTION_HEADER pSectionH *---------------------------------------------------------------------- */ void -DumpObjFile(PIMAGE_FILE_HEADER pImageFileHeader, FILE *fout, int full, int fort) +DumpObjFile(PIMAGE_FILE_HEADER pImageFileHeader, FILE *fout) { PIMAGE_SYMBOL PCOFFSymbolTable; PIMAGE_SECTION_HEADER PCOFFSectionHeaders; @@ -560,13 +271,9 @@ DumpObjFile(PIMAGE_FILE_HEADER pImageFileHeader, FILE *fout, int full, int fort) pImageFileHeader->SizeOfOptionalHeader); - if (full) { - DumpSymbolTable(PCOFFSymbolTable, PCOFFSectionHeaders, fout, COFFSymbolCount); - } else { - int haveExports = HaveExportedObjects(pImageFileHeader, PCOFFSectionHeaders, fout); - if (!haveExports) - DumpExternalsObjects(PCOFFSymbolTable, PCOFFSectionHeaders, fout, COFFSymbolCount, fort); - } + int haveExports = HaveExportedObjects(pImageFileHeader, PCOFFSectionHeaders); + if (!haveExports) + DumpExternalsObjects(PCOFFSymbolTable, PCOFFSectionHeaders, fout, COFFSymbolCount); } /* @@ -578,7 +285,7 @@ DumpObjFile(PIMAGE_FILE_HEADER pImageFileHeader, FILE *fout, int full, int fort) *---------------------------------------------------------------------- */ void -DumpFile(LPSTR filename, FILE *fout, int full, int fort) +DumpFile(LPSTR filename, FILE *fout) { HANDLE hFile; HANDLE hFileMapping; @@ -610,12 +317,8 @@ DumpFile(LPSTR filename, FILE *fout, int full, int fort) dosHeader = (PIMAGE_DOS_HEADER)lpFileBase; if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE) { -#if 0 - DumpExeFile( dosHeader ); -#else fprintf(stderr, "File is an executable. I don't dump those.\n"); return; -#endif } /* Does it look like a i386 COFF OBJ file??? */ else if ( @@ -627,7 +330,7 @@ DumpFile(LPSTR filename, FILE *fout, int full, int fort) * really checking for IMAGE_FILE_HEADER.Machine == i386 (0x14C) * and IMAGE_FILE_HEADER.SizeOfOptionalHeader == 0; */ - DumpObjFile((PIMAGE_FILE_HEADER) lpFileBase, fout, full, fort); + DumpObjFile((PIMAGE_FILE_HEADER) lpFileBase, fout); } else { printf("unrecognized file format\n"); } @@ -635,123 +338,3 @@ DumpFile(LPSTR filename, FILE *fout, int full, int fort) CloseHandle(hFileMapping); CloseHandle(hFile); } - -void -main(int argc, char **argv) -{ - std::string cmdline; - int i, arg; - FILE *fout; - int full = 0; - int fort = 0; - char *dllname = ""; - char *outfile = NULL; - - if (argc < 3) { -Usage: - fprintf(stderr, "Usage: %s ?-o outfile? ?-f(ull)? ..\n", argv[0]); - exit(1); - } - - arg = 1; - while (argv[arg][0] == '-') { - if (strcmp(argv[arg], "--") == 0) { - arg++; - break; - } else if (strcmp(argv[arg], "-f") == 0) { - full = 1; - } else if (strcmp(argv[arg], "-x") == 0) { - fort = 1; - } else if (strcmp(argv[arg], "-o") == 0) { - arg++; - if (arg == argc) { - goto Usage; - } - outfile = argv[arg]; - } - arg++; - } - if (arg == argc) { - goto Usage; - } - - if (outfile) { - fout = fopen(outfile, "w+"); - if (fout == NULL) { - fprintf(stderr, "Unable to open \'%s\' for writing:\n", - argv[arg]); - perror(""); - exit(1); - } - } else { - fout = stdout; - } - - if (! full) { - dllname = argv[arg]; - arg++; - if (arg == argc) { - goto Usage; - } - fprintf(fout, "LIBRARY %s\n", dllname); -#ifndef _X86_ - fprintf(fout, "CODE PRELOAD MOVEABLE DISCARDABLE\n"); - fprintf(fout, "DATA PRELOAD MOVEABLE MULTIPLE\n\n"); -#endif - } - - for (; arg < argc; arg++) { - WIN32_FIND_DATA FindFileData; - HANDLE SearchFile; - if (argv[arg][0] == '@') { - std::ifstream fargs(&argv[arg][1]); - if (!fargs) { - fprintf(stderr, "Unable to open \'%s\' for reading:\n", - argv[arg]); - perror(""); - exit(1); - } - char *fargv[1000]; - for (i = 0; i < arg; i++) { - cmdline += argv[i]; - fargv[i] = argv[i]; - } - std::string line; - std::getline(fargs, line); - cmdline += line; - fprintf(stderr, "%s\n", line.c_str()); - i += GetArgcArgv(line, &fargv[i]); - argc = i; - argv = fargv; - } - /* - * Argument can contain the wildcard names - */ - SearchFile = FindFirstFile(argv[arg],&FindFileData); - if (SearchFile == INVALID_HANDLE_VALUE){ - fprintf(stderr, "Unable to find \'%s\' for reading:\n", - argv[arg]); - exit(1); - } - else { - /* - * Since WIN32_FIND_DATA has no path information one has to extract it himself. - */ - TCHAR *filename = argv[arg]; - TCHAR path[2048]; - size_t i = strlen(filename); - i--; - while( filename[i] != '\\' && filename[i] != '/' && i >=0) i--; - do - { - if (i >= 0) strncpy( path, filename, i+1); /* Generate the 'path' info */ - path[i+1] = '\0'; - DumpFile(strcat(path, FindFileData.cFileName), fout, full, fort); - } while (FindNextFile(SearchFile,&FindFileData)); - - - FindClose(SearchFile); - } - } - exit(0); -} -- cgit v0.12 From 2963cb2a559fd27edd53b7fb7036cba0adc8b9ca Mon Sep 17 00:00:00 2001 From: Bill Hoffman Date: Fri, 19 Jun 2015 16:12:43 -0400 Subject: bindexplib: Wrap long lines --- Source/bindexplib.cxx | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/Source/bindexplib.cxx b/Source/bindexplib.cxx index 33f8161..8328213 100644 --- a/Source/bindexplib.cxx +++ b/Source/bindexplib.cxx @@ -109,7 +109,8 @@ const char* StrNStr(const char* start, const char* find, size_t &size) { *---------------------------------------------------------------------- */ int -HaveExportedObjects(PIMAGE_FILE_HEADER pImageFileHeader, PIMAGE_SECTION_HEADER pSectionHeaders) +HaveExportedObjects(PIMAGE_FILE_HEADER pImageFileHeader, + PIMAGE_SECTION_HEADER pSectionHeaders) { static int fImportFlag = 0; /* The status is nor defined yet */ WORD i; @@ -124,12 +125,14 @@ HaveExportedObjects(PIMAGE_FILE_HEADER pImageFileHeader, PIMAGE_SECTION_HEADER p i = 0; foundExports = 0; pDirectivesSectionHeader = 0; - for(i = 0; i < pImageFileHeader->NumberOfSections && !pDirectivesSectionHeader; i++) + for(i = 0; (i < pImageFileHeader->NumberOfSections && + !pDirectivesSectionHeader); i++) if (!strncmp((const char*)&pSectionHeaders[i].Name[0], ".drectve",8)) pDirectivesSectionHeader = &pSectionHeaders[i]; if (!pDirectivesSectionHeader) return 0; - rawdata=(const char*)pImageFileHeader+pDirectivesSectionHeader->PointerToRawData; + rawdata=(const char*) + pImageFileHeader+pDirectivesSectionHeader->PointerToRawData; if (!pDirectivesSectionHeader->PointerToRawData || !rawdata) return 0; size = pDirectivesSectionHeader->SizeOfRawData; @@ -164,7 +167,8 @@ HaveExportedObjects(PIMAGE_FILE_HEADER pImageFileHeader, PIMAGE_SECTION_HEADER p *---------------------------------------------------------------------- */ void -DumpExternalsObjects(PIMAGE_SYMBOL pSymbolTable, PIMAGE_SECTION_HEADER pSectionHeaders, +DumpExternalsObjects(PIMAGE_SYMBOL pSymbolTable, + PIMAGE_SECTION_HEADER pSectionHeaders, FILE *fout, unsigned cSymbols) { unsigned i; @@ -179,7 +183,8 @@ DumpExternalsObjects(PIMAGE_SYMBOL pSymbolTable, PIMAGE_SECTION_HEADER pSectionH stringTable = (PSTR)&pSymbolTable[cSymbols]; for ( i=0; i < cSymbols; i++ ) { - if (pSymbolTable->SectionNumber > 0 && ( pSymbolTable->Type == 0x20 || pSymbolTable->Type == 0x0)) { + if (pSymbolTable->SectionNumber > 0 && + ( pSymbolTable->Type == 0x20 || pSymbolTable->Type == 0x0)) { if (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) { /* * The name of the Function entry points @@ -207,12 +212,14 @@ DumpExternalsObjects(PIMAGE_SYMBOL pSymbolTable, PIMAGE_SECTION_HEADER pSectionH symbol.compare(0, 4, vectorPrefix) && symbol.find("real@") == std::string::npos) { - SectChar = pSectionHeaders[pSymbolTable->SectionNumber-1].Characteristics; + SectChar = + pSectionHeaders[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()); } else { - if ( pSymbolTable->Type || !(SectChar & IMAGE_SCN_MEM_READ)) { + if ( pSymbolTable->Type || + !(SectChar & IMAGE_SCN_MEM_READ)) { fprintf(fout, "\t%s\n", symbol.c_str()); } else { // printf(" strange symbol: %s \n",s); @@ -221,7 +228,8 @@ DumpExternalsObjects(PIMAGE_SYMBOL pSymbolTable, PIMAGE_SECTION_HEADER pSectionH } } } - else if (pSymbolTable->SectionNumber == IMAGE_SYM_UNDEFINED && !pSymbolTable->Type && 0){ + else if (pSymbolTable->SectionNumber == IMAGE_SYM_UNDEFINED && + !pSymbolTable->Type && 0) { /* * The IMPORT global variable entry points */ @@ -271,9 +279,11 @@ DumpObjFile(PIMAGE_FILE_HEADER pImageFileHeader, FILE *fout) pImageFileHeader->SizeOfOptionalHeader); - int haveExports = HaveExportedObjects(pImageFileHeader, PCOFFSectionHeaders); + int haveExports = HaveExportedObjects(pImageFileHeader, + PCOFFSectionHeaders); if (!haveExports) - DumpExternalsObjects(PCOFFSymbolTable, PCOFFSectionHeaders, fout, COFFSymbolCount); + DumpExternalsObjects(PCOFFSymbolTable, PCOFFSectionHeaders, + fout, COFFSymbolCount); } /* @@ -322,7 +332,8 @@ DumpFile(LPSTR filename, FILE *fout) } /* Does it look like a i386 COFF OBJ file??? */ else if ( - ((dosHeader->e_magic == IMAGE_FILE_MACHINE_I386) || (dosHeader->e_magic == IMAGE_FILE_MACHINE_AMD64)) + ((dosHeader->e_magic == IMAGE_FILE_MACHINE_I386) || + (dosHeader->e_magic == IMAGE_FILE_MACHINE_AMD64)) && (dosHeader->e_sp == 0) ) { /* -- cgit v0.12 From 8ea69dfef1e81a9811fe8a3d7198580dd21cb48f Mon Sep 17 00:00:00 2001 From: Bill Hoffman Date: Fri, 19 Jun 2015 16:12:43 -0400 Subject: bindexplib: Build source as part of CMakeLib --- Source/CMakeLists.txt | 1 + Source/bindexplib.cxx | 11 +++++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 6d012fd..069f283 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -430,6 +430,7 @@ if (WIN32) set(SRCS ${SRCS} cmCallVisualStudioMacro.cxx cmCallVisualStudioMacro.h + bindexplib.cxx ) if(NOT UNIX) diff --git a/Source/bindexplib.cxx b/Source/bindexplib.cxx index 8328213..f14d301 100644 --- a/Source/bindexplib.cxx +++ b/Source/bindexplib.cxx @@ -71,10 +71,12 @@ *---------------------------------------------------------------------- */ +#include #include #include #include #include +#include /* + * Utility func, strstr with size @@ -89,7 +91,7 @@ const char* StrNStr(const char* start, const char* find, size_t &size) { } len = strlen(find); - while (hint = (const char*) memchr(start, find[0], size-len+1)) { + while ((hint = (const char*) memchr(start, find[0], size-len+1))) { size -= (hint - start); if (!strncmp(hint, find, len)) return hint; @@ -169,7 +171,7 @@ HaveExportedObjects(PIMAGE_FILE_HEADER pImageFileHeader, void DumpExternalsObjects(PIMAGE_SYMBOL pSymbolTable, PIMAGE_SECTION_HEADER pSectionHeaders, - FILE *fout, unsigned cSymbols) + FILE *fout, DWORD_PTR cSymbols) { unsigned i; PSTR stringTable; @@ -295,14 +297,15 @@ DumpObjFile(PIMAGE_FILE_HEADER pImageFileHeader, FILE *fout) *---------------------------------------------------------------------- */ void -DumpFile(LPSTR filename, FILE *fout) +DumpFile(const char* filename, FILE *fout) { HANDLE hFile; HANDLE hFileMapping; LPVOID lpFileBase; PIMAGE_DOS_HEADER dosHeader; - hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, + hFile = CreateFileW(cmsys::Encoding::ToWide(filename).c_str(), + GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (hFile == INVALID_HANDLE_VALUE) { -- cgit v0.12 From de70c922d9c846cf3a6fabfbedd054c02f4b8934 Mon Sep 17 00:00:00 2001 From: Bill Hoffman Date: Fri, 19 Jun 2015 16:12:43 -0400 Subject: bindexplib: Teach DumpFile to return errors This will allow callers to know if it worked. --- Source/bindexplib.cxx | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/Source/bindexplib.cxx b/Source/bindexplib.cxx index f14d301..4024e2f 100644 --- a/Source/bindexplib.cxx +++ b/Source/bindexplib.cxx @@ -296,7 +296,8 @@ DumpObjFile(PIMAGE_FILE_HEADER pImageFileHeader, FILE *fout) * dumping routine *---------------------------------------------------------------------- */ -void + +bool DumpFile(const char* filename, FILE *fout) { HANDLE hFile; @@ -309,15 +310,15 @@ DumpFile(const char* filename, FILE *fout) OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (hFile == INVALID_HANDLE_VALUE) { - fprintf(stderr, "Couldn't open file with CreateFile()\n"); - return; + fprintf(stderr, "Couldn't open file '%s' with CreateFile()\n", filename); + return false; } hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); if (hFileMapping == 0) { CloseHandle(hFile); fprintf(stderr, "Couldn't open file mapping with CreateFileMapping()\n"); - return; + return false; } lpFileBase = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0); @@ -325,13 +326,13 @@ DumpFile(const char* filename, FILE *fout) CloseHandle(hFileMapping); CloseHandle(hFile); fprintf(stderr, "Couldn't map view of file with MapViewOfFile()\n"); - return; + return false; } dosHeader = (PIMAGE_DOS_HEADER)lpFileBase; if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE) { fprintf(stderr, "File is an executable. I don't dump those.\n"); - return; + return false; } /* Does it look like a i386 COFF OBJ file??? */ else if ( @@ -346,9 +347,11 @@ DumpFile(const char* filename, FILE *fout) */ DumpObjFile((PIMAGE_FILE_HEADER) lpFileBase, fout); } else { - printf("unrecognized file format\n"); + printf("unrecognized file format in '%s'\n", filename); + return false; } UnmapViewOfFile(lpFileBase); CloseHandle(hFileMapping); CloseHandle(hFile); + return true; } -- cgit v0.12 From 61bbbdcf9c0d1aed584fb976cd20c55ee9077850 Mon Sep 17 00:00:00 2001 From: Bill Hoffman Date: Fri, 19 Jun 2015 16:12:43 -0400 Subject: bindexplib: Fix treatment of some symbols --- Source/bindexplib.cxx | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/Source/bindexplib.cxx b/Source/bindexplib.cxx index 4024e2f..6a63279 100644 --- a/Source/bindexplib.cxx +++ b/Source/bindexplib.cxx @@ -198,7 +198,16 @@ DumpExternalsObjects(PIMAGE_SYMBOL pSymbolTable, symbol = stringTable + pSymbolTable->N.Name.Long; } + // clear out any leading spaces while (isspace(symbol[0])) symbol.erase(0,1); + // if it starts with _ and has an @ then it is a __cdecl + // so remove the @ stuff for the export + if(symbol[0] == '_') { + std::string::size_type posAt = symbol.find('@'); + if (posAt != std::string::npos) { + symbol.erase(posAt); + } + } if (symbol[0] == '_') symbol.erase(0,1); if (fImportFlag) { fImportFlag = 0; @@ -210,9 +219,13 @@ DumpExternalsObjects(PIMAGE_SYMBOL pSymbolTable, */ const char *scalarPrefix = "??_G"; const char *vectorPrefix = "??_E"; + // original code had a check for + // symbol.find("real@") == std::string::npos) + // but if this disallows memmber functions with the name real + // if scalarPrefix and vectorPrefix are not found then print + // the symbol if (symbol.compare(0, 4, scalarPrefix) && - symbol.compare(0, 4, vectorPrefix) && - symbol.find("real@") == std::string::npos) + symbol.compare(0, 4, vectorPrefix) ) { SectChar = pSectionHeaders[pSymbolTable->SectionNumber-1].Characteristics; @@ -224,7 +237,7 @@ DumpExternalsObjects(PIMAGE_SYMBOL pSymbolTable, !(SectChar & IMAGE_SCN_MEM_READ)) { fprintf(fout, "\t%s\n", symbol.c_str()); } else { - // printf(" strange symbol: %s \n",s); + // printf(" strange symbol: %s \n",symbol.c_str()); } } } -- cgit v0.12 From 069aa93b555293679f4b8c07623133ba62a74ee4 Mon Sep 17 00:00:00 2001 From: Bill Hoffman Date: Thu, 2 Jul 2015 17:46:25 -0400 Subject: bindexplib: Add support for "/bigobj" format objects --- Source/bindexplib.cxx | 294 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 176 insertions(+), 118 deletions(-) diff --git a/Source/bindexplib.cxx b/Source/bindexplib.cxx index 6a63279..11e3f34 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; -} - - - -/* - *---------------------------------------------------------------------- -* 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 + } + if(posImportFlag) { + return true; + } + return false; + } + + /* + *---------------------------------------------------------------------- + * DumpObjFile -- + * + * Dump an object file's exported symbols. + *---------------------------------------------------------------------- */ - stringTable = (PSTR)&pSymbolTable[cSymbols]; - - for ( i=0; i < cSymbols; i++ ) { + void DumpObjFile() { + if(!HaveExportedObjects()) { + this->DumpExternalsObjects(); + } + } + + /* + *---------------------------------------------------------------------- + * 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); -- cgit v0.12 From 8f86407cfd4331dc1f2eb67f4f179ed8fe9dea06 Mon Sep 17 00:00:00 2001 From: Bill Hoffman Date: Fri, 19 Jun 2015 16:12:43 -0400 Subject: Windows: Optionally generate DLL module definition files automatically Create target property WINDOWS_EXPORT_ALL_SYMBOLS to automatically generate a module definition file from MS-compatible .obj files and give it to the linker in order to export all symbols from the .dll part of a SHARED library. --- Help/manual/cmake-properties.7.rst | 1 + Help/manual/cmake-variables.7.rst | 1 + Help/prop_tgt/WINDOWS_EXPORT_ALL_SYMBOLS.rst | 18 ++++++ Help/release/dev/auto_export_dll_symbols.rst | 6 ++ Help/variable/CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS.rst | 6 ++ Modules/Platform/Windows-MSVC.cmake | 2 + Source/cmGlobalVisualStudioGenerator.cxx | 70 ++++++++++++++++++++++ Source/cmGlobalVisualStudioGenerator.h | 4 ++ Source/cmLocalVisualStudio7Generator.cxx | 31 +++++++++- Source/cmMakefileLibraryTargetGenerator.cxx | 53 ++++++++++++++++ Source/cmNinjaNormalTargetGenerator.cxx | 54 +++++++++++++++++ Source/cmTarget.cxx | 5 ++ Source/cmVisualStudio10TargetGenerator.cxx | 30 +++++++++- Source/cmcmd.cxx | 39 ++++++++++++ Tests/RunCMake/AutoExportDll/AutoExport.cmake | 7 +++ .../AutoExportDll/AutoExportBuild-stderr.txt | 1 + Tests/RunCMake/AutoExportDll/CMakeLists.txt | 3 + Tests/RunCMake/AutoExportDll/RunCMakeTest.cmake | 26 ++++++++ Tests/RunCMake/AutoExportDll/foo.c | 15 +++++ Tests/RunCMake/AutoExportDll/hello.cxx | 13 ++++ Tests/RunCMake/AutoExportDll/hello.h | 18 ++++++ Tests/RunCMake/AutoExportDll/say.cxx | 37 ++++++++++++ Tests/RunCMake/AutoExportDll/sub/CMakeLists.txt | 5 ++ Tests/RunCMake/AutoExportDll/sub/sub.cxx | 4 ++ Tests/RunCMake/AutoExportDll/world.cxx | 6 ++ Tests/RunCMake/CMakeLists.txt | 3 + 26 files changed, 455 insertions(+), 3 deletions(-) create mode 100644 Help/prop_tgt/WINDOWS_EXPORT_ALL_SYMBOLS.rst create mode 100644 Help/release/dev/auto_export_dll_symbols.rst create mode 100644 Help/variable/CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS.rst create mode 100644 Tests/RunCMake/AutoExportDll/AutoExport.cmake create mode 100644 Tests/RunCMake/AutoExportDll/AutoExportBuild-stderr.txt create mode 100644 Tests/RunCMake/AutoExportDll/CMakeLists.txt create mode 100644 Tests/RunCMake/AutoExportDll/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/AutoExportDll/foo.c create mode 100644 Tests/RunCMake/AutoExportDll/hello.cxx create mode 100644 Tests/RunCMake/AutoExportDll/hello.h create mode 100644 Tests/RunCMake/AutoExportDll/say.cxx create mode 100644 Tests/RunCMake/AutoExportDll/sub/CMakeLists.txt create mode 100644 Tests/RunCMake/AutoExportDll/sub/sub.cxx create mode 100644 Tests/RunCMake/AutoExportDll/world.cxx diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 9a60a10..b767ed6 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -251,6 +251,7 @@ Properties on Targets /prop_tgt/VS_WINRT_EXTENSIONS /prop_tgt/VS_WINRT_REFERENCES /prop_tgt/WIN32_EXECUTABLE + /prop_tgt/WINDOWS_EXPORT_ALL_SYMBOLS /prop_tgt/XCODE_ATTRIBUTE_an-attribute /prop_tgt/XCTEST diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 0e6222f..7c7db5e 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -275,6 +275,7 @@ Variables that Control the Build /variable/CMAKE_USE_RELATIVE_PATHS /variable/CMAKE_VISIBILITY_INLINES_HIDDEN /variable/CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD + /variable/CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS /variable/CMAKE_WIN32_EXECUTABLE /variable/CMAKE_XCODE_ATTRIBUTE_an-attribute /variable/EXECUTABLE_OUTPUT_PATH diff --git a/Help/prop_tgt/WINDOWS_EXPORT_ALL_SYMBOLS.rst b/Help/prop_tgt/WINDOWS_EXPORT_ALL_SYMBOLS.rst new file mode 100644 index 0000000..3f48af8 --- /dev/null +++ b/Help/prop_tgt/WINDOWS_EXPORT_ALL_SYMBOLS.rst @@ -0,0 +1,18 @@ +WINDOWS_EXPORT_ALL_SYMBOLS +-------------------------- + +This property is implemented only for MS-compatible tools on Windows. + +Enable this boolean property to automatically create a module definition +(``.def``) file with all global symbols found in the input ``.obj`` files +for a ``SHARED`` library on Windows. The module definition file will be +passed to the linker causing all symbols to be exported from the ``.dll``. +For global *data* symbols, ``__declspec(dllimport)`` must still be used when +compiling against the code in the ``.dll``. All other function symbols will +be automatically exported and imported by callers. This simplifies porting +projects to Windows by reducing the need for explicit ``dllexport`` markup, +even in ``C++`` classes. + +This property is initialized by the value of +the :variable:`CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS` variable if it is set +when a target is created. diff --git a/Help/release/dev/auto_export_dll_symbols.rst b/Help/release/dev/auto_export_dll_symbols.rst new file mode 100644 index 0000000..9db2b5e --- /dev/null +++ b/Help/release/dev/auto_export_dll_symbols.rst @@ -0,0 +1,6 @@ +auto_export_dll_symbols +----------------------- + +* On Windows with MS-compatible tools, CMake learned to optionally + generate a module definition (``.def``) file for ``SHARED`` libraries. + See the :prop_tgt:`WINDOWS_EXPORT_ALL_SYMBOLS` target property. diff --git a/Help/variable/CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS.rst b/Help/variable/CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS.rst new file mode 100644 index 0000000..1636842 --- /dev/null +++ b/Help/variable/CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS.rst @@ -0,0 +1,6 @@ +CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS +-------------------------------- + +Default value for :prop_tgt:`WINDOWS_EXPORT_ALL_SYMBOLS` target property. +This variable is used to initialize the property on each target as it is +created. diff --git a/Modules/Platform/Windows-MSVC.cmake b/Modules/Platform/Windows-MSVC.cmake index 13fe8bc..aeaa2bd 100644 --- a/Modules/Platform/Windows-MSVC.cmake +++ b/Modules/Platform/Windows-MSVC.cmake @@ -46,8 +46,10 @@ else() set(_PLATFORM_LINK_FLAGS "") endif() +set(CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS 1) if(CMAKE_GENERATOR MATCHES "Visual Studio 6") set (CMAKE_NO_BUILD_TYPE 1) + set(CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS 0) # not implemented for VS6 endif() if(NOT CMAKE_NO_BUILD_TYPE AND CMAKE_GENERATOR MATCHES "Visual Studio") set (CMAKE_NO_BUILD_TYPE 1) diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index 585d19a..bc134e1 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -13,12 +13,14 @@ #include "cmGlobalVisualStudioGenerator.h" #include "cmCallVisualStudioMacro.h" +#include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" #include "cmLocalVisualStudioGenerator.h" #include "cmMakefile.h" #include "cmSourceFile.h" #include "cmTarget.h" #include +#include "cmAlgorithms.h" //---------------------------------------------------------------------------- cmGlobalVisualStudioGenerator::cmGlobalVisualStudioGenerator(cmake* cm) @@ -887,3 +889,71 @@ std::string cmGlobalVisualStudioGenerator::ExpandCFGIntDir( } return tmp; } + +void cmGlobalVisualStudioGenerator::AddSymbolExportCommand( + cmGeneratorTarget* gt, std::vector& commands, + std::string const& configName) +{ + std::vector outputs; + std::string deffile = gt->ObjectDirectory; + deffile += "/exportall.def"; + outputs.push_back(deffile); + std::vector empty; + std::vector objectSources; + gt->GetObjectSources(objectSources, configName); + std::map mapping; + for(std::vector::const_iterator it + = objectSources.begin(); it != objectSources.end(); ++it) + { + mapping[*it]; + } + gt->LocalGenerator-> + ComputeObjectFilenames(mapping, gt); + std::string obj_dir = gt->ObjectDirectory; + std::string cmakeCommand = cmSystemTools::GetCMakeCommand(); + cmSystemTools::ConvertToWindowsExtendedPath(cmakeCommand); + cmCustomCommandLine cmdl; + cmdl.push_back(cmakeCommand); + cmdl.push_back("-E"); + cmdl.push_back("__create_def"); + cmdl.push_back(deffile); + std::string obj_dir_expanded = obj_dir; + cmSystemTools::ReplaceString(obj_dir_expanded, + this->GetCMakeCFGIntDir(), + configName.c_str()); + std::string objs_file = obj_dir_expanded; + cmSystemTools::MakeDirectory(objs_file.c_str()); + objs_file += "/objects.txt"; + cmdl.push_back(objs_file); + cmGeneratedFileStream fout(objs_file.c_str()); + if(!fout) + { + cmSystemTools::Error("could not open ", objs_file.c_str()); + return; + } + for(std::vector::const_iterator it + = objectSources.begin(); it != objectSources.end(); ++it) + { + // Find the object file name corresponding to this source file. + std::map::const_iterator + map_it = mapping.find(*it); + // It must exist because we populated the mapping just above. + assert(!map_it->second.empty()); + std::string objFile = obj_dir + map_it->second; + // replace $(ConfigurationName) in the object names + cmSystemTools::ReplaceString(objFile, this->GetCMakeCFGIntDir(), + configName.c_str()); + if(cmHasLiteralSuffix(objFile, ".obj")) + { + fout << objFile << "\n"; + } + } + cmCustomCommandLines commandLines; + commandLines.push_back(cmdl); + cmCustomCommand command(gt->Target->GetMakefile(), + outputs, empty, empty, + commandLines, + "Auto build dll exports", + "."); + commands.push_back(command); +} diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h index 69b4564..022e190 100644 --- a/Source/cmGlobalVisualStudioGenerator.h +++ b/Source/cmGlobalVisualStudioGenerator.h @@ -102,6 +102,10 @@ public: const std::string& config) const; void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const; + + void AddSymbolExportCommand( + cmGeneratorTarget*, std::vector& commands, + std::string const& configName); protected: virtual void Generate(); diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index dc3a16d..a0e9e4d 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -1081,6 +1081,14 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, this->ConvertToOutputFormat(this->ModuleDefinitionFile, SHELL); linkOptions.AddFlag("ModuleDefinitionFile", defFile.c_str()); } + if (target.GetType() == cmTarget::SHARED_LIBRARY && + this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) + { + if (target.GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) + { + linkOptions.AddFlag("ModuleDefinitionFile", "$(IntDir)/exportall.def"); + } + } switch(target.GetType()) { case cmTarget::UNKNOWN_LIBRARY: @@ -2015,7 +2023,28 @@ void cmLocalVisualStudio7Generator // Add pre-link event. tool = this->FortranProject? "VFPreLinkEventTool":"VCPreLinkEventTool"; event.Start(tool); - event.Write(target.GetPreLinkCommands()); + bool addedPrelink = false; + if (target.GetType() == cmTarget::SHARED_LIBRARY && + this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) + { + if (target.GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) + { + addedPrelink = true; + std::vector commands = + target.GetPreLinkCommands(); + cmGlobalVisualStudioGenerator* gg + = static_cast(this->GlobalGenerator); + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(&target); + gg->AddSymbolExportCommand( + gt, commands, configName); + event.Write(commands); + } + } + if (!addedPrelink) + { + event.Write(target.GetPreLinkCommands()); + } cmsys::auto_ptr pcc( this->MaybeCreateImplibDir(target, configName, this->FortranProject)); if(pcc.get()) diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index 660027c..696dcc4 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -18,6 +18,7 @@ #include "cmSourceFile.h" #include "cmTarget.h" #include "cmake.h" +#include "cmAlgorithms.h" //---------------------------------------------------------------------------- cmMakefileLibraryTargetGenerator @@ -563,6 +564,58 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules useResponseFileForObjects, buildObjs, depends, useWatcomQuote); + // maybe create .def file from list of objects + if (this->Target->GetType() == cmTarget::SHARED_LIBRARY && + this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) + { + if(this->Target->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) + { + std::string name_of_def_file = + this->Target->GetSupportDirectory(); + name_of_def_file += std::string("/") + + this->Target->GetName(); + name_of_def_file += ".def"; + std::string cmd = cmSystemTools::GetCMakeCommand(); + cmd = this->Convert(cmd, cmLocalGenerator::NONE, + cmLocalGenerator::SHELL); + cmd += " -E __create_def "; + cmd += this->Convert(name_of_def_file, + cmLocalGenerator::START_OUTPUT, + cmLocalGenerator::SHELL); + cmd += " "; + std::string objlist_file = name_of_def_file; + objlist_file += ".objs"; + cmd += this->Convert(objlist_file, + cmLocalGenerator::START_OUTPUT, + cmLocalGenerator::SHELL); + real_link_commands.push_back(cmd); + // create a list of obj files for the -E __create_def to read + cmGeneratedFileStream fout(objlist_file.c_str()); + for(std::vector::const_iterator i = this->Objects.begin(); + i != this->Objects.end(); ++i) + { + if(cmHasLiteralSuffix(*i, ".obj")) + { + fout << *i << "\n"; + } + } + for(std::vector::const_iterator i = + this->ExternalObjects.begin(); + i != this->ExternalObjects.end(); ++i) + { + fout << *i << "\n"; + } + // now add the def file link flag + linkFlags += " "; + linkFlags += + this->Makefile->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG"); + linkFlags += this->Convert(name_of_def_file, + cmLocalGenerator::START_OUTPUT, + cmLocalGenerator::SHELL); + linkFlags += " "; + } + } + cmLocalGenerator::RuleVariables vars; vars.TargetPDB = targetOutPathPDB.c_str(); diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 2fe53bf..88da09b 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -486,6 +486,22 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() linkPath, &genTarget, useWatcomQuote); + if(this->GetMakefile()->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS") + && target.GetType() == cmTarget::SHARED_LIBRARY) + { + if(target.GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) + { + std::string dllname = targetOutput; + std::string name_of_def_file + = target.GetSupportDirectory(); + name_of_def_file += "/" + target.GetName(); + name_of_def_file += ".def "; + vars["LINK_FLAGS"] += " /DEF:"; + vars["LINK_FLAGS"] += this->GetLocalGenerator() + ->ConvertToOutputFormat(name_of_def_file.c_str(), + cmLocalGenerator::SHELL); + } + } this->addPoolNinjaVariable("JOB_POOL_LINK", &target, vars); @@ -600,6 +616,44 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() } } + // maybe create .def file from list of objects + if (target.GetType() == cmTarget::SHARED_LIBRARY && + this->GetMakefile()->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) + { + if(target.GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) + { + std::string cmakeCommand = + this->GetLocalGenerator()->ConvertToOutputFormat( + cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL); + std::string dllname = targetOutput; + std::string name_of_def_file + = target.GetSupportDirectory(); + name_of_def_file += "/" + target.GetName(); + name_of_def_file += ".def"; + std::string cmd = cmakeCommand; + cmd += " -E __create_def "; + cmd += this->GetLocalGenerator() + ->ConvertToOutputFormat(name_of_def_file.c_str(), + cmLocalGenerator::SHELL); + cmd += " "; + cmNinjaDeps objs = this->GetObjects(); + std::string obj_list_file = name_of_def_file; + obj_list_file += ".objs"; + cmd += this->GetLocalGenerator() + ->ConvertToOutputFormat(obj_list_file.c_str(), + cmLocalGenerator::SHELL); + preLinkCmdLines.push_back(cmd); + // create a list of obj files for the -E __create_def to read + cmGeneratedFileStream fout(obj_list_file.c_str()); + for(cmNinjaDeps::iterator i=objs.begin(); i != objs.end(); ++i) + { + if(cmHasLiteralSuffix(*i, ".obj")) + { + fout << *i << "\n"; + } + } + } + } // If we have any PRE_LINK commands, we need to go back to HOME_OUTPUT for // the link commands. if (!preLinkCmdLines.empty()) diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index c7a13bc..8448431 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -429,6 +429,11 @@ void cmTarget::SetMakefile(cmMakefile* mf) { this->SetProperty("POSITION_INDEPENDENT_CODE", "True"); } + if(this->TargetTypeValue == cmTarget::SHARED_LIBRARY) + { + this->SetPropertyDefault("WINDOWS_EXPORT_ALL_SYMBOLS", 0); + } + if (this->GetType() != INTERFACE_LIBRARY && this->GetType() != UTILITY) { this->SetPropertyDefault("POSITION_INDEPENDENT_CODE", 0); diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 12a1e42..57ec212 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -2466,6 +2466,15 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config) "%(IgnoreSpecificDefaultLibraries)"); } + if (this->Target->GetType() == cmTarget::SHARED_LIBRARY && + this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) + { + if (this->Target->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) + { + linkOptions.AddFlag("ModuleDefinitionFile", "$(IntDir)exportall.def"); + } + } + this->LinkOptions[config] = pOptions.release(); return true; } @@ -2613,8 +2622,25 @@ void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups() void cmVisualStudio10TargetGenerator::WriteEvents(std::string const& configName) { - this->WriteEvent("PreLinkEvent", - this->Target->GetPreLinkCommands(), configName); + bool addedPrelink = false; + if (this->Target->GetType() == cmTarget::SHARED_LIBRARY && + this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) + { + if (this->Target->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) + { + addedPrelink = true; + std::vector commands = + this->Target->GetPreLinkCommands(); + this->GlobalGenerator->AddSymbolExportCommand( + this->GeneratorTarget, commands, configName); + this->WriteEvent("PreLinkEvent", commands, configName); + } + } + if (!addedPrelink) + { + this->WriteEvent("PreLinkEvent", + this->Target->GetPreLinkCommands(), configName); + } this->WriteEvent("PreBuildEvent", this->Target->GetPreBuildCommands(), configName); this->WriteEvent("PostBuildEvent", diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 3ea2186..63838b4 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -34,6 +34,10 @@ #include #include // required for atoi +#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE) +// defined in binexplib.cxx +bool DumpFile(const char* filename, FILE *fout); +#endif void CMakeCommandUsage(const char* program) { @@ -211,6 +215,41 @@ int cmcmd::ExecuteCMakeCommand(std::vector& args) return 0; } +#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE) + else if(args[1] == "__create_def") + { + if(args.size() < 4) + { + std::cerr << + "__create_def Usage: -E __create_def outfile.def objlistfile\n"; + return 1; + } + FILE* fout = cmsys::SystemTools::Fopen(args[2].c_str(), "w+"); + if(!fout) + { + std::cerr << "could not open output .def file: " << args[2].c_str() + << "\n"; + return 1; + } + cmsys::ifstream fin(args[3].c_str(), + std::ios::in | std::ios::binary); + if(!fin) + { + std::cerr << "could not open object list file: " << args[3].c_str() + << "\n"; + return 1; + } + std::string objfile; + while(cmSystemTools::GetLineFromStream(fin, objfile)) + { + if (!DumpFile(objfile.c_str(), fout)) + { + return 1; + } + } + return 0; + } +#endif // run include what you use command and then run the compile // command. This is an internal undocumented option and should // only be used by CMake itself when running iwyu. diff --git a/Tests/RunCMake/AutoExportDll/AutoExport.cmake b/Tests/RunCMake/AutoExportDll/AutoExport.cmake new file mode 100644 index 0000000..3b2b2c5 --- /dev/null +++ b/Tests/RunCMake/AutoExportDll/AutoExport.cmake @@ -0,0 +1,7 @@ +project(autoexport) +set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${autoexport_BINARY_DIR}/bin) +add_subdirectory(sub) +add_library(autoexport SHARED hello.cxx world.cxx foo.c) +add_executable(say say.cxx) +target_link_libraries(say autoexport autoexport2) diff --git a/Tests/RunCMake/AutoExportDll/AutoExportBuild-stderr.txt b/Tests/RunCMake/AutoExportDll/AutoExportBuild-stderr.txt new file mode 100644 index 0000000..d483c2c --- /dev/null +++ b/Tests/RunCMake/AutoExportDll/AutoExportBuild-stderr.txt @@ -0,0 +1 @@ +^.*$ diff --git a/Tests/RunCMake/AutoExportDll/CMakeLists.txt b/Tests/RunCMake/AutoExportDll/CMakeLists.txt new file mode 100644 index 0000000..18dfd26 --- /dev/null +++ b/Tests/RunCMake/AutoExportDll/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.2) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/AutoExportDll/RunCMakeTest.cmake b/Tests/RunCMake/AutoExportDll/RunCMakeTest.cmake new file mode 100644 index 0000000..3784a6a --- /dev/null +++ b/Tests/RunCMake/AutoExportDll/RunCMakeTest.cmake @@ -0,0 +1,26 @@ +include(RunCMake) +set(RunCMake_TEST_NO_CLEAN TRUE) +set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/AutoExport-build") +# start by cleaning up because we don't clean up along the way +file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") +# configure the AutoExport test +run_cmake(AutoExport) +unset(RunCMake_TEST_OPTIONS) +# don't run this test on VS 6 as it is not supported +if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 6|Watcom WMake|Borland Makefiles") + return() +endif() +# we build debug so the say.exe will be found in Debug/say.exe for +# Visual Studio generators +if("${RunCMake_GENERATOR}" MATCHES "Visual Studio|Xcode") + set(INTDIR "Debug/") +endif() +# build AutoExport +run_cmake_command(AutoExportBuild ${CMAKE_COMMAND} --build + ${RunCMake_TEST_BINARY_DIR} --config Debug --clean-first) +# run the executable that uses symbols from the dll +if(WIN32) + set(EXE_EXT ".exe") +endif() +run_cmake_command(AutoExportRun + ${RunCMake_BINARY_DIR}/AutoExport-build/bin/${INTDIR}say${EXE_EXT}) diff --git a/Tests/RunCMake/AutoExportDll/foo.c b/Tests/RunCMake/AutoExportDll/foo.c new file mode 100644 index 0000000..4b1318b --- /dev/null +++ b/Tests/RunCMake/AutoExportDll/foo.c @@ -0,0 +1,15 @@ +#ifdef _MSC_VER +#include "windows.h" +#else +#define WINAPI +#endif + +int WINAPI foo() +{ + return 10; +} + +int bar() +{ + return 5; +} diff --git a/Tests/RunCMake/AutoExportDll/hello.cxx b/Tests/RunCMake/AutoExportDll/hello.cxx new file mode 100644 index 0000000..3933fc1 --- /dev/null +++ b/Tests/RunCMake/AutoExportDll/hello.cxx @@ -0,0 +1,13 @@ +#include +#include "hello.h" +int Hello::Data = 0; +void Hello::real() +{ + return; +} +void hello() +{ + printf("hello"); +} +void Hello::operator delete[](void*) {}; +void Hello::operator delete(void*) {}; diff --git a/Tests/RunCMake/AutoExportDll/hello.h b/Tests/RunCMake/AutoExportDll/hello.h new file mode 100644 index 0000000..3749b97 --- /dev/null +++ b/Tests/RunCMake/AutoExportDll/hello.h @@ -0,0 +1,18 @@ +#ifndef _MSC_VER +#define winexport +#else +#ifdef autoexport_EXPORTS +#define winexport +#else +#define winexport __declspec(dllimport) +#endif +#endif + +class Hello +{ +public: + static winexport int Data; + void real(); + static void operator delete[](void*); + static void operator delete(void*); +}; diff --git a/Tests/RunCMake/AutoExportDll/say.cxx b/Tests/RunCMake/AutoExportDll/say.cxx new file mode 100644 index 0000000..655b3c2 --- /dev/null +++ b/Tests/RunCMake/AutoExportDll/say.cxx @@ -0,0 +1,37 @@ +#include +#include "hello.h" +#ifdef _MSC_VER +#include "windows.h" +#else +#define WINAPI +#endif + +extern "C" +{ +// test __cdecl stuff + int WINAPI foo(); +// test regular C + int bar(); +} + +// test c++ functions +// forward declare hello and world +void hello(); +void world(); + +int main() +{ + // test static data (needs declspec to work) + Hello::Data = 120; + Hello h; + h.real(); + hello(); + printf(" "); + world(); + printf("\n"); + foo(); + printf("\n"); + bar(); + printf("\n"); + return 0; +} diff --git a/Tests/RunCMake/AutoExportDll/sub/CMakeLists.txt b/Tests/RunCMake/AutoExportDll/sub/CMakeLists.txt new file mode 100644 index 0000000..8b70e7d --- /dev/null +++ b/Tests/RunCMake/AutoExportDll/sub/CMakeLists.txt @@ -0,0 +1,5 @@ +add_library(autoexport2 SHARED sub.cxx) +if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + # Try msvc "big" object format. + target_compile_options(autoexport2 PRIVATE /bigobj) +endif() diff --git a/Tests/RunCMake/AutoExportDll/sub/sub.cxx b/Tests/RunCMake/AutoExportDll/sub/sub.cxx new file mode 100644 index 0000000..9766b41 --- /dev/null +++ b/Tests/RunCMake/AutoExportDll/sub/sub.cxx @@ -0,0 +1,4 @@ +int sub() +{ + return 10; +} diff --git a/Tests/RunCMake/AutoExportDll/world.cxx b/Tests/RunCMake/AutoExportDll/world.cxx new file mode 100644 index 0000000..3a54df3 --- /dev/null +++ b/Tests/RunCMake/AutoExportDll/world.cxx @@ -0,0 +1,6 @@ +#include "stdio.h" + +void world() +{ + printf("world"); +} diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index bc706d3..743ef4b 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -266,3 +266,6 @@ if("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") endif() add_RunCMake_test_group(CPack "DEB;RPM") +# add a test to make sure symbols are exported from a shared library +# for MSVC compilers CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS property is used +add_RunCMake_test(AutoExportDll) -- cgit v0.12