This series contain fixes for winedump for debug information: - it fixes a bunch of incorrect information dumping, - it fixes a case of crash for .DBG files, - it allows dumping very large PDB files (>4G)
Note: for the later item, current tools' read_file() doesn't work with such large files. Instead of fixing read_file(), I opted for letting a dumper for a given file format to only use a fd to the target file, instead of forcing all dumpers to work from a full in-memory image of the target file. This is useful for PDB files, as their underlying storage requires to reassemble non-contiguous blocks, so this saves memory (the in-memory image of the target file) and one copy of the whole file. This means that all functions to guess the file format now uses a fd instead of the full image.
-- v2: tools/winedump: Support dumping large PDB files (>4G). tools/winedump: Support more than 64K files in PDB DBI module source substream. tools/winedump: Don't miss hash entries in PDB files. tools/winedump: Don't miss PDB_SYMBOL_RANGE* in PDB files. tools/winedump: Use correct field when dumping CodeView symbols. tools/winedump: Use correct computation for first section out of a .DBG file.
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- tools/winedump/pe.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/tools/winedump/pe.c b/tools/winedump/pe.c index 6a878b291de..34e22e3b27f 100644 --- a/tools/winedump/pe.c +++ b/tools/winedump/pe.c @@ -2617,7 +2617,7 @@ static void dump_dir_delay_imported_functions(void) printf("\n"); }
-static void dump_dir_debug_dir(const IMAGE_DEBUG_DIRECTORY* idd, int idx) +static void dump_dir_debug_dir(const IMAGE_DEBUG_DIRECTORY* idd, int idx, const IMAGE_SECTION_HEADER *first_section) { const char* str;
@@ -2657,8 +2657,7 @@ static void dump_dir_debug_dir(const IMAGE_DEBUG_DIRECTORY* idd, int idx) case IMAGE_DEBUG_TYPE_UNKNOWN: break; case IMAGE_DEBUG_TYPE_COFF: - dump_coff(idd->PointerToRawData, idd->SizeOfData, - IMAGE_FIRST_SECTION(PE_nt_headers)); + dump_coff(idd->PointerToRawData, idd->SizeOfData, first_section); break; case IMAGE_DEBUG_TYPE_CODEVIEW: dump_codeview(idd->PointerToRawData, idd->SizeOfData); @@ -2735,7 +2734,7 @@ static void dump_dir_debug(void)
for (i = 0; i < nb_dbg; i++) { - dump_dir_debug_dir(debugDir, i); + dump_dir_debug_dir(debugDir, i, IMAGE_FIRST_SECTION(PE_nt_headers)); debugDir++; } printf("\n"); @@ -4185,7 +4184,7 @@ void dbg_dump(void)
for (i = 0; i < nb_dbg; i++) { - dump_dir_debug_dir(debugDir, i); + dump_dir_debug_dir(debugDir, i, (const IMAGE_SECTION_HEADER*)(separateDebugHead + 1)); debugDir++; } }
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- tools/winedump/msc.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/tools/winedump/msc.c b/tools/winedump/msc.c index 997daab501b..7c61ba128a4 100644 --- a/tools/winedump/msc.c +++ b/tools/winedump/msc.c @@ -79,7 +79,7 @@ static int full_numeric_leaf(struct full_value *fv, const unsigned char *leaf)
case LF_USHORT: length += 2; - fv->v.i = *leaf; + fv->v.i = *(const unsigned short*)leaf; break;
case LF_LONG: @@ -676,21 +676,21 @@ static void do_field(const unsigned char* start, const unsigned char* end) printf("\t\tFriend function V1: '%s' type:%x\n", p_string(&fieldtype->friendfcn_v1.p_name), fieldtype->friendfcn_v1.type); - ptr += 2 + 2 + (1 + fieldtype->stmember_v2.p_name.namelen); + ptr += 2 + 2 + (1 + fieldtype->friendfcn_v1.p_name.namelen); break;
case LF_FRIENDFCN_V2: printf("\t\tFriend function V2: '%s' type:%x\n", p_string(&fieldtype->friendfcn_v2.p_name), fieldtype->friendfcn_v2.type); - ptr += 2 + 2 + 4 + (1 + fieldtype->stmember_v2.p_name.namelen); + ptr += 2 + 2 + 4 + (1 + fieldtype->friendfcn_v2.p_name.namelen); break;
case LF_FRIENDFCN_V3: printf("\t\tFriend function V3: '%s' type:%x\n", fieldtype->friendfcn_v3.name, fieldtype->friendfcn_v3.type); - ptr += 2 + 2 + 4 + (strlen(fieldtype->stmember_v3.name) + 1); + ptr += 2 + 2 + 4 + (strlen(fieldtype->friendfcn_v3.name) + 1); break;
case LF_BCLASS_V1: @@ -713,7 +713,7 @@ static void do_field(const unsigned char* start, const unsigned char* end) case LF_IVBCLASS_V1: leaf_len = numeric_leaf(&value, fieldtype->vbclass_v1.data); printf("\t\t%sirtual base class V1: type:%x (ptr:%x) attr:%s vbpoff:%d ", - (fieldtype->generic.id == LF_VBCLASS_V2) ? "V" : "Indirect v", + (fieldtype->generic.id == LF_VBCLASS_V1) ? "V" : "Indirect v", fieldtype->vbclass_v1.btype, fieldtype->vbclass_v1.vbtype, get_attr(fieldtype->vbclass_v1.attribute), value); ptr += 2 + 2 + 2 + 2 + leaf_len; @@ -724,7 +724,7 @@ static void do_field(const unsigned char* start, const unsigned char* end)
case LF_VBCLASS_V2: case LF_IVBCLASS_V2: - leaf_len = numeric_leaf(&value, fieldtype->vbclass_v1.data); + leaf_len = numeric_leaf(&value, fieldtype->vbclass_v2.data); printf("\t\t%sirtual base class V2: type:%x (ptr:%x) attr:%s vbpoff:%d ", (fieldtype->generic.id == LF_VBCLASS_V2) ? "V" : "Indirect v", fieldtype->vbclass_v2.btype, fieldtype->vbclass_v2.vbtype, @@ -902,7 +902,7 @@ static void codeview_dump_one_type(unsigned curr_type, const union codeview_type str, type->struct_v3.n_element, get_property(type->struct_v3.property), type->struct_v3.fieldlist, type->struct_v3.derived, type->struct_v3.vshape, value); - if (type->union_v3.property.has_decorated_name) + if (type->struct_v3.property.has_decorated_name) printf("\t\tDecorated name:%s\n", str + strlen(str) + 1); break;
@@ -958,7 +958,7 @@ static void codeview_dump_one_type(unsigned curr_type, const union codeview_type type->enumeration_v3.fieldlist, type->enumeration_v3.count, get_property(type->enumeration_v3.property)); - if (type->union_v3.property.has_decorated_name) + if (type->enumeration_v3.property.has_decorated_name) printf("\t\tDecorated name:%s\n", type->enumeration_v3.name + strlen(type->enumeration_v3.name) + 1); break;
@@ -990,7 +990,7 @@ static void codeview_dump_one_type(unsigned curr_type, const union codeview_type case LF_PROCEDURE_V2: printf("\t%x => Procedure V2 ret_type:%x callconv:%s attr:%s (#%u args_type:%x)\n", curr_type, type->procedure_v2.rvtype, - get_callconv(type->procedure_v2.callconv), get_funcattr(type->procedure_v1.funcattr), + get_callconv(type->procedure_v2.callconv), get_funcattr(type->procedure_v2.funcattr), type->procedure_v2.params, type->procedure_v2.arglist); break;
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- tools/winedump/pdb.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/tools/winedump/pdb.c b/tools/winedump/pdb.c index dc59695a826..4f25428d58f 100644 --- a/tools/winedump/pdb.c +++ b/tools/winedump/pdb.c @@ -579,10 +579,9 @@ static void pdb_dump_symbols(struct pdb_reader* reader) (symbols->sectcontrib_size - sizeof(unsigned)) / size, size, (symbols->sectcontrib_size - sizeof(unsigned)) % size); - src += sizeof(unsigned); - while (src + size <= last) + for (src += sizeof(unsigned); src + size <= last; src += size) { - range = (const PDB_SYMBOL_RANGE_EX*)(src + sizeof(unsigned)); + range = (const PDB_SYMBOL_RANGE_EX*)src; printf("\tRange #%tu\n", ((const BYTE*)range - ((const BYTE*)symbols + sizeof(PDB_SYMBOLS) + symbols->module_size)) / size); printf("\t\tsegment: %04x\n" @@ -607,7 +606,6 @@ static void pdb_dump_symbols(struct pdb_reader* reader) range->unknown); if (version == 0xeffe0000 + 20140516) printf("\t\tcoff_section: %08x\n", *(unsigned*)(range + 1)); - src += size; } } }
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- tools/winedump/pdb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/winedump/pdb.c b/tools/winedump/pdb.c index 4f25428d58f..718356ed207 100644 --- a/tools/winedump/pdb.c +++ b/tools/winedump/pdb.c @@ -911,7 +911,7 @@ static void pdb_dump_types_hash(struct pdb_reader* reader, const PDB_TYPES* type } printf("\n\tIndexes => offsets:\n"); table = (const unsigned*)((const BYTE*)hash + types->search_offset); - for (i = 0; i < types->search_size / (2 * sizeof(unsigned)); i += 2) + for (i = 0; i < types->search_size / (2 * sizeof(unsigned)); i++) { printf("\t\t%08x => %08x\n", table[2 * i + 0], table[2 * i + 1]); }
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- tools/winedump/pdb.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/tools/winedump/pdb.c b/tools/winedump/pdb.c index 718356ed207..298334f5779 100644 --- a/tools/winedump/pdb.c +++ b/tools/winedump/pdb.c @@ -613,7 +613,8 @@ static void pdb_dump_symbols(struct pdb_reader* reader) if (symbols->srcmodule_size && globals_dump_sect("DBI")) { const PDB_SYMBOL_SOURCE*src; - int i, j, cfile; + unsigned int i, j, cfile; + unsigned int num_source_files; const WORD* indx; const DWORD* offset; const char* start_cstr; @@ -639,15 +640,23 @@ static void pdb_dump_symbols(struct pdb_reader* reader) * 0-terminated string (depending on version) */ indx = &src->table[src->nModules]; + /* the file format limits the number of source files to 64K... so always + * recompute the number of source files and use that result instead of nSrcFiles + */ + num_source_files = 0; + for (i = 0; i < src->nModules; i++) + num_source_files += indx[i]; + if (num_source_files != src->nSrcFiles) + printf("\t\tnSrcFiles: %u (overriden by computed value)\n", num_source_files); offset = (const DWORD*)&src->table[2 * src->nModules]; - cstr = (const char*)&src->table[2 * (src->nModules + src->nSrcFiles)]; + cstr = (const char*)&src->table[2 * (src->nModules + num_source_files)]; start_cstr = cstr;
for (i = cfile = 0; i < src->nModules; i++) { printf("\t\tModule[%2d]:\n", i); cfile = src->table[i]; - for (j = cfile; j < src->nSrcFiles && j < cfile + indx[i]; j++) + for (j = cfile; j < num_source_files && j < cfile + indx[i]; j++) { /* FIXME: in some cases, it's a p_string but WHEN ? */ if (cstr + offset[j] >= start_cstr /* wrap around */ &&
From: Eric Pouech epouech@codeweavers.com
Also adding new format dump interface (using just a fd and not requiring to read first hand the whole file into memory).
Signed-off-by: Eric Pouech epouech@codeweavers.com --- tools/winedump/dump.c | 49 +++++++--- tools/winedump/pdb.c | 187 +++++++++++++++++++++++--------------- tools/winedump/winedump.h | 4 +- 3 files changed, 153 insertions(+), 87 deletions(-)
diff --git a/tools/winedump/dump.c b/tools/winedump/dump.c index fb8e248729f..6ff4c0b58a4 100644 --- a/tools/winedump/dump.c +++ b/tools/winedump/dump.c @@ -224,13 +224,15 @@ static const struct dumper enum FileSig kind; enum FileSig (*get_kind)(void); file_dumper dumper; /* default dump tool */ + enum FileSig (*alt_get_kind)( int fd ); + void (*alt_dumper)( int fd ); } dumpers[] = { {SIG_DOS, get_kind_exec, dos_dump}, {SIG_PE, get_kind_exec, pe_dump}, {SIG_DBG, get_kind_dbg, dbg_dump}, - {SIG_PDB, get_kind_pdb, pdb_dump}, + {SIG_PDB, .alt_get_kind = get_kind_pdb, .alt_dumper = pdb_dump}, {SIG_NE, get_kind_exec, ne_dump}, {SIG_LE, get_kind_exec, le_dump}, {SIG_COFFLIB, get_kind_lib, lib_dump}, @@ -249,31 +251,56 @@ dumpers[] = BOOL dump_analysis(const char *name, file_dumper fn, enum FileSig wanted_sig) { BOOL ret = TRUE; - const struct dumper *dpr; + const struct dumper*dpr; + int fd; + struct stat st;
setbuf(stdout, NULL);
- if (!(dump_base = read_file( name, &dump_total_len ))) fatal( "Cannot read file" ); - - printf("Contents of %s: %zu bytes\n\n", name, dump_total_len); + if ((fd = open( name, O_RDONLY | O_BINARY )) == -1) fatal( "Cannot read file" ); + fstat( fd, &st ); + printf("Contents of %s: %llu bytes\n\n", name, (unsigned long long)st.st_size);
for (dpr = dumpers; dpr->kind != SIG_UNKNOWN; dpr++) { - if (dpr->get_kind() == dpr->kind && + if (!dpr->alt_get_kind) continue; + /* alt interface isn't compatible with incoming file_dumper */ + if (wanted_sig == dpr->kind) + assert( !fn ); + + lseek( fd, 0, SEEK_SET ); + if (dpr->alt_get_kind( fd ) == dpr->kind && (wanted_sig == SIG_UNKNOWN || wanted_sig == dpr->kind)) { - if (fn) fn(); else dpr->dumper(); + lseek( fd, 0, SEEK_SET ); + dpr->alt_dumper( fd ); break; } } + close(fd); + if (dpr->kind == SIG_UNKNOWN) { - printf("Can't get a suitable file signature, aborting\n"); - ret = FALSE; - } + if (!(dump_base = read_file( name, &dump_total_len ))) fatal( "Cannot read file" ); + + for (dpr = dumpers; dpr->kind != SIG_UNKNOWN; dpr++) + { + if (dpr->get_kind() == dpr->kind && + (wanted_sig == SIG_UNKNOWN || wanted_sig == dpr->kind)) + { + if (fn) fn(); else dpr->dumper(); + break; + } + } + if (dpr->kind == SIG_UNKNOWN) + { + printf("Can't get a suitable file signature, aborting\n"); + ret = FALSE; + }
+ free( dump_base ); + } if (ret) printf("Done dumping %s\n", name); - free( dump_base );
return ret; } diff --git a/tools/winedump/pdb.c b/tools/winedump/pdb.c index 298334f5779..279f02d5c39 100644 --- a/tools/winedump/pdb.c +++ b/tools/winedump/pdb.c @@ -30,28 +30,36 @@ #include "winbase.h" #include "winedump.h"
+#define NUMBER_OF(x, y) (((x) + (y) - 1) / (y)) + struct pdb_reader { + int fd; union { struct { - const struct PDB_JG_HEADER* header; + const struct PDB_JG_HEADER header; const struct PDB_JG_TOC* toc; const struct PDB_JG_ROOT* root; } jg; struct { - const struct PDB_DS_HEADER* header; + const struct PDB_DS_HEADER header; const struct PDB_DS_TOC* toc; const struct PDB_DS_ROOT* root; } ds; } u; void* (*read_stream)(struct pdb_reader*, DWORD); - DWORD stream_used[1024]; + DWORD *stream_used; PDB_STRING_TABLE* global_string_table; };
+static ssize_t pdb_read_at(int fd, void *buffer, size_t count, off_t offset) +{ + return lseek(fd, offset, SEEK_SET) == (off_t)-1 ? (ssize_t)-1 : read(fd, buffer, count); +} + static inline BOOL has_stream_been_read(struct pdb_reader* reader, unsigned stream_nr) { return reader->stream_used[stream_nr / 32] & (1 << (stream_nr % 32)); @@ -67,20 +75,23 @@ static inline void clear_stream_been_read(struct pdb_reader* reader, unsigned st reader->stream_used[stream_nr / 32] &= ~(1 << (stream_nr % 32)); }
-static void* pdb_jg_read(const struct PDB_JG_HEADER* pdb, const WORD* block_list, int size) +static void* pdb_jg_read(int fd, const struct PDB_JG_HEADER* pdb, const WORD* block_list, int size) { int i, nBlocks; BYTE* buffer;
if (!size) return NULL;
- nBlocks = (size + pdb->block_size - 1) / pdb->block_size; + nBlocks = NUMBER_OF(size, pdb->block_size); buffer = xmalloc(nBlocks * pdb->block_size);
for (i = 0; i < nBlocks; i++) - memcpy(buffer + i * pdb->block_size, - (const char*)pdb + block_list[i] * pdb->block_size, pdb->block_size); - + if (pdb_read_at(fd, buffer + i * pdb->block_size, pdb->block_size, + block_list[i] * pdb->block_size) != pdb->block_size) + { + free(buffer); + return NULL; + } return buffer; }
@@ -97,25 +108,37 @@ static void* pdb_jg_read_stream(struct pdb_reader* reader, DWORD stream_nr) return NULL; block_list = (const WORD*) &reader->u.jg.toc->streams[reader->u.jg.toc->num_streams]; for (i = 0; i < stream_nr; i++) - block_list += (reader->u.jg.toc->streams[i].size + - reader->u.jg.header->block_size - 1) / reader->u.jg.header->block_size; + block_list += NUMBER_OF(reader->u.jg.toc->streams[i].size, reader->u.jg.header.block_size);
- return pdb_jg_read(reader->u.jg.header, block_list, + return pdb_jg_read(reader->fd, &reader->u.jg.header, block_list, reader->u.jg.toc->streams[stream_nr].size); }
-static BOOL pdb_jg_init(struct pdb_reader* reader) +static BOOL pdb_jg_init(int fd, struct pdb_reader* reader) { - reader->u.jg.header = PRD(0, sizeof(struct PDB_JG_HEADER)); - if (!reader->u.jg.header) return FALSE; + unsigned size_blocks; + WORD *blocks; + BOOL ret = FALSE; + + if (pdb_read_at(fd, (void*)&reader->u.jg.header, sizeof(reader->u.jg.header), 0) != sizeof(reader->u.jg.header)) return FALSE; + reader->fd = fd; reader->read_stream = pdb_jg_read_stream; - reader->u.jg.toc = pdb_jg_read(reader->u.jg.header, - reader->u.jg.header->toc_block, - reader->u.jg.header->toc.size); - memset(reader->stream_used, 0, sizeof(reader->stream_used)); - reader->u.jg.root = reader->read_stream(reader, 1); - if (!reader->u.jg.root) return FALSE; - return TRUE; + size_blocks = NUMBER_OF(reader->u.jg.header.toc.size, reader->u.jg.header.block_size) * sizeof(blocks[0]); + blocks = xmalloc(size_blocks); + ret = pdb_read_at(fd, blocks, size_blocks, + offsetof(struct PDB_JG_HEADER, toc_block)) == size_blocks; + + if (ret) + ret = (reader->u.jg.toc = pdb_jg_read(fd, &reader->u.jg.header, blocks, + reader->u.jg.header.toc.size)) != NULL; + free(blocks); + if (ret) + ret = (reader->stream_used = calloc(sizeof(DWORD), + NUMBER_OF(reader->u.jg.toc->num_streams, sizeof(DWORD) * 8))) != NULL; + if (ret) + ret = (reader->u.jg.root = reader->read_stream(reader, 1)) != NULL; + + return ret; }
static DWORD pdb_get_num_streams(const struct pdb_reader* reader) @@ -156,6 +179,7 @@ static void pdb_exit(struct pdb_reader* reader) } } free(reader->global_string_table); + free(reader->stream_used); if (reader->read_stream == pdb_jg_read_stream) { free((char*)reader->u.jg.root); @@ -1139,11 +1163,11 @@ static void pdb_jg_dump_header_root(struct pdb_reader* reader) "\tblock_size: %08x\n" "\tfree_list_block: %04x\n" "\ttotal_alloc: %04x\n", - (int)sizeof(pdb2) - 1, reader->u.jg.header->ident, - reader->u.jg.header->signature, - reader->u.jg.header->block_size, - reader->u.jg.header->free_list_block, - reader->u.jg.header->total_alloc); + (int)sizeof(pdb2) - 1, reader->u.jg.header.ident, + reader->u.jg.header.signature, + reader->u.jg.header.block_size, + reader->u.jg.header.free_list_block, + reader->u.jg.header.total_alloc);
printf("Root:\n" "\tVersion: %u\n" @@ -1195,19 +1219,23 @@ static void pdb_jg_dump_header_root(struct pdb_reader* reader) } }
-static void* pdb_ds_read(const struct PDB_DS_HEADER* header, const UINT *block_list, int size) +static void* pdb_ds_read(int fd, const struct PDB_DS_HEADER* header, const UINT *block_list, unsigned int size) { - int i, nBlocks; + unsigned int i, nBlocks; BYTE* buffer;
if (!size) return NULL;
- nBlocks = (size + header->block_size - 1) / header->block_size; + nBlocks = NUMBER_OF(size, header->block_size); buffer = xmalloc(nBlocks * header->block_size);
for (i = 0; i < nBlocks; i++) - memcpy(buffer + i * header->block_size, - (const char*)header + block_list[i] * header->block_size, header->block_size); + if (pdb_read_at(fd, buffer + i * header->block_size, header->block_size, + (size_t)block_list[i] * header->block_size) != header->block_size) + { + free(buffer); + return NULL; + }
return buffer; } @@ -1225,24 +1253,35 @@ static void* pdb_ds_read_stream(struct pdb_reader* reader, DWORD stream_number) return NULL; block_list = reader->u.ds.toc->stream_size + reader->u.ds.toc->num_streams; for (i = 0; i < stream_number; i++) - block_list += (reader->u.ds.toc->stream_size[i] + reader->u.ds.header->block_size - 1) / - reader->u.ds.header->block_size; + block_list += NUMBER_OF(reader->u.ds.toc->stream_size[i], reader->u.ds.header.block_size);
- return pdb_ds_read(reader->u.ds.header, block_list, reader->u.ds.toc->stream_size[stream_number]); + return pdb_ds_read(reader->fd, &reader->u.ds.header, block_list, reader->u.ds.toc->stream_size[stream_number]); }
-static BOOL pdb_ds_init(struct pdb_reader* reader) +static BOOL pdb_ds_init(int fd, struct pdb_reader* reader) { - reader->u.ds.header = PRD(0, sizeof(*reader->u.ds.header)); - if (!reader->u.ds.header) return FALSE; + unsigned size_blocks; + unsigned *blocks; + BOOL ret; + + if (pdb_read_at(fd, (void*)&reader->u.ds.header, sizeof(reader->u.ds.header), 0) != sizeof(reader->u.ds.header)) return FALSE; + reader->fd = fd; reader->read_stream = pdb_ds_read_stream; - reader->u.ds.toc = pdb_ds_read(reader->u.ds.header, - (const UINT *)((const char*)reader->u.ds.header + reader->u.ds.header->toc_block * reader->u.ds.header->block_size), - reader->u.ds.header->toc_size); - memset(reader->stream_used, 0, sizeof(reader->stream_used)); - reader->u.ds.root = reader->read_stream(reader, 1); - if (!reader->u.ds.root) return FALSE; - return TRUE; + size_blocks = NUMBER_OF(reader->u.ds.header.toc_size, reader->u.ds.header.block_size) * sizeof(blocks[0]); + blocks = xmalloc(size_blocks); + ret = pdb_read_at(fd, blocks, size_blocks, + (size_t)reader->u.ds.header.toc_block * reader->u.ds.header.block_size) == size_blocks; + if (ret) + ret = (reader->u.ds.toc = pdb_ds_read(reader->fd, &reader->u.ds.header, + blocks, reader->u.ds.header.toc_size)) != NULL; + free(blocks); + if (ret) + ret = (reader->stream_used = calloc(sizeof(DWORD), + NUMBER_OF(reader->u.ds.toc->num_streams, sizeof(DWORD) * 8))) != NULL; + if (ret) + ret = (reader->u.ds.root = reader->read_stream(reader, 1)) != NULL; + + return ret; }
static const char pdb7[] = "Microsoft C/C++ MSF 7.00"; @@ -1265,19 +1304,19 @@ static void pdb_ds_dump_header_root(struct pdb_reader* reader) "\ttoc_size: %08x\n" "\tunknown2: %08x\n" "\ttoc_block: %08x\n", - (int)sizeof(pdb7) - 1, reader->u.ds.header->signature, - reader->u.ds.header->block_size, - reader->u.ds.header->free_list_block, - reader->u.ds.header->num_blocks, - reader->u.ds.header->toc_size, - reader->u.ds.header->unknown2, - reader->u.ds.header->toc_block); + (int)sizeof(pdb7) - 1, reader->u.ds.header.signature, + reader->u.ds.header.block_size, + reader->u.ds.header.free_list_block, + reader->u.ds.header.num_blocks, + reader->u.ds.header.toc_size, + reader->u.ds.header.unknown2, + reader->u.ds.header.toc_block);
block_list = reader->u.ds.toc->stream_size + reader->u.ds.toc->num_streams; printf("\t\tnum_streams: %u\n", reader->u.ds.toc->num_streams); for (ofs = i = 0; i < reader->u.ds.toc->num_streams; i++) { - unsigned int nblk = (reader->u.ds.toc->stream_size[i] + reader->u.ds.header->block_size - 1) / reader->u.ds.header->block_size; + unsigned int nblk = NUMBER_OF(reader->u.ds.toc->stream_size[i], reader->u.ds.header.block_size); printf("\t\tstream[%#x]:\tsize: %u\n", i, reader->u.ds.toc->stream_size[i]); if (nblk) { @@ -1355,46 +1394,46 @@ static void pdb_ds_dump_header_root(struct pdb_reader* reader) } }
-enum FileSig get_kind_pdb(void) +enum FileSig get_kind_pdb(int fd) { - const char* head; + char tmp[max(sizeof(pdb7), sizeof(pdb2)) - 1];
- head = PRD(0, sizeof(pdb2) - 1); - if (head && !memcmp(head, pdb2, sizeof(pdb2) - 1)) - return SIG_PDB; - head = PRD(0, sizeof(pdb7) - 1); - if (head && !memcmp(head, pdb7, sizeof(pdb7) - 1)) + if (read(fd, tmp, sizeof(tmp)) == sizeof(tmp) && + (!memcmp(tmp, pdb2, sizeof(pdb2) - 1) || + !memcmp(tmp, pdb7, sizeof(pdb7) - 1))) return SIG_PDB; return SIG_UNKNOWN; }
-void pdb_dump(void) +void pdb_dump(int fd) { - const BYTE* head; + char tmp[max(sizeof(pdb2), sizeof(pdb7)) - 1]; const char** saved_dumpsect = globals.dumpsect; static const char* default_dumpsect[] = {"DBI", "TPI", "IPI", NULL}; struct pdb_reader reader;
if (!globals.dumpsect) globals.dumpsect = default_dumpsect;
- if ((head = PRD(0, sizeof(pdb2) - 1)) && !memcmp(head, pdb2, sizeof(pdb2) - 1)) + if (read(fd, tmp, sizeof(tmp)) == sizeof(tmp)) { - if (!pdb_jg_init(&reader)) + if (!memcmp(tmp, pdb2, sizeof(pdb2) - 1)) { - printf("Unable to get header information\n"); - return; + if (!pdb_jg_init(fd, &reader)) + { + printf("Unable to get header information\n"); + return; + } + pdb_jg_dump_header_root(&reader); } - - pdb_jg_dump_header_root(&reader); - } - else if ((head = PRD(0, sizeof(pdb7) - 1)) && !memcmp(head, pdb7, sizeof(pdb7) - 1)) - { - if (!pdb_ds_init(&reader)) + else if (!memcmp(tmp, pdb7, sizeof(pdb7) - 1)) { - printf("Unable to get header information\n"); - return; + if (!pdb_ds_init(fd, &reader)) + { + printf("Unable to get header information\n"); + return; + } + pdb_ds_dump_header_root(&reader); } - pdb_ds_dump_header_root(&reader); } mark_stream_been_read(&reader, 0); /* mark stream #0 (old TOC) as read */
diff --git a/tools/winedump/winedump.h b/tools/winedump/winedump.h index d15eacf2971..975a6bb1bf4 100644 --- a/tools/winedump/winedump.h +++ b/tools/winedump/winedump.h @@ -260,8 +260,8 @@ enum FileSig get_kind_emfspool(void); void emfspool_dump(void); enum FileSig get_kind_mf(void); void mf_dump(void); -enum FileSig get_kind_pdb(void); -void pdb_dump(void); +enum FileSig get_kind_pdb(int fd); +void pdb_dump(int fd); enum FileSig get_kind_fnt(void); void fnt_dump( void ); enum FileSig get_kind_tlb(void);
pushed V2:
* no longer changing all existing format detection routines * no longer using pread * added another fix for >64k source files in PDB