From: Eric Pouech eric.pouech@gmail.com
Signed-off-by: Eric Pouech eric.pouech@gmail.com --- dlls/dbghelp/dbghelp_private.h | 11 +++-- dlls/dbghelp/dwarf.c | 23 +++++----- dlls/dbghelp/msc.c | 79 +++++++++++++++++++++++++--------- dlls/dbghelp/symbol.c | 50 +++------------------ 4 files changed, 81 insertions(+), 82 deletions(-)
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index d1ca5d38868..b574dbc7462 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -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; diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c index cc31cc7912c..dd8606634ee 100644 --- a/dlls/dbghelp/dwarf.c +++ b/dlls/dbghelp/dwarf.c @@ -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 */ diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index 39beaf80c12..228b7019d4e 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -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; } diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index 082eec2a555..614bf40f0a3 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -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(¤t->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; } }