dbghelp: Store address range as FAM in symt_inlinesite.

Signed-off-by: Eric Pouech <eric.pouech@gmail.com>
This commit is contained in:
Eric Pouech 2022-11-01 10:39:59 +01:00 committed by Alexandre Julliard
parent a6f1f7be7e
commit c576b0c73f
4 changed files with 81 additions and 82 deletions

View file

@ -294,7 +294,8 @@ struct symt_function
struct symt_inlinesite
{
struct symt_function func;
struct vector vranges; /* of addr_range: where the inline site is actually defined */
unsigned num_ranges;
struct addr_range ranges[];
};
struct symt_hierarchy_point
@ -850,7 +851,8 @@ extern struct symt_inlinesite*
struct symt_function* func,
struct symt* parent,
const char* name,
struct symt* type) DECLSPEC_HIDDEN;
struct symt* type,
unsigned num_ranges) DECLSPEC_HIDDEN;
extern void symt_add_func_line(struct module* module,
struct symt_function* func,
unsigned source_idx, int line_num,
@ -880,11 +882,8 @@ 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,
symt_new_thunk(struct module* module,
struct symt_compiland* parent,
const char* name, THUNK_ORDINAL ord,
ULONG_PTR addr, ULONG_PTR size) DECLSPEC_HIDDEN;

View file

@ -2117,12 +2117,11 @@ static void dwarf2_parse_inlined_subroutine(dwarf2_subprogram_t* subpgm,
struct vector* children;
dwarf2_debug_info_t*child;
unsigned int i;
struct addr_range* adranges;
unsigned num_adranges;
unsigned num_ranges;
TRACE("%s\n", dwarf2_debug_di(di));
if ((adranges = dwarf2_get_ranges(di, &num_adranges)) == NULL)
if (!(num_ranges = dwarf2_get_num_ranges(di)))
{
WARN("cannot read ranges\n");
return;
@ -2141,16 +2140,17 @@ 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),
&sig_type->symt);
&sig_type->symt, num_ranges);
subpgm->current_func = (struct symt_function*)inlined;
subpgm->current_block = NULL;
for (i = 0; i < num_adranges; ++i)
symt_add_inlinesite_range(subpgm->ctx->module_ctx->module, inlined,
adranges[i].low, adranges[i].high);
if (!dwarf2_fill_ranges(di, inlined->ranges, num_ranges))
{
FIXME("Unexpected situation\n");
inlined->num_ranges = 0;
}
/* temporary: update address field */
inlined->func.address = adranges[0].low;
free(adranges);
inlined->func.address = inlined->ranges[0].low;
children = dwarf2_get_di_children(di);
if (children) for (i = 0; i < vector_length(children); i++)
@ -2616,10 +2616,9 @@ static void dwarf2_set_line_number(struct module* module, ULONG_PTR address,
for (inlined = func->next_inlinesite; inlined; inlined = inlined->func.next_inlinesite)
{
int i;
for (i = 0; i < inlined->vranges.num_elts; ++i)
for (i = 0; i < inlined->num_ranges; ++i)
{
struct addr_range* ar = (struct addr_range*)vector_at(&inlined->vranges, i);
if (ar->low <= address && address < ar->high)
if (inlined->ranges[i].low <= address && address < inlined->ranges[i].high)
{
symt_add_func_line(module, &inlined->func, *psrc, line, address);
return; /* only add to lowest matching inline site */

View file

@ -2077,18 +2077,48 @@ static BOOL cv_dbgsubsect_find_inlinee(const struct msc_debug_info* msc_dbg,
return FALSE;
}
static inline void inline_site_update_last_range(struct symt_inlinesite* inlined, ULONG_PTR hi)
static inline void inline_site_update_last_range(struct symt_inlinesite* inlined, unsigned index, ULONG_PTR hi)
{
unsigned num = inlined->vranges.num_elts;
if (num)
if (index && index <= inlined->num_ranges)
{
struct addr_range* range = vector_at(&inlined->vranges, num - 1);
struct addr_range* range = &inlined->ranges[index - 1];
/* only change range if it has no span (code start without code end) */
if (range->low == range->high)
range->high = hi;
}
}
static unsigned inline_site_get_num_ranges(const unsigned char* annot,
const unsigned char* last_annot)
{
struct cv_binannot cvba;
unsigned num_ranges = 0;
cvba.annot = annot;
cvba.last_annot = last_annot;
while (codeview_advance_binannot(&cvba))
{
switch (cvba.opcode)
{
case BA_OP_CodeOffset:
case BA_OP_ChangeCodeLength:
case BA_OP_ChangeFile:
case BA_OP_ChangeLineOffset:
break;
case BA_OP_ChangeCodeOffset:
case BA_OP_ChangeCodeOffsetAndLineOffset:
case BA_OP_ChangeCodeLengthAndCodeOffset:
num_ranges++;
break;
default:
WARN("Unsupported op %d\n", cvba.opcode);
break;
}
}
return num_ranges;
}
static struct symt_inlinesite* codeview_create_inline_site(const struct msc_debug_info* msc_dbg,
const struct cv_module_snarf* cvmod,
struct symt_function* top_func,
@ -2102,7 +2132,8 @@ static struct symt_inlinesite* codeview_create_inline_site(const struct msc_debu
struct symt_inlinesite* inlined;
struct cv_binannot cvba;
BOOL srcok;
unsigned offset, line, srcfile;
unsigned num_ranges;
unsigned offset, index, line, srcfile;
const struct CV_Checksum_t* chksms;
if (!cvmod->ipi_ctp || !(cvt = codeview_jump_to_type(cvmod->ipi_ctp, inlinee)))
@ -2110,19 +2141,23 @@ static struct symt_inlinesite* codeview_create_inline_site(const struct msc_debu
FIXME("Couldn't find type %x in IPI stream\n", inlinee);
return NULL;
}
num_ranges = inline_site_get_num_ranges(annot, last_annot);
if (!num_ranges) return NULL;
switch (cvt->generic.id)
{
case LF_FUNC_ID:
inlined = symt_new_inlinesite(msc_dbg->module, top_func, container,
cvt->func_id_v3.name,
codeview_get_type(cvt->func_id_v3.type, FALSE));
codeview_get_type(cvt->func_id_v3.type, FALSE),
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_type(cvt->mfunc_id_v3.type, FALSE));
codeview_get_type(cvt->mfunc_id_v3.type, FALSE),
num_ranges);
break;
default:
FIXME("unsupported inlinee kind %x\n", cvt->generic.id);
@ -2144,6 +2179,7 @@ static struct symt_inlinesite* codeview_create_inline_site(const struct msc_debu
/* rescan all annotations and store ranges & line information */
offset = 0;
index = 0;
cvba.annot = annot;
cvba.last_annot = last_annot;
@ -2156,18 +2192,15 @@ static struct symt_inlinesite* codeview_create_inline_site(const struct msc_debu
break;
case BA_OP_ChangeCodeOffset:
offset += cvba.arg1;
inline_site_update_last_range(inlined, top_func->address + offset);
inline_site_update_last_range(inlined, index, top_func->address + offset);
if (srcok)
symt_add_func_line(msc_dbg->module, &inlined->func, srcfile, line, top_func->address + offset);
symt_add_inlinesite_range(msc_dbg->module, inlined, top_func->address + offset, top_func->address + offset);
inlined->ranges[index ].low = top_func->address + offset;
inlined->ranges[index++].high = top_func->address + offset;
break;
case BA_OP_ChangeCodeLength:
/* this op doesn't seem widely used... */
if (inlined->vranges.num_elts)
{
struct addr_range* range = vector_at(&inlined->vranges, inlined->vranges.num_elts - 1);
inline_site_update_last_range(inlined, range->low + cvba.arg1);
}
inline_site_update_last_range(inlined, index, inlined->ranges[index - 1].low + cvba.arg1);
break;
case BA_OP_ChangeFile:
chksms = CV_RECORD_GAP(hdr_files, cvba.arg1);
@ -2180,31 +2213,35 @@ static struct symt_inlinesite* codeview_create_inline_site(const struct msc_debu
case BA_OP_ChangeCodeOffsetAndLineOffset:
line += binannot_getsigned(cvba.arg2);
offset += cvba.arg1;
inline_site_update_last_range(inlined, top_func->address + offset);
inline_site_update_last_range(inlined, index, top_func->address + offset);
if (srcok)
symt_add_func_line(msc_dbg->module, &inlined->func, srcfile, line, top_func->address + offset);
symt_add_inlinesite_range(msc_dbg->module, inlined, top_func->address + offset, top_func->address + offset);
inlined->ranges[index ].low = top_func->address + offset;
inlined->ranges[index++].high = top_func->address + offset;
break;
case BA_OP_ChangeCodeLengthAndCodeOffset:
offset += cvba.arg2;
inline_site_update_last_range(inlined, top_func->address + offset);
inline_site_update_last_range(inlined, index, top_func->address + offset);
if (srcok)
symt_add_func_line(msc_dbg->module, &inlined->func, srcfile, line, top_func->address + offset);
symt_add_inlinesite_range(msc_dbg->module, inlined, top_func->address + offset, top_func->address + offset + cvba.arg1);
inlined->ranges[index ].low = top_func->address + offset;
inlined->ranges[index++].high = top_func->address + offset + cvba.arg1;
break;
default:
WARN("Unsupported op %d\n", cvba.opcode);
break;
}
}
if (inlined->vranges.num_elts)
if (index != num_ranges) /* sanity check */
FIXME("Internal logic error\n");
if (inlined->num_ranges)
{
struct addr_range* range = vector_at(&inlined->vranges, inlined->vranges.num_elts - 1);
struct addr_range* range = &inlined->ranges[inlined->num_ranges - 1];
if (range->low == range->high) WARN("pending empty range at end of %s inside %s\n",
inlined->func.hash_elt.name,
top_func->hash_elt.name);
/* temporary: update address field */
inlined->func.address = ((struct addr_range*)vector_at(&inlined->vranges, 0))->low;
inlined->func.address = inlined->ranges[0].low;
}
return inlined;
}

View file

@ -362,20 +362,21 @@ struct symt_inlinesite* symt_new_inlinesite(struct module* module,
struct symt_function* func,
struct symt* container,
const char* name,
struct symt* sig_type)
struct symt* sig_type,
unsigned num_ranges)
{
struct symt_inlinesite* sym;
TRACE_(dbghelp_symt)("Adding inline site %s\n", name);
if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
if ((sym = pool_alloc(&module->pool, offsetof(struct symt_inlinesite, ranges[num_ranges]))))
{
struct symt** p;
assert(container);
init_function_or_inlinesite(&sym->func, module, SymTagInlineSite, container, name, 0, 0, sig_type);
vector_init(&sym->vranges, sizeof(struct addr_range), 2); /* FIXME: number of elts => to be set on input */
/* chain inline sites */
sym->func.next_inlinesite = func->next_inlinesite;
func->next_inlinesite = sym;
sym->num_ranges = num_ranges;
if (container->tag == SymTagFunction || container->tag == SymTagInlineSite)
p = vector_add(&((struct symt_function*)container)->vchildren, &module->pool);
else
@ -534,7 +535,7 @@ struct symt_block* symt_open_func_block(struct module* module,
assert(num_ranges > 0);
assert(!parent_block || parent_block->symt.tag == SymTagBlock);
block = pool_alloc(&module->pool, sizeof(*block) + num_ranges * sizeof(block->ranges[0]));
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;
@ -579,42 +580,6 @@ 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))
WARN("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,
@ -1244,11 +1209,10 @@ struct symt_inlinesite* symt_find_lowest_inlined(struct symt_function* func, DWO
assert(func->symt.tag == SymTagFunction);
for (current = func->next_inlinesite; current; current = current->func.next_inlinesite)
{
for (i = 0; i < current->vranges.num_elts; ++i)
for (i = 0; i < current->num_ranges; ++i)
{
struct addr_range* ar = (struct addr_range*)vector_at(&current->vranges, i);
/* first matching range gives the lowest inline site; see dbghelp_private.h for details */
if (ar->low <= addr && addr < ar->high)
if (current->ranges[i].low <= addr && addr < current->ranges[i].high)
return current;
}
}