pdb.c 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057
  1. /*
  2. * PDB dumping utility
  3. *
  4. * Copyright 2006 Eric Pouech
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  19. */
  20. #include "config.h"
  21. #include <stdlib.h>
  22. #include <stdarg.h>
  23. #include <stdio.h>
  24. #include <time.h>
  25. #include <fcntl.h>
  26. #define NONAMELESSUNION
  27. #include "windef.h"
  28. #include "winbase.h"
  29. #include "winedump.h"
  30. #include "wine/mscvpdb.h"
  31. struct pdb_reader
  32. {
  33. union
  34. {
  35. struct
  36. {
  37. const struct PDB_JG_HEADER* header;
  38. const struct PDB_JG_TOC* toc;
  39. const struct PDB_JG_ROOT* root;
  40. } jg;
  41. struct
  42. {
  43. const struct PDB_DS_HEADER* header;
  44. const struct PDB_DS_TOC* toc;
  45. const struct PDB_DS_ROOT* root;
  46. } ds;
  47. } u;
  48. void* (*read_file)(struct pdb_reader*, DWORD);
  49. DWORD file_used[1024];
  50. };
  51. static inline BOOL has_file_been_read(struct pdb_reader* reader, unsigned file_nr)
  52. {
  53. return reader->file_used[file_nr / 32] & (1 << (file_nr % 32));
  54. }
  55. static inline void mark_file_been_read(struct pdb_reader* reader, unsigned file_nr)
  56. {
  57. reader->file_used[file_nr / 32] |= 1 << (file_nr % 32);
  58. }
  59. static inline void clear_file_been_read(struct pdb_reader* reader, unsigned file_nr)
  60. {
  61. reader->file_used[file_nr / 32] &= ~(1 << (file_nr % 32));
  62. }
  63. static void* pdb_jg_read(const struct PDB_JG_HEADER* pdb, const WORD* block_list, int size)
  64. {
  65. int i, nBlocks;
  66. BYTE* buffer;
  67. if (!size) return NULL;
  68. nBlocks = (size + pdb->block_size - 1) / pdb->block_size;
  69. buffer = xmalloc(nBlocks * pdb->block_size);
  70. for (i = 0; i < nBlocks; i++)
  71. memcpy(buffer + i * pdb->block_size,
  72. (const char*)pdb + block_list[i] * pdb->block_size, pdb->block_size);
  73. return buffer;
  74. }
  75. static void* pdb_jg_read_file(struct pdb_reader* reader, DWORD file_nr)
  76. {
  77. const WORD* block_list;
  78. DWORD i;
  79. if (!reader->u.jg.toc || file_nr >= reader->u.jg.toc->num_files) return NULL;
  80. mark_file_been_read(reader, file_nr);
  81. if (reader->u.jg.toc->file[file_nr].size == 0 ||
  82. reader->u.jg.toc->file[file_nr].size == 0xFFFFFFFF)
  83. return NULL;
  84. block_list = (const WORD*) &reader->u.jg.toc->file[reader->u.jg.toc->num_files];
  85. for (i = 0; i < file_nr; i++)
  86. block_list += (reader->u.jg.toc->file[i].size +
  87. reader->u.jg.header->block_size - 1) / reader->u.jg.header->block_size;
  88. return pdb_jg_read(reader->u.jg.header, block_list,
  89. reader->u.jg.toc->file[file_nr].size);
  90. }
  91. static void pdb_jg_init(struct pdb_reader* reader)
  92. {
  93. reader->u.jg.header = PRD(0, sizeof(struct PDB_JG_HEADER));
  94. reader->read_file = pdb_jg_read_file;
  95. reader->u.jg.toc = pdb_jg_read(reader->u.jg.header,
  96. reader->u.jg.header->toc_block,
  97. reader->u.jg.header->toc.size);
  98. memset(reader->file_used, 0, sizeof(reader->file_used));
  99. }
  100. static DWORD pdb_get_num_files(const struct pdb_reader* reader)
  101. {
  102. if (reader->read_file == pdb_jg_read_file)
  103. return reader->u.jg.toc->num_files;
  104. else
  105. return reader->u.ds.toc->num_files;
  106. }
  107. static DWORD pdb_get_file_size(const struct pdb_reader* reader, unsigned idx)
  108. {
  109. if (reader->read_file == pdb_jg_read_file)
  110. return reader->u.jg.toc->file[idx].size;
  111. else
  112. return reader->u.ds.toc->file_size[idx];
  113. }
  114. static void pdb_exit(struct pdb_reader* reader)
  115. {
  116. unsigned i;
  117. unsigned char* file;
  118. DWORD size;
  119. for (i = 0; i < pdb_get_num_files(reader); i++)
  120. {
  121. if (has_file_been_read(reader, i)) continue;
  122. file = reader->read_file(reader, i);
  123. if (!file) continue;
  124. size = pdb_get_file_size(reader, i);
  125. printf("File --unused-- #%d (%x)\n", i, size);
  126. dump_data(file, size, " ");
  127. free(file);
  128. }
  129. if (reader->read_file == pdb_jg_read_file)
  130. {
  131. free((char*)reader->u.jg.root);
  132. free((char*)reader->u.jg.toc);
  133. }
  134. else
  135. {
  136. free((char*)reader->u.ds.root);
  137. free((char*)reader->u.ds.toc);
  138. }
  139. }
  140. static unsigned get_stream_by_name(struct pdb_reader* reader, const char* name)
  141. {
  142. DWORD* pdw;
  143. DWORD* ok_bits;
  144. DWORD cbstr, count;
  145. DWORD string_idx, stream_idx;
  146. unsigned i;
  147. const char* str;
  148. if (reader->read_file == pdb_jg_read_file)
  149. {
  150. str = reader->u.jg.root->names;
  151. cbstr = reader->u.jg.root->cbNames;
  152. }
  153. else
  154. {
  155. str = reader->u.ds.root->names;
  156. cbstr = reader->u.ds.root->cbNames;
  157. }
  158. pdw = (DWORD*)(str + cbstr);
  159. pdw++; /* number of ok entries */
  160. count = *pdw++;
  161. /* bitfield: first dword is len (in dword), then data */
  162. ok_bits = pdw;
  163. pdw += *ok_bits++ + 1;
  164. if (*pdw++ != 0)
  165. {
  166. printf("unexpected value\n");
  167. return -1;
  168. }
  169. for (i = 0; i < count; i++)
  170. {
  171. if (ok_bits[i / 32] & (1 << (i % 32)))
  172. {
  173. string_idx = *pdw++;
  174. stream_idx = *pdw++;
  175. if (!strcmp(name, &str[string_idx])) return stream_idx;
  176. }
  177. }
  178. return -1;
  179. }
  180. static void *read_string_table(struct pdb_reader* reader)
  181. {
  182. unsigned stream_idx;
  183. void* ret;
  184. stream_idx = get_stream_by_name(reader, "/names");
  185. if (stream_idx == -1) return NULL;
  186. ret = reader->read_file(reader, stream_idx);
  187. if (!ret) return NULL;
  188. if(*(const DWORD*)ret == 0xeffeeffe) return ret;
  189. printf("wrong header %x expecting 0xeffeeffe\n", *(const DWORD*)ret);
  190. free( ret );
  191. return NULL;
  192. }
  193. static void dump_global_symbol(struct pdb_reader* reader, unsigned file)
  194. {
  195. void* global = NULL;
  196. DWORD size;
  197. global = reader->read_file(reader, file);
  198. if (!global) return;
  199. size = pdb_get_file_size(reader, file);
  200. printf("Global symbols table:\n");
  201. dump_data(global, size, "\t");
  202. free(global);
  203. }
  204. static void dump_public_symbol(struct pdb_reader* reader, unsigned file)
  205. {
  206. void* public = NULL;
  207. DWORD size;
  208. public = reader->read_file(reader, file);
  209. if (!public) return;
  210. size = pdb_get_file_size(reader, file);
  211. printf("Public symbols table:\n");
  212. dump_data(public, size, "\t");
  213. free(public);
  214. }
  215. static void pdb_dump_symbols(struct pdb_reader* reader, PDB_STREAM_INDEXES* sidx)
  216. {
  217. PDB_SYMBOLS* symbols;
  218. unsigned char* modimage;
  219. const char* file;
  220. char* filesimage;
  221. DWORD filessize = 0;
  222. char tcver[32];
  223. sidx->FPO = sidx->unk0 = sidx->unk1 = sidx->unk2 = sidx->unk3 = sidx->segments =
  224. sidx->unk4 = sidx->unk5 = sidx->unk6 = sidx->FPO_EXT = sidx->unk7 = -1;
  225. symbols = reader->read_file(reader, 3);
  226. if (!symbols) return;
  227. switch (symbols->version)
  228. {
  229. case 0: /* VC 4.0 */
  230. case 19960307: /* VC 5.0 */
  231. case 19970606: /* VC 6.0 */
  232. case 19990903: /* VC 7.0 */
  233. break;
  234. default:
  235. printf("-Unknown symbol info version %d\n", symbols->version);
  236. }
  237. if (symbols->flags & 0x8000) /* new */
  238. sprintf(tcver, "%u.%u", (symbols->flags >> 8) & 0x7f, symbols->flags & 0xff);
  239. else
  240. sprintf(tcver, "old-%x", symbols->flags);
  241. printf("Symbols:\n"
  242. "\tsignature: %08x\n"
  243. "\tversion: %u\n"
  244. "\tage: %08x\n"
  245. "\tglobal_file: %u\n"
  246. "\tbuilder: %s\n"
  247. "\tpublic_file: %u\n"
  248. "\tbldVer: %u\n"
  249. "\tgsym_file: %u\n"
  250. "\trbldVer: %u\n"
  251. "\tmodule_size: %08x\n"
  252. "\toffset_size: %08x\n"
  253. "\thash_size: %08x\n"
  254. "\tsrc_module_size: %08x\n"
  255. "\tpdbimport_size: %08x\n"
  256. "\tresvd0: %08x\n"
  257. "\tstream_idx_size: %08x\n"
  258. "\tunknown2_size: %08x\n"
  259. "\tresvd3: %04x\n"
  260. "\tmachine: %s\n"
  261. "\tresvd4 %08x\n",
  262. symbols->signature,
  263. symbols->version,
  264. symbols->age,
  265. symbols->global_file,
  266. tcver, /* from symbols->flags */
  267. symbols->public_file,
  268. symbols->bldVer,
  269. symbols->gsym_file,
  270. symbols->rbldVer,
  271. symbols->module_size,
  272. symbols->offset_size,
  273. symbols->hash_size,
  274. symbols->srcmodule_size,
  275. symbols->pdbimport_size,
  276. symbols->resvd0,
  277. symbols->stream_index_size,
  278. symbols->unknown2_size,
  279. symbols->resvd3,
  280. get_machine_str( symbols->machine ),
  281. symbols->resvd4);
  282. if (symbols->offset_size)
  283. {
  284. const BYTE* src;
  285. printf("\t----------offsets------------\n");
  286. src = (const BYTE*)((const char*)symbols + sizeof(PDB_SYMBOLS) + symbols->module_size);
  287. dump_data(src, symbols->offset_size, " ");
  288. }
  289. if (!(filesimage = read_string_table(reader))) printf("string table not found\n");
  290. else filessize = *(const DWORD*)(filesimage + 8);
  291. if (symbols->srcmodule_size)
  292. {
  293. const PDB_SYMBOL_SOURCE*src;
  294. int i, j, cfile;
  295. const WORD* indx;
  296. const DWORD* offset;
  297. const char* start_cstr;
  298. const char* cstr;
  299. printf("\t----------src module------------\n");
  300. src = (const PDB_SYMBOL_SOURCE*)((const char*)symbols + sizeof(PDB_SYMBOLS) +
  301. symbols->module_size + symbols->offset_size + symbols->hash_size);
  302. printf("\tSource Modules\n"
  303. "\t\tnModules: %u\n"
  304. "\t\tnSrcFiles: %u\n",
  305. src->nModules, src->nSrcFiles);
  306. /* usage of table seems to be as follows:
  307. * two arrays of WORD (src->nModules as size)
  308. * - first array contains index into files for "module" compilation
  309. * (module = compilation unit ??)
  310. * - second array contains the number of source files in module
  311. * an array of DWORD (src->nSrcFiles as size)
  312. * - contains offset (in following string table) of the source file name
  313. * a string table
  314. * - each string is a pascal string (ie. with its length as first BYTE) or
  315. * 0-terminated string (depending on version)
  316. */
  317. indx = &src->table[src->nModules];
  318. offset = (const DWORD*)&src->table[2 * src->nModules];
  319. cstr = (const char*)&src->table[2 * (src->nModules + src->nSrcFiles)];
  320. start_cstr = cstr;
  321. for (i = cfile = 0; i < src->nModules; i++)
  322. {
  323. printf("\t\tModule[%2d]:\n", i);
  324. cfile = src->table[i];
  325. for (j = cfile; j < src->nSrcFiles && j < cfile + indx[i]; j++)
  326. {
  327. /* FIXME: in some cases, it's a p_string but WHEN ? */
  328. if (cstr + offset[j] >= start_cstr /* wrap around */ &&
  329. cstr + offset[j] < (const char*)src + symbols->srcmodule_size)
  330. printf("\t\t\tSource file: %s\n", cstr + offset[j]);
  331. else
  332. printf("\t\t\tSource file: <<out of bounds>>\n");
  333. }
  334. }
  335. }
  336. if (symbols->pdbimport_size)
  337. {
  338. const PDB_SYMBOL_IMPORT* imp;
  339. const char* first;
  340. const char* last;
  341. const char* ptr;
  342. printf("\t------------import--------------\n");
  343. imp = (const PDB_SYMBOL_IMPORT*)((const char*)symbols + sizeof(PDB_SYMBOLS) +
  344. symbols->module_size + symbols->offset_size +
  345. symbols->hash_size + symbols->srcmodule_size);
  346. first = (const char*)imp;
  347. last = (const char*)imp + symbols->pdbimport_size;
  348. while (imp < (const PDB_SYMBOL_IMPORT*)last)
  349. {
  350. ptr = (const char*)imp + sizeof(*imp) + strlen(imp->filename);
  351. printf("\tImport: %lx\n"
  352. "\t\tUnknown1: %08x\n"
  353. "\t\tUnknown2: %08x\n"
  354. "\t\tTimeDateStamp: %08x\n"
  355. "\t\tAge: %08u\n"
  356. "\t\tfile1: %s\n"
  357. "\t\tfile2: %s\n",
  358. (ULONG_PTR)((const char*)imp - first),
  359. imp->unknown1,
  360. imp->unknown2,
  361. imp->TimeDateStamp,
  362. imp->Age,
  363. imp->filename,
  364. ptr);
  365. imp = (const PDB_SYMBOL_IMPORT*)(first + ((ptr - first + strlen(ptr) + 1 + 3) & ~3));
  366. }
  367. }
  368. if (symbols->stream_index_size)
  369. {
  370. printf("\t------------stream indexes--------------\n");
  371. switch (symbols->stream_index_size)
  372. {
  373. case sizeof(PDB_STREAM_INDEXES_OLD):
  374. /* PDB_STREAM_INDEXES is a superset of PDB_STREAM_INDEX_OLD
  375. * FIXME: to be confirmed when all fields are fully understood
  376. */
  377. memcpy(sidx,
  378. (const char*)symbols + sizeof(PDB_SYMBOLS) + symbols->module_size +
  379. symbols->offset_size + symbols->hash_size + symbols->srcmodule_size +
  380. symbols->pdbimport_size + symbols->unknown2_size,
  381. sizeof(PDB_STREAM_INDEXES_OLD));
  382. printf("\tFPO: %04x\n"
  383. "\t?: %04x\n"
  384. "\t?: %04x\n"
  385. "\t?: %04x\n"
  386. "\t?: %04x\n"
  387. "\tSegments: %04x\n",
  388. sidx->FPO, sidx->unk0, sidx->unk1, sidx->unk2, sidx->unk3,
  389. sidx->segments);
  390. break;
  391. case sizeof(PDB_STREAM_INDEXES):
  392. memcpy(sidx,
  393. (const char*)symbols + sizeof(PDB_SYMBOLS) + symbols->module_size +
  394. symbols->offset_size + symbols->hash_size + symbols->srcmodule_size +
  395. symbols->pdbimport_size + symbols->unknown2_size,
  396. sizeof(*sidx));
  397. printf("\tFPO: %04x\n"
  398. "\t?: %04x\n"
  399. "\t?: %04x\n"
  400. "\t?: %04x\n"
  401. "\t?: %04x\n"
  402. "\tSegments: %04x\n"
  403. "\t?: %04x\n"
  404. "\t?: %04x\n"
  405. "\t?: %04x\n"
  406. "\tFPO-ext: %04x\n"
  407. "\t?: %04x\n",
  408. sidx->FPO, sidx->unk0, sidx->unk1, sidx->unk2, sidx->unk3,
  409. sidx->segments, sidx->unk4, sidx->unk5, sidx->unk6, sidx->FPO_EXT,
  410. sidx->unk7);
  411. break;
  412. default:
  413. printf("unexpected size for stream index %d\n", symbols->stream_index_size);
  414. break;
  415. }
  416. }
  417. /* Read global symbol table */
  418. modimage = reader->read_file(reader, symbols->gsym_file);
  419. if (modimage)
  420. {
  421. printf("\t------------globals-------------\n");
  422. codeview_dump_symbols(modimage, 0, pdb_get_file_size(reader, symbols->gsym_file));
  423. free(modimage);
  424. }
  425. /* Read per-module symbol / linenumber tables */
  426. file = (const char*)symbols + sizeof(PDB_SYMBOLS);
  427. while (file - (const char*)symbols < sizeof(PDB_SYMBOLS) + symbols->module_size)
  428. {
  429. int file_nr, symbol_size, lineno_size, lineno2_size;
  430. const char* file_name;
  431. const char* lib_name;
  432. if (symbols->version < 19970000)
  433. {
  434. const PDB_SYMBOL_FILE* sym_file = (const PDB_SYMBOL_FILE*) file;
  435. file_nr = sym_file->file;
  436. file_name = sym_file->filename;
  437. lib_name = file_name + strlen(file_name) + 1;
  438. symbol_size = sym_file->symbol_size;
  439. lineno_size = sym_file->lineno_size;
  440. lineno2_size = sym_file->lineno2_size;
  441. printf("\t--------symbol file-----------\n");
  442. printf("\tName: %s\n", file_name);
  443. if (strcmp(file_name, lib_name)) printf("\tLibrary: %s\n", lib_name);
  444. printf("\t\tunknown1: %08x\n"
  445. "\t\trange\n"
  446. "\t\t\tsegment: %04x\n"
  447. "\t\t\tpad1: %04x\n"
  448. "\t\t\toffset: %08x\n"
  449. "\t\t\tsize: %08x\n"
  450. "\t\t\tcharacteristics: %08x\n"
  451. "\t\t\tindex: %04x\n"
  452. "\t\t\tpad2: %04x\n"
  453. "\t\tflag: %04x\n"
  454. "\t\tfile: %04x\n"
  455. "\t\tsymb size: %08x\n"
  456. "\t\tline size: %08x\n"
  457. "\t\tline2 size: %08x\n"
  458. "\t\tnSrcFiles: %08x\n"
  459. "\t\tattribute: %08x\n",
  460. sym_file->unknown1,
  461. sym_file->range.segment,
  462. sym_file->range.pad1,
  463. sym_file->range.offset,
  464. sym_file->range.size,
  465. sym_file->range.characteristics,
  466. sym_file->range.index,
  467. sym_file->range.pad2,
  468. sym_file->flag,
  469. sym_file->file,
  470. sym_file->symbol_size,
  471. sym_file->lineno_size,
  472. sym_file->lineno2_size,
  473. sym_file->nSrcFiles,
  474. sym_file->attribute);
  475. }
  476. else
  477. {
  478. const PDB_SYMBOL_FILE_EX* sym_file = (const PDB_SYMBOL_FILE_EX*) file;
  479. file_nr = sym_file->file;
  480. file_name = sym_file->filename;
  481. lib_name = file_name + strlen(file_name) + 1;
  482. symbol_size = sym_file->symbol_size;
  483. lineno_size = sym_file->lineno_size;
  484. lineno2_size = sym_file->lineno2_size;
  485. printf("\t--------symbol file-----------\n");
  486. printf("\tName: %s\n", file_name);
  487. if (strcmp(file_name, lib_name)) printf("\tLibrary: %s\n", lib_name);
  488. printf("\t\tunknown1: %08x\n"
  489. "\t\trange\n"
  490. "\t\t\tsegment: %04x\n"
  491. "\t\t\tpad1: %04x\n"
  492. "\t\t\toffset: %08x\n"
  493. "\t\t\tsize: %08x\n"
  494. "\t\t\tcharacteristics: %08x\n"
  495. "\t\t\tindex: %04x\n"
  496. "\t\t\tpad2: %04x\n"
  497. "\t\t\ttimestamp: %08x\n"
  498. "\t\t\tunknown: %08x\n"
  499. "\t\tflag: %04x\n"
  500. "\t\tfile: %04x\n"
  501. "\t\tsymb size: %08x\n"
  502. "\t\tline size: %08x\n"
  503. "\t\tline2 size: %08x\n"
  504. "\t\tnSrcFiles: %08x\n"
  505. "\t\tattribute: %08x\n"
  506. "\t\treserved/0: %08x\n"
  507. "\t\treserved/1: %08x\n",
  508. sym_file->unknown1,
  509. sym_file->range.segment,
  510. sym_file->range.pad1,
  511. sym_file->range.offset,
  512. sym_file->range.size,
  513. sym_file->range.characteristics,
  514. sym_file->range.index,
  515. sym_file->range.pad2,
  516. sym_file->range.timestamp,
  517. sym_file->range.unknown,
  518. sym_file->flag,
  519. sym_file->file,
  520. sym_file->symbol_size,
  521. sym_file->lineno_size,
  522. sym_file->lineno2_size,
  523. sym_file->nSrcFiles,
  524. sym_file->attribute,
  525. sym_file->reserved[0],
  526. sym_file->reserved[1]);
  527. }
  528. modimage = reader->read_file(reader, file_nr);
  529. if (modimage)
  530. {
  531. int total_size = pdb_get_file_size(reader, file_nr);
  532. if (symbol_size)
  533. codeview_dump_symbols((const char*)modimage, sizeof(DWORD), symbol_size);
  534. /* line number info */
  535. if (lineno_size)
  536. codeview_dump_linetab((const char*)modimage + symbol_size, TRUE, " ");
  537. else if (lineno2_size) /* actually, only one of the 2 lineno should be present */
  538. codeview_dump_linetab2((const char*)modimage + symbol_size, lineno2_size,
  539. filesimage ? filesimage + 12 : NULL, filessize, " ");
  540. /* what's that part ??? */
  541. if (0)
  542. dump_data(modimage + symbol_size + lineno_size + lineno2_size,
  543. total_size - (symbol_size + lineno_size + lineno2_size), " ");
  544. free(modimage);
  545. }
  546. file = (char*)((DWORD_PTR)(lib_name + strlen(lib_name) + 1 + 3) & ~3);
  547. }
  548. dump_global_symbol(reader, symbols->global_file);
  549. dump_public_symbol(reader, symbols->public_file);
  550. free(symbols);
  551. free(filesimage);
  552. }
  553. static void pdb_dump_types_hash(struct pdb_reader* reader, unsigned file, const char* strmname)
  554. {
  555. void* hash = NULL;
  556. DWORD size;
  557. hash = reader->read_file(reader, file);
  558. if (!hash) return;
  559. size = pdb_get_file_size(reader, file);
  560. printf("Types (%s) hash:\n", strmname);
  561. dump_data(hash, size, " ");
  562. free(hash);
  563. }
  564. /* there are two 'type' related streams, but with different indexes... */
  565. static void pdb_dump_types(struct pdb_reader* reader, unsigned strmidx, const char* strmname)
  566. {
  567. PDB_TYPES* types = NULL;
  568. BOOL used = has_file_been_read(reader, strmidx);
  569. if (pdb_get_file_size(reader, strmidx) < sizeof(*types))
  570. {
  571. if (strmidx == 2)
  572. printf("-Too small type header\n");
  573. return;
  574. }
  575. types = reader->read_file(reader, strmidx);
  576. if (!types) return;
  577. switch (types->version)
  578. {
  579. case 19950410: /* VC 4.0 */
  580. case 19951122:
  581. case 19961031: /* VC 5.0 / 6.0 */
  582. case 19990903: /* VC 7.0 */
  583. case 20040203: /* VC 8.0 */
  584. break;
  585. default:
  586. /* IPI stream is not always present in older PDB files */
  587. if (strmidx == 2)
  588. printf("-Unknown type info version %d\n", types->version);
  589. free(types);
  590. if (used) clear_file_been_read(reader, strmidx);
  591. return;
  592. }
  593. /* Read type table */
  594. printf("Types (%s):\n"
  595. "\tversion: %u\n"
  596. "\ttype_offset: %08x\n"
  597. "\tfirst_index: %x\n"
  598. "\tlast_index: %x\n"
  599. "\ttype_size: %x\n"
  600. "\tfile: %x\n"
  601. "\tpad: %x\n"
  602. "\thash_size: %x\n"
  603. "\thash_base: %x\n"
  604. "\thash_offset: %x\n"
  605. "\thash_len: %x\n"
  606. "\tsearch_offset: %x\n"
  607. "\tsearch_len: %x\n"
  608. "\tunknown_offset: %x\n"
  609. "\tunknown_len: %x\n",
  610. strmname,
  611. types->version,
  612. types->type_offset,
  613. types->first_index,
  614. types->last_index,
  615. types->type_size,
  616. types->file,
  617. types->pad,
  618. types->hash_size,
  619. types->hash_base,
  620. types->hash_offset,
  621. types->hash_len,
  622. types->search_offset,
  623. types->search_len,
  624. types->unknown_offset,
  625. types->unknown_len);
  626. codeview_dump_types_from_block((const char*)types + types->type_offset, types->type_size);
  627. pdb_dump_types_hash(reader, types->file, strmname);
  628. free(types);
  629. }
  630. static void pdb_dump_fpo(struct pdb_reader* reader, unsigned stream_idx)
  631. {
  632. FPO_DATA* fpo;
  633. unsigned i, size;
  634. const char* frame_type[4] = {"Fpo", "Trap", "Tss", "NonFpo"};
  635. if (stream_idx == (WORD)-1) return;
  636. fpo = reader->read_file(reader, stream_idx);
  637. size = pdb_get_file_size(reader, stream_idx);
  638. if (fpo && (size % sizeof(*fpo)) == 0)
  639. {
  640. size /= sizeof(*fpo);
  641. printf("FPO data:\n\t Start Length #loc #pmt #prolog #reg frame SEH /BP\n");
  642. for (i = 0; i < size; i++)
  643. {
  644. printf("\t%08x %08x %4d %4d %7d %4d %6s %c %c\n",
  645. fpo[i].ulOffStart, fpo[i].cbProcSize, fpo[i].cdwLocals, fpo[i].cdwParams,
  646. fpo[i].cbProlog, fpo[i].cbRegs, frame_type[fpo[i].cbFrame],
  647. fpo[i].fHasSEH ? 'Y' : 'N', fpo[i].fUseBP ? 'Y' : 'N');
  648. }
  649. }
  650. free(fpo);
  651. }
  652. static void pdb_dump_fpo_ext(struct pdb_reader* reader, unsigned stream_idx)
  653. {
  654. PDB_FPO_DATA* fpoext;
  655. unsigned i, size, strsize;
  656. char* strbase;
  657. if (stream_idx == (WORD)-1) return;
  658. strbase = read_string_table(reader);
  659. if (!strbase) return;
  660. strsize = *(const DWORD*)(strbase + 8);
  661. fpoext = reader->read_file(reader, stream_idx);
  662. size = pdb_get_file_size(reader, stream_idx);
  663. if (fpoext && (size % sizeof(*fpoext)) == 0)
  664. {
  665. size /= sizeof(*fpoext);
  666. printf("FPO data (extended):\n"
  667. "\t Start Length Locals Params MaxStack Prolog #SavedRegs Flags Command\n");
  668. for (i = 0; i < size; i++)
  669. {
  670. printf("\t%08x %08x %8x %8x %8x %6x %8x %08x %s\n",
  671. fpoext[i].start, fpoext[i].func_size, fpoext[i].locals_size, fpoext[i].params_size,
  672. fpoext[i].maxstack_size, fpoext[i].prolog_size, fpoext[i].savedregs_size, fpoext[i].flags,
  673. fpoext[i].str_offset < strsize ? strbase + 12 + fpoext[i].str_offset : "<out of bounds>");
  674. }
  675. }
  676. free(fpoext);
  677. free(strbase);
  678. }
  679. static void pdb_dump_segments(struct pdb_reader* reader, unsigned stream_idx)
  680. {
  681. const char* segs;
  682. DWORD size;
  683. const char* ptr;
  684. if (stream_idx == (WORD)-1) return;
  685. segs = reader->read_file(reader, stream_idx);
  686. if (segs)
  687. {
  688. size = pdb_get_file_size(reader, stream_idx);
  689. for (ptr = segs; ptr < segs + size; )
  690. {
  691. printf("Segment %s\n", ptr);
  692. ptr += (strlen(ptr) + 1 + 3) & ~3;
  693. printf("\tdword[0]: %08x\n", *(DWORD*)ptr); ptr += 4;
  694. printf("\tdword[1]: %08x\n", *(DWORD*)ptr); ptr += 4;
  695. printf("\tdword[2]: %08x\n", *(DWORD*)ptr); ptr += 4;
  696. printf("\tdword[3]: %08x\n", *(DWORD*)ptr); ptr += 4;
  697. printf("\tdword[4]: %08x\n", *(DWORD*)ptr); ptr += 4;
  698. printf("\tdword[5]: %08x\n", *(DWORD*)ptr); ptr += 4;
  699. printf("\tdword[6]: %08x\n", *(DWORD*)ptr); ptr += 4;
  700. printf("\tdword[7]: %08x\n", *(DWORD*)ptr); ptr += 4;
  701. }
  702. free((char*)segs);
  703. } else printf("nosdfsdffd\n");
  704. }
  705. static const char pdb2[] = "Microsoft C/C++ program database 2.00";
  706. static void pdb_jg_dump(void)
  707. {
  708. struct pdb_reader reader;
  709. /*
  710. * Read in TOC and well-known files
  711. */
  712. pdb_jg_init(&reader);
  713. printf("Header (JG):\n"
  714. "\tident: %.*s\n"
  715. "\tsignature: %08x\n"
  716. "\tblock_size: %08x\n"
  717. "\tfree_list: %04x\n"
  718. "\ttotal_alloc:%04x\n",
  719. (int)sizeof(pdb2) - 1, reader.u.jg.header->ident,
  720. reader.u.jg.header->signature,
  721. reader.u.jg.header->block_size,
  722. reader.u.jg.header->free_list,
  723. reader.u.jg.header->total_alloc);
  724. reader.u.jg.root = reader.read_file(&reader, 1);
  725. if (reader.u.jg.root)
  726. {
  727. DWORD* pdw;
  728. DWORD* ok_bits;
  729. DWORD numok, count;
  730. unsigned i;
  731. PDB_STREAM_INDEXES sidx;
  732. printf("Root:\n"
  733. "\tVersion: %u\n"
  734. "\tTimeDateStamp: %08x\n"
  735. "\tAge: %08x\n"
  736. "\tnames: %d\n",
  737. reader.u.jg.root->Version,
  738. reader.u.jg.root->TimeDateStamp,
  739. reader.u.jg.root->Age,
  740. (unsigned)reader.u.jg.root->cbNames);
  741. pdw = (DWORD*)(reader.u.jg.root->names + reader.u.jg.root->cbNames);
  742. numok = *pdw++;
  743. count = *pdw++;
  744. printf("\tStreams directory:\n"
  745. "\t\tok: %08x\n"
  746. "\t\tcount: %08x\n"
  747. "\t\ttable:\n",
  748. numok, count);
  749. /* bitfield: first dword is len (in dword), then data */
  750. ok_bits = pdw;
  751. pdw += *ok_bits++ + 1;
  752. if (*pdw++ != 0)
  753. {
  754. printf("unexpected value\n");
  755. return;
  756. }
  757. for (i = 0; i < count; i++)
  758. {
  759. if (ok_bits[i / 32] & (1 << (i % 32)))
  760. {
  761. DWORD string_idx, stream_idx;
  762. string_idx = *pdw++;
  763. stream_idx = *pdw++;
  764. printf("\t\t\t%2d) %-20s => %x\n", i, &reader.u.jg.root->names[string_idx], stream_idx);
  765. numok--;
  766. }
  767. }
  768. if (numok) printf(">>> unmatched present field with found\n");
  769. /* Check for unknown versions */
  770. switch (reader.u.jg.root->Version)
  771. {
  772. case 19950623: /* VC 4.0 */
  773. case 19950814:
  774. case 19960307: /* VC 5.0 */
  775. case 19970604: /* VC 6.0 */
  776. break;
  777. default:
  778. printf("-Unknown root block version %d\n", reader.u.jg.root->Version);
  779. }
  780. pdb_dump_types(&reader, 2, "TPI");
  781. pdb_dump_types(&reader, 4, "IPI");
  782. pdb_dump_symbols(&reader, &sidx);
  783. pdb_dump_fpo(&reader, sidx.FPO);
  784. pdb_dump_segments(&reader, sidx.segments);
  785. }
  786. else printf("-Unable to get root\n");
  787. pdb_exit(&reader);
  788. }
  789. static void* pdb_ds_read(const struct PDB_DS_HEADER* header, const DWORD* block_list, int size)
  790. {
  791. int i, nBlocks;
  792. BYTE* buffer;
  793. if (!size) return NULL;
  794. nBlocks = (size + header->block_size - 1) / header->block_size;
  795. buffer = xmalloc(nBlocks * header->block_size);
  796. for (i = 0; i < nBlocks; i++)
  797. memcpy(buffer + i * header->block_size,
  798. (const char*)header + block_list[i] * header->block_size, header->block_size);
  799. return buffer;
  800. }
  801. static void* pdb_ds_read_file(struct pdb_reader* reader, DWORD file_number)
  802. {
  803. const DWORD* block_list;
  804. DWORD i;
  805. if (!reader->u.ds.toc || file_number >= reader->u.ds.toc->num_files) return NULL;
  806. mark_file_been_read(reader, file_number);
  807. if (reader->u.ds.toc->file_size[file_number] == 0 ||
  808. reader->u.ds.toc->file_size[file_number] == 0xFFFFFFFF)
  809. return NULL;
  810. block_list = reader->u.ds.toc->file_size + reader->u.ds.toc->num_files;
  811. for (i = 0; i < file_number; i++)
  812. block_list += (reader->u.ds.toc->file_size[i] + reader->u.ds.header->block_size - 1) /
  813. reader->u.ds.header->block_size;
  814. return pdb_ds_read(reader->u.ds.header, block_list, reader->u.ds.toc->file_size[file_number]);
  815. }
  816. static BOOL pdb_ds_init(struct pdb_reader* reader)
  817. {
  818. reader->u.ds.header = PRD(0, sizeof(*reader->u.ds.header));
  819. if (!reader->u.ds.header) return FALSE;
  820. reader->read_file = pdb_ds_read_file;
  821. reader->u.ds.toc = pdb_ds_read(reader->u.ds.header,
  822. (const DWORD*)((const char*)reader->u.ds.header + reader->u.ds.header->toc_page * reader->u.ds.header->block_size),
  823. reader->u.ds.header->toc_size);
  824. memset(reader->file_used, 0, sizeof(reader->file_used));
  825. return TRUE;
  826. }
  827. static const char pdb7[] = "Microsoft C/C++ MSF 7.00";
  828. static void pdb_ds_dump(void)
  829. {
  830. struct pdb_reader reader;
  831. pdb_ds_init(&reader);
  832. printf("Header (DS)\n"
  833. "\tsignature: %.*s\n"
  834. "\tblock_size: %08x\n"
  835. "\tunknown1: %08x\n"
  836. "\tnum_pages: %08x\n"
  837. "\ttoc_size: %08x\n"
  838. "\tunknown2: %08x\n"
  839. "\ttoc_page: %08x\n",
  840. (int)sizeof(pdb7) - 1, reader.u.ds.header->signature,
  841. reader.u.ds.header->block_size,
  842. reader.u.ds.header->unknown1,
  843. reader.u.ds.header->num_pages,
  844. reader.u.ds.header->toc_size,
  845. reader.u.ds.header->unknown2,
  846. reader.u.ds.header->toc_page);
  847. /* files with static indexes:
  848. * 0: JG says old toc pages
  849. * 1: root structure
  850. * 2: types
  851. * 3: modules
  852. * 4: types (second stream)
  853. * other known streams:
  854. * - string table: its index is in the stream table from ROOT object under "/names"
  855. * - type hash table: its index is in the types header (2 and 4)
  856. * - global and public streams: from symbol stream header
  857. * those streams get their indexes out of the PDB_STREAM_INDEXES object
  858. * - FPO data
  859. * - segments
  860. * - extended FPO data
  861. */
  862. mark_file_been_read(&reader, 0); /* mark stream #0 as read */
  863. reader.u.ds.root = reader.read_file(&reader, 1);
  864. if (reader.u.ds.root)
  865. {
  866. DWORD* pdw;
  867. DWORD* ok_bits;
  868. DWORD numok, count;
  869. unsigned i;
  870. PDB_STREAM_INDEXES sidx;
  871. printf("Root:\n"
  872. "\tVersion: %u\n"
  873. "\tTimeDateStamp: %08x\n"
  874. "\tAge: %08x\n"
  875. "\tguid %s\n"
  876. "\tcbNames: %08x\n",
  877. reader.u.ds.root->Version,
  878. reader.u.ds.root->TimeDateStamp,
  879. reader.u.ds.root->Age,
  880. get_guid_str(&reader.u.ds.root->guid),
  881. reader.u.ds.root->cbNames);
  882. pdw = (DWORD*)(reader.u.ds.root->names + reader.u.ds.root->cbNames);
  883. numok = *pdw++;
  884. count = *pdw++;
  885. printf("\tStreams directory:\n"
  886. "\t\tok: %08x\n"
  887. "\t\tcount: %08x\n"
  888. "\t\ttable:\n",
  889. numok, count);
  890. /* bitfield: first dword is len (in dword), then data */
  891. ok_bits = pdw;
  892. pdw += *ok_bits++ + 1;
  893. if (*pdw++ != 0)
  894. {
  895. printf("unexpected value\n");
  896. return;
  897. }
  898. for (i = 0; i < count; i++)
  899. {
  900. if (ok_bits[i / 32] & (1 << (i % 32)))
  901. {
  902. DWORD string_idx, stream_idx;
  903. string_idx = *pdw++;
  904. stream_idx = *pdw++;
  905. printf("\t\t\t%2d) %-20s => %x\n", i, &reader.u.ds.root->names[string_idx], stream_idx);
  906. numok--;
  907. }
  908. }
  909. if (numok) printf(">>> unmatched present field with found\n");
  910. pdb_dump_types(&reader, 2, "TPI");
  911. pdb_dump_types(&reader, 4, "IPI");
  912. pdb_dump_symbols(&reader, &sidx);
  913. pdb_dump_fpo(&reader, sidx.FPO);
  914. pdb_dump_fpo_ext(&reader, sidx.FPO_EXT);
  915. pdb_dump_segments(&reader, sidx.segments);
  916. }
  917. else printf("-Unable to get root\n");
  918. pdb_exit(&reader);
  919. }
  920. enum FileSig get_kind_pdb(void)
  921. {
  922. const char* head;
  923. head = PRD(0, sizeof(pdb2) - 1);
  924. if (head && !memcmp(head, pdb2, sizeof(pdb2) - 1))
  925. return SIG_PDB;
  926. head = PRD(0, sizeof(pdb7) - 1);
  927. if (head && !memcmp(head, pdb7, sizeof(pdb7) - 1))
  928. return SIG_PDB;
  929. return SIG_UNKNOWN;
  930. }
  931. void pdb_dump(void)
  932. {
  933. const char* head;
  934. /* init_types(); */
  935. head = PRD(0, sizeof(pdb2) - 1);
  936. if (head && !memcmp(head, pdb2, sizeof(pdb2) - 1))
  937. {
  938. pdb_jg_dump();
  939. return;
  940. }
  941. head = PRD(0, sizeof(pdb7) - 1);
  942. if (head && !memcmp(head, pdb7, sizeof(pdb7) - 1))
  943. {
  944. pdb_ds_dump();
  945. return;
  946. }
  947. printf("Unrecognized header %s\n", head);
  948. }