| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370 |
- /*============================================================================
- 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 <[email protected]> to distribute
- this derived work under the CMake license.
- -------------------------------------------------------------------------*/
- /*
- *----------------------------------------------------------------------
- * 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: [email protected])
- *----------------------------------------------------------------------
- */
- #include <cmsys/Encoding.hxx>
- #include <windows.h>
- #include <stdio.h>
- #include <string>
- #include <fstream>
- #include <iostream>
- /*
- + * 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)
- {
- 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, 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
- */
- 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;
- }
- // 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;
- fprintf(fout,"EXPORTS \n");
- }
- /*
- Check whether it is "Scalar deleting destructor" and
- "Vector deleting destructor"
- */
- 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) )
- {
- 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",symbol.c_str());
- }
- }
- }
- }
- }
- 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)
- {
- 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
- DumpFile(const char* filename, FILE *fout)
- {
- HANDLE hFile;
- HANDLE hFileMapping;
- LPVOID lpFileBase;
- PIMAGE_DOS_HEADER dosHeader;
- 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) {
- 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 false;
- }
- 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 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 false;
- }
- /* 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);
- } else {
- printf("unrecognized file format in '%s'\n", filename);
- return false;
- }
- UnmapViewOfFile(lpFileBase);
- CloseHandle(hFileMapping);
- CloseHandle(hFile);
- return true;
- }
|