pdb.c 33 KB

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