[PATCH 1/6] tools/winedump{pdb}: explore a bit more TPI hash elements
Eric Pouech
wine at gitlab.winehq.org
Wed Jun 22 09:41:15 CDT 2022
From: Eric Pouech <eric.pouech at gmail.com>
Renamed of couple of fields in PDB structures for clarity
Signed-off-by: Eric Pouech <eric.pouech at gmail.com>
---
dlls/dbghelp/msc.c | 2 +-
include/wine/mscvpdb.h | 10 +--
tools/winedump/pdb.c | 189 +++++++++++++++++++++++++++++++++++------
3 files changed, 168 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..6774cd11876 100644
--- a/tools/winedump/pdb.c
+++ b/tools/winedump/pdb.c
@@ -608,18 +608,153 @@ 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("]");
+}
+
+static struct
+{
+ const BYTE* hash;
+ unsigned hash_size;
+} collision_arg;
+
+static int collision_compar(const void *p1, const void *p2)
+{
+ unsigned idx1 = *(unsigned*)p1;
+ unsigned idx2 = *(unsigned*)p2;
+ return memcmp(collision_arg.hash + idx1 * collision_arg.hash_size,
+ collision_arg.hash + idx2 * collision_arg.hash_size,
+ collision_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)
+ {
+ unsigned head_printed = 0;
+
+ collision_arg.hash = (const BYTE*)hash + types->hash_offset;
+ collision_arg.hash_size = types->hash_size;
+
+ for (i = 0; i < types->last_index - types->first_index; i++) collision[i] = i;
+ qsort(collision, types->last_index - types->first_index, sizeof(unsigned), collision_compar);
+ 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);
+ 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 +792,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);
}
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/298
More information about the wine-devel
mailing list