dbghelp/dwarf: Store each subrange for an inlined function.
Signed-off-by: Eric Pouech <eric.pouech@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
690c2e51bf
commit
fb34c82ef8
|
@ -268,6 +268,18 @@ struct addr_range
|
|||
DWORD64 high; /* absolute address of first byte after the range */
|
||||
};
|
||||
|
||||
/* tests whether ar2 is inside ar1 */
|
||||
static inline BOOL addr_range_inside(const struct addr_range* ar1, const struct addr_range* ar2)
|
||||
{
|
||||
return ar1->low <= ar2->low && ar2->high <= ar1->high;
|
||||
}
|
||||
|
||||
/* tests whether ar1 and ar2 are disjoint */
|
||||
static inline BOOL addr_range_disjoint(const struct addr_range* ar1, const struct addr_range* ar2)
|
||||
{
|
||||
return ar1->high <= ar2->low || ar2->high <= ar1->low;
|
||||
}
|
||||
|
||||
/* a symt_inlinesite* can be casted to a symt_function* to access all function bits */
|
||||
struct symt_inlinesite
|
||||
{
|
||||
|
@ -841,6 +853,9 @@ extern struct symt_hierarchy_point*
|
|||
enum SymTagEnum point,
|
||||
const struct location* loc,
|
||||
const char* name) DECLSPEC_HIDDEN;
|
||||
extern BOOL symt_add_inlinesite_range(struct module* module,
|
||||
struct symt_inlinesite* inlined,
|
||||
ULONG_PTR low, ULONG_PTR high) DECLSPEC_HIDDEN;
|
||||
extern struct symt_thunk*
|
||||
symt_new_thunk(struct module* module,
|
||||
struct symt_compiland* parent,
|
||||
|
|
|
@ -1272,6 +1272,66 @@ static BOOL dwarf2_read_range(dwarf2_parse_context_t* ctx, const dwarf2_debug_in
|
|||
}
|
||||
}
|
||||
|
||||
static BOOL dwarf2_feed_inlined_ranges(dwarf2_parse_context_t* ctx, const dwarf2_debug_info_t* di,
|
||||
struct symt_inlinesite* inlined)
|
||||
{
|
||||
struct attribute range;
|
||||
|
||||
if (dwarf2_find_attribute(di, DW_AT_ranges, &range))
|
||||
{
|
||||
dwarf2_traverse_context_t traverse;
|
||||
|
||||
traverse.data = ctx->module_ctx->sections[section_ranges].address + range.u.uvalue;
|
||||
traverse.end_data = ctx->module_ctx->sections[section_ranges].address +
|
||||
ctx->module_ctx->sections[section_ranges].size;
|
||||
|
||||
while (traverse.data + 2 * ctx->head.word_size < traverse.end_data)
|
||||
{
|
||||
ULONG_PTR low = dwarf2_parse_addr_head(&traverse, &ctx->head);
|
||||
ULONG_PTR high = dwarf2_parse_addr_head(&traverse, &ctx->head);
|
||||
if (low == 0 && high == 0) break;
|
||||
if (low == (ctx->head.word_size == 8 ? (~(DWORD64)0u) : (DWORD64)(~0u)))
|
||||
FIXME("unsupported yet (base address selection)\n");
|
||||
/* range values are relative to start of compilation unit */
|
||||
symt_add_inlinesite_range(ctx->module_ctx->module, inlined,
|
||||
ctx->compiland->address + low, ctx->compiland->address + high);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct attribute low_pc;
|
||||
struct attribute high_pc;
|
||||
|
||||
if (!dwarf2_find_attribute(di, DW_AT_low_pc, &low_pc) ||
|
||||
!dwarf2_find_attribute(di, DW_AT_high_pc, &high_pc))
|
||||
return FALSE;
|
||||
if (ctx->head.version >= 4)
|
||||
switch (high_pc.form)
|
||||
{
|
||||
case DW_FORM_addr:
|
||||
break;
|
||||
case DW_FORM_data1:
|
||||
case DW_FORM_data2:
|
||||
case DW_FORM_data4:
|
||||
case DW_FORM_data8:
|
||||
case DW_FORM_sdata:
|
||||
case DW_FORM_udata:
|
||||
/* From dwarf4 on, when FORM's class is constant, high_pc is an offset from low_pc */
|
||||
high_pc.u.uvalue += low_pc.u.uvalue;
|
||||
break;
|
||||
default:
|
||||
FIXME("Unsupported class for high_pc\n");
|
||||
break;
|
||||
}
|
||||
symt_add_inlinesite_range(ctx->module_ctx->module, inlined,
|
||||
ctx->module_ctx->load_offset + low_pc.u.uvalue,
|
||||
ctx->module_ctx->load_offset + high_pc.u.uvalue);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* dwarf2_read_one_debug_info
|
||||
*
|
||||
|
@ -2038,6 +2098,9 @@ static void dwarf2_parse_inlined_subroutine(dwarf2_subprogram_t* subpgm,
|
|||
subpgm->current_func = (struct symt_function*)inlined;
|
||||
subpgm->current_block = NULL;
|
||||
|
||||
if (!dwarf2_feed_inlined_ranges(subpgm->ctx, di, inlined))
|
||||
WARN("cannot read ranges\n");
|
||||
|
||||
children = dwarf2_get_di_children(di);
|
||||
if (children) for (i = 0; i < vector_length(children); i++)
|
||||
{
|
||||
|
|
|
@ -576,6 +576,42 @@ struct symt_hierarchy_point* symt_add_function_point(struct module* module,
|
|||
return sym;
|
||||
}
|
||||
|
||||
/* low and high are absolute addresses */
|
||||
BOOL symt_add_inlinesite_range(struct module* module,
|
||||
struct symt_inlinesite* inlined,
|
||||
ULONG_PTR low, ULONG_PTR high)
|
||||
{
|
||||
struct addr_range* p;
|
||||
|
||||
p = vector_add(&inlined->vranges, &module->pool);
|
||||
p->low = low;
|
||||
p->high = high;
|
||||
if (TRUE)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* see dbghelp_private.h for the assumptions */
|
||||
for (i = 0; i < inlined->vranges.num_elts - 1; i++)
|
||||
{
|
||||
if (!addr_range_disjoint((struct addr_range*)vector_at(&inlined->vranges, i), p))
|
||||
{
|
||||
FIXME("Added addr_range isn't disjoint from siblings\n");
|
||||
}
|
||||
}
|
||||
for ( ; inlined->func.symt.tag != SymTagFunction; inlined = (struct symt_inlinesite*)symt_get_upper_inlined(inlined))
|
||||
{
|
||||
for (i = 0; i < inlined->vranges.num_elts; i++)
|
||||
{
|
||||
struct addr_range* ar = (struct addr_range*)vector_at(&inlined->vranges, i);
|
||||
if (!addr_range_disjoint(ar, p) && !addr_range_inside(ar, p))
|
||||
FIXME("Added addr_range not compatible with parent\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
struct symt_thunk* symt_new_thunk(struct module* module,
|
||||
struct symt_compiland* compiland,
|
||||
const char* name, THUNK_ORDINAL ord,
|
||||
|
|
Loading…
Reference in New Issue