From 73f79e7fadfd7782da717cb1dfcd2496d1d2287f Mon Sep 17 00:00:00 2001 From: Eric Pouech Date: Thu, 18 Mar 2010 21:31:43 +0100 Subject: [PATCH] dbghelp: Create new infrastructure to hold specific information for multiple file/debug formats in a single module, and use it to store dwarf2 stuff. --- dlls/dbghelp/dbghelp_private.h | 30 ++++++++++++++--- dlls/dbghelp/dwarf.c | 59 +++++++++++++++++++++------------- dlls/dbghelp/module.c | 11 +++++-- dlls/dbghelp/symbol.c | 14 +++++++- 4 files changed, 84 insertions(+), 30 deletions(-) diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 57598cc0a17..ec08993afc6 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -313,6 +313,30 @@ enum module_type }; struct process; +struct module; + +/* a module can be made of several debug information formats, so we have to + * support them all + */ +enum format_info +{ + DFI_DWARF, + DFI_LAST +}; + +struct module_format +{ + struct module* module; + void (*remove)(struct process* pcs, struct module_format* modfmt); + void (*loc_compute)(struct process* pcs, + const struct module_format* modfmt, + const struct symt_function* func, + struct location* loc); + union + { + struct dwarf2_module_info_s* dwarf2_info; + } u; +}; struct module { @@ -326,8 +350,8 @@ struct module /* specific information for debug types */ struct elf_module_info* elf_info; struct pe_module_info* pe_info; - struct dwarf2_module_info_s*dwarf2_info; void (*module_remove)(struct process* pcs, struct module* module); + struct module_format* format_info[DFI_LAST]; struct macho_module_info* macho_info; @@ -342,10 +366,6 @@ struct module unsigned sorttab_size; struct symt_ht** addr_sorttab; struct hash_table ht_symbols; - void (*loc_compute)(struct process* pcs, - const struct module* module, - const struct symt_function* func, - struct location* loc); /* types */ struct hash_table ht_types; diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c index 88a942b1376..199b3bb4b8a 100644 --- a/dlls/dbghelp/dwarf.c +++ b/dlls/dbghelp/dwarf.c @@ -2212,7 +2212,7 @@ static BOOL dwarf2_parse_compilation_unit(const dwarf2_section_t* sections, return ret; } -static BOOL dwarf2_lookup_loclist(const struct module* module, const BYTE* start, +static BOOL dwarf2_lookup_loclist(const struct module_format* modfmt, const BYTE* start, unsigned long ip, dwarf2_traverse_context_t* lctx) { @@ -2220,7 +2220,7 @@ static BOOL dwarf2_lookup_loclist(const struct module* module, const BYTE* start const BYTE* ptr = start; DWORD len; - while (ptr < module->dwarf2_info->debug_loc.address + module->dwarf2_info->debug_loc.size) + while (ptr < modfmt->u.dwarf2_info->debug_loc.address + modfmt->u.dwarf2_info->debug_loc.size) { beg = dwarf2_get_u4(ptr); ptr += 4; end = dwarf2_get_u4(ptr); ptr += 4; @@ -2241,7 +2241,7 @@ static BOOL dwarf2_lookup_loclist(const struct module* module, const BYTE* start } static enum location_error loc_compute_frame(struct process* pcs, - const struct module* module, + const struct module_format* modfmt, const struct symt_function* func, DWORD ip, struct location* frame) { @@ -2267,8 +2267,8 @@ static enum location_error loc_compute_frame(struct process* pcs, break; case loc_dwarf2_location_list: WARN("Searching loclist for %s\n", func->hash_elt.name); - if (!dwarf2_lookup_loclist(module, - module->dwarf2_info->debug_loc.address + pframe->offset, + if (!dwarf2_lookup_loclist(modfmt, + modfmt->u.dwarf2_info->debug_loc.address + pframe->offset, ip, &lctx)) return loc_err_out_of_scope; if ((err = compute_location(&lctx, frame, pcs->handle, NULL)) < 0) return err; @@ -2290,7 +2290,7 @@ static enum location_error loc_compute_frame(struct process* pcs, } static void dwarf2_location_compute(struct process* pcs, - const struct module* module, + const struct module_format* modfmt, const struct symt_function* func, struct location* loc) { @@ -2309,14 +2309,14 @@ static void dwarf2_location_compute(struct process* pcs, /* instruction pointer relative to compiland's start */ ip = pcs->ctx_frame.InstructionOffset - ((struct symt_compiland*)func->container)->address; - if ((err = loc_compute_frame(pcs, module, func, ip, &frame)) == 0) + if ((err = loc_compute_frame(pcs, modfmt, func, ip, &frame)) == 0) { switch (loc->kind) { case loc_dwarf2_location_list: /* Then, if the variable has a location list, find it !! */ - if (dwarf2_lookup_loclist(module, - module->dwarf2_info->debug_loc.address + loc->offset, + if (dwarf2_lookup_loclist(modfmt, + modfmt->u.dwarf2_info->debug_loc.address + loc->offset, ip, &lctx)) goto do_compute; err = loc_err_out_of_scope; @@ -2351,6 +2351,12 @@ static void dwarf2_location_compute(struct process* pcs, } } +static void dwarf2_module_remove(struct process* pcs, struct module_format* modfmt) +{ + HeapFree(GetProcessHeap(), 0, modfmt->u.dwarf2_info); + HeapFree(GetProcessHeap(), 0, modfmt); +} + static inline BOOL dwarf2_init_section(dwarf2_section_t* section, struct image_file_map* fmap, const char* sectname, struct image_section_map* ism) { @@ -2380,6 +2386,7 @@ BOOL dwarf2_parse(struct module* module, unsigned long load_offset, struct image_section_map debug_sect, debug_str_sect, debug_abbrev_sect, debug_line_sect, debug_loclist_sect; BOOL ret = TRUE; + struct module_format* dwarf2_modfmt; if (!dwarf2_init_section(§ion[section_debug], fmap, ".debug_info", &debug_sect)) { @@ -2389,7 +2396,6 @@ BOOL dwarf2_parse(struct module* module, unsigned long load_offset, dwarf2_init_section(§ion[section_abbrev], fmap, ".debug_abbrev", &debug_abbrev_sect); dwarf2_init_section(§ion[section_string], fmap, ".debug_str", &debug_str_sect); dwarf2_init_section(§ion[section_line], fmap, ".debug_line", &debug_line_sect); - image_find_section(fmap, ".debug_loc", &debug_loclist_sect); if (section[section_debug].address == IMAGE_NO_MAP || section[section_abbrev].address == IMAGE_NO_MAP || @@ -2413,32 +2419,41 @@ BOOL dwarf2_parse(struct module* module, unsigned long load_offset, mod_ctx.start_data = mod_ctx.data = section[section_debug].address; mod_ctx.end_data = mod_ctx.data + section[section_debug].size; - module->loc_compute = dwarf2_location_compute; + dwarf2_modfmt = HeapAlloc(GetProcessHeap(), 0, sizeof(*dwarf2_modfmt)); + if (!dwarf2_modfmt) return FALSE; + dwarf2_modfmt->module = module; + dwarf2_modfmt->remove = dwarf2_module_remove; + dwarf2_modfmt->loc_compute = dwarf2_location_compute; + dwarf2_modfmt->u.dwarf2_info = NULL; + dwarf2_modfmt->module->format_info[DFI_DWARF] = dwarf2_modfmt; + + image_find_section(fmap, ".debug_loc", &debug_loclist_sect); if (image_get_map_size(&debug_loclist_sect)) { /* initialize the dwarf2 specific info block for this module. * As we'll need later the .debug_loc section content, we won't unmap this * section upon existing this function */ - module->dwarf2_info = HeapAlloc(GetProcessHeap(), 0, sizeof(*module->dwarf2_info)); - if (!module->dwarf2_info) return FALSE; - module->dwarf2_info->debug_loc.address = (const BYTE*)image_map_section(&debug_loclist_sect); - module->dwarf2_info->debug_loc.size = image_get_map_size(&debug_loclist_sect); + dwarf2_modfmt->u.dwarf2_info = HeapAlloc(GetProcessHeap(), 0, + sizeof(*dwarf2_modfmt->u.dwarf2_info)); + if (!dwarf2_modfmt->u.dwarf2_info) goto leave; + dwarf2_modfmt->u.dwarf2_info->debug_loc.address = (const BYTE*)image_map_section(&debug_loclist_sect); + dwarf2_modfmt->u.dwarf2_info->debug_loc.size = image_get_map_size(&debug_loclist_sect); } else image_unmap_section(&debug_loclist_sect); while (mod_ctx.data < mod_ctx.end_data) { - dwarf2_parse_compilation_unit(section, module, thunks, &mod_ctx, load_offset); + dwarf2_parse_compilation_unit(section, dwarf2_modfmt->module, thunks, &mod_ctx, load_offset); } - module->module.SymType = SymDia; - module->module.CVSig = 'D' | ('W' << 8) | ('A' << 16) | ('R' << 24); + dwarf2_modfmt->module->module.SymType = SymDia; + dwarf2_modfmt->module->module.CVSig = 'D' | ('W' << 8) | ('A' << 16) | ('R' << 24); /* FIXME: we could have a finer grain here */ - module->module.GlobalSymbols = TRUE; - module->module.TypeInfo = TRUE; - module->module.SourceIndexed = TRUE; - module->module.Publics = TRUE; + dwarf2_modfmt->module->module.GlobalSymbols = TRUE; + dwarf2_modfmt->module->module.TypeInfo = TRUE; + dwarf2_modfmt->module->module.SourceIndexed = TRUE; + dwarf2_modfmt->module->module.Publics = TRUE; leave: image_unmap_section(&debug_sect); diff --git a/dlls/dbghelp/module.c b/dlls/dbghelp/module.c index cbb5c40f361..1dc3889992f 100644 --- a/dlls/dbghelp/module.c +++ b/dlls/dbghelp/module.c @@ -126,6 +126,7 @@ struct module* module_new(struct process* pcs, const WCHAR* name, unsigned long stamp, unsigned long checksum) { struct module* module; + unsigned i; assert(type == DMT_ELF || type == DMT_PE || type == DMT_MACHO); if (!(module = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*module)))) @@ -168,7 +169,7 @@ struct module* module_new(struct process* pcs, const WCHAR* name, module->type = type; module->is_virtual = virtual ? TRUE : FALSE; - module->module_remove = NULL; + for (i = 0; i < DFI_LAST; i++) module->format_info[i] = NULL; module->sortlist_valid = FALSE; module->sorttab_size = 0; module->addr_sorttab = NULL; @@ -622,16 +623,22 @@ DWORD64 WINAPI SymLoadModule64(HANDLE hProcess, HANDLE hFile, PCSTR ImageName, */ BOOL module_remove(struct process* pcs, struct module* module) { + struct module_format*modfmt; struct module** p; + unsigned i; TRACE("%s (%p)\n", debugstr_w(module->module.ModuleName), module); if (module->module_remove) module->module_remove(pcs, module); + for (i = 0; i < DFI_LAST; i++) + { + if ((modfmt = module->format_info[i]) && modfmt->remove) + modfmt->remove(pcs, module->format_info[i]); + } hash_table_destroy(&module->ht_symbols); hash_table_destroy(&module->ht_types); HeapFree(GetProcessHeap(), 0, module->sources); HeapFree(GetProcessHeap(), 0, module->addr_sorttab); - HeapFree(GetProcessHeap(), 0, module->dwarf2_info); pool_destroy(&module->pool); /* native dbghelp doesn't invoke registered callback(,CBA_SYMBOLS_UNLOADED,) here * so do we diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index 07ba9a37cef..650f6a28086 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -693,8 +693,20 @@ static void symt_fill_sym_info(struct module_pair* pair, struct location loc = data->u.var; if (loc.kind >= loc_user) - pair->effective->loc_compute(pair->pcs, pair->effective, func, &loc); + { + unsigned i; + struct module_format* modfmt; + for (i = 0; i < DFI_LAST; i++) + { + modfmt = pair->effective->format_info[i]; + if (modfmt && modfmt->loc_compute) + { + modfmt->loc_compute(pair->pcs, modfmt, func, &loc); + break; + } + } + } switch (loc.kind) { case loc_error: