debug.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  1. /*
  2. * Made after:
  3. * CVDump - Parses through a Visual Studio .DBG file in CodeView 4 format
  4. * and dumps the info to STDOUT in a human-readable format
  5. *
  6. * Copyright 2000 John R. Sheets
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2.1 of the License, or (at your option) any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with this library; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  21. */
  22. #include "config.h"
  23. #include "wine/port.h"
  24. #include <stdlib.h>
  25. #include <stdarg.h>
  26. #include <stdio.h>
  27. #ifdef HAVE_UNISTD_H
  28. # include <unistd.h>
  29. #endif
  30. #include <time.h>
  31. #ifdef HAVE_SYS_TYPES_H
  32. # include <sys/types.h>
  33. #endif
  34. #ifdef HAVE_SYS_STAT_H
  35. # include <sys/stat.h>
  36. #endif
  37. #ifdef HAVE_SYS_MMAN_H
  38. #include <sys/mman.h>
  39. #endif
  40. #include <fcntl.h>
  41. #include "windef.h"
  42. #include "winbase.h"
  43. #include "winedump.h"
  44. #include "wine/mscvpdb.h"
  45. /*
  46. * .DBG File Layout:
  47. *
  48. * IMAGE_SEPARATE_DEBUG_HEADER
  49. * IMAGE_SECTION_HEADER[]
  50. * IMAGE_DEBUG_DIRECTORY[]
  51. * OMFSignature
  52. * debug data (typical example)
  53. * - IMAGE_DEBUG_TYPE_MISC
  54. * - IMAGE_DEBUG_TYPE_FPO
  55. * - IMAGE_DEBUG_TYPE_CODEVIEW
  56. * OMFDirHeader
  57. * OMFDirEntry[]
  58. */
  59. /*
  60. * Descriptions:
  61. *
  62. * (hdr) IMAGE_SEPARATE_DEBUG_HEADER - .DBG-specific file header; holds info that
  63. * applies to the file as a whole, including # of COFF sections, file offsets, etc.
  64. * (hdr) IMAGE_SECTION_HEADER - list of COFF sections copied verbatim from .EXE;
  65. * although this directory contains file offsets, these offsets are meaningless
  66. * in the context of the .DBG file, because only the section headers are copied
  67. * to the .DBG file... not the binary data it points to.
  68. * (hdr) IMAGE_DEBUG_DIRECTORY - list of different formats of debug info contained in file
  69. * (see IMAGE_DEBUG_TYPE_* descriptions below); tells where each section starts
  70. * (hdr) OMFSignature (CV) - Contains "NBxx" signature, plus file offset telling how far
  71. * into the IMAGE_DEBUG_TYPE_CODEVIEW section the OMFDirHeader and OMFDirEntry's sit
  72. * (data) IMAGE_DEBUG_TYPE_MISC - usually holds name of original .EXE file
  73. * (data) IMAGE_DEBUG_TYPE_FPO - Frame Pointer Optimization data; used for dealing with
  74. * optimized stack frames (optional)
  75. * (data) IMAGE_DEBUG_TYPE_CODEVIEW - *** THE GOOD STUFF ***
  76. * This block of data contains all the symbol tables, line number info, etc.,
  77. * that the Visual C++ debugger needs.
  78. * (hdr) OMFDirHeader (CV) -
  79. * (hdr) OMFDirEntry (CV) - list of subsections within CodeView debug data section
  80. */
  81. /*
  82. * The .DBG file typically has three arrays of directory entries, which tell
  83. * the OS or debugger where in the file to look for the actual data
  84. *
  85. * IMAGE_SECTION_HEADER - number of entries determined by:
  86. * (IMAGE_SEPARATE_DEBUG_HEADER.NumberOfSections)
  87. *
  88. * IMAGE_DEBUG_DIRECTORY - number of entries determined by:
  89. * (IMAGE_SEPARATE_DEBUG_HEADER.DebugDirectorySize / sizeof (IMAGE_DEBUG_DIRECTORY))
  90. *
  91. * OMFDirEntry - number of entries determined by:
  92. * (OMFDirHeader.cDir)
  93. */
  94. extern const IMAGE_NT_HEADERS* PE_nt_headers;
  95. static const void* cv_base /* = 0 */;
  96. static BOOL dump_cv_sst_module(const OMFDirEntry* omfde)
  97. {
  98. const OMFModule* module;
  99. const OMFSegDesc* segDesc;
  100. int i;
  101. module = PRD(Offset(cv_base) + omfde->lfo, sizeof(OMFModule));
  102. if (!module) {printf("Can't get the OMF-Module, aborting\n"); return FALSE;}
  103. printf(" olvNumber: %u\n", module->ovlNumber);
  104. printf(" iLib: %u\n", module->iLib);
  105. printf(" cSeg: %u\n", module->cSeg);
  106. printf(" Style: %c%c\n", module->Style[0], module->Style[1]);
  107. printf(" Name: %.*s\n",
  108. *(const BYTE*)((const char*)(module + 1) + sizeof(OMFSegDesc) * module->cSeg),
  109. (const char*)(module + 1) + sizeof(OMFSegDesc) * module->cSeg + 1);
  110. segDesc = PRD(Offset(module + 1), sizeof(OMFSegDesc) * module->cSeg);
  111. if (!segDesc) {printf("Can't get the OMF-SegDesc, aborting\n"); return FALSE;}
  112. for (i = 0; i < module->cSeg; i++)
  113. {
  114. printf (" segment #%2d: offset = [0x%8x], size = [0x%8x]\n",
  115. segDesc->Seg, segDesc->Off, segDesc->cbSeg);
  116. segDesc++;
  117. }
  118. return TRUE;
  119. }
  120. static BOOL dump_cv_sst_global_pub(const OMFDirEntry* omfde)
  121. {
  122. long fileoffset;
  123. const OMFSymHash* header;
  124. const BYTE* symbols;
  125. fileoffset = Offset(cv_base) + omfde->lfo;
  126. printf (" GlobalPub section starts at file offset 0x%lx\n", fileoffset);
  127. printf (" Symbol table starts at 0x%lx\n", fileoffset + sizeof (OMFSymHash));
  128. printf ("\n ----- Begin Symbol Table -----\n");
  129. header = PRD(fileoffset, sizeof(OMFSymHash));
  130. if (!header) {printf("Can't get OMF-SymHash, aborting\n");return FALSE;}
  131. symbols = PRD(fileoffset + sizeof(OMFSymHash), header->cbSymbol);
  132. if (!symbols) {printf("Can't OMF-SymHash details, aborting\n"); return FALSE;}
  133. codeview_dump_symbols(symbols, header->cbSymbol);
  134. return TRUE;
  135. }
  136. static BOOL dump_cv_sst_global_sym(const OMFDirEntry* omfde)
  137. {
  138. /*** NOT YET IMPLEMENTED ***/
  139. return TRUE;
  140. }
  141. static BOOL dump_cv_sst_static_sym(const OMFDirEntry* omfde)
  142. {
  143. /*** NOT YET IMPLEMENTED ***/
  144. return TRUE;
  145. }
  146. static BOOL dump_cv_sst_libraries(const OMFDirEntry* omfde)
  147. {
  148. /*** NOT YET IMPLEMENTED ***/
  149. return TRUE;
  150. }
  151. static BOOL dump_cv_sst_global_types(const OMFDirEntry* omfde)
  152. {
  153. long fileoffset;
  154. const OMFGlobalTypes*types;
  155. const BYTE* data;
  156. unsigned sz;
  157. fileoffset = Offset(cv_base) + omfde->lfo;
  158. printf (" GlobalTypes section starts at file offset 0x%lx\n", fileoffset);
  159. printf ("\n ----- Begin Global Types Table -----\n");
  160. types = PRD(fileoffset, sizeof(OMFGlobalTypes));
  161. if (!types) {printf("Can't get OMF-GlobalTypes, aborting\n");return FALSE;}
  162. sz = omfde->cb - sizeof(OMFGlobalTypes) - sizeof(DWORD) * types->cTypes;
  163. data = PRD(fileoffset + sizeof(OMFGlobalTypes) + sizeof(DWORD) * types->cTypes, sz);
  164. if (!data) {printf("Can't OMF-SymHash details, aborting\n"); return FALSE;}
  165. /* doc says:
  166. * - for NB07 & NB08 (that we don't support yet), offsets are from types
  167. * - for NB09, offsets are from data
  168. * For now, we only support the latter
  169. */
  170. codeview_dump_types_from_offsets(data, (const DWORD*)(types + 1), types->cTypes);
  171. return TRUE;
  172. }
  173. static BOOL dump_cv_sst_seg_map(const OMFDirEntry* omfde)
  174. {
  175. const OMFSegMap* segMap;
  176. const OMFSegMapDesc* segMapDesc;
  177. int i;
  178. segMap = PRD(Offset(cv_base) + omfde->lfo, sizeof(OMFSegMap));
  179. if (!segMap) {printf("Can't get SegMap, aborting\n");return FALSE;}
  180. printf(" cSeg: %u\n", segMap->cSeg);
  181. printf(" cSegLog: %u\n", segMap->cSegLog);
  182. segMapDesc = PRD(Offset(segMap + 1), segMap->cSeg * sizeof(OMFSegDesc));
  183. if (!segMapDesc) {printf("Can't get SegDescr array, aborting\n");return FALSE;}
  184. for (i = 0; i < segMap->cSeg; i++)
  185. {
  186. printf(" SegDescr #%2d\n", i + 1);
  187. printf(" flags: %04X\n", segMapDesc[i].flags);
  188. printf(" ovl: %u\n", segMapDesc[i].ovl);
  189. printf(" group: %u\n", segMapDesc[i].group);
  190. printf(" frame: %u\n", segMapDesc[i].frame);
  191. printf(" iSegName: %u\n", segMapDesc[i].iSegName);
  192. printf(" iClassName: %u\n", segMapDesc[i].iClassName);
  193. printf(" offset: %lu\n", segMapDesc[i].offset);
  194. printf(" cbSeg: %lu\n", segMapDesc[i].cbSeg);
  195. }
  196. return TRUE;
  197. }
  198. static BOOL dump_cv_sst_file_index(const OMFDirEntry* omfde)
  199. {
  200. /*** NOT YET IMPLEMENTED ***/
  201. return TRUE;
  202. }
  203. static BOOL dump_cv_sst_src_module(const OMFDirEntry* omfde)
  204. {
  205. int i, j;
  206. const BYTE* rawdata;
  207. const unsigned long* seg_info_dw;
  208. const unsigned short* seg_info_w;
  209. unsigned ofs;
  210. const OMFSourceModule* sourceModule;
  211. const OMFSourceFile* sourceFile;
  212. const OMFSourceLine* sourceLine;
  213. rawdata = PRD(Offset(cv_base) + omfde->lfo, omfde->cb);
  214. if (!rawdata) {printf("Can't get srcModule subsection details, aborting\n");return FALSE;}
  215. /* FIXME: check ptr validity */
  216. sourceModule = (const void*)rawdata;
  217. printf (" Module table: Found %d file(s) and %d segment(s)\n",
  218. sourceModule->cFile, sourceModule->cSeg);
  219. for (i = 0; i < sourceModule->cFile; i++)
  220. {
  221. printf (" File #%2d begins at an offset of 0x%lx in this section\n",
  222. i + 1, sourceModule->baseSrcFile[i]);
  223. }
  224. /* FIXME: check ptr validity */
  225. seg_info_dw = (const void*)((const char*)(sourceModule + 1) +
  226. sizeof(unsigned long) * (sourceModule->cFile - 1));
  227. seg_info_w = (const unsigned short*)(&seg_info_dw[sourceModule->cSeg * 2]);
  228. for (i = 0; i < sourceModule->cSeg; i++)
  229. {
  230. printf (" Segment #%2d start = 0x%lx, end = 0x%lx, seg index = %u\n",
  231. i + 1, seg_info_dw[i * 2], seg_info_dw[(i * 2) + 1],
  232. seg_info_w[i]);
  233. }
  234. ofs = sizeof(OMFSourceModule) + sizeof(unsigned long) * (sourceModule->cFile - 1) +
  235. sourceModule->cSeg * (2 * sizeof(unsigned long) + sizeof(unsigned short));
  236. ofs = (ofs + 3) & ~3;
  237. /* the OMFSourceFile is quite unpleasant to use:
  238. * we have first:
  239. * unsigned short number of segments
  240. * unsigned short reserved
  241. * unsigned long baseSrcLn[# segments]
  242. * unsigned long offset[2 * #segments]
  243. * odd indices are start offsets
  244. * even indices are end offsets
  245. * unsigned char string length for file name
  246. * char file name (length is previous field)
  247. */
  248. /* FIXME: check ptr validity */
  249. sourceFile = (const void*)(rawdata + ofs);
  250. seg_info_dw = (const void*)((const char*)sourceFile + 2 * sizeof(unsigned short) +
  251. sourceFile->cSeg * sizeof(unsigned long));
  252. ofs += 2 * sizeof(unsigned short) + 3 * sourceFile->cSeg * sizeof(unsigned long);
  253. printf(" File table: %.*s\n",
  254. *(const BYTE*)((const char*)sourceModule + ofs), (const char*)sourceModule + ofs + 1);
  255. for (i = 0; i < sourceFile->cSeg; i++)
  256. {
  257. printf (" Segment #%2d start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
  258. i + 1, seg_info_dw[i * 2], seg_info_dw[(i * 2) + 1], sourceFile->baseSrcLn[i]);
  259. }
  260. /* add file name length */
  261. ofs += *(const BYTE*)((const char*)sourceModule + ofs) + 1;
  262. ofs = (ofs + 3) & ~3;
  263. for (i = 0; i < sourceModule->cSeg; i++)
  264. {
  265. sourceLine = (const void*)(rawdata + ofs);
  266. seg_info_dw = (const void*)((const char*)sourceLine + 2 * sizeof(unsigned short));
  267. seg_info_w = (const void*)(&seg_info_dw[sourceLine->cLnOff]);
  268. printf (" Line table #%2d: Found %d line numbers for segment index %d\n",
  269. i, sourceLine->cLnOff, sourceLine->Seg);
  270. for (j = 0; j < sourceLine->cLnOff; j++)
  271. {
  272. printf (" Pair #%2d: offset = [0x%8lx], linenumber = %d\n",
  273. j + 1, seg_info_dw[j], seg_info_w[j]);
  274. }
  275. ofs += 2 * sizeof(unsigned short) +
  276. sourceLine->cLnOff * (sizeof(unsigned long) + sizeof(unsigned short));
  277. ofs = (ofs + 3) & ~3;
  278. }
  279. return TRUE;
  280. }
  281. static BOOL dump_cv_sst_align_sym(const OMFDirEntry* omfde)
  282. {
  283. const char* rawdata = PRD(Offset(cv_base) + omfde->lfo, omfde->cb);
  284. if (!rawdata) {printf("Can't get srcAlignSym subsection details, aborting\n");return FALSE;}
  285. if (omfde->cb < sizeof(DWORD)) return TRUE;
  286. codeview_dump_symbols(rawdata + sizeof(DWORD), omfde->cb - sizeof(DWORD));
  287. return TRUE;
  288. }
  289. static void dump_codeview_all_modules(const OMFDirHeader *omfdh)
  290. {
  291. unsigned i;
  292. const OMFDirEntry* dirEntry;
  293. const char* str;
  294. if (!omfdh || !omfdh->cDir) return;
  295. dirEntry = PRD(Offset(omfdh + 1), omfdh->cDir * sizeof(OMFDirEntry));
  296. if (!dirEntry) {printf("Can't read DirEntry array, aborting\n"); return;}
  297. for (i = 0; i < omfdh->cDir; i++)
  298. {
  299. switch (dirEntry[i].SubSection)
  300. {
  301. case sstModule: str = "sstModule"; break;
  302. case sstAlignSym: str = "sstAlignSym"; break;
  303. case sstSrcModule: str = "sstSrcModule"; break;
  304. case sstLibraries: str = "sstLibraries"; break;
  305. case sstGlobalSym: str = "sstGlobalSym"; break;
  306. case sstGlobalPub: str = "sstGlobalPub"; break;
  307. case sstGlobalTypes: str = "sstGlobalTypes"; break;
  308. case sstSegMap: str = "sstSegMap"; break;
  309. case sstFileIndex: str = "sstFileIndex"; break;
  310. case sstStaticSym: str = "sstStaticSym"; break;
  311. default: str = "<undefined>"; break;
  312. }
  313. printf("Module #%2d (%p)\n", i + 1, &dirEntry[i]);
  314. printf(" SubSection: %04X (%s)\n", dirEntry[i].SubSection, str);
  315. printf(" iMod: %d\n", dirEntry[i].iMod);
  316. printf(" lfo: %d\n", dirEntry[i].lfo);
  317. printf(" cb: %u\n", dirEntry[i].cb);
  318. switch (dirEntry[i].SubSection)
  319. {
  320. case sstModule: dump_cv_sst_module(&dirEntry[i]); break;
  321. case sstAlignSym: dump_cv_sst_align_sym(&dirEntry[i]); break;
  322. case sstSrcModule: dump_cv_sst_src_module(&dirEntry[i]); break;
  323. case sstLibraries: dump_cv_sst_libraries(&dirEntry[i]); break;
  324. case sstGlobalSym: dump_cv_sst_global_sym(&dirEntry[i]); break;
  325. case sstGlobalPub: dump_cv_sst_global_pub(&dirEntry[i]); break;
  326. case sstGlobalTypes: dump_cv_sst_global_types(&dirEntry[i]); break;
  327. case sstSegMap: dump_cv_sst_seg_map(&dirEntry[i]); break;
  328. case sstFileIndex: dump_cv_sst_file_index(&dirEntry[i]); break;
  329. case sstStaticSym: dump_cv_sst_static_sym(&dirEntry[i]); break;
  330. default: printf("unsupported type %x\n", dirEntry[i].SubSection); break;
  331. }
  332. printf("\n");
  333. }
  334. return;
  335. }
  336. static void dump_codeview_headers(unsigned long base, unsigned long len)
  337. {
  338. const OMFDirHeader* dirHeader;
  339. const char* signature;
  340. const OMFDirEntry* dirEntry;
  341. const OMFSignature* sig;
  342. unsigned i;
  343. int modulecount = 0, alignsymcount = 0, srcmodulecount = 0, librariescount = 0;
  344. int globalsymcount = 0, globalpubcount = 0, globaltypescount = 0;
  345. int segmapcount = 0, fileindexcount = 0, staticsymcount = 0;
  346. cv_base = PRD(base, len);
  347. if (!cv_base) {printf("Can't get full debug content, aborting\n");return;}
  348. signature = cv_base;
  349. printf(" CodeView Data\n");
  350. printf(" Signature: %.4s\n", signature);
  351. if (memcmp(signature, "NB10", 4) == 0)
  352. {
  353. const CODEVIEW_PDB_DATA* pdb_data;
  354. pdb_data = cv_base;
  355. printf(" Filepos: 0x%08lX\n", pdb_data->filepos);
  356. printf(" TimeStamp: %08X (%s)\n",
  357. pdb_data->timestamp, get_time_str(pdb_data->timestamp));
  358. printf(" Age: %08X\n", pdb_data->age);
  359. printf(" Filename: %s\n", pdb_data->name);
  360. return;
  361. }
  362. if (memcmp(signature, "RSDS", 4) == 0)
  363. {
  364. const OMFSignatureRSDS* rsds_data;
  365. rsds_data = cv_base;
  366. printf(" Guid: %s\n", get_guid_str(&rsds_data->guid));
  367. printf(" Age: %08X\n", rsds_data->age);
  368. printf(" Filename: %s\n", rsds_data->name);
  369. return;
  370. }
  371. if (memcmp(signature, "NB09", 4) != 0 && memcmp(signature, "NB11", 4) != 0)
  372. {
  373. printf("Unsupported signature (%.4s), aborting\n", signature);
  374. return;
  375. }
  376. sig = cv_base;
  377. printf(" Filepos: 0x%08lX\n", sig->filepos);
  378. dirHeader = PRD(Offset(cv_base) + sig->filepos, sizeof(OMFDirHeader));
  379. if (!dirHeader) {printf("Can't get debug header, aborting\n"); return;}
  380. printf(" Size of header: 0x%4X\n", dirHeader->cbDirHeader);
  381. printf(" Size per entry: 0x%4X\n", dirHeader->cbDirEntry);
  382. printf(" # of entries: 0x%8X (%d)\n", dirHeader->cDir, dirHeader->cDir);
  383. printf(" Offset to NextDir: 0x%8X\n", dirHeader->lfoNextDir);
  384. printf(" Flags: 0x%8X\n", dirHeader->flags);
  385. if (!dirHeader->cDir) return;
  386. dirEntry = PRD(Offset(dirHeader + 1), sizeof(OMFDirEntry) * dirHeader->cDir);
  387. if (!dirEntry) {printf("Can't get DirEntry array, aborting\n");return;}
  388. for (i = 0; i < dirHeader->cDir; i++)
  389. {
  390. switch (dirEntry[i].SubSection)
  391. {
  392. case sstModule: modulecount++; break;
  393. case sstAlignSym: alignsymcount++; break;
  394. case sstSrcModule: srcmodulecount++; break;
  395. case sstLibraries: librariescount++; break;
  396. case sstGlobalSym: globalsymcount++; break;
  397. case sstGlobalPub: globalpubcount++; break;
  398. case sstGlobalTypes: globaltypescount++; break;
  399. case sstSegMap: segmapcount++; break;
  400. case sstFileIndex: fileindexcount++; break;
  401. case sstStaticSym: staticsymcount++; break;
  402. }
  403. }
  404. /* This one has to be > 0
  405. */
  406. printf ("\nFound: %d sstModule subsections\n", modulecount);
  407. if (alignsymcount > 0) printf (" %d sstAlignSym subsections\n", alignsymcount);
  408. if (srcmodulecount > 0) printf (" %d sstSrcModule subsections\n", srcmodulecount);
  409. if (librariescount > 0) printf (" %d sstLibraries subsections\n", librariescount);
  410. if (globalsymcount > 0) printf (" %d sstGlobalSym subsections\n", globalsymcount);
  411. if (globalpubcount > 0) printf (" %d sstGlobalPub subsections\n", globalpubcount);
  412. if (globaltypescount > 0) printf (" %d sstGlobalTypes subsections\n", globaltypescount);
  413. if (segmapcount > 0) printf (" %d sstSegMap subsections\n", segmapcount);
  414. if (fileindexcount > 0) printf (" %d sstFileIndex subsections\n", fileindexcount);
  415. if (staticsymcount > 0) printf (" %d sstStaticSym subsections\n", staticsymcount);
  416. dump_codeview_all_modules(dirHeader);
  417. }
  418. static const char *get_coff_name( const IMAGE_SYMBOL *coff_sym, const char *coff_strtab )
  419. {
  420. static char namebuff[9];
  421. const char* nampnt;
  422. if( coff_sym->N.Name.Short )
  423. {
  424. memcpy(namebuff, coff_sym->N.ShortName, 8);
  425. namebuff[8] = '\0';
  426. nampnt = namebuff;
  427. }
  428. else
  429. {
  430. nampnt = coff_strtab + coff_sym->N.Name.Long;
  431. }
  432. if( nampnt[0] == '_' )
  433. nampnt++;
  434. return nampnt;
  435. }
  436. static const char* storage_class(BYTE sc)
  437. {
  438. static char tmp[7];
  439. switch (sc)
  440. {
  441. case IMAGE_SYM_CLASS_STATIC: return "static";
  442. case IMAGE_SYM_CLASS_EXTERNAL: return "extrnl";
  443. case IMAGE_SYM_CLASS_LABEL: return "label ";
  444. }
  445. sprintf(tmp, "#%d", sc);
  446. return tmp;
  447. }
  448. void dump_coff_symbol_table(const IMAGE_SYMBOL *coff_symbols, unsigned num_sym,
  449. const IMAGE_SECTION_HEADER *sectHead)
  450. {
  451. const IMAGE_SYMBOL *coff_sym;
  452. const char *coff_strtab = (const char *) (coff_symbols + num_sym);
  453. unsigned int i;
  454. const char *nampnt;
  455. int naux;
  456. printf("\nDebug table: COFF format.\n");
  457. printf(" ID | seg:offs [ abs ] | Kind | symbol/function name\n");
  458. for (i=0; i < num_sym; i++)
  459. {
  460. coff_sym = coff_symbols + i;
  461. naux = coff_sym->NumberOfAuxSymbols;
  462. switch (coff_sym->StorageClass)
  463. {
  464. case IMAGE_SYM_CLASS_FILE:
  465. printf("file %s\n", (const char *) (coff_sym + 1));
  466. break;
  467. case IMAGE_SYM_CLASS_STATIC:
  468. case IMAGE_SYM_CLASS_EXTERNAL:
  469. case IMAGE_SYM_CLASS_LABEL:
  470. if (coff_sym->SectionNumber > 0)
  471. {
  472. DWORD base = sectHead[coff_sym->SectionNumber - 1].VirtualAddress;
  473. nampnt = get_coff_name( coff_sym, coff_strtab );
  474. printf("%05d | %02d:%08x [%08x] | %s | %s\n",
  475. i, coff_sym->SectionNumber - 1, coff_sym->Value,
  476. base + coff_sym->Value,
  477. storage_class(coff_sym->StorageClass), nampnt);
  478. }
  479. break;
  480. default:
  481. printf("%05d | %s\n", i, storage_class(coff_sym->StorageClass));
  482. }
  483. /*
  484. * For now, skip past the aux entries.
  485. */
  486. i += naux;
  487. }
  488. }
  489. void dump_coff(unsigned long coffbase, unsigned long len, const IMAGE_SECTION_HEADER* sectHead)
  490. {
  491. const IMAGE_COFF_SYMBOLS_HEADER *coff = PRD(coffbase, len);
  492. const IMAGE_SYMBOL *coff_symbols =
  493. (const IMAGE_SYMBOL *) ((const char *)coff + coff->LvaToFirstSymbol);
  494. dump_coff_symbol_table(coff_symbols, coff->NumberOfSymbols, sectHead);
  495. }
  496. void dump_codeview(unsigned long base, unsigned long len)
  497. {
  498. dump_codeview_headers(base, len);
  499. }
  500. void dump_frame_pointer_omission(unsigned long base, unsigned long len)
  501. {
  502. const FPO_DATA* fpo;
  503. const FPO_DATA* last;
  504. const char* x;
  505. /* FPO is used to describe nonstandard stack frames */
  506. printf("Range #loc #pmt Prlg #reg Info\n"
  507. "-----------------+----+----+----+----+------------\n");
  508. fpo = PRD(base, len);
  509. if (!fpo) {printf("Couldn't get FPO blob\n"); return;}
  510. last = (const FPO_DATA*)((const char*)fpo + len);
  511. while (fpo < last && fpo->ulOffStart)
  512. {
  513. switch (fpo->cbFrame)
  514. {
  515. case FRAME_FPO: x = "FRAME_FPO"; break;
  516. case FRAME_NONFPO: x = "FRAME_NONFPO"; break;
  517. case FRAME_TRAP: x = "FRAME_TRAP"; break;
  518. case FRAME_TSS: x = "case FRAME_TSS"; break;
  519. default: x = NULL; break;
  520. }
  521. printf("%08x-%08x %4u %4u %4u %4u %s%s%s\n",
  522. fpo->ulOffStart, fpo->ulOffStart + fpo->cbProcSize,
  523. fpo->cdwLocals, fpo->cdwParams, fpo->cbProlog, fpo->cbRegs,
  524. x, fpo->fHasSEH ? " SEH" : "", fpo->fUseBP ? " UseBP" : "");
  525. fpo++;
  526. }
  527. }
  528. struct stab_nlist
  529. {
  530. union
  531. {
  532. char* n_name;
  533. struct stab_nlist* n_next;
  534. long n_strx;
  535. } n_un;
  536. unsigned char n_type;
  537. char n_other;
  538. short n_desc;
  539. unsigned long n_value;
  540. };
  541. static const char * const stabs_defs[] = {
  542. NULL,NULL,NULL,NULL, /* 00 */
  543. NULL,NULL,NULL,NULL, /* 08 */
  544. NULL,NULL,NULL,NULL, /* 10 */
  545. NULL,NULL,NULL,NULL, /* 18 */
  546. "GSYM","FNAME","FUN","STSYM", /* 20 */
  547. "LCSYM","MAIN","ROSYM","PC", /* 28 */
  548. NULL,"NSYMS","NOMAP",NULL, /* 30 */
  549. "OBJ",NULL,"OPT",NULL, /* 38 */
  550. "RSYM","M2C","SLINE","DSLINE", /* 40 */
  551. "BSLINE","DEFD","FLINE",NULL, /* 48 */
  552. "EHDECL",NULL,"CATCH",NULL, /* 50 */
  553. NULL,NULL,NULL,NULL, /* 58 */
  554. "SSYM","ENDM","SO",NULL, /* 60 */
  555. NULL,NULL,NULL,NULL, /* 68 */
  556. NULL,NULL,NULL,NULL, /* 70 */
  557. NULL,NULL,NULL,NULL, /* 78 */
  558. "LSYM","BINCL","SOL",NULL, /* 80 */
  559. NULL,NULL,NULL,NULL, /* 88 */
  560. NULL,NULL,NULL,NULL, /* 90 */
  561. NULL,NULL,NULL,NULL, /* 98 */
  562. "PSYM","EINCL","ENTRY",NULL, /* a0 */
  563. NULL,NULL,NULL,NULL, /* a8 */
  564. NULL,NULL,NULL,NULL, /* b0 */
  565. NULL,NULL,NULL,NULL, /* b8 */
  566. "LBRAC","EXCL","SCOPE",NULL, /* c0 */
  567. NULL,NULL,NULL,NULL, /* c8 */
  568. NULL,NULL,NULL,NULL, /* d0 */
  569. NULL,NULL,NULL,NULL, /* d8 */
  570. "RBRAC","BCOMM","ECOMM",NULL, /* e0 */
  571. "ECOML","WITH",NULL,NULL, /* e8 */
  572. "NBTEXT","NBDATA","NBBSS","NBSTS", /* f0 */
  573. "NBLCS",NULL,NULL,NULL /* f8 */
  574. };
  575. void dump_stabs(const void* pv_stabs, unsigned szstabs, const char* stabstr, unsigned szstr)
  576. {
  577. int i;
  578. int nstab;
  579. const char* ptr;
  580. char* stabbuff;
  581. unsigned int stabbufflen;
  582. const struct stab_nlist* stab_ptr = pv_stabs;
  583. const char* strs_end;
  584. char n_buffer[16];
  585. nstab = szstabs / sizeof(struct stab_nlist);
  586. strs_end = stabstr + szstr;
  587. /*
  588. * Allocate a buffer into which we can build stab strings for cases
  589. * where the stab is continued over multiple lines.
  590. */
  591. stabbufflen = 65536;
  592. stabbuff = malloc(stabbufflen);
  593. stabbuff[0] = '\0';
  594. printf("#Sym n_type n_othr n_desc n_value n_strx String\n");
  595. for (i = 0; i < nstab; i++, stab_ptr++)
  596. {
  597. ptr = stabstr + stab_ptr->n_un.n_strx;
  598. if ((ptr > strs_end) || (ptr + strlen(ptr) > strs_end))
  599. {
  600. ptr = "[[*** bad string ***]]";
  601. }
  602. else if (ptr[strlen(ptr) - 1] == '\\')
  603. {
  604. /*
  605. * Indicates continuation. Append this to the buffer, and go onto the
  606. * next record. Repeat the process until we find a stab without the
  607. * '/' character, as this indicates we have the whole thing.
  608. */
  609. unsigned len = strlen(ptr);
  610. if (strlen(stabbuff) + len > stabbufflen)
  611. {
  612. stabbufflen += 65536;
  613. stabbuff = realloc(stabbuff, stabbufflen);
  614. }
  615. strcat(stabbuff, ptr);
  616. continue;
  617. }
  618. else if (stabbuff[0] != '\0')
  619. {
  620. strcat(stabbuff, ptr);
  621. ptr = stabbuff;
  622. }
  623. if ((stab_ptr->n_type & 1) || !stabs_defs[stab_ptr->n_type / 2])
  624. sprintf(n_buffer, "<0x%02x>", stab_ptr->n_type);
  625. else
  626. sprintf(n_buffer, "%-6s", stabs_defs[stab_ptr->n_type / 2]);
  627. printf("%4d %s %-8x % 6d %-8lx %-6lx %s\n",
  628. i, n_buffer, stab_ptr->n_other, stab_ptr->n_desc, stab_ptr->n_value,
  629. stab_ptr->n_un.n_strx, ptr);
  630. }
  631. free(stabbuff);
  632. }