From 60fbda43cb92f4574f96383eeefc734e1dbf0fc2 Mon Sep 17 00:00:00 2001 From: Eric Pouech Date: Tue, 18 Jan 2011 21:49:05 +0100 Subject: [PATCH] dbghelp: Use AT_range attribute (for function, block... addresses) when AT_low_pc and AT_high_pc are not present. --- dlls/dbghelp/dwarf.c | 108 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 84 insertions(+), 24 deletions(-) diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c index 2130c71060b..d60a5fd12cf 100644 --- a/dlls/dbghelp/dwarf.c +++ b/dlls/dbghelp/dwarf.c @@ -163,7 +163,7 @@ typedef struct dwarf2_section_s DWORD_PTR rva; } dwarf2_section_t; -enum dwarf2_sections {section_debug, section_string, section_abbrev, section_line, section_max}; +enum dwarf2_sections {section_debug, section_string, section_abbrev, section_line, section_ranges, section_max}; typedef struct dwarf2_traverse_context_s { @@ -945,6 +945,61 @@ static struct symt* dwarf2_lookup_type(dwarf2_parse_context_t* ctx, } /****************************************************************** + * dwarf2_read_range + * + * read a range for a given debug_info (either using AT_range attribute, in which + * case we don't return all the details, or using AT_low_pc & AT_high_pc attributes) + * in all cases, range is relative to beginning of compilation unit + */ +static BOOL dwarf2_read_range(dwarf2_parse_context_t* ctx, const dwarf2_debug_info_t* di, + unsigned long* plow, unsigned long* phigh) +{ + struct attribute range; + + if (dwarf2_find_attribute(ctx, di, DW_AT_ranges, &range)) + { + dwarf2_traverse_context_t traverse; + unsigned long low, high; + + traverse.data = ctx->sections[section_ranges].address + range.u.uvalue; + traverse.end_data = ctx->sections[section_ranges].address + + ctx->sections[section_ranges].size; + traverse.word_size = ctx->module->format_info[DFI_DWARF]->u.dwarf2_info->word_size; + + *plow = ULONG_MAX; + *phigh = 0; + while (traverse.data + 2 * traverse.word_size < traverse.end_data) + { + low = dwarf2_parse_addr(&traverse); + high = dwarf2_parse_addr(&traverse); + if (low == 0 && high == 0) break; + if (low == ULONG_MAX) FIXME("unsupported yet (base address selection)\n"); + if (low < *plow) *plow = low; + if (high > *phigh) *phigh = high; + } + if (*plow == ULONG_MAX || *phigh == 0) {FIXME("no entry found\n"); return FALSE;} + if (*plow == *phigh) {FIXME("entry found, but low=high\n"); return FALSE;} + + return TRUE; + } + else + { + struct attribute low_pc; + struct attribute high_pc; + + if (!dwarf2_find_attribute(ctx, di, DW_AT_low_pc, &low_pc) || + !dwarf2_find_attribute(ctx, di, DW_AT_high_pc, &high_pc)) + { + FIXME("missing low or high value\n"); + return FALSE; + } + *plow = low_pc.u.uvalue; + *phigh = high_pc.u.uvalue; + return TRUE; + } +} + +/****************************************************************** * dwarf2_read_one_debug_info * * Loads into memory one debug info entry, and recursively its children (if any) @@ -1563,17 +1618,19 @@ static void dwarf2_parse_inlined_subroutine(dwarf2_subprogram_t* subpgm, const dwarf2_debug_info_t* di) { struct symt_block* block; - struct attribute low_pc; - struct attribute high_pc; + unsigned long low_pc, high_pc; TRACE("%s, for %s\n", dwarf2_debug_ctx(subpgm->ctx), dwarf2_debug_di(di)); - if (!dwarf2_find_attribute(subpgm->ctx, di, DW_AT_low_pc, &low_pc)) low_pc.u.uvalue = 0; - if (!dwarf2_find_attribute(subpgm->ctx, di, DW_AT_high_pc, &high_pc)) high_pc.u.uvalue = 0; + if (!dwarf2_read_range(subpgm->ctx, di, &low_pc, &high_pc)) + { + FIXME("cannot read range\n"); + return; + } block = symt_open_func_block(subpgm->ctx->module, subpgm->func, parent_block, - subpgm->ctx->load_offset + low_pc.u.uvalue - subpgm->func->address, - high_pc.u.uvalue - low_pc.u.uvalue); + subpgm->ctx->load_offset + low_pc - subpgm->func->address, + high_pc - low_pc); if (di->abbrev->have_child) /** any interest to not have child ? */ { @@ -1614,19 +1671,19 @@ static void dwarf2_parse_subprogram_block(dwarf2_subprogram_t* subpgm, const dwarf2_debug_info_t* di) { struct symt_block* block; - struct attribute low_pc; - struct attribute high_pc; + unsigned long low_pc, high_pc; TRACE("%s, for %s\n", dwarf2_debug_ctx(subpgm->ctx), dwarf2_debug_di(di)); - if (!dwarf2_find_attribute(subpgm->ctx, di, DW_AT_low_pc, &low_pc)) - low_pc.u.uvalue = 0; - if (!dwarf2_find_attribute(subpgm->ctx, di, DW_AT_high_pc, &high_pc)) - high_pc.u.uvalue = 0; + if (!dwarf2_read_range(subpgm->ctx, di, &low_pc, &high_pc)) + { + FIXME("no range\n"); + return; + } block = symt_open_func_block(subpgm->ctx->module, subpgm->func, parent_block, - subpgm->ctx->load_offset + low_pc.u.uvalue - subpgm->func->address, - high_pc.u.uvalue - low_pc.u.uvalue); + subpgm->ctx->load_offset + low_pc - subpgm->func->address, + high_pc - low_pc); if (di->abbrev->have_child) /** any interest to not have child ? */ { @@ -1683,8 +1740,7 @@ static struct symt* dwarf2_parse_subprogram(dwarf2_parse_context_t* ctx, struct symt_compiland* compiland) { struct attribute name; - struct attribute low_pc; - struct attribute high_pc; + unsigned long low_pc, high_pc; struct attribute is_decl; struct attribute inline_flags; struct symt* ret_type; @@ -1710,14 +1766,17 @@ static struct symt* dwarf2_parse_subprogram(dwarf2_parse_context_t* ctx, return NULL; } - if (!dwarf2_find_attribute(ctx, di, DW_AT_low_pc, &low_pc)) low_pc.u.uvalue = 0; - if (!dwarf2_find_attribute(ctx, di, DW_AT_high_pc, &high_pc)) high_pc.u.uvalue = 0; + if (!dwarf2_read_range(ctx, di, &low_pc, &high_pc)) + { + FIXME("cannot get range\n"); + return NULL; + } + /* As functions (defined as inline assembly) get debug info with dwarf * (not the case for stabs), we just drop Wine's thunks here... * Actual thunks will be created in elf_module from the symbol table */ - if (elf_is_in_thunk_area(ctx->load_offset + low_pc.u.uvalue, - ctx->thunks) >= 0) + if (elf_is_in_thunk_area(ctx->load_offset + low_pc, ctx->thunks) >= 0) return NULL; if (!dwarf2_find_attribute(ctx, di, DW_AT_declaration, &is_decl)) is_decl.u.uvalue = 0; @@ -1733,8 +1792,7 @@ static struct symt* dwarf2_parse_subprogram(dwarf2_parse_context_t* ctx, if (!is_decl.u.uvalue) { subpgm.func = symt_new_function(ctx->module, compiland, name.u.string, - ctx->load_offset + low_pc.u.uvalue, - high_pc.u.uvalue - low_pc.u.uvalue, + ctx->load_offset + low_pc, high_pc - low_pc, &sig_type->symt); di->symt = &subpgm.func->symt; } @@ -3119,7 +3177,7 @@ BOOL dwarf2_parse(struct module* module, unsigned long load_offset, dwarf2_section_t section[section_max]; dwarf2_traverse_context_t mod_ctx; struct image_section_map debug_sect, debug_str_sect, debug_abbrev_sect, - debug_line_sect; + debug_line_sect, debug_ranges_sect; BOOL ret = TRUE; struct module_format* dwarf2_modfmt; @@ -3130,6 +3188,7 @@ 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); + dwarf2_init_section(§ion[section_ranges], fmap, ".debug_ranges", &debug_ranges_sect); if (section[section_debug].address == IMAGE_NO_MAP || section[section_abbrev].address == IMAGE_NO_MAP || @@ -3192,6 +3251,7 @@ leave: image_unmap_section(&debug_abbrev_sect); image_unmap_section(&debug_str_sect); image_unmap_section(&debug_line_sect); + image_unmap_section(&debug_ranges_sect); return ret; } -- 2.11.4.GIT