dbghelp: Use AT_range attribute (for function, block... addresses) when AT_low_pc and AT_high_pc are not present.

This commit is contained in:
Eric Pouech 2011-01-18 21:49:05 +01:00 committed by Alexandre Julliard
parent 52dc1bcd37
commit 60fbda43cb
1 changed files with 84 additions and 24 deletions

View File

@ -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
{
@ -944,6 +944,61 @@ static struct symt* dwarf2_lookup_type(dwarf2_parse_context_t* ctx,
return NULL;
}
/******************************************************************
* 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
*
@ -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(&section[section_abbrev], fmap, ".debug_abbrev", &debug_abbrev_sect);
dwarf2_init_section(&section[section_string], fmap, ".debug_str", &debug_str_sect);
dwarf2_init_section(&section[section_line], fmap, ".debug_line", &debug_line_sect);
dwarf2_init_section(&section[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;
}