This is serie #11 about PDB rewrite.
It finishes the migration of the types management to the new PDB reader (also disabling remaining type handling in old PDB reader when using new PDB reader). It starts the handling in new PDB reader of functions and symbols: - it implements line information support in new PDB reader for inlined functions, - it uses (for all debug info backend) the opaque symref_t to refer to symbol's container (so that we can let backend decide how to store it).
From: Eric Pouech epouech@codeweavers.com
And no longer load typedef information from old PDB backend.
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/msc.c | 2 +- dlls/dbghelp/pdb.c | 367 ++++++++++++++++++++++++++++++++++++++++---- dlls/dbghelp/type.c | 18 +-- 3 files changed, 340 insertions(+), 47 deletions(-)
diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index 09b36803be8..8b346f0043f 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -3890,7 +3890,7 @@ static BOOL pdb_process_internal(const struct process *pcs, * streams' loading can succeed them. */ globalimage = pdb_read_stream(pdb_file, symbols.gsym_stream); - if (globalimage) + if (globalimage && !pdb_file->pdb_reader) { const BYTE* data; unsigned global_size = pdb_get_stream_size(pdb_file, symbols.gsym_stream); diff --git a/dlls/dbghelp/pdb.c b/dlls/dbghelp/pdb.c index 95531866959..555c1c6574f 100644 --- a/dlls/dbghelp/pdb.c +++ b/dlls/dbghelp/pdb.c @@ -29,7 +29,6 @@
#include "windef.h" #include "winbase.h" -#include "winternl.h"
#include "wine/exception.h" #include "wine/debug.h" @@ -82,6 +81,7 @@ enum pdb_action_type { action_type_cv_typ_t, /* cv_typ_t or cv_typ16_t (depending on size) */ action_type_field, /* union codeview_fieldtype */ + action_type_globals, /* union codeview_symbol in DBI's globals stream */ };
struct pdb_action_entry @@ -98,6 +98,12 @@ struct pdb_type_hash_entry struct pdb_type_hash_entry *next; };
+struct pdb_dbi_hash_entry +{ + pdbsize_t dbi_stream_offset; + struct pdb_dbi_hash_entry *next; +}; + struct pdb_reader { struct module *module; @@ -127,8 +133,11 @@ struct pdb_reader struct pdb_type_hash_entry *tpi_types_hash;
/* symbol (and types) management */ + PDB_SYMBOLS dbi_header; + unsigned num_action_globals; unsigned num_action_entries; struct pdb_action_entry *action_store; + struct pdb_dbi_hash_entry *dbi_symbols_hash;
/* cache PE module sections for mapping... * we should rather use pe_module information @@ -361,6 +370,8 @@ static enum pdb_result pdb_reader_push_action(struct pdb_reader *pdb, enum pdb_a return R_PDB_SUCCESS; }
+static enum pdb_result pdb_reader_init_DBI(struct pdb_reader *pdb); + static enum pdb_result pdb_reader_init(struct pdb_reader *pdb, struct module *module, HANDLE file) { enum pdb_result result; @@ -416,6 +427,7 @@ static enum pdb_result pdb_reader_init(struct pdb_reader *pdb, struct module *mo } /* hack (must be set before loading debug info so it can be used therein) */ pdb->module->ops_symref_modfmt = module->format_info[DFI_PDB]; + pdb_reader_init_DBI(pdb);
return R_PDB_SUCCESS;
@@ -642,6 +654,28 @@ static enum pdb_result pdb_reader_read_DBI_header(struct pdb_reader* pdb, PDB_SY return R_PDB_SUCCESS; }
+static UINT32 codeview_compute_hash(const char* ptr, unsigned len) +{ + const char* last = ptr + len; + UINT32 ret = 0; + + while (ptr + sizeof(UINT32) <= last) + { + ret ^= *(UINT32*)ptr; + ptr += sizeof(UINT32); + } + if (ptr + sizeof(UINT16) <= last) + { + ret ^= *(UINT16*)ptr; + ptr += sizeof(UINT16); + } + if (ptr + sizeof(BYTE) <= last) + ret ^= *(BYTE*)ptr; + ret |= 0x20202020; + ret ^= (ret >> 11); + return ret ^ (ret >> 16); +} + static enum pdb_result pdb_reader_read_DBI_cu_header(struct pdb_reader* pdb, DWORD dbi_header_version, struct pdb_reader_walker *walker, PDB_SYMBOL_FILE_EX *dbi_cu_header) @@ -1404,9 +1438,191 @@ static enum pdb_result pdb_reader_alloc_and_read_full_codeview_symbol(struct pdb return pdb_reader_alloc_and_read_full_blob(pdb, walker, (void **)cv_symbol); }
-static void pdb_method_location_compute(const struct module_format *modfmt, - const struct symt_function *func, - struct location *loc) +static enum pdb_result pdb_reader_load_DBI_hash_table(struct pdb_reader *pdb) +{ + enum pdb_result result; + struct pdb_reader_walker walker; + DBI_HASH_HEADER dbi_hash_header; + unsigned num_hash_records; + DBI_HASH_RECORD hash_record; + UINT32 bitmap; + UINT32 start_index, end_index; + unsigned index, last_index, i, j; + struct pdb_dbi_hash_entry *entry; + + if ((result = pdb_reader_walker_init(pdb, pdb->dbi_header.global_hash_stream, &walker))) return result; + if ((result = pdb_reader_READ(pdb, &walker, &dbi_hash_header))) return result; + if (dbi_hash_header.signature != 0xFFFFFFFF || + dbi_hash_header.version != 0xeffe0000 + 19990810) + { + WARN("Incorrect hash stream header\n"); + return R_PDB_INVALID_PDB_FILE; + } + if (dbi_hash_header.hash_records_size) + { + if ((dbi_hash_header.hash_records_size % sizeof(DBI_HASH_RECORD)) != 0 || + sizeof(DBI_HASH_HEADER) + dbi_hash_header.hash_records_size + DBI_BITMAP_HASH_SIZE > walker.last || + (walker.last - (sizeof(DBI_HASH_HEADER) + dbi_hash_header.hash_records_size + DBI_BITMAP_HASH_SIZE)) % sizeof(uint32_t)) + { + WARN("Incorrect hash structure\n"); + return R_PDB_INVALID_PDB_FILE; + } + } + + if ((result = pdb_reader_alloc(pdb, sizeof(pdb->dbi_symbols_hash[0]) * (DBI_MAX_HASH + 1), (void **)&pdb->dbi_symbols_hash))) return result; + memset(pdb->dbi_symbols_hash, 0, sizeof(pdb->dbi_symbols_hash[0]) * (DBI_MAX_HASH + 1)); + for (index = 0, i = 0; i <= DBI_MAX_HASH; i++) + pdb->dbi_symbols_hash[i].next = &pdb->dbi_symbols_hash[i]; + + if (!dbi_hash_header.hash_records_size) return R_PDB_SUCCESS; + num_hash_records = dbi_hash_header.hash_records_size / sizeof(DBI_HASH_RECORD); + last_index = (walker.last - (sizeof(DBI_HASH_HEADER) + dbi_hash_header.hash_records_size + DBI_BITMAP_HASH_SIZE)) / sizeof(UINT32); + + for (index = 0, i = 0; i <= DBI_MAX_HASH; i++) + { + if ((i & 31) == 0) + { + walker.offset = sizeof(DBI_HASH_HEADER) + dbi_hash_header.hash_records_size + (i / 32) * 4; + if ((result = pdb_reader_READ(pdb, &walker, &bitmap))) goto on_error; + } + if (bitmap & (1u << (i % 32))) + { + walker.offset = sizeof(DBI_HASH_HEADER) + dbi_hash_header.hash_records_size + DBI_BITMAP_HASH_SIZE + index * sizeof(UINT32); + /* Yes, offsets for accessing the hash_record:s are stored as multiple of 12; + * and not as multiple of sizeof(hash_record) = 8 as one might expect. + * Perhaps, native implementation likes to keep the same offsets between + * in memory representation vs on file representations. + */ + if ((result = pdb_reader_READ(pdb, &walker, &start_index))) goto on_error; + start_index /= 12; + if (index + 1 < last_index) + { + if ((result = pdb_reader_READ(pdb, &walker, &end_index))) goto on_error; + end_index /= 12; + } + else + end_index = num_hash_records; + index++; + + for (j = start_index; j < end_index; j++) + { + walker.offset = sizeof(DBI_HASH_HEADER) + j * sizeof(DBI_HASH_RECORD); + if ((result = pdb_reader_READ(pdb, &walker, &hash_record))) goto on_error; + if (pdb->dbi_symbols_hash[i].next == &pdb->dbi_symbols_hash[i]) /* empty slot */ + { + pdb->dbi_symbols_hash[i].dbi_stream_offset = hash_record.offset - 1; + pdb->dbi_symbols_hash[i].next = NULL; + } + else + { + struct pdb_dbi_hash_entry **last; + if ((result = pdb_reader_alloc(pdb, sizeof(*entry), (void **)&entry))) goto on_error; + entry->dbi_stream_offset = hash_record.offset - 1; + entry->next = NULL; + for (last = &pdb->dbi_symbols_hash[i].next; *last; last = &(*last)->next) {} + *last = entry; + } + } + } + } + return R_PDB_SUCCESS; +on_error: + for (i = 0; i <= DBI_MAX_HASH; i++) + { + struct pdb_dbi_hash_entry *current, *next; + if (pdb->dbi_symbols_hash[i].next == &pdb->dbi_symbols_hash[i]) continue; + for (current = pdb->dbi_symbols_hash[i].next; current; current = next) + { + next = current->next; + pdb_reader_free(pdb, current); + } + } + pdb_reader_free(pdb, pdb->dbi_symbols_hash); + pdb->dbi_symbols_hash = NULL; + return result; +} + +static enum pdb_result pdb_reader_extract_name_out_of_codeview_symbol(union codeview_symbol *cv_symbol, char **name, size_t *length) +{ + switch (cv_symbol->generic.id) + { + case S_UDT: + *name = cv_symbol->udt_v3.name; + break; + default: + return R_PDB_INVALID_ARGUMENT; + } + *length = strlen(*name); + return R_PDB_SUCCESS; +} + +static enum pdb_result pdb_reader_read_DBI_codeview_symbol_by_name(struct pdb_reader *pdb, const char *name, + pdbsize_t *stream_offset, union codeview_symbol *cv_symbol) +{ + enum pdb_result result; + UINT32 hash; + struct pdb_reader_walker walker; + union codeview_symbol *full_cv_symbol; + char *cv_name; + size_t cv_length; + + if ((result = pdb_reader_walker_init(pdb, pdb->dbi_header.gsym_stream, &walker))) return result; + hash = codeview_compute_hash(name, strlen(name)) % DBI_MAX_HASH; + if (pdb->dbi_symbols_hash[hash].next != &pdb->dbi_symbols_hash[hash]) + { + struct pdb_dbi_hash_entry *entry; + for (entry = &pdb->dbi_symbols_hash[hash]; entry; entry = entry->next) + { + BOOL match; + + walker.offset = entry->dbi_stream_offset; + if ((result = pdb_reader_alloc_and_read_full_codeview_symbol(pdb, &walker, &full_cv_symbol))) return result; + match = pdb_reader_extract_name_out_of_codeview_symbol(full_cv_symbol, &cv_name, &cv_length) == R_PDB_SUCCESS && + !strcmp(name, cv_name); + pdb_reader_free(pdb, full_cv_symbol); + if (match) + { + *cv_symbol = *full_cv_symbol; + *stream_offset = entry->dbi_stream_offset; + return R_PDB_SUCCESS; + } + } + } + TRACE("not found in hash bucket %s\n", debugstr_a(name)); + return R_PDB_NOT_FOUND; +} + +static enum pdb_result pdb_reader_init_DBI(struct pdb_reader *pdb) +{ + enum pdb_result result; + struct pdb_reader_walker walker; + union codeview_symbol cv_symbol; + symref_t symref; + + if ((result = pdb_reader_read_DBI_header(pdb, &pdb->dbi_header, &walker))) return result; + + /* register the globals entries not bound to a compiland */ + if ((result = pdb_reader_walker_init(pdb, pdb->dbi_header.gsym_stream, &walker))) return result; + while (pdb_reader_READ(pdb, &walker, &cv_symbol.generic) == R_PDB_SUCCESS) + { + switch (cv_symbol.generic.id) + { + case S_UDT: + if ((result = pdb_reader_push_action(pdb, action_type_globals, walker.offset - sizeof(cv_symbol.generic), + cv_symbol.generic.len + sizeof(cv_symbol.generic.len), 0, &symref))) return result; + } + walker.offset += cv_symbol.generic.len - sizeof(cv_symbol.generic.id); + } + pdb->num_action_globals = pdb->num_action_entries; + + if ((result = pdb_reader_load_DBI_hash_table(pdb))) return result; + + return R_PDB_SUCCESS; +} + +static void pdb_method_location_compute(const struct module_format* modfmt, + const struct symt_function* func, + struct location* loc) { enum pdb_result result; struct pdb_reader_walker walker; @@ -1965,28 +2181,6 @@ static enum pdb_result pdb_reader_TPI_alloc_and_read_full_reftype(struct pdb_rea return pdb_reader_alloc_and_read_full_blob(pdb, &walker, (void**)cv_reftype); }
-static UINT32 codeview_compute_hash(const char* ptr, unsigned len) -{ - const char* last = ptr + len; - UINT32 ret = 0; - - while (ptr + sizeof(UINT32) <= last) - { - ret ^= *(UINT32*)ptr; - ptr += sizeof(UINT32); - } - if (ptr + sizeof(UINT16) <= last) - { - ret ^= *(UINT16*)ptr; - ptr += sizeof(UINT16); - } - if (ptr + sizeof(BYTE) <= last) - ret ^= *(BYTE*)ptr; - ret |= 0x20202020; - ret ^= (ret >> 11); - return ret ^ (ret >> 16); -} - static enum pdb_result pdb_reader_read_codeview_type_by_name(struct pdb_reader *pdb, const char *name, struct pdb_reader_walker *walker, union codeview_type *cv_type, cv_typ_t *cv_typeid) { @@ -2025,6 +2219,16 @@ static enum pdb_result pdb_reader_read_codeview_type_by_name(struct pdb_reader * return R_PDB_NOT_FOUND; }
+static int my_action_global_cmp(const void *p1, const void *p2) +{ + pdbsize_t o1 = *(pdbsize_t*)p1; + pdbsize_t o2 = ((const struct pdb_action_entry *)p2)->stream_offset; + + if (o1 < o2) return -1; + if (o1 > o2) return +1; + return 0; +} + static enum method_result pdb_method_find_type(struct module_format *modfmt, const char *name, symref_t *ref) { struct pdb_reader *pdb; @@ -2032,14 +2236,30 @@ static enum method_result pdb_method_find_type(struct module_format *modfmt, con struct pdb_reader_walker walker; cv_typ_t cv_typeid; union codeview_type cv_type; + union codeview_symbol cv_symbol; struct symref_code code; struct pdb_type_details *type_details; + pdbsize_t stream_offset;
if (!pdb_hack_get_main_info(modfmt, &pdb, NULL)) return MR_FAILURE; if ((result = pdb_reader_init_TPI(pdb))) return pdb_method_result(result); - if ((result = pdb_reader_read_codeview_type_by_name(pdb, name, &walker, &cv_type, &cv_typeid))) return pdb_method_result(result); - if ((result = pdb_reader_get_type_details(pdb, cv_typeid, &type_details))) return pdb_method_result(result); - return pdb_reader_encode_symref(pdb, symref_code_init_from_cv_typeid(&code, cv_typeid), ref) == R_PDB_SUCCESS ? MR_SUCCESS : MR_FAILURE; + /* search in TPI hash table */ + if ((result = pdb_reader_read_codeview_type_by_name(pdb, name, &walker, &cv_type, &cv_typeid)) == R_PDB_SUCCESS) + { + if ((result = pdb_reader_get_type_details(pdb, cv_typeid, &type_details))) return MR_FAILURE; + return pdb_reader_encode_symref(pdb, symref_code_init_from_cv_typeid(&code, cv_typeid), ref) == R_PDB_SUCCESS ? MR_SUCCESS : MR_FAILURE; + } + /* search in DBI globals' hash table */ + if ((result = pdb_reader_read_DBI_codeview_symbol_by_name(pdb, name, &stream_offset, &cv_symbol)) == R_PDB_SUCCESS) + { + struct pdb_action_entry *entry; + entry = bsearch(&stream_offset, pdb->action_store, pdb->num_action_globals, sizeof(pdb->action_store[0]), + &my_action_global_cmp); + if (entry) + return pdb_reader_encode_symref(pdb, symref_code_init_from_action(&code, entry - pdb->action_store), + ref) == R_PDB_SUCCESS ? MR_SUCCESS : MR_FAILURE; + } + return MR_FAILURE; }
static BOOL codeview_type_is_forward(const union codeview_type* cvtype) @@ -2167,7 +2387,39 @@ static enum method_result pdb_method_enumerate_types(struct module_format *modfm } } } - return MR_NOT_FOUND; /* hack: as typedef are not migrated yet, ask to continue searching */ + + /* typedef:s are stored in DBI globals' stream */ + for (i = 0; i < pdb->num_action_globals; i++) + { + struct pdb_reader_walker walker; + union codeview_symbol *cv_symbol; + struct pdb_action_entry *entry; + pdbsize_t num_read; + + entry = &pdb->action_store[i]; + if ((result = pdb_reader_walker_init(pdb, pdb->dbi_header.gsym_stream, &walker))) return MR_FAILURE; + walker.offset = entry->stream_offset; + if ((result = pdb_reader_alloc(pdb, entry->action_length, (void**)&cv_symbol))) return MR_FAILURE; + if ((result = pdb_reader_read_from_stream(pdb, &walker, cv_symbol, entry->action_length, &num_read))) return MR_FAILURE; + if ((result = pdb_reader_encode_symref(pdb, symref_code_init_from_action(&code, i), &symref))) return MR_FAILURE; + if (num_read == entry->action_length) + { + switch (cv_symbol->generic.id) + { + case S_UDT: + ret = (*cb)(symref, cv_symbol->udt_v3.name, user); + break; + default: + WARN("Got unexpected %x\n", cv_symbol->generic.id); + ret = FALSE; + break; + } + } + else ret = TRUE; + pdb_reader_free(pdb, cv_symbol); + if (!ret) break; + } + return MR_SUCCESS; }
static enum pdb_result pdb_reader_index_from_cv_typeid(struct pdb_reader *pdb, cv_typ_t cv_typeid, DWORD *index) @@ -2846,6 +3098,59 @@ static enum method_result pdb_reader_TPI_field_request(struct pdb_reader *pdb, s return ret; }
+static enum method_result pdb_reader_DBI_typedef_request(struct pdb_reader *pdb, struct pdb_action_entry *entry, union codeview_symbol *cv_symbol, + IMAGEHLP_SYMBOL_TYPE_INFO req, void *data) +{ + switch (req) + { + case TI_GET_SYMTAG: + *((DWORD*)data) = SymTagTypedef; + return MR_SUCCESS; + case TI_GET_SYMNAME: + *((WCHAR **)data) = heap_allocate_symname(cv_symbol->udt_v3.name); + return *((WCHAR **)data) != NULL ? MR_SUCCESS : MR_FAILURE; + case TI_GET_LENGTH: + return pdb_reader_request_cv_typeid(pdb, cv_symbol->udt_v3.type, req, data) == R_PDB_SUCCESS ? MR_SUCCESS : MR_FAILURE; + case TI_GET_TYPE: + case TI_GET_TYPEID: + return pdb_reader_index_from_cv_typeid(pdb, cv_symbol->udt_v3.type, (DWORD*)data) == R_PDB_SUCCESS ? MR_SUCCESS : MR_FAILURE; + case TI_FINDCHILDREN: + case TI_GET_CHILDRENCOUNT: + case TI_GET_LEXICALPARENT: + return pdb_reader_default_request(pdb, req, data); + default: + return MR_FAILURE; + } +} + +static enum method_result pdb_reader_DBI_globals_request(struct pdb_reader *pdb, struct pdb_action_entry *entry, IMAGEHLP_SYMBOL_TYPE_INFO req, void *data) +{ + enum pdb_result result; + struct pdb_reader_walker walker; + union codeview_symbol *cv_symbol; + pdbsize_t num_read; + enum method_result ret = MR_FAILURE; + + if ((result = pdb_reader_walker_init(pdb, pdb->dbi_header.gsym_stream, &walker))) return MR_FAILURE; + walker.offset = entry->stream_offset; + if ((result = pdb_reader_alloc(pdb, entry->action_length, (void**)&cv_symbol))) return MR_FAILURE; + if ((result = pdb_reader_read_from_stream(pdb, &walker, cv_symbol, entry->action_length, &num_read))) return MR_FAILURE; + if (num_read == entry->action_length) + { + switch (cv_symbol->generic.id) + { + case S_UDT: + ret = pdb_reader_DBI_typedef_request(pdb, entry, cv_symbol, req, data); + break; + default: + WARN("Got unexpected %x\n", cv_symbol->generic.id); + break; + } + } + pdb_reader_free(pdb, cv_symbol); + return ret; +} + static enum method_result pdb_reader_TPI_request(struct pdb_reader *pdb, symref_t symref, struct pdb_type_details *type_details, IMAGEHLP_SYMBOL_TYPE_INFO req, void *data) { enum pdb_result result; @@ -2921,6 +3226,8 @@ static enum method_result pdb_reader_request_symref_t(struct pdb_reader *pdb, sy return pdb_reader_TPI_argtype_request(pdb, entry, req, data); case action_type_field: return pdb_reader_TPI_field_request(pdb, entry, req, data); + case action_type_globals: + return pdb_reader_DBI_globals_request(pdb, entry, req, data); default: return MR_FAILURE; } diff --git a/dlls/dbghelp/type.c b/dlls/dbghelp/type.c index 2d728541998..b4c1a414d99 100644 --- a/dlls/dbghelp/type.c +++ b/dlls/dbghelp/type.c @@ -485,7 +485,6 @@ static BOOL sym_enum_types(struct module_pair *pair, const char *type_name, PSYM void* ptr; struct symt_ht *type; DWORD64 size; - BOOL hack_only_typedef = FALSE;
sym_info->SizeOfStruct = sizeof(SYMBOL_INFO); sym_info->MaxNameLen = sizeof(buffer) - sizeof(SYMBOL_INFO); @@ -496,17 +495,7 @@ static BOOL sym_enum_types(struct module_pair *pair, const char *type_name, PSYM { struct sym_modfmt_type_enum info = {pair->effective, sym_info, cb, user, type_name}; enum method_result result = iter.modfmt->vtable->enumerate_types(iter.modfmt, sym_modfmt_type_enum_cb, &info); - - switch (result) - { - case MR_FAILURE: - return FALSE; - case MR_SUCCESS: - return TRUE; - case MR_NOT_FOUND: - hack_only_typedef = TRUE; - break; - } + return result != MR_FAILURE; }
hash_table_iter_init(&pair->effective->ht_types, &hti, type_name); @@ -515,7 +504,6 @@ static BOOL sym_enum_types(struct module_pair *pair, const char *type_name, PSYM type = CONTAINING_RECORD(ptr, struct symt_ht, hash_elt);
if (type_name && !SymMatchStringA(type->hash_elt.name, type_name, TRUE)) continue; - if (hack_only_typedef && !symt_check_tag(&type->symt, SymTagTypedef)) continue;
sym_info->TypeIndex = symt_ptr_to_index(pair->effective, &type->symt); sym_info->Index = 0; /* FIXME */ @@ -1207,7 +1195,6 @@ BOOL WINAPI SymGetTypeFromName(HANDLE hProcess, ULONG64 BaseOfDll, struct module_pair pair; struct symt* type; DWORD64 size; - BOOL hack_only_typedef = FALSE; struct module_format_vtable_iterator iter = {};
if (!module_init_pair(&pair, hProcess, BaseOfDll)) return FALSE; @@ -1231,12 +1218,11 @@ BOOL WINAPI SymGetTypeFromName(HANDLE hProcess, ULONG64 BaseOfDll, symt_get_info_from_symref(pair.effective, symref, TI_GET_SYMTAG, &Symbol->Tag); return TRUE; } - hack_only_typedef = TRUE; + if (result == MR_FAILURE) return FALSE; }
type = symt_find_type_by_name(pair.effective, SymTagNull, Name); if (!type) return FALSE; - if (hack_only_typedef && !symt_check_tag(type, SymTagTypedef)) return FALSE; Symbol->Index = Symbol->TypeIndex = symt_ptr_to_index(pair.effective, type); symbol_setname(Symbol, symt_get_name(type)); symt_get_info(pair.effective, type, TI_GET_LENGTH, &size);
From: Eric Pouech epouech@codeweavers.com
And store DBI offset to function from old PDB backend (to be used by new PDB backend during migration).
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/coff.c | 6 +++--- dlls/dbghelp/dbghelp_private.h | 4 +++- dlls/dbghelp/dwarf.c | 4 ++-- dlls/dbghelp/elf_module.c | 2 +- dlls/dbghelp/macho_module.c | 2 +- dlls/dbghelp/msc.c | 15 +++++++++------ dlls/dbghelp/stabs.c | 4 ++-- dlls/dbghelp/symbol.c | 16 ++++++++++------ 8 files changed, 31 insertions(+), 22 deletions(-)
diff --git a/dlls/dbghelp/coff.c b/dlls/dbghelp/coff.c index aa7273db24e..65ed3b7def2 100644 --- a/dlls/dbghelp/coff.c +++ b/dlls/dbghelp/coff.c @@ -285,7 +285,7 @@ BOOL coff_process_info(const struct msc_debug_info* msc_dbg) nampnt, msc_dbg->module->module.BaseOfImage + base + coff_sym->Value, 0 /* FIXME */, - 0 /* FIXME */)->symt); + 0 /* FIXME */, 0)->symt); continue; }
@@ -318,13 +318,13 @@ BOOL coff_process_info(const struct msc_debug_info* msc_dbg) coff_add_symbol(&coff_files.files[j], &symt_new_function(msc_dbg->module, compiland, nampnt, msc_dbg->module->module.BaseOfImage + base + coff_sym->Value, - 0 /* FIXME */, 0 /* FIXME */)->symt); + 0 /* FIXME */, 0 /* FIXME */, 0)->symt); } else { symt_new_function(msc_dbg->module, NULL, nampnt, msc_dbg->module->module.BaseOfImage + base + coff_sym->Value, - 0 /* FIXME */, 0 /* FIXME */); + 0 /* FIXME */, 0 /* FIXME */, 0); } i += naux; continue; diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 54ea829e21b..86e990b422f 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -299,6 +299,7 @@ struct symt_function struct vector vlines; struct vector vchildren; /* locals, params, blocks, start/end, labels, inline sites */ struct symt_function* next_inlinesite;/* linked list of inline sites in this function */ + DWORD_PTR user; /* free to use by debug info backends */ unsigned num_ranges; struct addr_range ranges[]; }; @@ -922,13 +923,14 @@ extern struct symt_function* struct symt_compiland* parent, const char* name, ULONG_PTR addr, ULONG_PTR size, - symref_t type); + symref_t type, DWORD_PTR user); extern struct symt_function* symt_new_inlinesite(struct module* module, struct symt_function* func, struct symt* parent, const char* name, symref_t type, + DWORD_PTR user, unsigned num_ranges); extern void symt_add_func_line(struct module* module, struct symt_function* func, diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c index 2361df37647..831c56af63b 100644 --- a/dlls/dbghelp/dwarf.c +++ b/dlls/dbghelp/dwarf.c @@ -2242,7 +2242,7 @@ static void dwarf2_parse_inlined_subroutine(dwarf2_subprogram_t* subpgm, subpgm->top_func, subpgm->current_block ? &subpgm->current_block->symt : &subpgm->current_func->symt, dwarf2_get_cpp_name(di, name.u.string), - symt_ptr_to_symref(dwarf2_parse_subroutine_type(di)), num_ranges); + symt_ptr_to_symref(dwarf2_parse_subroutine_type(di)), 0, num_ranges); subpgm->current_func = inlined; subpgm->current_block = NULL;
@@ -2452,7 +2452,7 @@ static struct symt* dwarf2_parse_subprogram(dwarf2_debug_info_t* di) subpgm.top_func = symt_new_function(di->unit_ctx->module_ctx->module, di->unit_ctx->compiland, dwarf2_get_cpp_name(di, name.u.string), addr_ranges[0].low, addr_ranges[0].high - addr_ranges[0].low, - symt_ptr_to_symref(dwarf2_parse_subroutine_type(di))); + symt_ptr_to_symref(dwarf2_parse_subroutine_type(di)), 0); if (num_addr_ranges > 1) WARN("Function %s has multiple address ranges, only using the first one\n", debugstr_a(name.u.string)); free(addr_ranges); diff --git a/dlls/dbghelp/elf_module.c b/dlls/dbghelp/elf_module.c index b62fca9fc3e..8053f7a5a9a 100644 --- a/dlls/dbghelp/elf_module.c +++ b/dlls/dbghelp/elf_module.c @@ -960,7 +960,7 @@ static int elf_new_wine_thunks(struct module* module, const struct hash_table* h { case ELF_STT_FUNC: symt_new_function(module, ste->compiland, ste->ht_elt.name, - addr, ste->sym.st_size, 0); + addr, ste->sym.st_size, 0, 0); break; case ELF_STT_OBJECT: loc.kind = loc_absolute; diff --git a/dlls/dbghelp/macho_module.c b/dlls/dbghelp/macho_module.c index b14591beb66..152dd16284f 100644 --- a/dlls/dbghelp/macho_module.c +++ b/dlls/dbghelp/macho_module.c @@ -1190,7 +1190,7 @@ static void macho_finish_stabs(struct module* module, struct hash_table* ht_symt if (ste->is_code) { symt_new_function(module, ste->compiland, ste->ht_elt.name, - ste->addr, 0, 0); + ste->addr, 0, 0, 0); } else { diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index 8b346f0043f..d9a4934696d 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -2188,6 +2188,7 @@ static struct symt_function* codeview_create_inline_site(const struct msc_debug_ struct symt_function* top_func, struct symt* container, cv_itemid_t inlinee, + DWORD_PTR user, const unsigned char* annot, const unsigned char* last_annot) { @@ -2214,14 +2215,14 @@ static struct symt_function* codeview_create_inline_site(const struct msc_debug_ inlined = symt_new_inlinesite(msc_dbg->module, top_func, container, cvt->func_id_v3.name, codeview_get_symref(msc_dbg->module, cvt->func_id_v3.type), - num_ranges); + user, num_ranges); break; case LF_MFUNC_ID: /* FIXME we just declare a function, not a method */ inlined = symt_new_inlinesite(msc_dbg->module, top_func, container, cvt->mfunc_id_v3.name, codeview_get_symref(msc_dbg->module, cvt->mfunc_id_v3.type), - num_ranges); + user, num_ranges); break; default: FIXME("unsupported inlinee kind %x\n", cvt->generic.id); @@ -2438,7 +2439,7 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, terminate_string(&sym->proc_v1.p_name), codeview_get_address(msc_dbg, sym->proc_v1.segment, sym->proc_v1.offset), sym->proc_v1.proc_len, - codeview_get_symref(msc_dbg->module, sym->proc_v1.proctype)))) + codeview_get_symref(msc_dbg->module, sym->proc_v1.proctype), i))) { curr_func = top_func; loc.kind = loc_absolute; @@ -2455,7 +2456,7 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, terminate_string(&sym->proc_v2.p_name), codeview_get_address(msc_dbg, sym->proc_v2.segment, sym->proc_v2.offset), sym->proc_v2.proc_len, - codeview_get_symref(msc_dbg->module, sym->proc_v2.proctype)))) + codeview_get_symref(msc_dbg->module, sym->proc_v2.proctype), i))) { curr_func = top_func; loc.kind = loc_absolute; @@ -2472,7 +2473,7 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, sym->proc_v3.name, codeview_get_address(msc_dbg, sym->proc_v3.segment, sym->proc_v3.offset), sym->proc_v3.proc_len, - codeview_get_symref(msc_dbg->module, sym->proc_v3.proctype)))) + codeview_get_symref(msc_dbg->module, sym->proc_v3.proctype), i))) { curr_func = top_func; loc.kind = loc_absolute; @@ -2742,6 +2743,7 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, struct symt_function* inlined = codeview_create_inline_site(msc_dbg, cvmod, top_func, block ? &block->symt : &curr_func->symt, sym->inline_site_v3.inlinee, + i, sym->inline_site_v3.binaryAnnotations, (const unsigned char*)sym + length); if (inlined) @@ -2763,6 +2765,7 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, struct symt_function* inlined = codeview_create_inline_site(msc_dbg, cvmod, top_func, block ? &block->symt : &curr_func->symt, sym->inline_site2_v3.inlinee, + i, sym->inline_site2_v3.binaryAnnotations, (const unsigned char*)sym + length); if (inlined) @@ -2826,7 +2829,7 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, struct symt_function* pfunc = (struct symt_function*)parent; top_func = symt_new_function(msc_dbg->module, compiland, pfunc->hash_elt.name, codeview_get_address(msc_dbg, sym->sepcode_v3.sect, sym->sepcode_v3.off), - sym->sepcode_v3.length, pfunc->type); + sym->sepcode_v3.length, pfunc->type, i); curr_func = top_func; } else diff --git a/dlls/dbghelp/stabs.c b/dlls/dbghelp/stabs.c index efd2bb2f943..ea5bed152e6 100644 --- a/dlls/dbghelp/stabs.c +++ b/dlls/dbghelp/stabs.c @@ -1547,11 +1547,11 @@ BOOL stabs_parse(struct module* module, ULONG_PTR load_offset, n_value ? (load_offset + n_value - curr_func->ranges[0].low) : 0); } - func_type = symt_new_function_signature(module, + func_type = symt_new_function_signature(module, stabs_parse_type(ptr), -1); curr_func = symt_new_function(module, compiland, symname, load_offset + n_value, 0, - symt_ptr_to_symref(&func_type->symt)); + symt_ptr_to_symref(&func_type->symt), 0); pending_flush(&pending_func, module, curr_func, NULL); } else diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index ade18cc0a94..cf6bfe8c037 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -322,18 +322,20 @@ static struct symt_function* init_function_or_inlinesite(struct module* module, struct symt* container, const char* name, symref_t sig_type, + DWORD_PTR user, unsigned num_ranges) { struct symt_function* sym;
if ((sym = pool_alloc(&module->pool, offsetof(struct symt_function, ranges[num_ranges])))) { - sym->symt.tag = tag; + sym->symt.tag = tag; sym->hash_elt.name = pool_strdup(&module->pool, name); - sym->container = container; - sym->type = sig_type; + sym->container = container; + sym->type = sig_type; vector_init(&sym->vlines, sizeof(struct line_info), 0); vector_init(&sym->vchildren, sizeof(struct symt*), 0); + sym->user = user; sym->num_ranges = num_ranges; } return sym; @@ -343,13 +345,14 @@ struct symt_function* symt_new_function(struct module* module, struct symt_compiland* compiland, const char* name, ULONG_PTR addr, ULONG_PTR size, - symref_t sig_type) + symref_t sig_type, DWORD_PTR user) { struct symt_function* sym;
TRACE_(dbghelp_symt)("Adding global function %s:%s @%Ix-%Ix\n", debugstr_w(module->modulename), debugstr_a(name), addr, addr + size - 1); - if ((sym = init_function_or_inlinesite(module, SymTagFunction, &compiland->symt, name, sig_type, 1))) + + if ((sym = init_function_or_inlinesite(module, SymTagFunction, &compiland->symt, name, sig_type, user, 1))) { struct symt** p; sym->ranges[0].low = addr; @@ -370,12 +373,13 @@ struct symt_function* symt_new_inlinesite(struct module* module, struct symt* container, const char* name, symref_t sig_type, + DWORD_PTR user, unsigned num_ranges) { struct symt_function* sym;
TRACE_(dbghelp_symt)("Adding inline site %s\n", debugstr_a(name)); - if ((sym = init_function_or_inlinesite(module, SymTagInlineSite, container, name, sig_type, num_ranges))) + if ((sym = init_function_or_inlinesite(module, SymTagInlineSite, container, name, sig_type, user, num_ranges))) { struct symt** p; assert(container);
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/dbghelp_private.h | 2 + dlls/dbghelp/pdb.c | 444 ++++++++++++++++++++++++++++++++- dlls/dbghelp/symbol.c | 19 ++ 3 files changed, 464 insertions(+), 1 deletion(-)
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 86e990b422f..5576766fcfc 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -456,6 +456,8 @@ struct module_format_vtable struct lineinfo_t *line_info, BOOL forward); enum method_result (*enumerate_lines)(struct module_format *modfmt, const WCHAR* compiland_regex, const WCHAR *source_file_regex, PSYM_ENUMLINES_CALLBACK cb, void *user); + enum method_result (*get_line_from_inlined_address)(struct module_format *modfmt, struct symt_function *inlined, + DWORD64 address, struct lineinfo_t *line_info);
/* source files information */ enum method_result (*enumerate_sources)(struct module_format *modfmt, const WCHAR *sourcefile_regex, diff --git a/dlls/dbghelp/pdb.c b/dlls/dbghelp/pdb.c index 555c1c6574f..ba09f8e37ba 100644 --- a/dlls/dbghelp/pdb.c +++ b/dlls/dbghelp/pdb.c @@ -189,6 +189,23 @@ static enum pdb_result pdb_reader_get_segment_address(struct pdb_reader *pdb, un return R_PDB_SUCCESS; }
+static enum pdb_result pdb_reader_get_segment_offset_from_address(struct pdb_reader *pdb, DWORD64 address, unsigned *segment, unsigned *offset) +{ + unsigned i; + + for (i = 0; i < pdb->num_sections; i++) + { + if (address >= pdb->module->module.BaseOfImage + pdb->sections[i].VirtualAddress && + address < pdb->module->module.BaseOfImage + pdb->sections[i].VirtualAddress + pdb->sections[i].Misc.VirtualSize) + { + *segment = i + 1; + *offset = address - (pdb->module->module.BaseOfImage + pdb->sections[i].VirtualAddress); + return R_PDB_SUCCESS; + } + } + return R_PDB_NOT_FOUND; +} + static inline enum pdb_result pdb_reader_alloc(struct pdb_reader *pdb, size_t size, void **ptr) { return (*ptr = pool_alloc(&pdb->pool, size)) ? R_PDB_SUCCESS : R_PDB_OUT_OF_MEMORY; @@ -371,6 +388,9 @@ static enum pdb_result pdb_reader_push_action(struct pdb_reader *pdb, enum pdb_a }
static enum pdb_result pdb_reader_init_DBI(struct pdb_reader *pdb); +static enum pdb_result pdb_reader_internal_binary_search(size_t num_elt, + enum pdb_result (*cmp)(unsigned idx, int *cmp_ressult, void *user), + size_t *found, void *user);
static enum pdb_result pdb_reader_init(struct pdb_reader *pdb, struct module *module, HANDLE file) { @@ -730,6 +750,74 @@ static enum pdb_result pdb_reader_compiland_iterator_next(struct pdb_reader *pdb return pdb_reader_read_DBI_cu_header(pdb, iter->dbi_header.version, &iter->dbi_walker, &iter->dbi_cu_header); }
+struct pdb_compiland_lookup +{ + struct pdb_reader *pdb; + struct pdb_reader_walker walker; + unsigned segment; + unsigned offset; + unsigned range_size; + PDB_SYMBOL_RANGE_EX range; +}; + +static enum pdb_result pdb_reader_contrib_range_cmp(unsigned idx, int *cmp, void *user) +{ + enum pdb_result result; + struct pdb_compiland_lookup *lookup = user; + struct pdb_reader_walker walker = lookup->walker; + + walker.offset += idx * lookup->range_size; + if ((result = pdb_reader_READ(lookup->pdb, &walker, &lookup->range))) return result; + *cmp = lookup->range.segment - lookup->segment; + if (!*cmp) + *cmp = lookup->range.offset - lookup->offset; + return R_PDB_SUCCESS; +} + +static enum pdb_result pdb_reader_lookup_compiland_by_address(struct pdb_reader *pdb, DWORD_PTR address, unsigned *compiland) +{ + enum pdb_result result; + struct pdb_compiland_lookup lookup = {.pdb = pdb}; + UINT32 version; + PDB_SYMBOLS dbi_header; + size_t found; + unsigned num_ranges; + + if ((result = pdb_reader_get_segment_offset_from_address(pdb, address, &lookup.segment, &lookup.offset))) return result; + if ((result = pdb_reader_walker_init(pdb, PDB_STREAM_DBI, &lookup.walker))) return result; + if ((result = pdb_reader_read_DBI_header(pdb, &dbi_header, &lookup.walker))) return result; + if ((result = pdb_reader_walker_narrow(&lookup.walker, lookup.walker.offset + dbi_header.module_size, dbi_header.sectcontrib_size))) return result; + + if ((result = pdb_reader_READ(pdb, &lookup.walker, &version))) return result; + lookup.range_size = sizeof(PDB_SYMBOL_RANGE_EX); + switch (version) + { + case 0xeffe0000 + 19970605: break; + case 0xeffe0000 + 20140516: lookup.range_size += sizeof(UINT32); break; + default: + WARN("Unsupported contrib version %x\n", version); + return R_PDB_INVALID_PDB_FILE; + } + if ((lookup.walker.last - lookup.walker.offset) % lookup.range_size) + { + WARN("Unexpected lookup values\n"); + return R_PDB_INVALID_PDB_FILE; + } + num_ranges = (lookup.walker.last - lookup.walker.offset) / lookup.range_size; + /* we assume contributions are stored in ascending order of segment / offset */ + result = pdb_reader_internal_binary_search(num_ranges, pdb_reader_contrib_range_cmp, &found, &lookup); + if (result) + { + if (result != R_PDB_NOT_FOUND) return result; + /* ensure address is within contribution range */ + if (lookup.segment != lookup.range.segment || + lookup.offset < lookup.range.offset || + lookup.offset >= lookup.range.offset + lookup.range.size) return R_PDB_NOT_FOUND; + } + *compiland = lookup.range.index; + return R_PDB_SUCCESS; +} + static enum pdb_result pdb_reader_subsection_next(struct pdb_reader *pdb, struct pdb_reader_walker *in_walker, enum DEBUG_S_SUBSECTION_TYPE subsection_type, struct pdb_reader_walker *sub_walker) @@ -863,8 +951,8 @@ static enum pdb_result pdb_reader_get_line_from_address_internal(struct pdb_read DWORD64 address, struct lineinfo_t *line_info, pdbsize_t *compiland_offset) { - enum pdb_result result; struct pdb_reader_compiland_iterator compiland_iter; + enum pdb_result result;
if ((result = pdb_reader_compiland_iterator_init(pdb, &compiland_iter))) return result; do @@ -3256,6 +3344,359 @@ BOOL cv_hack_ptr_to_symref(struct pdb_reader *pdb, cv_typ_t cv_typeid, symref_t return pdb_reader_encode_symref(pdb, symref_code_init_from_cv_typeid(&code, cv_typeid), symref) == R_PDB_SUCCESS; }
+static enum pdb_result pdb_reader_walker_from_compiland_index(struct pdb_reader *pdb, unsigned compiland, PDB_SYMBOL_FILE_EX *dbi_cu_header) +{ + enum pdb_result result; + struct pdb_reader_compiland_iterator compiland_iter; + + if ((result = pdb_reader_compiland_iterator_init(pdb, &compiland_iter))) return result; + do + { + if (!compiland--) + { + *dbi_cu_header = compiland_iter.dbi_cu_header; + return R_PDB_SUCCESS; + } + } while (pdb_reader_compiland_iterator_next(pdb, &compiland_iter) == R_PDB_SUCCESS); + return R_PDB_NOT_FOUND; +} + +/* walk the top level global symbols to find matching address */ +static enum pdb_result pdb_reader_search_codeview_symbol_by_address(struct pdb_reader *pdb, struct pdb_reader_walker *walker, + DWORD_PTR address, union codeview_symbol *cv_symbol, pdbsize_t *end_stream_offset) +{ + enum pdb_result result; + unsigned short segment; + unsigned offset, pend; + DWORD64 symbol_address; + + while (pdb_reader_read_partial_codeview_symbol(pdb, walker, cv_symbol) == R_PDB_SUCCESS && cv_symbol->generic.id) + { + switch (cv_symbol->generic.id) + { + case S_GDATA32: + case S_LDATA32: + segment = cv_symbol->data_v3.segment; + offset = cv_symbol->data_v3.offset; + pend = 0; + break; + case S_THUNK32: + segment = cv_symbol->thunk_v3.segment; + offset = cv_symbol->thunk_v3.offset; + pend = cv_symbol->thunk_v3.pend; + break; + case S_GPROC32: + case S_LPROC32: + segment = cv_symbol->proc_v3.segment; + offset = cv_symbol->proc_v3.offset; + pend = cv_symbol->proc_v3.pend; + break; + + default: + WARN("Unexpected codeview symbol id %x\n", cv_symbol->generic.id); + /* fall through */ + case S_OBJNAME: + case S_COMPILE: + case S_COMPILE2: + case S_COMPILE3: + case S_BUILDINFO: + case S_UDT: + case S_UNAMESPACE: + segment = 0; + offset = 0; + pend = 0; + break; + } + if (segment) + { + if ((result = pdb_reader_get_segment_address(pdb, segment, offset, &symbol_address))) return result; + if (address == symbol_address) + { + *end_stream_offset = pend; + return R_PDB_SUCCESS; + } + } + if (pend) /* jump to S_END, and skip it */ + { + walker->offset = pend; + if ((result = pdb_reader_read_partial_codeview_symbol(pdb, walker, cv_symbol))) return result; + if (cv_symbol->generic.id != S_END) return R_PDB_INVALID_PDB_FILE; + } + walker->offset += cv_symbol->generic.len; + } + return R_PDB_NOT_FOUND; +} + +static enum pdb_result pdb_reader_alloc_and_fetch_from_checksum(struct pdb_reader *pdb, struct pdb_reader_walker checksum_walker, + unsigned chksum_offset, char **string) +{ + enum pdb_result result; + struct CV_Checksum_t checksum; + + checksum_walker.offset += chksum_offset; + if ((result = pdb_reader_READ(pdb, &checksum_walker, &checksum))) return result; + return pdb_reader_alloc_and_fetch_global_string(pdb, checksum.strOffset, string); +} + +static enum pdb_result pdb_reader_alloc_and_fetch_from_checksum_subsection(struct pdb_reader *pdb, struct pdb_reader_walker linetab2_walker, + cv_itemid_t cv_inlinee, char **string, unsigned *line_number) +{ + enum pdb_result result; + struct pdb_reader_walker sub_walker; + struct pdb_reader_walker checksum_walker; + struct pdb_reader_walker inlineelines_walker; + + sub_walker = linetab2_walker; + if ((result = pdb_reader_subsection_next(pdb, &sub_walker, DEBUG_S_FILECHKSMS, &checksum_walker))) + { + WARN("No DEBUG_S_FILECHKSMS found\n"); + return R_PDB_MISSING_INFORMATION; + } + + for (sub_walker = linetab2_walker; !(result = pdb_reader_subsection_next(pdb, &sub_walker, DEBUG_S_INLINEELINES, &inlineelines_walker)); ) + { + UINT32 inlinee_kind; + struct CV_InlineeSourceLine_t inlsrc; + struct CV_InlineeSourceLineEx_t inlsrcex; + + if ((result = pdb_reader_READ(pdb, &inlineelines_walker, &inlinee_kind))) return result; + switch (inlinee_kind) + { + case CV_INLINEE_SOURCE_LINE_SIGNATURE: + while (!pdb_reader_READ(pdb, &inlineelines_walker, &inlsrc)) + { + if (inlsrc.inlinee == cv_inlinee) + { + if ((result = pdb_reader_alloc_and_fetch_from_checksum(pdb, checksum_walker, inlsrc.fileId, string))) return result; + *line_number = inlsrc.sourceLineNum; + return R_PDB_SUCCESS; + } + } + break; + case CV_INLINEE_SOURCE_LINE_SIGNATURE_EX: + while (!pdb_reader_READ(pdb, &inlineelines_walker, &inlsrcex)) + { + if (inlsrc.inlinee == cv_inlinee) + { + if ((result = pdb_reader_alloc_and_fetch_from_checksum(pdb, checksum_walker, inlsrcex.fileId, string))) return result; + *line_number = inlsrcex.sourceLineNum; + return R_PDB_SUCCESS; + } + inlineelines_walker.offset += inlsrcex.countOfExtraFiles * sizeof(inlsrcex.extraFileId[0]); + } + break; + default: + WARN("Unknown signature %x in INLINEELINES subsection\n", inlinee_kind); + break; + } + } + return R_PDB_NOT_FOUND; +} + +static enum pdb_result pdb_reader_uncompress_inlinesite_annotation(struct pdb_reader *pdb, struct pdb_reader_walker *walker, unsigned *value) +{ + enum pdb_result result; + unsigned res; + unsigned char ch; + unsigned i, num_shift; + + if ((result = pdb_reader_READ(pdb, walker, &ch))) return result; + + if ((ch & 0x80) == 0x00) + { + res = ch; + num_shift = 0; + } + else if ((ch & 0xC0) == 0x80) + { + res = ch & 0x3f; + num_shift = 1; + } + else if ((ch & 0xE0) == 0xC0) + { + res = (ch & 0x1f); + num_shift = 3; + } + else + { + res = (unsigned)(-1); + num_shift = 0; + } + for (i = 0; i < num_shift; i++) + { + if ((result = pdb_reader_READ(pdb, walker, &ch))) return result; + res <<= 8; + res |= ch; + } + *value = res; + return R_PDB_SUCCESS; +} + +static enum pdb_result pdb_reader_read_inlinesite_annotation(struct pdb_reader *pdb, struct pdb_reader_walker *annotation_walker, + unsigned *opcode, unsigned *arg1, unsigned *arg2) +{ + enum pdb_result result; + + if ((result = pdb_reader_uncompress_inlinesite_annotation(pdb, annotation_walker, opcode))) return result; + if (*opcode == BA_OP_Invalid) + *arg1 = *arg2 = 0; + else if (*opcode <= BA_OP_ChangeColumnEnd) + { + if ((result = pdb_reader_uncompress_inlinesite_annotation(pdb, annotation_walker, arg1))) return result; + if (*opcode == BA_OP_ChangeCodeOffsetAndLineOffset) + { + *arg2 = *arg1 >> 4; + *arg1 &= 0x0F; + } + else if (*opcode == BA_OP_ChangeCodeLengthAndCodeOffset) + { + if ((result = pdb_reader_uncompress_inlinesite_annotation(pdb, annotation_walker, arg2))) return result; + } + else *arg2 = 0; + } + else + { + WARN("Unexpected BA annotation options %x\n", *opcode); + return R_PDB_INVALID_PDB_FILE; + } + return R_PDB_SUCCESS; +} + +static inline int pdb_reader_convert_binannot_to_signed(unsigned i) +{ + return (i & 1) ? -(int)(i >> 1) : (int)(i >> 1); +} + +static enum pdb_result pdb_method_get_line_from_inlined_address_internal(struct pdb_reader *pdb, struct symt_function *inlined, + DWORD64 address, struct lineinfo_t *line_info) +{ + struct symt_function *function = symt_get_function_from_inlined(inlined); + enum pdb_result result; + PDB_SYMBOL_FILE_EX dbi_cu_header; + struct pdb_reader_walker cu_walker; + struct pdb_reader_walker linetab2_walker; + struct pdb_reader_walker inlinee_walker; + DWORD64 top_function_address; + unsigned compiland; + union codeview_symbol cv_top_function_symbol; + union codeview_symbol cv_inlinee_symbol; + pdbsize_t end_stream_offset; + cv_itemid_t cv_inlinee; + size_t annotation_offset; + char *source_file_name; + unsigned line_number; + unsigned opcode, arg1, arg2; + unsigned offset_top_function; + + if (!symt_get_info(pdb->module, &function->symt, TI_GET_ADDRESS, &top_function_address)) return R_PDB_INVALID_ARGUMENT; + if ((result = pdb_reader_lookup_compiland_by_address(pdb, top_function_address, &compiland))) return result; + if ((result = pdb_reader_walker_from_compiland_index(pdb, compiland, &dbi_cu_header))) return result; + if ((result = pdb_reader_walker_init(pdb, dbi_cu_header.stream, &cu_walker))) return result; + cu_walker.offset += sizeof(UINT32); + + if ((result = pdb_reader_search_codeview_symbol_by_address(pdb, &cu_walker, top_function_address, &cv_top_function_symbol, &end_stream_offset))) return result; + if (inlined->user < cu_walker.offset || inlined->user >= end_stream_offset) return R_PDB_INVALID_ARGUMENT; + + inlinee_walker.stream_id = cu_walker.stream_id; + inlinee_walker.offset = inlined->user; + inlinee_walker.last = end_stream_offset; + if ((result = pdb_reader_read_partial_codeview_symbol(pdb, &inlinee_walker, &cv_inlinee_symbol))) return result; + switch (cv_inlinee_symbol.generic.id) + { + case S_INLINESITE: + cv_inlinee = cv_inlinee_symbol.inline_site_v3.inlinee; + annotation_offset = offsetof(union codeview_symbol, inline_site_v3.binaryAnnotations); + break; + case S_INLINESITE2: + cv_inlinee = cv_inlinee_symbol.inline_site2_v3.inlinee; + annotation_offset = offsetof(union codeview_symbol, inline_site2_v3.binaryAnnotations); + break; + default: + WARN("Unexpected symbol id %x for %u\n", cv_inlinee_symbol.generic.id, inlined->symt.tag); + return R_PDB_INVALID_PDB_FILE; + } + if ((result = pdb_reader_walker_init_linetab2(pdb, &dbi_cu_header, &linetab2_walker))) return result; + + if ((result = pdb_reader_alloc_and_fetch_from_checksum_subsection(pdb, linetab2_walker, cv_inlinee, &source_file_name, &line_number))) return result; + + /* then walk annotations */ + if ((result = pdb_reader_walker_narrow(&inlinee_walker, + inlinee_walker.offset + annotation_offset - sizeof(cv_inlinee_symbol.generic.len), + cv_inlinee_symbol.generic.len - annotation_offset + sizeof(cv_inlinee_symbol.generic.len)))) return result; + offset_top_function = 0; + while (!(result = pdb_reader_read_inlinesite_annotation(pdb, &inlinee_walker, &opcode, &arg1, &arg2)) && + opcode != BA_OP_Invalid) + { + BOOL check_address = FALSE; + switch (opcode) + { + case BA_OP_CodeOffset: + offset_top_function = arg1; + break; + case BA_OP_ChangeCodeOffset: + offset_top_function += arg1; + check_address = TRUE; + break; + case BA_OP_ChangeCodeLength: + /* this op isn't widely used by MSVC, but clang uses it a lot... */ + offset_top_function += arg1; + break; + case BA_OP_ChangeFile: + pdb_reader_free(pdb, source_file_name); + { + struct pdb_reader_walker sub_walker = linetab2_walker; + struct pdb_reader_walker checksum_walker = linetab2_walker; + if ((result = pdb_reader_subsection_next(pdb, &sub_walker, DEBUG_S_FILECHKSMS, &checksum_walker))) + { + WARN("No DEBUG_S_FILECHKSMS found\n"); + return R_PDB_MISSING_INFORMATION; + } + if ((result = pdb_reader_alloc_and_fetch_from_checksum(pdb, checksum_walker, arg1, &source_file_name))) return result; + } + break; + case BA_OP_ChangeLineOffset: + line_number += pdb_reader_convert_binannot_to_signed(arg1); + break; + case BA_OP_ChangeCodeOffsetAndLineOffset: + line_number += pdb_reader_convert_binannot_to_signed(arg2); + offset_top_function += arg1; + check_address = TRUE; + break; + case BA_OP_ChangeCodeLengthAndCodeOffset: + offset_top_function += arg2; + check_address = TRUE; + break; + default: + WARN("Unsupported op %d\n", opcode); + break; + } + if (check_address) + { + if (top_function_address + offset_top_function > address) /* we're above the searched address */ + break; + line_info->address = top_function_address + offset_top_function; + line_info->line_number = line_number; + if (top_function_address + offset_top_function == address) /* we've reached our address */ + break; + } + } + line_info->key = NULL; + result = lineinfo_set_nameA(pdb->module->process, line_info, source_file_name) ? R_PDB_SUCCESS : R_PDB_OUT_OF_MEMORY; + pdb_reader_free(pdb, source_file_name); + + return result; +} + +static enum method_result pdb_method_get_line_from_inlined_address(struct module_format *modfmt, struct symt_function *inlined, + DWORD64 address, struct lineinfo_t *line_info) +{ + struct pdb_reader *pdb; + + if (!pdb_hack_get_main_info(modfmt, &pdb, NULL)) return MR_FAILURE; + + return pdb_method_result(pdb_method_get_line_from_inlined_address_internal(pdb, inlined, address, line_info)); +} + static struct module_format_vtable pdb_module_format_vtable = { NULL,/*pdb_module_remove*/ @@ -3266,6 +3707,7 @@ static struct module_format_vtable pdb_module_format_vtable = pdb_method_get_line_from_address, pdb_method_advance_line_info, pdb_method_enumerate_lines, + pdb_method_get_line_from_inlined_address, pdb_method_enumerate_sources, };
diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index cf6bfe8c037..c3ec770b2ba 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -2778,6 +2778,25 @@ static BOOL get_line_from_inline_context(HANDLE hProcess, DWORD64 addr, ULONG in { case IFC_MODE_INLINE: inlined = symt_find_inlined_site(pair.effective, addr, inline_ctx); + if (symt_check_tag(&inlined->symt, SymTagInlineSite)) + { + struct module_format_vtable_iterator iter = {}; + while ((module_format_vtable_iterator_next(pair.effective, &iter, + MODULE_FORMAT_VTABLE_INDEX(get_line_from_inlined_address)))) + { + enum method_result result = iter.modfmt->vtable->get_line_from_inlined_address(iter.modfmt, inlined, addr, line_info); + switch (result) + { + case MR_SUCCESS: + if (disp) *disp = addr - line_info->address; + return TRUE; + case MR_NOT_FOUND: /* continue */ + break; + default: + return FALSE; + } + } + } if (inlined && get_line_from_function(&pair, inlined, addr, disp, line_info)) return TRUE; /* fall through: check if we can find line info at top function level */
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/coff.c | 9 ++++----- dlls/dbghelp/dbghelp_private.h | 9 +++++---- dlls/dbghelp/dwarf.c | 6 ++++-- dlls/dbghelp/elf_module.c | 13 ++++++------- dlls/dbghelp/msc.c | 5 ++--- dlls/dbghelp/pe_module.c | 2 +- dlls/dbghelp/source.c | 26 ++++++++++++++++---------- dlls/dbghelp/stabs.c | 2 +- dlls/dbghelp/symbol.c | 6 +++--- dlls/dbghelp/type.c | 3 +-- 10 files changed, 43 insertions(+), 38 deletions(-)
diff --git a/dlls/dbghelp/coff.c b/dlls/dbghelp/coff.c index 65ed3b7def2..d4d804d935e 100644 --- a/dlls/dbghelp/coff.c +++ b/dlls/dbghelp/coff.c @@ -114,7 +114,7 @@ static int coff_add_file(struct CoffFileSet* coff_files, struct module* module, file = coff_files->files + coff_files->nfiles; file->startaddr = 0xffffffff; file->endaddr = 0; - file->compiland = symt_new_compiland(module, source_new(module, NULL, filename)); + file->compiland = symt_new_compiland(module, filename); file->linetab_offset = -1; file->linecnt = 0; file->entries = NULL; @@ -218,8 +218,7 @@ BOOL coff_process_info(const struct msc_debug_info* msc_dbg) */ const char* fn;
- fn = source_get(msc_dbg->module, - coff_files.files[curr_file_idx].compiland->source); + fn = coff_files.files[curr_file_idx].compiland->filename;
TRACE("Duplicating sect from %s: %lx %x %x %d %d\n", fn, aux->Section.Length, @@ -241,7 +240,7 @@ BOOL coff_process_info(const struct msc_debug_info* msc_dbg) else { TRACE("New text sect from %s: %lx %x %x %d %d\n", - source_get(msc_dbg->module, coff_files.files[curr_file_idx].compiland->source), + coff_files.files[curr_file_idx].compiland->filename, aux->Section.Length, aux->Section.NumberOfRelocations, aux->Section.NumberOfLinenumbers, @@ -420,7 +419,7 @@ BOOL coff_process_info(const struct msc_debug_info* msc_dbg) { symt_add_func_line(msc_dbg->module, (struct symt_function*)coff_files.files[j].entries[l+1], - coff_files.files[j].compiland->source, + source_new(msc_dbg->module, NULL, coff_files.files[j].compiland->filename), linepnt->Linenumber, msc_dbg->module->module.BaseOfImage + linepnt->Type.VirtualAddress); } diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 5576766fcfc..7b489f091fe 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -207,7 +207,7 @@ struct symt_compiland struct symt symt; struct symt_module* container; /* symt_module */ ULONG_PTR address; - unsigned source; + const char *filename; struct vector vchildren; /* global variables & functions */ void* user; /* when debug info provider needs to store information */ }; @@ -866,6 +866,7 @@ extern BOOL pe_has_buildid_debug(struct image_file_map *fmap, GUID *guid extern unsigned source_new(struct module* module, const char* basedir, const char* source); extern const char* source_get(const struct module* module, unsigned idx); extern int source_rb_compare(const void *key, const struct wine_rb_entry *entry); +extern char *source_build_path(const char *base, const char *name);
/* stabs.c */ typedef void (*stabs_def_cb)(struct module* module, ULONG_PTR load_offset, @@ -906,10 +907,10 @@ extern struct symt_ht* extern struct symt_module* symt_new_module(struct module* module); extern struct symt_compiland* - symt_new_compiland(struct module* module, unsigned src_idx); + symt_new_compiland(struct module* module, const char *filename); extern struct symt_public* - symt_new_public(struct module* module, - struct symt_compiland* parent, + symt_new_public(struct module* module, + struct symt_compiland* parent, const char* typename, BOOL is_function, ULONG_PTR address, diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c index 831c56af63b..3e77da64d9c 100644 --- a/dlls/dbghelp/dwarf.c +++ b/dlls/dbghelp/dwarf.c @@ -3048,6 +3048,7 @@ static BOOL dwarf2_parse_compilation_unit(dwarf2_parse_context_t* ctx) struct attribute stmt_list, low_pc; struct attribute comp_dir; struct attribute language; + char *tmp;
if (!dwarf2_find_attribute(di, DW_AT_name, &name)) name.u.string = NULL; @@ -3064,8 +3065,9 @@ static BOOL dwarf2_parse_compilation_unit(dwarf2_parse_context_t* ctx)
ctx->language = language.u.uvalue;
- ctx->compiland = symt_new_compiland(ctx->module_ctx->module, - source_new(ctx->module_ctx->module, comp_dir.u.string, name.u.string)); + tmp = source_build_path(comp_dir.u.string, name.u.string); + ctx->compiland = symt_new_compiland(ctx->module_ctx->module, tmp); + HeapFree(GetProcessHeap(), 0, tmp); ctx->compiland->address = ctx->module_ctx->load_offset + low_pc.u.uvalue; dwarf2_cache_cuhead(ctx->module_ctx->module->format_info[DFI_DWARF]->u.dwarf2_info, ctx->compiland, &ctx->head); di->symt = &ctx->compiland->symt; diff --git a/dlls/dbghelp/elf_module.c b/dlls/dbghelp/elf_module.c index 8053f7a5a9a..dad0d459409 100644 --- a/dlls/dbghelp/elf_module.c +++ b/dlls/dbghelp/elf_module.c @@ -699,7 +699,7 @@ static void elf_hash_symtab(struct module* module, struct pool* pool, { case ELF_STT_FILE: if (symname) - compiland = symt_new_compiland(module, source_new(module, NULL, symname)); + compiland = symt_new_compiland(module, symname); else compiland = NULL; continue; @@ -778,12 +778,11 @@ static const struct elf_sym *elf_lookup_symtab(const struct module* module, */ if (compiland) { - compiland_name = source_get(module, - ((const struct symt_compiland*)compiland)->source); + compiland_name = ((const struct symt_compiland*)compiland)->filename; compiland_basename = file_nameA(compiland_name); } else compiland_name = compiland_basename = NULL; - + hash_table_iter_init(ht_symtab, &hti, name); while ((ste = hash_table_iter_up(&hti))) { @@ -794,7 +793,7 @@ static const struct elf_sym *elf_lookup_symtab(const struct module* module, continue; if (ste->compiland && compiland_name) { - const char* filename = source_get(module, ste->compiland->source); + const char* filename = ste->compiland->filename; if (strcmp(filename, compiland_name)) { base = file_nameA(filename); @@ -805,9 +804,9 @@ static const struct elf_sym *elf_lookup_symtab(const struct module* module, { FIXME("Already found symbol %s (%s) in symtab %s @%08x and %s @%08x\n", debugstr_a(name), debugstr_a(compiland_name), - debugstr_a(source_get(module, result->compiland->source)), + debugstr_a(result->compiland->filename), (unsigned int)result->sym.st_value, - debugstr_a(source_get(module, ste->compiland->source)), + debugstr_a(ste->compiland->filename), (unsigned int)ste->sym.st_value); } else diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index d9a4934696d..fbd7e29b531 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -2312,7 +2312,6 @@ static struct symt_function* codeview_create_inline_site(const struct msc_debug_
static struct symt_compiland* codeview_new_compiland(const struct msc_debug_info* msc_dbg, const char* objname) { - unsigned int src_idx = source_new(msc_dbg->module, NULL, objname); unsigned int i;
/* In some cases MSVC generates several compiland entries with same pathname in PDB file. @@ -2322,10 +2321,10 @@ static struct symt_compiland* codeview_new_compiland(const struct msc_debug_info for (i = 0; i < msc_dbg->module->top->vchildren.num_elts; i++) { struct symt_compiland** p = vector_at(&msc_dbg->module->top->vchildren, i); - if (symt_check_tag(&(*p)->symt, SymTagCompiland) && (*p)->source == src_idx) + if (symt_check_tag(&(*p)->symt, SymTagCompiland) && !strcmp((*p)->filename, objname)) return *p; } - return symt_new_compiland(msc_dbg->module, src_idx); + return symt_new_compiland(msc_dbg->module, objname); }
static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, diff --git a/dlls/dbghelp/pe_module.c b/dlls/dbghelp/pe_module.c index 1f2022fc1af..6b5a9a4b425 100644 --- a/dlls/dbghelp/pe_module.c +++ b/dlls/dbghelp/pe_module.c @@ -503,7 +503,7 @@ static BOOL pe_load_coff_symbol_table(struct module* module) if (name[0] == '_') name++;
if (!compiland && lastfilename) - compiland = symt_new_compiland(module, source_new(module, NULL, lastfilename)); + compiland = symt_new_compiland(module, lastfilename);
if (!(dbghelp_options & SYMOPT_NO_PUBLICS)) symt_new_public(module, compiland, name, FALSE, diff --git a/dlls/dbghelp/source.c b/dlls/dbghelp/source.c index 24ba224a499..79b4ff9989c 100644 --- a/dlls/dbghelp/source.c +++ b/dlls/dbghelp/source.c @@ -56,6 +56,21 @@ static unsigned source_find(const char* name) return WINE_RB_ENTRY_VALUE(e, struct source_rb, entry)->source; }
+char *source_build_path(const char *base, const char *name) +{ + char *dst; + unsigned bsz = strlen(base); + + dst = HeapAlloc(GetProcessHeap(), 0, bsz + 1 + strlen(name) + 1); + if (dst) + { + strcpy(dst, base); + if (bsz && dst[bsz - 1] != '/' && dst[bsz - 1] != '\') dst[bsz++] = '/'; + strcpy(&dst[bsz], name); + } + return dst; +} + /****************************************************************** * source_new * @@ -71,16 +86,7 @@ unsigned source_new(struct module* module, const char* base, const char* name) if (!base || *name == '/') full = name; else - { - unsigned bsz = strlen(base); - - tmp = HeapAlloc(GetProcessHeap(), 0, bsz + 1 + strlen(name) + 1); - if (!tmp) return ret; - full = tmp; - strcpy(tmp, base); - if (bsz && tmp[bsz - 1] != '/') tmp[bsz++] = '/'; - strcpy(&tmp[bsz], name); - } + full = source_build_path(base, name); rb_module = module; if (!module->sources || (ret = source_find(full)) == (unsigned)-1) { diff --git a/dlls/dbghelp/stabs.c b/dlls/dbghelp/stabs.c index ea5bed152e6..8aa9907449c 100644 --- a/dlls/dbghelp/stabs.c +++ b/dlls/dbghelp/stabs.c @@ -1587,7 +1587,7 @@ BOOL stabs_parse(struct module* module, ULONG_PTR load_offset, { stabs_reset_includes(); source_idx = source_new(module, srcpath, ptr); - compiland = symt_new_compiland(module, source_idx); + compiland = symt_new_compiland(module, source_get(module, source_idx)); } else { diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index c3ec770b2ba..e4c5361f897 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -231,19 +231,19 @@ struct symt_module* symt_new_module(struct module* module) return sym; }
-struct symt_compiland* symt_new_compiland(struct module* module, unsigned src_idx) +struct symt_compiland* symt_new_compiland(struct module* module, const char *filename) { struct symt_compiland* sym; struct symt_compiland** p;
TRACE_(dbghelp_symt)("Adding compiland symbol %s:%s\n", - debugstr_w(module->modulename), debugstr_a(source_get(module, src_idx))); + debugstr_w(module->modulename), debugstr_a(filename)); if ((sym = pool_alloc(&module->pool, sizeof(*sym)))) { sym->symt.tag = SymTagCompiland; sym->container = module->top; sym->address = 0; - sym->source = src_idx; + sym->filename = pool_strdup(&module->pool, filename); vector_init(&sym->vchildren, sizeof(struct symt*), 0); sym->user = NULL; p = vector_add(&module->top->vchildren, &module->pool); diff --git a/dlls/dbghelp/type.c b/dlls/dbghelp/type.c index b4c1a414d99..e0a79086ccf 100644 --- a/dlls/dbghelp/type.c +++ b/dlls/dbghelp/type.c @@ -102,8 +102,7 @@ const char* symt_get_name(const struct symt* sym) case SymTagEnum: return ((const struct symt_enum*)sym)->hash_elt.name; case SymTagTypedef: return ((const struct symt_typedef*)sym)->hash_elt.name; case SymTagUDT: return ((const struct symt_udt*)sym)->hash_elt.name; - case SymTagCompiland: return source_get(((const struct symt_compiland*)sym)->container->module, - ((const struct symt_compiland*)sym)->source); + case SymTagCompiland: return ((const struct symt_compiland*)sym)->filename; default: FIXME("Unsupported sym-tag %s\n", symt_get_tag_str(sym->tag)); /* fall through */
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/dbghelp_private.h | 29 ++++++--- dlls/dbghelp/dwarf.c | 34 +++++----- dlls/dbghelp/elf_module.c | 9 +-- dlls/dbghelp/module.c | 12 ++-- dlls/dbghelp/msc.c | 17 ++--- dlls/dbghelp/symbol.c | 109 ++++++++++++++++++--------------- dlls/dbghelp/type.c | 39 ++++++------ 7 files changed, 138 insertions(+), 111 deletions(-)
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 7b489f091fe..106d84cdde7 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -189,7 +189,7 @@ typedef ULONG_PTR symref_t; struct symt_block { struct symt symt; - struct symt* container; /* block, or func */ + symref_t container; /* block, or func */ struct vector vchildren; /* sub-blocks & local variables */ unsigned num_ranges; struct addr_range ranges[]; @@ -205,7 +205,7 @@ struct symt_module /* in fact any of .exe, .dll... */ struct symt_compiland { struct symt symt; - struct symt_module* container; /* symt_module */ + symref_t container; /* symt_module */ ULONG_PTR address; const char *filename; struct vector vchildren; /* global variables & functions */ @@ -217,7 +217,7 @@ struct symt_data struct symt symt; struct hash_table_elt hash_elt; /* if global symbol */ enum DataKind kind; - struct symt* container; + symref_t container; symref_t type; union /* depends on kind */ { @@ -294,7 +294,7 @@ struct symt_function { struct symt symt; /* SymTagFunction or SymTagInlineSite */ struct hash_table_elt hash_elt; /* if global symbol, inline site */ - struct symt* container; /* compiland (for SymTagFunction) or function (for SymTagInlineSite) */ + symref_t container; /* compiland (for SymTagFunction) or function (for SymTagInlineSite) */ symref_t type; /* points to function_signature */ struct vector vlines; struct vector vchildren; /* locals, params, blocks, start/end, labels, inline sites */ @@ -308,7 +308,7 @@ struct symt_hierarchy_point { struct symt symt; /* either SymTagFunctionDebugStart, SymTagFunctionDebugEnd, SymTagLabel */ struct hash_table_elt hash_elt; /* if label (and in compiland's hash table if global) */ - struct symt* parent; /* symt_function or symt_compiland */ + symref_t container; /* symt_function or symt_compiland */ struct location loc; };
@@ -316,7 +316,7 @@ struct symt_public { struct symt symt; struct hash_table_elt hash_elt; - struct symt* container; /* compiland */ + symref_t container; /* compiland */ BOOL is_function; ULONG_PTR address; ULONG_PTR size; @@ -326,7 +326,7 @@ struct symt_thunk { struct symt symt; struct hash_table_elt hash_elt; - struct symt* container; /* compiland */ + symref_t container; /* compiland */ ULONG_PTR address; ULONG_PTR size; THUNK_ORDINAL ordinal; /* FIXME: doesn't seem to be accessible */ @@ -978,12 +978,25 @@ extern struct symt_hierarchy_point* symt_new_label(struct module* module, struct symt_compiland* compiland, const char* name, ULONG_PTR address); +static inline BOOL symt_is_symref_ptr(symref_t ref) {return (ref & 3) == 0;} static inline symref_t symt_ptr_to_symref(const struct symt *symt) {return (ULONG_PTR)symt;} +static inline struct symt* + _symt_symref_to_ptr(const char *file, unsigned lineno, symref_t symref) +{ + if (!symt_is_symref_ptr(symref)) + { + MESSAGE("%s:%u can't convert symref to ptr\n", file, lineno); + return NULL; + } + return (struct symt*)symref; +} +/* this function shall be used with care as not all symref:s are actual pointers */ +#define SYMT_SYMREF_TO_PTR(s) _symt_symref_to_ptr(__FILE__, __LINE__, (s)) extern symref_t symt_index_to_symref(struct module* module, DWORD id); extern DWORD symt_symref_to_index(struct module* module, symref_t sym); static inline DWORD symt_ptr_to_index(struct module *module, const struct symt *symt) {return symt_symref_to_index(module, symt_ptr_to_symref(symt));} -static inline BOOL symt_is_symref_ptr(symref_t ref) {return (ref & 3) == 0;} + extern struct symt_custom* symt_new_custom(struct module* module, const char* name, DWORD64 addr, DWORD size); diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c index 3e77da64d9c..31ef65f158d 100644 --- a/dlls/dbghelp/dwarf.c +++ b/dlls/dbghelp/dwarf.c @@ -2280,7 +2280,7 @@ static void dwarf2_parse_inlined_subroutine(dwarf2_subprogram_t* subpgm, child->abbrev->tag, dwarf2_debug_di(di)); } } - subpgm->current_block = symt_check_tag(subpgm->current_func->container, SymTagBlock) ? + subpgm->current_block = symt_check_tag(SYMT_SYMREF_TO_PTR(subpgm->current_func->container), SymTagBlock) ? (struct symt_block*)subpgm->current_func->container : NULL; subpgm->current_func = (struct symt_function*)symt_get_upper_inlined(subpgm->current_func); } @@ -2924,22 +2924,22 @@ static BOOL dwarf2_parse_line_numbers(dwarf2_parse_context_t* ctx, return TRUE; }
-unsigned dwarf2_cache_cuhead(struct dwarf2_module_info_s* module, struct symt_compiland* c, const dwarf2_cuhead_t* head) +static unsigned dwarf2_cache_cuhead(struct module *module, struct dwarf2_module_info_s* module_info, struct symt_compiland* c, const dwarf2_cuhead_t* head) { dwarf2_cuhead_t* ah; unsigned i; - for (i = 0; i < module->num_cuheads; ++i) + for (i = 0; i < module_info->num_cuheads; ++i) { - if (memcmp(module->cuheads[i], head, sizeof(*head)) == 0) + if (memcmp(module_info->cuheads[i], head, sizeof(*head)) == 0) { - c->user = module->cuheads[i]; + c->user = module_info->cuheads[i]; return TRUE; } } - if (!(ah = pool_alloc(&c->container->module->pool, sizeof(*head)))) return FALSE; + if (!(ah = pool_alloc(&module->pool, sizeof(*head)))) return FALSE; memcpy(ah, head, sizeof(*head)); - module->cuheads = realloc(module->cuheads, ++module->num_cuheads * sizeof(head)); - module->cuheads[module->num_cuheads - 1] = ah; + module_info->cuheads = realloc(module_info->cuheads, ++module_info->num_cuheads * sizeof(head)); + module_info->cuheads[module_info->num_cuheads - 1] = ah; c->user = ah; return TRUE; } @@ -3069,7 +3069,7 @@ static BOOL dwarf2_parse_compilation_unit(dwarf2_parse_context_t* ctx) ctx->compiland = symt_new_compiland(ctx->module_ctx->module, tmp); HeapFree(GetProcessHeap(), 0, tmp); ctx->compiland->address = ctx->module_ctx->load_offset + low_pc.u.uvalue; - dwarf2_cache_cuhead(ctx->module_ctx->module->format_info[DFI_DWARF]->u.dwarf2_info, ctx->compiland, &ctx->head); + dwarf2_cache_cuhead(ctx->module_ctx->module, ctx->module_ctx->module->format_info[DFI_DWARF]->u.dwarf2_info, ctx->compiland, &ctx->head); di->symt = &ctx->compiland->symt; children = dwarf2_get_di_children(di); if (children) for (i = 0; i < vector_length(children); i++) @@ -3121,9 +3121,9 @@ static const dwarf2_cuhead_t* get_cuhead_from_func(const struct symt_function* f { if (symt_check_tag(&func->symt, SymTagInlineSite)) func = symt_get_function_from_inlined((struct symt_function*)func); - if (symt_check_tag(&func->symt, SymTagFunction) && symt_check_tag(func->container, SymTagCompiland)) + if (symt_check_tag(&func->symt, SymTagFunction) && symt_check_tag(SYMT_SYMREF_TO_PTR(func->container), SymTagCompiland)) { - struct symt_compiland* c = (struct symt_compiland*)func->container; + struct symt_compiland* c = (struct symt_compiland*)SYMT_SYMREF_TO_PTR(func->container); return (const dwarf2_cuhead_t*)c->user; } FIXME("Should have a compilation unit head\n"); @@ -3138,7 +3138,7 @@ static enum location_error loc_compute_frame(const struct module_format* modfmt, struct location* frame) { struct process *pcs = modfmt->module->process; - struct symt** psym = NULL; + struct symt* sym; struct location* pframe; dwarf2_traverse_context_t lctx; enum location_error err; @@ -3146,10 +3146,10 @@ static enum location_error loc_compute_frame(const struct module_format* modfmt,
for (i=0; i<vector_length(&func->vchildren); i++) { - psym = vector_at(&func->vchildren, i); - if (psym && symt_check_tag(*psym, SymTagCustom)) + sym = SYMT_SYMREF_TO_PTR(*(symref_t*)vector_at(&func->vchildren, i)); + if (symt_check_tag(sym, SymTagCustom)) { - pframe = &((struct symt_hierarchy_point*)*psym)->loc; + pframe = &((struct symt_hierarchy_point*)sym)->loc;
/* First, recompute the frame information, if needed */ switch (pframe->kind) @@ -3173,7 +3173,7 @@ static enum location_error loc_compute_frame(const struct module_format* modfmt, } break; case loc_dwarf2_frame_cfa: - err = compute_call_frame_cfa(modfmt->module, ip + ((struct symt_compiland*)func->container)->address, frame); + err = compute_call_frame_cfa(modfmt->module, ip + ((struct symt_compiland*)SYMT_SYMREF_TO_PTR(func->container))->address, frame); if (err < 0) return err; break; default: @@ -4030,7 +4030,7 @@ static void dwarf2_location_compute(const struct module_format* modfmt, { struct process *pcs = modfmt->module->process; /* instruction pointer relative to compiland's start */ - ip = pcs->localscope_pc - ((struct symt_compiland*)func->container)->address; + ip = pcs->localscope_pc - ((struct symt_compiland*)SYMT_SYMREF_TO_PTR(func->container))->address;
if ((err = loc_compute_frame(modfmt, func, ip, head, &frame)) == 0) { diff --git a/dlls/dbghelp/elf_module.c b/dlls/dbghelp/elf_module.c index dad0d459409..f6d17c7ebd9 100644 --- a/dlls/dbghelp/elf_module.c +++ b/dlls/dbghelp/elf_module.c @@ -762,7 +762,7 @@ static void elf_hash_symtab(struct module* module, struct pool* pool, */ static const struct elf_sym *elf_lookup_symtab(const struct module* module, const struct hash_table* ht_symtab, - const char* name, const struct symt* compiland) + const char* name, symref_t symref_compiland) { struct symtab_elt* weak_result = NULL; /* without compiland name */ struct symtab_elt* result = NULL; @@ -771,8 +771,9 @@ static const struct elf_sym *elf_lookup_symtab(const struct module* module, const char* compiland_name; const char* compiland_basename; const char* base; + struct symt_compiland *compiland = (struct symt_compiland*)SYMT_SYMREF_TO_PTR(symref_compiland);
- /* we need weak match up (at least) when symbols of same name, + /* we need weak match up (at least) when symbols of same name, * defined several times in different compilation units, * are merged in a single one (hence a different filename for c.u.) */ @@ -856,7 +857,7 @@ static void elf_finish_stabs_info(struct module* module, const struct hash_table { break; } - symp = elf_lookup_symtab(module, symtab, sym->hash_elt.name, + symp = elf_lookup_symtab(module, symtab, sym->hash_elt.name, ((struct symt_function*)sym)->container); if (symp) { @@ -885,7 +886,7 @@ static void elf_finish_stabs_info(struct module* module, const struct hash_table if (((struct symt_data*)sym)->u.var.kind != loc_absolute || ((struct symt_data*)sym)->u.var.offset != elf_info->elf_addr) break; - symp = elf_lookup_symtab(module, symtab, sym->hash_elt.name, + symp = elf_lookup_symtab(module, symtab, sym->hash_elt.name, ((struct symt_data*)sym)->container); if (symp) { diff --git a/dlls/dbghelp/module.c b/dlls/dbghelp/module.c index 750d0d08655..c5eafee4db5 100644 --- a/dlls/dbghelp/module.c +++ b/dlls/dbghelp/module.c @@ -1044,12 +1044,14 @@ BOOL module_remove(struct process* pcs, struct module* module) locsym = &symt_get_function_from_inlined((struct symt_function*)locsym)->symt; if (symt_check_tag(locsym, SymTagFunction)) { - locsym = ((struct symt_function*)locsym)->container; - if (symt_check_tag(locsym, SymTagCompiland) && - module == ((struct symt_compiland*)locsym)->container->module) + struct symt_compiland *compiland = (struct symt_compiland*)SYMT_SYMREF_TO_PTR(((struct symt_function*)locsym)->container); + if (symt_check_tag(&compiland->symt, SymTagCompiland)) { - pcs->localscope_pc = 0; - pcs->localscope_symt = NULL; + if (module == ((struct symt_module*)SYMT_SYMREF_TO_PTR(compiland->container))->module) + { + pcs->localscope_pc = 0; + pcs->localscope_symt = NULL; + } } } } diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index fbd7e29b531..d65b7707921 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -1814,8 +1814,9 @@ static BOOL func_has_local(struct symt_function* func, const char* name)
for (i = 0; i < func->vchildren.num_elts; ++i) { - struct symt* p = *(struct symt**)vector_at(&func->vchildren, i); - if (symt_check_tag(p, SymTagData) && !strcmp(((struct symt_data*)p)->hash_elt.name, name)) + struct symt *lsym = SYMT_SYMREF_TO_PTR(*(symref_t*)vector_at(&func->vchildren, i)); + + if (symt_check_tag(lsym, SymTagData) && !strcmp(((struct symt_data*)lsym)->hash_elt.name, name)) return TRUE; } return FALSE; @@ -1865,7 +1866,7 @@ static inline void codeview_add_variable(const struct msc_debug_info* msc_dbg, if (symdata->kind == (is_local ? DataIsFileStatic : DataIsGlobal) && symdata->u.var.kind == loc.kind && symdata->u.var.offset == loc.offset && - symdata->container == &compiland->symt) + symdata->container == symt_ptr_to_symref(&compiland->symt)) { /* We don't compare types yet... Unfortunately, they are not * always the same typeid... it'd require full type equivalence @@ -2320,9 +2321,9 @@ static struct symt_compiland* codeview_new_compiland(const struct msc_debug_info */ for (i = 0; i < msc_dbg->module->top->vchildren.num_elts; i++) { - struct symt_compiland** p = vector_at(&msc_dbg->module->top->vchildren, i); - if (symt_check_tag(&(*p)->symt, SymTagCompiland) && !strcmp((*p)->filename, objname)) - return *p; + struct symt_compiland* p = (struct symt_compiland*)SYMT_SYMREF_TO_PTR(*(symref_t*)vector_at(&msc_dbg->module->top->vchildren, i)); + if (symt_check_tag(&p->symt, SymTagCompiland) && !strcmp(p->filename, objname)) + return p; } return symt_new_compiland(msc_dbg->module, objname); } @@ -2783,8 +2784,8 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, break;
case S_INLINESITE_END: - block = symt_check_tag(curr_func->container, SymTagBlock) ? - (struct symt_block*)curr_func->container : NULL; + block = symt_check_tag(SYMT_SYMREF_TO_PTR(curr_func->container), SymTagBlock) ? + (struct symt_block *)((struct symt_block*)curr_func->container) : NULL; curr_func = (struct symt_function*)symt_get_upper_inlined(curr_func); break;
diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index e4c5361f897..9f8049e3330 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -226,7 +226,7 @@ struct symt_module* symt_new_module(struct module* module) { sym->symt.tag = SymTagExe; sym->module = module; - vector_init(&sym->vchildren, sizeof(struct symt*), 0); + vector_init(&sym->vchildren, sizeof(symref_t), 0); } return sym; } @@ -234,20 +234,20 @@ struct symt_module* symt_new_module(struct module* module) struct symt_compiland* symt_new_compiland(struct module* module, const char *filename) { struct symt_compiland* sym; - struct symt_compiland** p; + symref_t* p;
TRACE_(dbghelp_symt)("Adding compiland symbol %s:%s\n", debugstr_w(module->modulename), debugstr_a(filename)); if ((sym = pool_alloc(&module->pool, sizeof(*sym)))) { sym->symt.tag = SymTagCompiland; - sym->container = module->top; + sym->container = symt_ptr_to_symref(&module->top->symt); sym->address = 0; sym->filename = pool_strdup(&module->pool, filename); - vector_init(&sym->vchildren, sizeof(struct symt*), 0); + vector_init(&sym->vchildren, sizeof(symref_t), 0); sym->user = NULL; p = vector_add(&module->top->vchildren, &module->pool); - *p = sym; + if (p) *p = symt_ptr_to_symref(&sym->symt); } return sym; } @@ -259,7 +259,7 @@ struct symt_public* symt_new_public(struct module* module, ULONG_PTR address, unsigned size) { struct symt_public* sym; - struct symt** p; + symref_t* p;
TRACE_(dbghelp_symt)("Adding public symbol %s:%s @%Ix\n", debugstr_w(module->modulename), debugstr_a(name), address); @@ -270,7 +270,7 @@ struct symt_public* symt_new_public(struct module* module, { sym->symt.tag = SymTagPublicSymbol; sym->hash_elt.name = pool_strdup(&module->pool, name); - sym->container = compiland ? &compiland->symt : NULL; + sym->container = compiland ? symt_ptr_to_symref(&compiland->symt) : 0; sym->is_function = is_function; sym->address = address; sym->size = size; @@ -278,7 +278,7 @@ struct symt_public* symt_new_public(struct module* module, if (compiland) { p = vector_add(&compiland->vchildren, &module->pool); - *p = &sym->symt; + if (p) *p = symt_ptr_to_symref(&sym->symt); } } return sym; @@ -291,7 +291,7 @@ struct symt_data* symt_new_global_variable(struct module* module, symref_t type) { struct symt_data* sym; - struct symt** p; + symref_t* p; DWORD64 tsz;
TRACE_(dbghelp_symt)("Adding global symbol %s:%s %d@%Ix %Ix\n", @@ -301,7 +301,7 @@ struct symt_data* symt_new_global_variable(struct module* module, sym->symt.tag = SymTagData; sym->hash_elt.name = pool_strdup(&module->pool, name); sym->kind = is_static ? DataIsFileStatic : DataIsGlobal; - sym->container = compiland ? &compiland->symt : &module->top->symt; + sym->container = symt_ptr_to_symref(compiland ? &compiland->symt : &module->top->symt); sym->type = type; sym->u.var = loc; if (type && size && symt_get_info_from_symref(module, type, TI_GET_LENGTH, &tsz)) @@ -312,7 +312,7 @@ struct symt_data* symt_new_global_variable(struct module* module, } symt_add_module_ht(module, (struct symt_ht*)sym); p = vector_add(compiland ? &compiland->vchildren : &module->top->vchildren, &module->pool); - *p = &sym->symt; + if (p) *p = symt_ptr_to_symref(&sym->symt); } return sym; } @@ -331,10 +331,10 @@ static struct symt_function* init_function_or_inlinesite(struct module* module, { sym->symt.tag = tag; sym->hash_elt.name = pool_strdup(&module->pool, name); - sym->container = container; + sym->container = symt_ptr_to_symref(container); sym->type = sig_type; vector_init(&sym->vlines, sizeof(struct line_info), 0); - vector_init(&sym->vchildren, sizeof(struct symt*), 0); + vector_init(&sym->vchildren, sizeof(symref_t), 0); sym->user = user; sym->num_ranges = num_ranges; } @@ -354,7 +354,7 @@ struct symt_function* symt_new_function(struct module* module,
if ((sym = init_function_or_inlinesite(module, SymTagFunction, &compiland->symt, name, sig_type, user, 1))) { - struct symt** p; + symref_t* p; sym->ranges[0].low = addr; sym->ranges[0].high = addr + size; sym->next_inlinesite = NULL; /* first of list */ @@ -362,7 +362,7 @@ struct symt_function* symt_new_function(struct module* module, if (compiland) { p = vector_add(&compiland->vchildren, &module->pool); - *p = &sym->symt; + if (p) *p = symt_ptr_to_symref(&sym->symt); } } return sym; @@ -381,7 +381,7 @@ struct symt_function* symt_new_inlinesite(struct module* module, TRACE_(dbghelp_symt)("Adding inline site %s\n", debugstr_a(name)); if ((sym = init_function_or_inlinesite(module, SymTagInlineSite, container, name, sig_type, user, num_ranges))) { - struct symt** p; + symref_t* p; assert(container);
/* chain inline sites */ @@ -394,7 +394,7 @@ struct symt_function* symt_new_inlinesite(struct module* module, assert(container->tag == SymTagBlock); p = vector_add(&((struct symt_block*)container)->vchildren, &module->pool); } - *p = &sym->symt; + if (p) *p = symt_ptr_to_symref(&sym->symt); } return sym; } @@ -472,7 +472,7 @@ struct symt_data* symt_add_func_local(struct module* module, symref_t type, const char* name) { struct symt_data* locsym; - struct symt** p; + symref_t* p;
TRACE_(dbghelp_symt)("Adding local symbol (%s:%s): %s %Ix\n", debugstr_w(module->modulename), debugstr_a(func->hash_elt.name), @@ -486,14 +486,14 @@ struct symt_data* symt_add_func_local(struct module* module, locsym->hash_elt.name = pool_strdup(&module->pool, name); locsym->hash_elt.next = NULL; locsym->kind = dt; - locsym->container = block ? &block->symt : &func->symt; + locsym->container = symt_ptr_to_symref(block ? &block->symt : &func->symt); locsym->type = type; locsym->u.var = *loc; if (block) p = vector_add(&block->vchildren, &module->pool); else p = vector_add(&func->vchildren, &module->pool); - *p = &locsym->symt; + if (p) *p = symt_ptr_to_symref(&locsym->symt); if (dt == DataIsStaticLocal) symt_add_module_addr(module, (struct symt_ht*)locsym); return locsym; @@ -511,7 +511,7 @@ struct symt_data* symt_add_func_constant(struct module* module, VARIANT* v) { struct symt_data* locsym; - struct symt** p; + symref_t* p;
TRACE_(dbghelp_symt)("Adding local constant (%s:%s): %s %Ix\n", debugstr_w(module->modulename), debugstr_a(func->hash_elt.name), @@ -524,14 +524,14 @@ struct symt_data* symt_add_func_constant(struct module* module, locsym->hash_elt.name = pool_strdup(&module->pool, name); locsym->hash_elt.next = NULL; locsym->kind = DataIsConstant; - locsym->container = block ? &block->symt : &func->symt; + locsym->container = symt_ptr_to_symref(block ? &block->symt : &func->symt); locsym->type = type; locsym->u.value = *v; if (block) p = vector_add(&block->vchildren, &module->pool); else p = vector_add(&func->vchildren, &module->pool); - *p = &locsym->symt; + if (p) *p = symt_ptr_to_symref(&locsym->symt); return locsym; }
@@ -541,7 +541,7 @@ struct symt_block* symt_open_func_block(struct module* module, unsigned num_ranges) { struct symt_block* block; - struct symt** p; + symref_t* p;
assert(symt_check_tag(&func->symt, SymTagFunction) || symt_check_tag(&func->symt, SymTagInlineSite)); assert(num_ranges > 0); @@ -550,13 +550,13 @@ struct symt_block* symt_open_func_block(struct module* module, block = pool_alloc(&module->pool, offsetof(struct symt_block, ranges[num_ranges])); block->symt.tag = SymTagBlock; block->num_ranges = num_ranges; - block->container = parent_block ? &parent_block->symt : &func->symt; - vector_init(&block->vchildren, sizeof(struct symt*), 0); + block->container = symt_ptr_to_symref(parent_block ? &parent_block->symt : &func->symt); + vector_init(&block->vchildren, sizeof(symref_t), 0); if (parent_block) p = vector_add(&parent_block->vchildren, &module->pool); else p = vector_add(&func->vchildren, &module->pool); - *p = &block->symt; + if (p) *p = symt_ptr_to_symref(&block->symt);
return block; } @@ -565,10 +565,15 @@ struct symt_block* symt_close_func_block(struct module* module, const struct symt_function* func, struct symt_block* block) { + struct symt *container; + assert(symt_check_tag(&func->symt, SymTagFunction) || symt_check_tag(&func->symt, SymTagInlineSite));
- return (block->container->tag == SymTagBlock) ? - CONTAINING_RECORD(block->container, struct symt_block, symt) : NULL; + container = SYMT_SYMREF_TO_PTR(block->container); + assert(container); + + return (container->tag == SymTagBlock) ? + CONTAINING_RECORD(container, struct symt_block, symt) : NULL; }
struct symt_hierarchy_point* symt_add_function_point(struct module* module, @@ -577,17 +582,17 @@ struct symt_hierarchy_point* symt_add_function_point(struct module* module, const struct location* loc, const char* name) { - struct symt_hierarchy_point*sym; - struct symt** p; + struct symt_hierarchy_point *sym; + symref_t *p;
if ((sym = pool_alloc(&module->pool, sizeof(*sym)))) { - sym->symt.tag = point; - sym->parent = &func->symt; - sym->loc = *loc; + sym->symt.tag = point; + sym->container = symt_ptr_to_symref(&func->symt); + sym->loc = *loc; sym->hash_elt.name = name ? pool_strdup(&module->pool, name) : NULL; p = vector_add(&func->vchildren, &module->pool); - *p = &sym->symt; + if (p) *p = symt_ptr_to_symref(&sym->symt); } return sym; } @@ -606,16 +611,16 @@ struct symt_thunk* symt_new_thunk(struct module* module, { sym->symt.tag = SymTagThunk; sym->hash_elt.name = pool_strdup(&module->pool, name); - sym->container = &compiland->symt; + sym->container = symt_ptr_to_symref(&compiland->symt); sym->address = addr; sym->size = size; sym->ordinal = ord; symt_add_module_ht(module, (struct symt_ht*)sym); if (compiland) { - struct symt** p; + symref_t *p; p = vector_add(&compiland->vchildren, &module->pool); - *p = &sym->symt; + if (p) *p = symt_ptr_to_symref(&sym->symt); } } return sym; @@ -636,15 +641,15 @@ struct symt_data* symt_new_constant(struct module* module, sym->symt.tag = SymTagData; sym->hash_elt.name = pool_strdup(&module->pool, name); sym->kind = DataIsConstant; - sym->container = compiland ? &compiland->symt : &module->top->symt; + sym->container = symt_ptr_to_symref(compiland ? &compiland->symt : &module->top->symt); sym->type = type; sym->u.value = *v; symt_add_module_ht(module, (struct symt_ht*)sym); if (compiland) { - struct symt** p; + symref_t *p; p = vector_add(&compiland->vchildren, &module->pool); - *p = &sym->symt; + if (p) *p = symt_ptr_to_symref(&sym->symt); } } return sym; @@ -665,13 +670,13 @@ struct symt_hierarchy_point* symt_new_label(struct module* module, sym->hash_elt.name = pool_strdup(&module->pool, name); sym->loc.kind = loc_absolute; sym->loc.offset = address; - sym->parent = compiland ? &compiland->symt : NULL; + sym->container = compiland ? symt_ptr_to_symref(&compiland->symt) : 0; symt_add_module_ht(module, (struct symt_ht*)sym); if (compiland) { - struct symt** p; + symref_t *p; p = vector_add(&compiland->vchildren, &module->pool); - *p = &sym->symt; + if (p) *p = symt_ptr_to_symref(&sym->symt); } } return sym; @@ -795,8 +800,8 @@ static BOOL symt_fill_sym_info(struct module_pair* pair, break; case DataIsConstant: sym_info->Flags |= SYMFLAG_VALUEPRESENT; - if (data->container && - (data->container->tag == SymTagFunction || data->container->tag == SymTagBlock)) + if (symt_check_tag(SYMT_SYMREF_TO_PTR(data->container), SymTagFunction) || + symt_check_tag(SYMT_SYMREF_TO_PTR(data->container), SymTagBlock)) sym_info->Flags |= SYMFLAG_LOCAL; switch (V_VT(&data->u.value)) { @@ -1093,7 +1098,7 @@ static BOOL symt_enum_locals_helper(struct module_pair* pair, const WCHAR* match, const struct sym_enum* se, struct symt_function* func, const struct vector* v) { - struct symt* lsym = NULL; + const struct symt* lsym; DWORD_PTR pc = pair->pcs->localscope_pc; unsigned int i; WCHAR* nameW; @@ -1101,7 +1106,8 @@ static BOOL symt_enum_locals_helper(struct module_pair* pair,
for (i=0; i<vector_length(v); i++) { - lsym = *(struct symt**)vector_at(v, i); + lsym = SYMT_SYMREF_TO_PTR(*(symref_t*)vector_at(v, i)); + switch (lsym->tag) { case SymTagBlock: @@ -1240,9 +1246,9 @@ struct symt* symt_get_upper_inlined(struct symt_function* inlined) { assert(symt); if (symt->tag == SymTagBlock) - symt = ((struct symt_block*)symt)->container; + symt = SYMT_SYMREF_TO_PTR(((struct symt_block*)symt)->container); else - symt = ((struct symt_function*)symt)->container; + symt = SYMT_SYMREF_TO_PTR(((struct symt_function*)symt)->container); } while (symt->tag == SymTagBlock); assert(symt->tag == SymTagFunction || symt->tag == SymTagInlineSite); return symt; @@ -1638,7 +1644,8 @@ BOOL WINAPI SymFromName(HANDLE hProcess, PCSTR Name, PSYMBOL_INFO Symbol)
for (i = 0; i < vector_length(v); i++) { - struct symt* lsym = *(struct symt**)vector_at(v, i); + struct symt* lsym = SYMT_SYMREF_TO_PTR(*(symref_t*)vector_at(v, i)); + switch (lsym->tag) { case SymTagBlock: /* no recursion */ diff --git a/dlls/dbghelp/type.c b/dlls/dbghelp/type.c index e0a79086ccf..f0469845277 100644 --- a/dlls/dbghelp/type.c +++ b/dlls/dbghelp/type.c @@ -159,10 +159,12 @@ BOOL symt_get_address(const struct symt* type, ULONG64* addr) case SymTagFuncDebugStart: case SymTagFuncDebugEnd: case SymTagLabel: - if (!((const struct symt_hierarchy_point*)type)->parent || - !symt_get_address(((const struct symt_hierarchy_point*)type)->parent, addr)) - *addr = 0; - *addr += ((const struct symt_hierarchy_point*)type)->loc.offset; + *addr = 0; + if (SYMT_SYMREF_TO_PTR(((const struct symt_hierarchy_point*)type)->container)) + { + if (symt_get_address(SYMT_SYMREF_TO_PTR(((const struct symt_hierarchy_point*)type)->container), addr)) + *addr += ((const struct symt_hierarchy_point*)type)->loc.offset; + } break; case SymTagThunk: *addr = ((const struct symt_thunk*)type)->address; @@ -308,13 +310,13 @@ BOOL symt_add_udt_element(struct module* module, struct symt_udt* udt_type, m->hash_elt.next = NULL;
m->kind = DataIsMember; - m->container = &module->top->symt; /* native defines lexical parent as module, not udt... */ + m->container = symt_ptr_to_symref(&module->top->symt); /* native defines lexical parent as module, not udt... */ m->type = elt_type; m->u.member.offset = offset; m->u.member.bit_offset = bit_offset; m->u.member.bit_length = bit_size; p = vector_add(&udt_type->vchildren, &module->pool); - *p = &m->symt; + if (p) *p = &m->symt;
return TRUE; } @@ -354,7 +356,7 @@ BOOL symt_add_enum_element(struct module* module, struct symt_enum* enum_type, e->hash_elt.name = pool_strdup(&module->pool, name); e->hash_elt.next = NULL; e->kind = DataIsConstant; - e->container = &enum_type->symt; + e->container = symt_ptr_to_symref(&enum_type->symt); e->type = symt_ptr_to_symref(enum_type->base_type); e->u.value = *variant;
@@ -672,7 +674,7 @@ BOOL symt_get_info(struct module* module, const struct symt* type, case TI_FINDCHILDREN: { const struct vector* v; - struct symt** pt; + symref_t* symref; unsigned i; TI_FINDCHILDREN_PARAMS* tifp = pInfo;
@@ -699,14 +701,14 @@ BOOL symt_get_info(struct module* module, const struct symt* type, /* for those, CHILDRENCOUNT returns 0 */ return tifp->Count == 0; default: - FIXME("Unsupported sym-tag %s for find-children\n", + FIXME("Unsupported sym-tag %s for find-children\n", symt_get_tag_str(type->tag)); return FALSE; } for (i = 0; i < tifp->Count; i++) { - if (!(pt = vector_at(v, tifp->Start + i))) return FALSE; - tifp->ChildId[i] = symt_ptr_to_index(module, *pt); + if (!(symref = (symref_t *)vector_at(v, tifp->Start + i))) return FALSE; + tifp->ChildId[i] = symt_symref_to_index(module, *symref); } } break; @@ -885,25 +887,25 @@ BOOL symt_get_info(struct module* module, const struct symt* type, switch (type->tag) { case SymTagCompiland: - X(DWORD) = symt_ptr_to_index(module, &((const struct symt_compiland*)type)->container->symt); + X(DWORD) = symt_symref_to_index(module, ((const struct symt_compiland*)type)->container); break; case SymTagBlock: - X(DWORD) = symt_ptr_to_index(module, ((const struct symt_block*)type)->container); + X(DWORD) = symt_symref_to_index(module, ((const struct symt_block*)type)->container); break; case SymTagData: - X(DWORD) = symt_ptr_to_index(module, ((const struct symt_data*)type)->container); + X(DWORD) = symt_symref_to_index(module, ((const struct symt_data*)type)->container); break; case SymTagFunction: case SymTagInlineSite: - X(DWORD) = symt_ptr_to_index(module, ((const struct symt_function*)type)->container); + X(DWORD) = symt_symref_to_index(module, ((const struct symt_function*)type)->container); break; case SymTagThunk: - X(DWORD) = symt_ptr_to_index(module, ((const struct symt_thunk*)type)->container); + X(DWORD) = symt_symref_to_index(module, ((const struct symt_thunk*)type)->container); break; case SymTagFuncDebugStart: case SymTagFuncDebugEnd: case SymTagLabel: - X(DWORD) = symt_ptr_to_index(module, ((const struct symt_hierarchy_point*)type)->parent); + X(DWORD) = symt_symref_to_index(module, ((const struct symt_hierarchy_point*)type)->container); break; case SymTagUDT: case SymTagEnum: @@ -1086,7 +1088,8 @@ BOOL symt_get_info(struct module* module, const struct symt* type, MODULE_FORMAT_VTABLE_INDEX(loc_compute)))) { iter.modfmt->vtable->loc_compute(iter.modfmt, - (const struct symt_function*)((const struct symt_data*)type)->container, &loc); + (const struct symt_function*)SYMT_SYMREF_TO_PTR(((const struct symt_data*)type)->container), + &loc); break; } if (loc.kind != loc_absolute) return FALSE;