From: Eric Pouech eric.pouech@gmail.com
Renamed of couple of fields in PDB structures for clarity
Signed-off-by: Eric Pouech eric.pouech@gmail.com --- dlls/dbghelp/msc.c | 2 +- include/wine/mscvpdb.h | 10 +-- tools/winedump/pdb.c | 186 +++++++++++++++++++++++++++++++++++------ 3 files changed, 165 insertions(+), 33 deletions(-)
diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index 5b45c474160..2be648ca578 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -2954,7 +2954,7 @@ static void pdb_convert_types_header(PDB_TYPES* types, const BYTE* image) types->type_size = old->type_size; types->first_index = old->first_index; types->last_index = old->last_index; - types->file = old->file; + types->hash_file = old->hash_file; } else { diff --git a/include/wine/mscvpdb.h b/include/wine/mscvpdb.h index 1772e6d10df..f0fbfa92b39 100644 --- a/include/wine/mscvpdb.h +++ b/include/wine/mscvpdb.h @@ -2403,7 +2403,7 @@ typedef struct _PDB_TYPES_OLD unsigned short first_index; unsigned short last_index; unsigned int type_size; - unsigned short file; + unsigned short hash_file; unsigned short pad; } PDB_TYPES_OLD, *PPDB_TYPES_OLD;
@@ -2414,16 +2414,16 @@ typedef struct _PDB_TYPES unsigned int first_index; unsigned int last_index; unsigned int type_size; - unsigned short file; + unsigned short hash_file; unsigned short pad; unsigned int hash_size; - unsigned int hash_base; + unsigned int hash_num_buckets; unsigned int hash_offset; unsigned int hash_len; unsigned int search_offset; unsigned int search_len; - unsigned int unknown_offset; - unsigned int unknown_len; + unsigned int type_remap_offset; + unsigned int type_remap_len; } PDB_TYPES, *PPDB_TYPES;
typedef struct _PDB_SYMBOL_RANGE diff --git a/tools/winedump/pdb.c b/tools/winedump/pdb.c index 2277e6556f9..29fc25b1785 100644 --- a/tools/winedump/pdb.c +++ b/tools/winedump/pdb.c @@ -608,18 +608,150 @@ static void pdb_dump_symbols(struct pdb_reader* reader, PDB_STREAM_INDEXES* sidx free(filesimage); }
-static void pdb_dump_types_hash(struct pdb_reader* reader, unsigned file, const char* strmname) +static BOOL is_bit_set(const unsigned* dw, unsigned len, unsigned i) { - void* hash = NULL; - DWORD size; + if (i >= len * sizeof(unsigned) * 8) return FALSE; + return (dw[i >> 5] & (1u << (i & 31u))) != 0; +}
- hash = reader->read_file(reader, file); - if (!hash) return; +static void pdb_dump_hash_value(const BYTE* ptr, unsigned len) +{ + int i;
- size = pdb_get_file_size(reader, file); + printf("["); + for (i = len - 1; i >= 0; i--) + printf("%02x", ptr[i]); + printf("]"); +} + +struct collision_arg +{ + const BYTE* hash; + unsigned hash_size; +}; + +static int collision_compar(const void *p1, const void *p2, void *_arg) +{ + unsigned idx1 = *(unsigned*)p1; + unsigned idx2 = *(unsigned*)p2; + struct collision_arg* arg = _arg; + return memcmp(arg->hash + idx1 * arg->hash_size, arg->hash + idx2 * arg->hash_size, arg->hash_size); +} + +static void pdb_dump_types_hash(struct pdb_reader* reader, const PDB_TYPES* types, const char* strmname) +{ + void* hash = NULL; + unsigned i, strmsize; + const unsigned* table; + char* strbase; + unsigned *collision; + hash = reader->read_file(reader, types->hash_file); + if (!hash) return;
printf("Types (%s) hash:\n", strmname); - dump_data(hash, size, " "); + strmsize = pdb_get_file_size(reader, types->hash_file); + if (types->hash_offset + types->hash_len > strmsize || + (types->last_index - types->first_index) * types->hash_size != types->hash_len || + types->search_offset + types->search_len > strmsize || + types->type_remap_offset + types->type_remap_len > strmsize) + { + printf("\nIncoherent sizes... skipping\n"); + return; + } + printf("\n\tIndexes => hash value:\n"); + for (i = types->first_index; i < types->last_index; i++) + { + printf("\t\t%08x => ", i); + pdb_dump_hash_value((const BYTE*)hash + types->hash_offset + (i - types->first_index) * types->hash_size, types->hash_size); + printf("\n"); + } + /* print collisions in hash table (if any) */ + collision = malloc((types->last_index - types->first_index) * sizeof(unsigned)); + if (collision) + { + struct collision_arg arg = {(const BYTE*)hash + types->hash_offset, types->hash_size}; + unsigned head_printed = 0; + for (i = 0; i < types->last_index - types->first_index; i++) collision[i] = i; + qsort_r(collision, types->last_index - types->first_index, sizeof(unsigned), collision_compar, &arg); + for (i = 0; i < types->last_index - types->first_index; i++) + { + unsigned j; + for (j = i + 1; j < types->last_index - types->first_index; j++) + if (memcmp((const BYTE*)hash + types->hash_offset + collision[i] * types->hash_size, + (const BYTE*)hash + types->hash_offset + collision[j] * types->hash_size, + types->hash_size)) + break; + if (j > i + 1) + { + unsigned k; + if (!head_printed) + { + printf("\n\t\tcollisions:\n"); + head_printed = 1; + } + printf("\t\t\tHash "); + pdb_dump_hash_value((const BYTE*)hash + types->hash_offset + collision[i] * types->hash_size, types->hash_size); + printf(":"); + for (k = i; k < j; k++) + printf(" %x", types->first_index + collision[k]); + printf("\n"); + i = j - 1; + } + } + free(collision); + } + printf("\n\tIndexes => offsets:\n"); + table = (const unsigned*)((const BYTE*)hash + types->search_offset); + for (i = 0; i < types->search_len / (2 * sizeof(unsigned)); i += 2) + { + printf("\t\t%08x => %08x\n", table[2 * i + 0], table[2 * i + 1]); + } + if (types->type_remap_len && (strbase = read_string_table(reader))) + { + unsigned num, capa, count_present, count_deleted; + const unsigned* present_bitset; + const unsigned* deleted_bitset; + + printf("\n\tType remap:\n"); + table = (const unsigned*)((const BYTE*)hash + types->type_remap_offset); + /* dump_data((const BYTE*)table, types->type_remap_len, "\t\t"); */ + num = *table++; + capa = *table++; + count_present = *table++; + present_bitset = table; + table += count_present; + count_deleted = *table++; + deleted_bitset = table; + table += count_deleted; + printf("\t\tNumber of present entries: %u\n", num); + printf("\t\tCapacity: %u\n", capa); + printf("\t\tBitset present:\n"); + printf("\t\t\tCount: %u\n", count_present); + printf("\t\t\tBitset: "); + pdb_dump_hash_value((const BYTE*)present_bitset, count_present * sizeof(unsigned)); + printf("\n"); + printf("\t\tBitset deleted:\n"); + printf("\t\t\tCount: %u\n", count_deleted); + printf("\t\t\tBitset: "); + pdb_dump_hash_value((const BYTE*)deleted_bitset, count_deleted * sizeof(unsigned)); + printf("\n"); + for (i = 0; i < capa; ++i) + { + printf("\t\t%2u) %c", + i, + is_bit_set(present_bitset, count_present, i) ? 'P' : + is_bit_set(deleted_bitset, count_deleted, i) ? 'D' : '_'); + if (is_bit_set(present_bitset, count_present, i)) + { + printf(" %s => ", strbase + 12 + *table++); + pdb_dump_hash_value((const BYTE*)table, types->hash_size); + table = (const unsigned*)((const BYTE*)table + types->hash_size); + } + printf("\n"); + } + free(strbase); + printf("\n"); + } free(hash); }
@@ -657,39 +789,39 @@ static void pdb_dump_types(struct pdb_reader* reader, unsigned strmidx, const ch
/* Read type table */ printf("Types (%s):\n" - "\tversion: %u\n" - "\ttype_offset: %08x\n" - "\tfirst_index: %x\n" - "\tlast_index: %x\n" - "\ttype_size: %x\n" - "\tfile: %x\n" - "\tpad: %x\n" - "\thash_size: %x\n" - "\thash_base: %x\n" - "\thash_offset: %x\n" - "\thash_len: %x\n" - "\tsearch_offset: %x\n" - "\tsearch_len: %x\n" - "\tunknown_offset: %x\n" - "\tunknown_len: %x\n", + "\tversion: %u\n" + "\ttype_offset: %08x\n" + "\tfirst_index: %x\n" + "\tlast_index: %x\n" + "\ttype_size: %x\n" + "\thash_file: %x\n" + "\tpad: %x\n" + "\thash_size: %x\n" + "\thash_buckets %x\n" + "\thash_offset: %x\n" + "\thash_len: %x\n" + "\tsearch_offset: %x\n" + "\tsearch_len: %x\n" + "\ttype_remap_offset: %x\n" + "\ttype_remap_len: %x\n", strmname, types->version, types->type_offset, types->first_index, types->last_index, types->type_size, - types->file, + types->hash_file, types->pad, types->hash_size, - types->hash_base, + types->hash_num_buckets, types->hash_offset, types->hash_len, types->search_offset, types->search_len, - types->unknown_offset, - types->unknown_len); + types->type_remap_offset, + types->type_remap_len); codeview_dump_types_from_block((const char*)types + types->type_offset, types->type_size); - pdb_dump_types_hash(reader, types->file, strmname); + pdb_dump_types_hash(reader, types, strmname); free(types); }