4 * Copyright 2006 Eric Pouech
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.
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.
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
22 #include "wine/port.h"
31 #ifdef HAVE_SYS_TYPES_H
32 # include <sys/types.h>
34 #ifdef HAVE_SYS_STAT_H
35 # include <sys/stat.h>
37 #ifdef HAVE_SYS_MMAN_H
42 #define NONAMELESSUNION
43 #define NONAMELESSSTRUCT
47 #include "wine/mscvpdb.h"
55 const struct PDB_JG_HEADER
* header
;
56 const struct PDB_JG_TOC
* toc
;
57 const struct PDB_JG_ROOT
* root
;
61 const struct PDB_DS_HEADER
* header
;
62 const struct PDB_DS_TOC
* toc
;
63 const struct PDB_DS_ROOT
* root
;
66 void* (*read_file
)(struct pdb_reader
*, DWORD
);
67 DWORD file_used
[1024];
70 static void* pdb_jg_read(const struct PDB_JG_HEADER
* pdb
, const WORD
* block_list
, int size
)
75 if (!size
) return NULL
;
77 nBlocks
= (size
+ pdb
->block_size
- 1) / pdb
->block_size
;
78 buffer
= malloc(nBlocks
* pdb
->block_size
);
80 for (i
= 0; i
< nBlocks
; i
++)
81 memcpy(buffer
+ i
* pdb
->block_size
,
82 (const char*)pdb
+ block_list
[i
] * pdb
->block_size
, pdb
->block_size
);
87 static void* pdb_jg_read_file(struct pdb_reader
* reader
, DWORD file_nr
)
89 const WORD
* block_list
;
92 if (!reader
->u
.jg
.toc
|| file_nr
>= reader
->u
.jg
.toc
->num_files
) return NULL
;
94 reader
->file_used
[file_nr
/ 32] |= 1 << (file_nr
% 32);
95 if (reader
->u
.jg
.toc
->file
[file_nr
].size
== 0 ||
96 reader
->u
.jg
.toc
->file
[file_nr
].size
== 0xFFFFFFFF)
98 block_list
= (const WORD
*) &reader
->u
.jg
.toc
->file
[reader
->u
.jg
.toc
->num_files
];
99 for (i
= 0; i
< file_nr
; i
++)
100 block_list
+= (reader
->u
.jg
.toc
->file
[i
].size
+
101 reader
->u
.jg
.header
->block_size
- 1) / reader
->u
.jg
.header
->block_size
;
103 return pdb_jg_read(reader
->u
.jg
.header
, block_list
,
104 reader
->u
.jg
.toc
->file
[file_nr
].size
);
107 static void pdb_jg_init(struct pdb_reader
* reader
)
109 reader
->u
.jg
.header
= PRD(0, sizeof(struct PDB_JG_HEADER
));
110 reader
->read_file
= pdb_jg_read_file
;
111 reader
->u
.jg
.toc
= pdb_jg_read(reader
->u
.jg
.header
,
112 reader
->u
.jg
.header
->toc_block
,
113 reader
->u
.jg
.header
->toc
.size
);
114 memset(reader
->file_used
, 0, sizeof(reader
->file_used
));
117 static DWORD
pdb_get_num_files(const struct pdb_reader
* reader
)
119 if (reader
->read_file
== pdb_jg_read_file
)
120 return reader
->u
.jg
.toc
->num_files
;
122 return reader
->u
.ds
.toc
->num_files
;
125 static DWORD
pdb_get_file_size(const struct pdb_reader
* reader
, unsigned idx
)
127 if (reader
->read_file
== pdb_jg_read_file
)
128 return reader
->u
.jg
.toc
->file
[idx
].size
;
130 return reader
->u
.ds
.toc
->file_size
[idx
];
133 static void pdb_exit(struct pdb_reader
* reader
)
139 for (i
= 0; i
< pdb_get_num_files(reader
); i
++)
141 if (reader
->file_used
[i
/ 32] & (1 << (i
% 32))) continue;
143 file
= reader
->read_file(reader
, i
);
146 size
= pdb_get_file_size(reader
, i
);
148 printf("File --unused-- #%d (%x)\n", i
, size
);
149 dump_data(file
, size
, " ");
153 if (reader
->read_file
== pdb_jg_read_file
)
155 free((char*)reader
->u
.jg
.root
);
156 free((char*)reader
->u
.jg
.toc
);
160 free((char*)reader
->u
.ds
.root
);
161 free((char*)reader
->u
.ds
.toc
);
165 static unsigned get_stream_by_name(struct pdb_reader
* reader
, const char* name
)
170 DWORD string_idx
, stream_idx
;
174 if (reader
->read_file
== pdb_jg_read_file
)
176 str
= reader
->u
.jg
.root
->names
;
177 cbstr
= reader
->u
.jg
.root
->cbNames
;
181 str
= reader
->u
.ds
.root
->names
;
182 cbstr
= reader
->u
.ds
.root
->cbNames
;
185 pdw
= (DWORD
*)(str
+ cbstr
);
186 pdw
++; /* number of ok entries */
189 /* bitfield: first dword is len (in dword), then data */
191 pdw
+= *ok_bits
++ + 1;
194 printf("unexpected value\n");
198 for (i
= 0; i
< count
; i
++)
200 if (ok_bits
[i
/ 32] & (1 << (i
% 32)))
204 if (!strcmp(name
, &str
[string_idx
])) return stream_idx
;
210 static void *read_string_table(struct pdb_reader
* reader
)
215 stream_idx
= get_stream_by_name(reader
, "/names");
216 if (stream_idx
== -1) return NULL
;
217 ret
= reader
->read_file(reader
, stream_idx
);
218 if (ret
&& *(const DWORD
*)ret
== 0xeffeeffe) return ret
;
219 printf("wrong header %x expecting 0xeffeeffe\n", *(const DWORD
*)ret
);
224 static void pdb_dump_symbols(struct pdb_reader
* reader
, PDB_STREAM_INDEXES
* sidx
)
226 PDB_SYMBOLS
* symbols
;
227 unsigned char* modimage
;
232 sidx
->FPO
= sidx
->unk0
= sidx
->unk1
= sidx
->unk2
= sidx
->unk3
= sidx
->segments
=
233 sidx
->unk4
= sidx
->unk5
= sidx
->unk6
= sidx
->FPO_EXT
= sidx
->unk7
= -1;
235 symbols
= reader
->read_file(reader
, 3);
236 if (!symbols
) return;
238 switch (symbols
->version
)
241 case 19960307: /* VC 5.0 */
242 case 19970606: /* VC 6.0 */
243 case 19990903: /* VC 7.0 */
246 printf("-Unknown symbol info version %d\n", symbols
->version
);
249 "\tsignature: %08x\n"
252 "\thash1_file: %08x\n"
253 "\thash2_file: %08x\n"
254 "\tgsym_file: %04x\n"
256 "\tmodule_size: %08x\n"
257 "\toffset_size: %08x\n"
258 "\thash_size: %08x\n"
259 "\tsrc_module_size: %08x\n"
260 "\tpdbimport_size: %08x\n"
262 "\tstream_idx_size: %08x\n"
263 "\tunknown2_size: %08x\n"
274 symbols
->module_size
,
275 symbols
->offset_size
,
277 symbols
->srcmodule_size
,
278 symbols
->pdbimport_size
,
280 symbols
->stream_index_size
,
281 symbols
->unknown2_size
,
283 get_machine_str( symbols
->machine
),
286 if (symbols
->offset_size
)
290 printf("\t----------offsets------------\n");
291 src
= (const BYTE
*)((const char*)symbols
+ sizeof(PDB_SYMBOLS
) + symbols
->module_size
);
292 dump_data(src
, symbols
->offset_size
, " ");
295 if (!(filesimage
= read_string_table(reader
))) printf("string table not found\n");
296 else filessize
= *(const DWORD
*)(filesimage
+ 8);
298 if (symbols
->srcmodule_size
)
300 const PDB_SYMBOL_SOURCE
*src
;
304 const char* start_cstr
;
307 printf("\t----------src module------------\n");
308 src
= (const PDB_SYMBOL_SOURCE
*)((const char*)symbols
+ sizeof(PDB_SYMBOLS
) +
309 symbols
->module_size
+ symbols
->offset_size
+ symbols
->hash_size
);
310 printf("\tSource Modules\n"
312 "\t\tnSrcFiles: %u\n",
313 src
->nModules
, src
->nSrcFiles
);
315 /* usage of table seems to be as follows:
316 * two arrays of WORD (src->nModules as size)
317 * - first array contains index into files for "module" compilation
318 * (module = compilation unit ??)
319 * - second array contains the number of source files in module
320 * an array of DWORD (src->nSrcFiles as size)
321 * - contains offset (in following string table) of the source file name
323 * - each string is a pascal string (ie. with its length as first BYTE) or
324 * 0-terminated string (depending on version)
326 indx
= &src
->table
[src
->nModules
];
327 offset
= (const DWORD
*)&src
->table
[2 * src
->nModules
];
328 cstr
= (const char*)&src
->table
[2 * (src
->nModules
+ src
->nSrcFiles
)];
331 for (i
= cfile
= 0; i
< src
->nModules
; i
++)
333 printf("\t\tModule[%2d]:\n", i
);
334 cfile
= src
->table
[i
];
335 for (j
= cfile
; j
< src
->nSrcFiles
&& j
< cfile
+ indx
[i
]; j
++)
337 /* FIXME: in some cases, it's a p_string but WHEN ? */
338 if (cstr
+ offset
[j
] >= (const char*)start_cstr
/* wrap around */ &&
339 cstr
+ offset
[j
] < (const char*)src
+ symbols
->srcmodule_size
)
340 printf("\t\t\tSource file: %s\n", cstr
+ offset
[j
]);
342 printf("\t\t\tSource file: <<out of bounds>>\n");
346 if (symbols
->pdbimport_size
)
348 const PDB_SYMBOL_IMPORT
* imp
;
353 printf("\t------------import--------------\n");
354 imp
= (const PDB_SYMBOL_IMPORT
*)((const char*)symbols
+ sizeof(PDB_SYMBOLS
) +
355 symbols
->module_size
+ symbols
->offset_size
+
356 symbols
->hash_size
+ symbols
->srcmodule_size
);
357 first
= (const char*)imp
;
358 last
= (const char*)imp
+ symbols
->pdbimport_size
;
359 while (imp
< (const PDB_SYMBOL_IMPORT
*)last
)
361 ptr
= (const char*)imp
+ sizeof(*imp
) + strlen(imp
->filename
);
362 printf("\tImport: %lx\n"
363 "\t\tUnknown1: %08x\n"
364 "\t\tUnknown2: %08x\n"
365 "\t\tTimeDateStamp: %08x\n"
369 (ULONG_PTR
)((const char*)imp
- (const char*)first
),
376 imp
= (const PDB_SYMBOL_IMPORT
*)(first
+ ((ptr
- first
+ strlen(ptr
) + 1 + 3) & ~3));
379 if (symbols
->stream_index_size
)
381 printf("\t------------stream indexes--------------\n");
382 switch (symbols
->stream_index_size
)
384 case sizeof(PDB_STREAM_INDEXES_OLD
):
385 /* PDB_STREAM_INDEXES is a superset of PDB_STREAM_INDEX_OLD
386 * FIXME: to be confirmed when all fields are fully understood
389 (const char*)symbols
+ sizeof(PDB_SYMBOLS
) + symbols
->module_size
+
390 symbols
->offset_size
+ symbols
->hash_size
+ symbols
->srcmodule_size
+
391 symbols
->pdbimport_size
+ symbols
->unknown2_size
,
392 sizeof(PDB_STREAM_INDEXES_OLD
));
393 printf("\tFPO: %04x\n"
398 "\tSegments: %04x\n",
399 sidx
->FPO
, sidx
->unk0
, sidx
->unk1
, sidx
->unk2
, sidx
->unk3
,
402 case sizeof(PDB_STREAM_INDEXES
):
404 (const char*)symbols
+ sizeof(PDB_SYMBOLS
) + symbols
->module_size
+
405 symbols
->offset_size
+ symbols
->hash_size
+ symbols
->srcmodule_size
+
406 symbols
->pdbimport_size
+ symbols
->unknown2_size
,
408 printf("\tFPO: %04x\n"
419 sidx
->FPO
, sidx
->unk0
, sidx
->unk1
, sidx
->unk2
, sidx
->unk3
,
420 sidx
->segments
, sidx
->unk4
, sidx
->unk5
, sidx
->unk6
, sidx
->FPO_EXT
,
424 printf("unexpected size for stream index %d\n", symbols
->stream_index_size
);
429 /* Read global symbol table */
430 modimage
= reader
->read_file(reader
, symbols
->gsym_file
);
433 printf("\t------------globals-------------\n");
434 codeview_dump_symbols(modimage
, pdb_get_file_size(reader
, symbols
->gsym_file
));
438 /* Read per-module symbol / linenumber tables */
439 file
= (const char*)symbols
+ sizeof(PDB_SYMBOLS
);
440 while (file
- (const char*)symbols
< sizeof(PDB_SYMBOLS
) + symbols
->module_size
)
442 int file_nr
, symbol_size
, lineno_size
;
443 const char* file_name
;
445 if (symbols
->version
< 19970000)
447 const PDB_SYMBOL_FILE
* sym_file
= (const PDB_SYMBOL_FILE
*) file
;
448 file_nr
= sym_file
->file
;
449 file_name
= sym_file
->filename
;
450 symbol_size
= sym_file
->symbol_size
;
451 lineno_size
= sym_file
->lineno_size
;
452 printf("\t--------symbol file----------- %s\n", file_name
);
453 printf("\tgot symbol_file\n"
454 "\t\tunknown1: %08x\n"
456 "\t\t\tsegment: %04x\n"
458 "\t\t\toffset: %08x\n"
460 "\t\t\tcharacteristics: %08x\n"
461 "\t\t\tindex: %04x\n"
465 "\t\tsymb size: %08x\n"
466 "\t\tline size: %08x\n"
467 "\t\tunknown2: %08x\n"
468 "\t\tnSrcFiles: %08x\n"
469 "\t\tattribute: %08x\n",
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
,
480 sym_file
->symbol_size
,
481 sym_file
->lineno_size
,
484 sym_file
->attribute
);
488 const PDB_SYMBOL_FILE_EX
* sym_file
= (const PDB_SYMBOL_FILE_EX
*) file
;
489 file_nr
= sym_file
->file
;
490 file_name
= sym_file
->filename
;
491 symbol_size
= sym_file
->symbol_size
;
492 lineno_size
= sym_file
->lineno_size
;
493 printf("\t--------symbol file----------- %s\n", file_name
);
494 printf("\t\tunknown1: %08x\n"
496 "\t\t\tsegment: %04x\n"
498 "\t\t\toffset: %08x\n"
500 "\t\t\tcharacteristics: %08x\n"
501 "\t\t\tindex: %04x\n"
503 "\t\t\ttimestamp: %08x\n"
504 "\t\t\tunknown: %08x\n"
507 "\t\tsymb size: %08x\n"
508 "\t\tline size: %08x\n"
509 "\t\tunknown2: %08x\n"
510 "\t\tnSrcFiles: %08x\n"
511 "\t\tattribute: %08x\n"
512 "\t\treserved/0: %08x\n"
513 "\t\treserved/1: %08x\n",
515 sym_file
->range
.segment
,
516 sym_file
->range
.pad1
,
517 sym_file
->range
.offset
,
518 sym_file
->range
.size
,
519 sym_file
->range
.characteristics
,
520 sym_file
->range
.index
,
521 sym_file
->range
.pad2
,
522 sym_file
->range
.timestamp
,
523 sym_file
->range
.unknown
,
526 sym_file
->symbol_size
,
527 sym_file
->lineno_size
,
531 sym_file
->reserved
[0],
532 sym_file
->reserved
[1]);
534 modimage
= reader
->read_file(reader
, file_nr
);
537 int total_size
= pdb_get_file_size(reader
, file_nr
);
540 codeview_dump_symbols((const char*)modimage
+ sizeof(DWORD
), symbol_size
);
542 /* line number info */
544 codeview_dump_linetab((const char*)modimage
+ symbol_size
, TRUE
, " ");
545 /* anyway, lineno_size doesn't see to really be the size of the line number information, and
546 * it's not clear yet when to call for linetab2...
548 codeview_dump_linetab2((const char*)modimage
+ symbol_size
+ lineno_size
,
549 total_size
- (symbol_size
+ lineno_size
),
550 filesimage
? filesimage
+ 12 : NULL
, filessize
, " ");
551 /* what's that part ??? */
553 dump_data(modimage
+ symbol_size
+ lineno_size
, total_size
- (symbol_size
+ lineno_size
), " ");
557 file_name
+= strlen(file_name
) + 1;
558 file
= (char*)((DWORD_PTR
)(file_name
+ strlen(file_name
) + 1 + 3) & ~3);
564 static void pdb_dump_types(struct pdb_reader
* reader
)
566 PDB_TYPES
* types
= NULL
;
568 types
= reader
->read_file(reader
, 2);
570 switch (types
->version
)
572 case 19950410: /* VC 4.0 */
574 case 19961031: /* VC 5.0 / 6.0 */
575 case 19990903: /* VC 7.0 */
576 case 20040203: /* VC 8.0 */
579 printf("-Unknown type info version %d\n", types
->version
);
582 /* Read type table */
585 "\ttype_offset: %08x\n"
586 "\tfirst_index: %x\n"
593 "\thash_offset: %x\n"
595 "\tsearch_offset: %x\n"
597 "\tunknown_offset: %x\n"
598 "\tunknown_len: %x\n",
610 types
->search_offset
,
612 types
->unknown_offset
,
614 codeview_dump_types_from_block((const char*)types
+ types
->type_offset
, types
->type_size
);
618 static void pdb_dump_fpo(struct pdb_reader
* reader
, unsigned stream_idx
)
622 const char* frame_type
[4] = {"Fpo", "Trap", "Tss", "NonFpo"};
624 if (stream_idx
== (WORD
)-1) return;
625 fpo
= reader
->read_file(reader
, stream_idx
);
626 size
= pdb_get_file_size(reader
, stream_idx
);
627 if (fpo
&& (size
% sizeof(*fpo
)) == 0)
629 size
/= sizeof(*fpo
);
630 printf("FPO data:\n\t Start Length #loc #pmt #prolog #reg frame SEH /BP\n");
631 for (i
= 0; i
< size
; i
++)
633 printf("\t%08x %08x %4d %4d %7d %4d %6s %c %c\n",
634 fpo
[i
].ulOffStart
, fpo
[i
].cbProcSize
, fpo
[i
].cdwLocals
, fpo
[i
].cdwParams
,
635 fpo
[i
].cbProlog
, fpo
[i
].cbRegs
, frame_type
[fpo
[i
].cbFrame
],
636 fpo
[i
].fHasSEH
? 'Y' : 'N', fpo
[i
].fUseBP
? 'Y' : 'N');
642 static void pdb_dump_fpo_ext(struct pdb_reader
* reader
, unsigned stream_idx
)
644 PDB_FPO_DATA
* fpoext
;
645 unsigned i
, size
, strsize
;
648 if (stream_idx
== (WORD
)-1) return;
649 strbase
= read_string_table(reader
);
650 if (!strbase
) return;
652 strsize
= *(const DWORD
*)(strbase
+ 8);
653 fpoext
= reader
->read_file(reader
, stream_idx
);
654 size
= pdb_get_file_size(reader
, stream_idx
);
655 if (fpoext
&& (size
% sizeof(*fpoext
)) == 0)
657 size
/= sizeof(*fpoext
);
658 printf("FPO data (extended):\n"
659 "\t Start Length Locals Params MaxStack Prolog #SavedRegs Flags Command\n");
660 for (i
= 0; i
< size
; i
++)
662 printf("\t%08x %08x %8x %8x %8x %6x %8x %08x %s\n",
663 fpoext
[i
].start
, fpoext
[i
].func_size
, fpoext
[i
].locals_size
, fpoext
[i
].params_size
,
664 fpoext
[i
].maxstack_size
, fpoext
[i
].prolog_size
, fpoext
[i
].savedregs_size
, fpoext
[i
].flags
,
665 fpoext
[i
].str_offset
< strsize
? strbase
+ 12 + fpoext
[i
].str_offset
: "<out of bounds>");
672 static void pdb_dump_segments(struct pdb_reader
* reader
, unsigned stream_idx
)
678 if (stream_idx
== (WORD
)-1) return;
679 segs
= reader
->read_file(reader
, stream_idx
);
683 size
= pdb_get_file_size(reader
, stream_idx
);
684 for (ptr
= segs
; ptr
< segs
+ size
; )
686 printf("Segment %s\n", ptr
);
687 ptr
+= (strlen(ptr
) + 1 + 3) & ~3;
688 printf("\tdword[0]: %08x\n", *(DWORD
*)ptr
); ptr
+= 4;
689 printf("\tdword[1]: %08x\n", *(DWORD
*)ptr
); ptr
+= 4;
690 printf("\tdword[2]: %08x\n", *(DWORD
*)ptr
); ptr
+= 4;
691 printf("\tdword[3]: %08x\n", *(DWORD
*)ptr
); ptr
+= 4;
692 printf("\tdword[4]: %08x\n", *(DWORD
*)ptr
); ptr
+= 4;
693 printf("\tdword[5]: %08x\n", *(DWORD
*)ptr
); ptr
+= 4;
694 printf("\tdword[6]: %08x\n", *(DWORD
*)ptr
); ptr
+= 4;
695 printf("\tdword[7]: %08x\n", *(DWORD
*)ptr
); ptr
+= 4;
698 } else printf("nosdfsdffd\n");
701 static const char pdb2
[] = "Microsoft C/C++ program database 2.00";
703 static void pdb_jg_dump(void)
705 struct pdb_reader reader
;
708 * Read in TOC and well-known files
710 pdb_jg_init(&reader
);
711 printf("Header (JG):\n"
713 "\tsignature: %08x\n"
714 "\tblock_size: %08x\n"
715 "\tfree_list: %04x\n"
716 "\ttotal_alloc:%04x\n",
717 (int)sizeof(pdb2
) - 1, reader
.u
.jg
.header
->ident
,
718 reader
.u
.jg
.header
->signature
,
719 reader
.u
.jg
.header
->block_size
,
720 reader
.u
.jg
.header
->free_list
,
721 reader
.u
.jg
.header
->total_alloc
);
723 reader
.u
.jg
.root
= reader
.read_file(&reader
, 1);
724 if (reader
.u
.jg
.root
)
730 PDB_STREAM_INDEXES sidx
;
734 "\tTimeDateStamp: %08x\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
);
742 pdw
= (DWORD
*)(reader
.u
.jg
.root
->names
+ reader
.u
.jg
.root
->cbNames
);
745 printf("\tStreams directory:\n"
751 /* bitfield: first dword is len (in dword), then data */
753 pdw
+= *ok_bits
++ + 1;
756 printf("unexpected value\n");
760 for (i
= 0; i
< count
; i
++)
762 if (ok_bits
[i
/ 32] & (1 << (i
% 32)))
764 DWORD string_idx
, stream_idx
;
767 printf("\t\t\t%2d) %-20s => %x\n", i
, &reader
.u
.jg
.root
->names
[string_idx
], stream_idx
);
771 if (numok
) printf(">>> unmatched present field with found\n");
773 /* Check for unknown versions */
774 switch (reader
.u
.jg
.root
->Version
)
776 case 19950623: /* VC 4.0 */
778 case 19960307: /* VC 5.0 */
779 case 19970604: /* VC 6.0 */
782 printf("-Unknown root block version %d\n", reader
.u
.jg
.root
->Version
);
784 pdb_dump_types(&reader
);
785 pdb_dump_symbols(&reader
, &sidx
);
786 pdb_dump_fpo(&reader
, sidx
.FPO
);
787 pdb_dump_segments(&reader
, sidx
.segments
);
789 else printf("-Unable to get root\n");
794 static void* pdb_ds_read(const struct PDB_DS_HEADER
* header
, const DWORD
* block_list
, int size
)
799 if (!size
) return NULL
;
801 nBlocks
= (size
+ header
->block_size
- 1) / header
->block_size
;
802 buffer
= malloc(nBlocks
* header
->block_size
);
804 for (i
= 0; i
< nBlocks
; i
++)
805 memcpy(buffer
+ i
* header
->block_size
,
806 (const char*)header
+ block_list
[i
] * header
->block_size
, header
->block_size
);
811 static void* pdb_ds_read_file(struct pdb_reader
* reader
, DWORD file_number
)
813 const DWORD
* block_list
;
816 if (!reader
->u
.ds
.toc
|| file_number
>= reader
->u
.ds
.toc
->num_files
) return NULL
;
818 reader
->file_used
[file_number
/ 32] |= 1 << (file_number
% 32);
819 if (reader
->u
.ds
.toc
->file_size
[file_number
] == 0 ||
820 reader
->u
.ds
.toc
->file_size
[file_number
] == 0xFFFFFFFF)
822 block_list
= reader
->u
.ds
.toc
->file_size
+ reader
->u
.ds
.toc
->num_files
;
823 for (i
= 0; i
< file_number
; i
++)
824 block_list
+= (reader
->u
.ds
.toc
->file_size
[i
] + reader
->u
.ds
.header
->block_size
- 1) /
825 reader
->u
.ds
.header
->block_size
;
827 return pdb_ds_read(reader
->u
.ds
.header
, block_list
, reader
->u
.ds
.toc
->file_size
[file_number
]);
830 static BOOL
pdb_ds_init(struct pdb_reader
* reader
)
832 reader
->u
.ds
.header
= PRD(0, sizeof(*reader
->u
.ds
.header
));
833 if (!reader
->u
.ds
.header
) return FALSE
;
834 reader
->read_file
= pdb_ds_read_file
;
835 reader
->u
.ds
.toc
= pdb_ds_read(reader
->u
.ds
.header
,
836 (const DWORD
*)((const char*)reader
->u
.ds
.header
+ reader
->u
.ds
.header
->toc_page
* reader
->u
.ds
.header
->block_size
),
837 reader
->u
.ds
.header
->toc_size
);
838 memset(reader
->file_used
, 0, sizeof(reader
->file_used
));
842 static const char pdb7
[] = "Microsoft C/C++ MSF 7.00";
844 static void pdb_ds_dump(void)
846 struct pdb_reader reader
;
848 pdb_ds_init(&reader
);
849 printf("Header (DS)\n"
850 "\tsignature: %.*s\n"
851 "\tblock_size: %08x\n"
853 "\tnum_pages: %08x\n"
856 "\ttoc_page: %08x\n",
857 (int)sizeof(pdb7
) - 1, reader
.u
.ds
.header
->signature
,
858 reader
.u
.ds
.header
->block_size
,
859 reader
.u
.ds
.header
->unknown1
,
860 reader
.u
.ds
.header
->num_pages
,
861 reader
.u
.ds
.header
->toc_size
,
862 reader
.u
.ds
.header
->unknown2
,
863 reader
.u
.ds
.header
->toc_page
);
866 * 0: JG says old toc pages, I'd say free pages (tbc, low prio)
870 * other known streams:
871 * - string table: its index is in the stream table from ROOT object under "/names"
872 * those streams get their indexes out of the PDB_STREAM_INDEXES object
875 * - extended FPO data
877 reader
.u
.ds
.root
= reader
.read_file(&reader
, 1);
878 if (reader
.u
.ds
.root
)
884 PDB_STREAM_INDEXES sidx
;
888 "\tTimeDateStamp: %08x\n"
892 reader
.u
.ds
.root
->Version
,
893 reader
.u
.ds
.root
->TimeDateStamp
,
894 reader
.u
.ds
.root
->Age
,
895 get_guid_str(&reader
.u
.ds
.root
->guid
),
896 reader
.u
.ds
.root
->cbNames
);
897 pdw
= (DWORD
*)(reader
.u
.ds
.root
->names
+ reader
.u
.ds
.root
->cbNames
);
900 printf("\tStreams directory:\n"
906 /* bitfield: first dword is len (in dword), then data */
908 pdw
+= *ok_bits
++ + 1;
911 printf("unexpected value\n");
915 for (i
= 0; i
< count
; i
++)
917 if (ok_bits
[i
/ 32] & (1 << (i
% 32)))
919 DWORD string_idx
, stream_idx
;
922 printf("\t\t\t%2d) %-20s => %x\n", i
, &reader
.u
.ds
.root
->names
[string_idx
], stream_idx
);
926 if (numok
) printf(">>> unmatched present field with found\n");
928 pdb_dump_types(&reader
);
929 pdb_dump_symbols(&reader
, &sidx
);
930 pdb_dump_fpo(&reader
, sidx
.FPO
);
931 pdb_dump_fpo_ext(&reader
, sidx
.FPO_EXT
);
932 pdb_dump_segments(&reader
, sidx
.segments
);
934 else printf("-Unable to get root\n");
939 enum FileSig
get_kind_pdb(void)
943 head
= PRD(0, sizeof(pdb2
) - 1);
944 if (head
&& !memcmp(head
, pdb2
, sizeof(pdb2
) - 1))
946 head
= PRD(0, sizeof(pdb7
) - 1);
947 if (head
&& !memcmp(head
, pdb7
, sizeof(pdb7
) - 1))
957 head
= PRD(0, sizeof(pdb2
) - 1);
958 if (head
&& !memcmp(head
, pdb2
, sizeof(pdb2
) - 1))
963 head
= PRD(0, sizeof(pdb7
) - 1);
964 if (head
&& !memcmp(head
, pdb7
, sizeof(pdb7
) - 1))
969 printf("Unrecognized header %s\n", head
);