Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/dbghelp/dbghelp_private.h | 51 ++++++++++++++++++++++++++++++++++++++-- dlls/dbghelp/dwarf.c | 2 +- dlls/dbghelp/msc.c | 4 ++- dlls/dbghelp/symbol.c | 16 +++++-------- dlls/dbghelp/type.c | 16 +++++++++++++ 5 files changed, 75 insertions(+), 14 deletions(-)
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 7ab7d1b7fc3..7dfb7a7c6dd 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -216,16 +216,63 @@ struct symt_data } u; };
+/* We must take into account that most debug formats (dwarf and pdb) report for + * code (esp. inlined functions) inside functions the following way: + * - block + * + is represented by a contiguous area of memory, + * or at least have lo/hi addresses to encompass it's contents + * + but most importantly, block A's lo/hi range is always embedded within + * its parent (block or function) + * - inline site: + * + is most of the times represented by a set of ranges (instead of a + * contiguous block) + * + native dbghelp only exports the start address, not its size + * + the set of ranges isn't always embedded in enclosing block (if any) + * + the set of ranges is always embedded in top function + * - (top) function + * + is described as a contiguous block of memory + * + * On top of the items above (taken as assumptions), we also assume that: + * - a range in inline site A, is disjoint from all the other ranges in + * inline site A + * - a range in inline site A, is either disjoint or embedded into any of + * the ranges of inline sites parent of A + * + * Therefore, we also store all inline sites inside a function: + * - available as a linked list to simplify the walk among them + * - this linked list shall preserve the weak order of the lexical-parent + * relationship (eg for any inline site A, which has inline site B + * as lexical parent, then A is present before B in the linked list) + * - hence (from the assumptions above), when looking up which inline site + * contains a given address, the first range containing that address found + * while walking the list of inline sites is the right one. + */ + struct symt_function { - struct symt symt; + struct symt symt; /* SymTagFunction (or SymTagInlineSite when embedded in symt_inlinesite) */ struct hash_table_elt hash_elt; /* if global symbol */ ULONG_PTR address; struct symt* container; /* compiland */ struct symt* type; /* points to function_signature */ ULONG_PTR size; struct vector vlines; - struct vector vchildren; /* locals, params, blocks, start/end, labels */ + struct vector vchildren; /* locals, params, blocks, start/end, labels, inline sites */ + struct symt_inlinesite* next_inlinesite;/* linked list of inline sites in this function */ +}; + +/* FIXME: this could be optimized later on by using relative offsets and smaller integral sizes */ +struct addr_range +{ + DWORD64 low; /* absolute address of first byte of the range */ + DWORD64 high; /* absolute address of first byte after the range */ +}; + +/* a symt_inlinesite* can be casted to a symt_function* to access all function bits */ +struct symt_inlinesite +{ + struct symt_function func; + struct vector vranges; /* of addr_range: where the inline site is actually defined */ };
struct symt_hierarchy_point diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c index c503be4dcc1..86650e991a8 100644 --- a/dlls/dbghelp/dwarf.c +++ b/dlls/dbghelp/dwarf.c @@ -2438,7 +2438,7 @@ static void dwarf2_set_line_number(struct module* module, ULONG_PTR address, TRACE("%s %lx %s %u\n", debugstr_w(module->modulename), address, debugstr_a(source_get(module, *psrc)), line); symt = symt_find_nearest(module, address); - if (symt && symt_check_tag(&symt->symt, SymTagFunction)) + if (symt_check_tag(&symt->symt, SymTagFunction)) { func = (struct symt_function*)symt; symt_add_func_line(module, func, *psrc, line, address - func->address); diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index 2468051acc7..c557cb24636 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -1446,7 +1446,7 @@ static void codeview_snarf_linetab(const struct msc_debug_info* msc_dbg, const B { func = (struct symt_function*)symt_find_nearest(msc_dbg->module, addr); /* FIXME: at least labels support line numbers */ - if (!func || func->symt.tag != SymTagFunction) + if (!symt_check_tag(&func->symt, SymTagFunction) && !symt_check_tag(&func->symt, SymTagInlineSite)) { WARN("--not a func at %04x:%08x %lx tag=%d\n", ltb->seg, ltb->offsets[k], addr, func ? func->symt.tag : -1); @@ -1509,7 +1509,7 @@ static void codeview_snarf_linetab2(const struct msc_debug_info* msc_dbg, const source = source_new(msc_dbg->module, NULL, strimage + fd->offset); func = (struct symt_function*)symt_find_nearest(msc_dbg->module, addr); /* FIXME: at least labels support line numbers */ - if (!func || func->symt.tag != SymTagFunction) + if (!symt_check_tag(&func->symt, SymTagFunction) && !symt_check_tag(&func->symt, SymTagInlineSite)) { WARN("--not a func at %04x:%08x %lx tag=%d\n", lines_blk->seg, lines_blk->start, addr, func ? func->symt.tag : -1); diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index 0f53bcd023c..95cacc057a7 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -366,7 +366,7 @@ void symt_add_func_line(struct module* module, struct symt_function* func, func, func->hash_elt.name, offset, source_get(module, source_idx), line_num);
- assert(func->symt.tag == SymTagFunction); + assert(func->symt.tag == SymTagFunction || func->symt.tag == SymTagInlineSite);
for (i=vector_length(&func->vlines)-1; i>=0; i--) { @@ -424,8 +424,7 @@ struct symt_data* symt_add_func_local(struct module* module, debugstr_w(module->modulename), func->hash_elt.name, name, type);
- assert(func); - assert(func->symt.tag == SymTagFunction); + assert(symt_check_tag(&func->symt, SymTagFunction) || symt_check_tag(&func->symt, SymTagInlineSite)); assert(dt == DataIsParam || dt == DataIsLocal);
locsym = pool_alloc(&module->pool, sizeof(*locsym)); @@ -462,8 +461,7 @@ struct symt_data* symt_add_func_constant(struct module* module, debugstr_w(module->modulename), func->hash_elt.name, name, type);
- assert(func); - assert(func->symt.tag == SymTagFunction); + assert(symt_check_tag(&func->symt, SymTagFunction) || symt_check_tag(&func->symt, SymTagInlineSite));
locsym = pool_alloc(&module->pool, sizeof(*locsym)); locsym->symt.tag = SymTagData; @@ -489,8 +487,7 @@ struct symt_block* symt_open_func_block(struct module* module, struct symt_block* block; struct symt** p;
- assert(func); - assert(func->symt.tag == SymTagFunction); + assert(symt_check_tag(&func->symt, SymTagFunction) || symt_check_tag(&func->symt, SymTagInlineSite));
assert(!parent_block || parent_block->symt.tag == SymTagBlock); block = pool_alloc(&module->pool, sizeof(*block)); @@ -512,8 +509,7 @@ struct symt_block* symt_close_func_block(struct module* module, const struct symt_function* func, struct symt_block* block, unsigned pc) { - assert(func); - assert(func->symt.tag == SymTagFunction); + assert(symt_check_tag(&func->symt, SymTagFunction) || symt_check_tag(&func->symt, SymTagInlineSite));
if (pc) block->size = func->address + pc - block->address; return (block->container->tag == SymTagBlock) ? @@ -781,6 +777,7 @@ static void symt_fill_sym_info(struct module_pair* pair, } break; case SymTagFunction: + case SymTagInlineSite: symt_get_address(sym, &sym_info->Address); break; case SymTagThunk: @@ -1061,6 +1058,7 @@ static BOOL symt_enum_locals_helper(struct module_pair* pair, case SymTagFuncDebugStart: case SymTagFuncDebugEnd: case SymTagCustom: + case SymTagInlineSite: break; default: FIXME("Unknown type: %u (%x)\n", lsym->tag, lsym->tag); diff --git a/dlls/dbghelp/type.c b/dlls/dbghelp/type.c index 80f8eca768e..3a7ebfb6a0a 100644 --- a/dlls/dbghelp/type.c +++ b/dlls/dbghelp/type.c @@ -95,6 +95,7 @@ const char* symt_get_name(const struct symt* sym) /* lexical tree */ case SymTagData: return ((const struct symt_data*)sym)->hash_elt.name; case SymTagFunction: return ((const struct symt_function*)sym)->hash_elt.name; + case SymTagInlineSite: return ((const struct symt_inlinesite*)sym)->func.hash_elt.name; case SymTagPublicSymbol: return ((const struct symt_public*)sym)->hash_elt.name; case SymTagBaseType: return ((const struct symt_basic*)sym)->hash_elt.name; case SymTagLabel: return ((const struct symt_hierarchy_point*)sym)->hash_elt.name; @@ -153,6 +154,9 @@ BOOL symt_get_address(const struct symt* type, ULONG64* addr) case SymTagFunction: *addr = ((const struct symt_function*)type)->address; break; + case SymTagInlineSite: + *addr = ((const struct symt_inlinesite*)type)->func.address; + break; case SymTagPublicSymbol: *addr = ((const struct symt_public*)type)->address; break; @@ -572,6 +576,7 @@ BOOL symt_get_info(struct module* module, const struct symt* type, case SymTagEnum: v = &((const struct symt_enum*)type)->vchildren; break; case SymTagFunctionType: v = &((const struct symt_function_signature*)type)->vchildren; break; case SymTagFunction: v = &((const struct symt_function*)type)->vchildren; break; + case SymTagInlineSite: v = &((const struct symt_inlinesite*)type)->func.vchildren; break; case SymTagBlock: v = &((const struct symt_block*)type)->vchildren; break; case SymTagPointerType: case SymTagArrayType: @@ -644,6 +649,9 @@ BOOL symt_get_info(struct module* module, const struct symt* type, case SymTagFunction: X(DWORD) = vector_length(&((const struct symt_function*)type)->vchildren); break; + case SymTagInlineSite: + X(DWORD) = vector_length(&((const struct symt_inlinesite*)type)->func.vchildren); + break; case SymTagBlock: X(DWORD) = vector_length(&((const struct symt_block*)type)->vchildren); break; @@ -745,6 +753,7 @@ BOOL symt_get_info(struct module* module, const struct symt* type, case SymTagCompiland: case SymTagFunctionType: case SymTagFunctionArgType: + case SymTagInlineSite: /* native doesn't expose it, perhaps because of non-contiguous range */ case SymTagLabel: case SymTagFuncDebugStart: case SymTagFuncDebugEnd: @@ -767,6 +776,9 @@ BOOL symt_get_info(struct module* module, const struct symt* type, case SymTagFunction: X(DWORD) = symt_ptr2index(module, ((const struct symt_function*)type)->container); break; + case SymTagInlineSite: + X(DWORD) = symt_ptr2index(module, ((const struct symt_inlinesite*)type)->func.container); + break; case SymTagThunk: X(DWORD) = symt_ptr2index(module, ((const struct symt_thunk*)type)->container); break; @@ -846,6 +858,7 @@ BOOL symt_get_info(struct module* module, const struct symt* type, case SymTagFuncDebugStart: case SymTagFuncDebugEnd: case SymTagLabel: + case SymTagInlineSite: case SymTagCustom: return FALSE; } @@ -899,6 +912,9 @@ BOOL symt_get_info(struct module* module, const struct symt* type, case SymTagFunction: X(DWORD) = symt_ptr2index(module, ((const struct symt_function*)type)->type); break; + case SymTagInlineSite: + X(DWORD) = symt_ptr2index(module, ((const struct symt_inlinesite*)type)->func.type); + break; case SymTagEnum: X(DWORD) = symt_ptr2index(module, ((const struct symt_enum*)type)->base_type); break;