bindexplib.cxx 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. /*============================================================================
  2. CMake - Cross Platform Makefile Generator
  3. Copyright 2000-2015 Kitware, Inc.
  4. Distributed under the OSI-approved BSD License (the "License");
  5. see accompanying file Copyright.txt for details.
  6. This software is distributed WITHOUT ANY WARRANTY; without even the
  7. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  8. See the License for more information.
  9. ============================================================================*/
  10. /*-------------------------------------------------------------------------
  11. Portions of this source have been derived from the 'bindexplib' tool
  12. provided by the CERN ROOT Data Analysis Framework project (root.cern.ch).
  13. Permission has been granted by Pere Mato <[email protected]> to distribute
  14. this derived work under the CMake license.
  15. -------------------------------------------------------------------------*/
  16. /*
  17. *----------------------------------------------------------------------
  18. * Program: dumpexts.exe
  19. * Author: Gordon Chaffee
  20. *
  21. * History: The real functionality of this file was written by
  22. * Matt Pietrek in 1993 in his pedump utility. I've
  23. * modified it to dump the externals in a bunch of object
  24. * files to create a .def file.
  25. *
  26. * Notes: Visual C++ puts an underscore before each exported symbol.
  27. * This file removes them. I don't know if this is a problem
  28. * this other compilers. If _MSC_VER is defined,
  29. * the underscore is removed. If not, it isn't. To get a
  30. * full dump of an object file, use the -f option. This can
  31. * help determine the something that may be different with a
  32. * compiler other than Visual C++.
  33. * ======================================
  34. * Corrections (Axel 2006-04-04):
  35. * Conversion to C++. Mostly.
  36. *
  37. * Extension (Axel 2006-03-15)
  38. * As soon as an object file contains an /EXPORT directive (which
  39. * is generated by the compiler when a symbol is declared as
  40. * declspec(dllexport)) no to-be-exported symbols are printed,
  41. * as the linker will see these directives, and if those directives
  42. * are present we only export selectively (i.e. we trust the
  43. * programmer).
  44. *
  45. * ======================================
  46. * ======================================
  47. * Corrections (Valery Fine 23/02/98):
  48. *
  49. * The "(vector) deleting destructor" MUST not be exported
  50. * To recognize it the following test are introduced:
  51. * "@@UAEPAXI@Z" scalar deleting dtor
  52. * "@@QAEPAXI@Z" vector deleting dtor
  53. * "AEPAXI@Z" vector deleting dtor with thunk adjustor
  54. * ======================================
  55. * Corrections (Valery Fine 12/02/97):
  56. *
  57. * It created a wrong EXPORTS for the global pointers and constants.
  58. * The Section Header has been involved to discover the missing information
  59. * Now the pointers are correctly supplied supplied with "DATA" descriptor
  60. * the constants with no extra descriptor.
  61. *
  62. * Corrections (Valery Fine 16/09/96):
  63. *
  64. * It didn't work for C++ code with global variables and class definitons
  65. * The DumpExternalObject function has been introduced to generate .DEF file
  66. *
  67. * Author: Valery Fine 16/09/96 (E-mail: [email protected])
  68. *----------------------------------------------------------------------
  69. */
  70. #include <cmsys/Encoding.hxx>
  71. #include <windows.h>
  72. #include <stdio.h>
  73. #include <string>
  74. #include <fstream>
  75. #include <iostream>
  76. /*
  77. + * Utility func, strstr with size
  78. + */
  79. const char* StrNStr(const char* start, const char* find, size_t &size) {
  80. size_t len;
  81. const char* hint;
  82. if (!start || !find || !size) {
  83. size = 0;
  84. return 0;
  85. }
  86. len = strlen(find);
  87. while ((hint = (const char*) memchr(start, find[0], size-len+1))) {
  88. size -= (hint - start);
  89. if (!strncmp(hint, find, len))
  90. return hint;
  91. start = hint + 1;
  92. }
  93. size = 0;
  94. return 0;
  95. }
  96. /*
  97. *----------------------------------------------------------------------
  98. * HaveExportedObjects --
  99. *
  100. * Returns >0 if export directives (declspec(dllexport)) exist.
  101. *
  102. *----------------------------------------------------------------------
  103. */
  104. int
  105. HaveExportedObjects(PIMAGE_FILE_HEADER pImageFileHeader,
  106. PIMAGE_SECTION_HEADER pSectionHeaders)
  107. {
  108. static int fImportFlag = 0; /* The status is nor defined yet */
  109. WORD i;
  110. size_t size;
  111. char foundExports;
  112. const char * rawdata;
  113. PIMAGE_SECTION_HEADER pDirectivesSectionHeader;
  114. if (fImportFlag) return 1;
  115. i = 0;
  116. foundExports = 0;
  117. pDirectivesSectionHeader = 0;
  118. for(i = 0; (i < pImageFileHeader->NumberOfSections &&
  119. !pDirectivesSectionHeader); i++)
  120. if (!strncmp((const char*)&pSectionHeaders[i].Name[0], ".drectve",8))
  121. pDirectivesSectionHeader = &pSectionHeaders[i];
  122. if (!pDirectivesSectionHeader) return 0;
  123. rawdata=(const char*)
  124. pImageFileHeader+pDirectivesSectionHeader->PointerToRawData;
  125. if (!pDirectivesSectionHeader->PointerToRawData || !rawdata) return 0;
  126. size = pDirectivesSectionHeader->SizeOfRawData;
  127. const char* posImportFlag = rawdata;
  128. while ((posImportFlag = StrNStr(posImportFlag, " /EXPORT:", size))) {
  129. const char* lookingForDict = posImportFlag + 9;
  130. if (!strncmp(lookingForDict, "_G__cpp_",8) ||
  131. !strncmp(lookingForDict, "_G__set_cpp_",12)) {
  132. posImportFlag = lookingForDict;
  133. continue;
  134. }
  135. const char* lookingForDATA = posImportFlag + 9;
  136. while (*(++lookingForDATA) && *lookingForDATA != ' ');
  137. lookingForDATA -= 5;
  138. // ignore DATA exports
  139. if (strncmp(lookingForDATA, ",DATA", 5)) break;
  140. posImportFlag = lookingForDATA + 5;
  141. }
  142. fImportFlag = (int)posImportFlag;
  143. return fImportFlag;
  144. }
  145. /*
  146. *----------------------------------------------------------------------
  147. * DumpExternalsObjects --
  148. *
  149. * Dumps a COFF symbol table from an EXE or OBJ. We only use
  150. * it to dump tables from OBJs.
  151. *----------------------------------------------------------------------
  152. */
  153. void
  154. DumpExternalsObjects(PIMAGE_SYMBOL pSymbolTable,
  155. PIMAGE_SECTION_HEADER pSectionHeaders,
  156. FILE *fout, DWORD_PTR cSymbols)
  157. {
  158. unsigned i;
  159. PSTR stringTable;
  160. std::string symbol;
  161. DWORD SectChar;
  162. static int fImportFlag = -1; /* The status is nor defined yet */
  163. /*
  164. * The string table apparently starts right after the symbol table
  165. */
  166. stringTable = (PSTR)&pSymbolTable[cSymbols];
  167. for ( i=0; i < cSymbols; i++ ) {
  168. if (pSymbolTable->SectionNumber > 0 &&
  169. ( pSymbolTable->Type == 0x20 || pSymbolTable->Type == 0x0)) {
  170. if (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) {
  171. /*
  172. * The name of the Function entry points
  173. */
  174. if (pSymbolTable->N.Name.Short != 0) {
  175. symbol = "";
  176. symbol.insert(0, (const char *)pSymbolTable->N.ShortName, 8);
  177. } else {
  178. symbol = stringTable + pSymbolTable->N.Name.Long;
  179. }
  180. // clear out any leading spaces
  181. while (isspace(symbol[0])) symbol.erase(0,1);
  182. // if it starts with _ and has an @ then it is a __cdecl
  183. // so remove the @ stuff for the export
  184. if(symbol[0] == '_') {
  185. std::string::size_type posAt = symbol.find('@');
  186. if (posAt != std::string::npos) {
  187. symbol.erase(posAt);
  188. }
  189. }
  190. if (symbol[0] == '_') symbol.erase(0,1);
  191. if (fImportFlag) {
  192. fImportFlag = 0;
  193. fprintf(fout,"EXPORTS \n");
  194. }
  195. /*
  196. Check whether it is "Scalar deleting destructor" and
  197. "Vector deleting destructor"
  198. */
  199. const char *scalarPrefix = "??_G";
  200. const char *vectorPrefix = "??_E";
  201. // original code had a check for
  202. // symbol.find("real@") == std::string::npos)
  203. // but if this disallows memmber functions with the name real
  204. // if scalarPrefix and vectorPrefix are not found then print
  205. // the symbol
  206. if (symbol.compare(0, 4, scalarPrefix) &&
  207. symbol.compare(0, 4, vectorPrefix) )
  208. {
  209. SectChar =
  210. pSectionHeaders[pSymbolTable->SectionNumber-1].Characteristics;
  211. if (!pSymbolTable->Type && (SectChar & IMAGE_SCN_MEM_WRITE)) {
  212. // Read only (i.e. constants) must be excluded
  213. fprintf(fout, "\t%s \t DATA\n", symbol.c_str());
  214. } else {
  215. if ( pSymbolTable->Type ||
  216. !(SectChar & IMAGE_SCN_MEM_READ)) {
  217. fprintf(fout, "\t%s\n", symbol.c_str());
  218. } else {
  219. // printf(" strange symbol: %s \n",symbol.c_str());
  220. }
  221. }
  222. }
  223. }
  224. }
  225. else if (pSymbolTable->SectionNumber == IMAGE_SYM_UNDEFINED &&
  226. !pSymbolTable->Type && 0) {
  227. /*
  228. * The IMPORT global variable entry points
  229. */
  230. if (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) {
  231. symbol = stringTable + pSymbolTable->N.Name.Long;
  232. while (isspace(symbol[0])) symbol.erase(0,1);
  233. if (symbol[0] == '_') symbol.erase(0,1);
  234. if (!fImportFlag) {
  235. fImportFlag = 1;
  236. fprintf(fout,"IMPORTS \n");
  237. }
  238. fprintf(fout, "\t%s DATA \n", symbol.c_str()+1);
  239. }
  240. }
  241. /*
  242. * Take into account any aux symbols
  243. */
  244. i += pSymbolTable->NumberOfAuxSymbols;
  245. pSymbolTable += pSymbolTable->NumberOfAuxSymbols;
  246. pSymbolTable++;
  247. }
  248. }
  249. /*
  250. *----------------------------------------------------------------------
  251. * DumpObjFile --
  252. *
  253. * Dump an object file--either a full listing or just the exported
  254. * symbols.
  255. *----------------------------------------------------------------------
  256. */
  257. void
  258. DumpObjFile(PIMAGE_FILE_HEADER pImageFileHeader, FILE *fout)
  259. {
  260. PIMAGE_SYMBOL PCOFFSymbolTable;
  261. PIMAGE_SECTION_HEADER PCOFFSectionHeaders;
  262. DWORD_PTR COFFSymbolCount;
  263. PCOFFSymbolTable = (PIMAGE_SYMBOL)
  264. ((DWORD_PTR)pImageFileHeader + pImageFileHeader->PointerToSymbolTable);
  265. COFFSymbolCount = pImageFileHeader->NumberOfSymbols;
  266. PCOFFSectionHeaders = (PIMAGE_SECTION_HEADER)
  267. ((DWORD_PTR)pImageFileHeader +
  268. IMAGE_SIZEOF_FILE_HEADER +
  269. pImageFileHeader->SizeOfOptionalHeader);
  270. int haveExports = HaveExportedObjects(pImageFileHeader,
  271. PCOFFSectionHeaders);
  272. if (!haveExports)
  273. DumpExternalsObjects(PCOFFSymbolTable, PCOFFSectionHeaders,
  274. fout, COFFSymbolCount);
  275. }
  276. /*
  277. *----------------------------------------------------------------------
  278. * DumpFile --
  279. *
  280. * Open up a file, memory map it, and call the appropriate
  281. * dumping routine
  282. *----------------------------------------------------------------------
  283. */
  284. bool
  285. DumpFile(const char* filename, FILE *fout)
  286. {
  287. HANDLE hFile;
  288. HANDLE hFileMapping;
  289. LPVOID lpFileBase;
  290. PIMAGE_DOS_HEADER dosHeader;
  291. hFile = CreateFileW(cmsys::Encoding::ToWide(filename).c_str(),
  292. GENERIC_READ, FILE_SHARE_READ, NULL,
  293. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  294. if (hFile == INVALID_HANDLE_VALUE) {
  295. fprintf(stderr, "Couldn't open file '%s' with CreateFile()\n", filename);
  296. return false;
  297. }
  298. hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
  299. if (hFileMapping == 0) {
  300. CloseHandle(hFile);
  301. fprintf(stderr, "Couldn't open file mapping with CreateFileMapping()\n");
  302. return false;
  303. }
  304. lpFileBase = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
  305. if (lpFileBase == 0) {
  306. CloseHandle(hFileMapping);
  307. CloseHandle(hFile);
  308. fprintf(stderr, "Couldn't map view of file with MapViewOfFile()\n");
  309. return false;
  310. }
  311. dosHeader = (PIMAGE_DOS_HEADER)lpFileBase;
  312. if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE) {
  313. fprintf(stderr, "File is an executable. I don't dump those.\n");
  314. return false;
  315. }
  316. /* Does it look like a i386 COFF OBJ file??? */
  317. else if (
  318. ((dosHeader->e_magic == IMAGE_FILE_MACHINE_I386) ||
  319. (dosHeader->e_magic == IMAGE_FILE_MACHINE_AMD64))
  320. && (dosHeader->e_sp == 0)
  321. ) {
  322. /*
  323. * The two tests above aren't what they look like. They're
  324. * really checking for IMAGE_FILE_HEADER.Machine == i386 (0x14C)
  325. * and IMAGE_FILE_HEADER.SizeOfOptionalHeader == 0;
  326. */
  327. DumpObjFile((PIMAGE_FILE_HEADER) lpFileBase, fout);
  328. } else {
  329. printf("unrecognized file format in '%s'\n", filename);
  330. return false;
  331. }
  332. UnmapViewOfFile(lpFileBase);
  333. CloseHandle(hFileMapping);
  334. CloseHandle(hFile);
  335. return true;
  336. }