The following series implements: - fixes and dwarf4 evolutions for function range computation - support for a few more dwarf types (restrict, rvalue ref, subrange)
v2 including missing signed-off clauses
A+ ---
Eric Pouech (9): dbghelp/dwarf: in DW_AT_ranges, the values are relative to the start of the CU dbghelp/dwarf: properly detect base address selection in AT_ranges dbghelp: removed unneeded #include <limits.h> dbghelp/dwarf: dwarf4 integrates some tweaks in high / low pc attritbutes dbghelp/dwarf: Added support for parsing dwarf's 3 restrict type TAG dbghelp/dwarf: Support enumeration as index type for arrays dbghelp/dwarf: Added support for DW_TAG_subrange_type in various places dbghelp/dwarf: Support more dwarf's TAG related to types in udt parsing dbghelp/dwarf: Handle C++ rvalue reference type as a reference
dlls/dbghelp/dwarf.c | 107 ++++++++++++++++++++++++++++++++++++++++-- dlls/dbghelp/stabs.c | 1 - dlls/dbghelp/symbol.c | 1 - 3 files changed, 102 insertions(+), 7 deletions(-)
(and not the module, as most of the other addresses)
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/dbghelp/dwarf.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c index f67efc43993..3009dead905 100644 --- a/dlls/dbghelp/dwarf.c +++ b/dlls/dbghelp/dwarf.c @@ -1222,6 +1222,9 @@ static BOOL dwarf2_read_range(dwarf2_parse_context_t* ctx, const dwarf2_debug_in high = dwarf2_parse_addr_head(&traverse, &ctx->head); if (low == 0 && high == 0) break; if (low == ULONG_MAX) FIXME("unsupported yet (base address selection)\n"); + /* range values are relative to start of compilation unit */ + low += ctx->compiland->address - ctx->module_ctx->load_offset; + high += ctx->compiland->address - ctx->module_ctx->load_offset; if (low < *plow) *plow = low; if (high > *phigh) *phigh = high; }
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/dbghelp/dwarf.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c index 3009dead905..5f433e1d872 100644 --- a/dlls/dbghelp/dwarf.c +++ b/dlls/dbghelp/dwarf.c @@ -1209,26 +1209,28 @@ static BOOL dwarf2_read_range(dwarf2_parse_context_t* ctx, const dwarf2_debug_in { dwarf2_traverse_context_t traverse; ULONG_PTR low, high; + const ULONG_PTR UMAX = ~(ULONG_PTR)0u;
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;
- *plow = ULONG_MAX; + *plow = UMAX; *phigh = 0; while (traverse.data + 2 * ctx->head.word_size < traverse.end_data) { low = dwarf2_parse_addr_head(&traverse, &ctx->head); high = dwarf2_parse_addr_head(&traverse, &ctx->head); if (low == 0 && high == 0) break; - if (low == ULONG_MAX) FIXME("unsupported yet (base address selection)\n"); + 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 */ low += ctx->compiland->address - ctx->module_ctx->load_offset; high += ctx->compiland->address - ctx->module_ctx->load_offset; 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 == UMAX || *phigh == 0) {FIXME("no entry found\n"); return FALSE;} if (*plow == *phigh) {FIXME("entry found, but low=high\n"); return FALSE;}
return TRUE;
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/dbghelp/dwarf.c | 1 - dlls/dbghelp/stabs.c | 1 - dlls/dbghelp/symbol.c | 1 - 3 files changed, 3 deletions(-)
diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c index 5f433e1d872..16ebd5dbf65 100644 --- a/dlls/dbghelp/dwarf.c +++ b/dlls/dbghelp/dwarf.c @@ -23,7 +23,6 @@ #define NONAMELESSUNION
#include <sys/types.h> -#include <limits.h> #include <stdlib.h> #include <string.h> #include <stdio.h> diff --git a/dlls/dbghelp/stabs.c b/dlls/dbghelp/stabs.c index 7008f60ea82..9d7d5131fc4 100644 --- a/dlls/dbghelp/stabs.c +++ b/dlls/dbghelp/stabs.c @@ -31,7 +31,6 @@
#include <sys/types.h> #include <fcntl.h> -#include <limits.h> #include <stdint.h> #include <stdlib.h> #include <string.h> diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index 3b44315eebd..29376812653 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -24,7 +24,6 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <limits.h> #include <sys/types.h> #include <assert.h>
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/dbghelp/dwarf.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c index 16ebd5dbf65..6eb7bbf1337 100644 --- a/dlls/dbghelp/dwarf.c +++ b/dlls/dbghelp/dwarf.c @@ -1244,6 +1244,24 @@ static BOOL dwarf2_read_range(dwarf2_parse_context_t* ctx, const dwarf2_debug_in return FALSE; *plow = low_pc.u.uvalue; *phigh = high_pc.u.uvalue; + 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 contant, high_pc is an offset from low_pc */ + *phigh += *plow; + break; + default: + FIXME("Unsupported class for high_pc\n"); + break; + } return TRUE; } }
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/dbghelp/dwarf.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c index 6eb7bbf1337..c67e88cb243 100644 --- a/dlls/dbghelp/dwarf.c +++ b/dlls/dbghelp/dwarf.c @@ -1507,6 +1507,21 @@ static struct symt* dwarf2_parse_volatile_type(dwarf2_debug_info_t* di) return ref_type; }
+static struct symt* dwarf2_parse_restrict_type(dwarf2_debug_info_t* di) +{ + struct symt* ref_type; + + if (di->symt) return di->symt; + + TRACE("%s\n", dwarf2_debug_di(di)); + + ref_type = dwarf2_lookup_type(di); + if (dwarf2_get_di_children(di)) FIXME("Unsupported children\n"); + di->symt = ref_type; + + return ref_type; +} + static struct symt* dwarf2_parse_unspecified_type(dwarf2_debug_info_t* di) { struct attribute name; @@ -2265,6 +2280,9 @@ static void dwarf2_load_one_entry(dwarf2_debug_info_t* di) case DW_TAG_volatile_type: dwarf2_parse_volatile_type(di); break; + case DW_TAG_restrict_type: + dwarf2_parse_restrict_type(di); + break; case DW_TAG_unspecified_type: dwarf2_parse_unspecified_type(di); break;
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/dbghelp/dwarf.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-)
diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c index c67e88cb243..29d6a691f48 100644 --- a/dlls/dbghelp/dwarf.c +++ b/dlls/dbghelp/dwarf.c @@ -1433,9 +1433,10 @@ static struct symt* dwarf2_parse_array_type(dwarf2_debug_info_t* di) { struct symt* ref_type; struct symt* idx_type = NULL; + struct symt* symt = NULL; struct attribute min, max, cnt; dwarf2_debug_info_t* child; - unsigned int i; + unsigned int i, j; const struct vector* children;
if (di->symt) return di->symt; @@ -1467,6 +1468,28 @@ static struct symt* dwarf2_parse_array_type(dwarf2_debug_info_t* di) else if (!dwarf2_find_attribute(child, DW_AT_count, &cnt)) cnt.u.uvalue = 0; break; + case DW_TAG_enumeration_type: + symt = dwarf2_parse_enumeration_type(child); + if (symt_check_tag(symt, SymTagEnum)) + { + struct symt_enum* enum_symt = (struct symt_enum*)symt; + idx_type = enum_symt->base_type; + min.u.uvalue = ~0U; + max.u.uvalue = ~0U; + for (j = 0; j < enum_symt->vchildren.num_elts; ++j) + { + struct symt** pc = vector_at(&enum_symt->vchildren, j); + if (pc && symt_check_tag(*pc, SymTagData)) + { + struct symt_data* elt = (struct symt_data*)(*pc); + if (elt->u.value.n1.n2.n3.lVal < min.u.uvalue) + min.u.uvalue = elt->u.value.n1.n2.n3.lVal; + if (elt->u.value.n1.n2.n3.lVal > max.u.uvalue) + max.u.uvalue = elt->u.value.n1.n2.n3.lVal; + } + } + } + break; default: FIXME("Unhandled Tag type 0x%lx at %s\n", child->abbrev->tag, dwarf2_debug_di(di));
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/dbghelp/dwarf.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+)
diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c index 29d6a691f48..2b36393b132 100644 --- a/dlls/dbghelp/dwarf.c +++ b/dlls/dbghelp/dwarf.c @@ -1429,6 +1429,28 @@ static struct symt* dwarf2_parse_pointer_type(dwarf2_debug_info_t* di) return di->symt; }
+static struct symt* dwarf2_parse_subrange_type(dwarf2_debug_info_t* di) +{ + struct symt* ref_type; + struct attribute name; + struct attribute dummy; + + if (di->symt) return di->symt; + + TRACE("%s\n", dwarf2_debug_di(di)); + + if (dwarf2_find_attribute(di, DW_AT_name, &name)) FIXME("Found name for subrange %s\n", name.u.string); + if (dwarf2_find_attribute(di, DW_AT_byte_size, &dummy)) FIXME("Found byte_size %lu\n", dummy.u.uvalue); + if (dwarf2_find_attribute(di, DW_AT_bit_size, &dummy)) FIXME("Found bit_size %lu\n", dummy.u.uvalue); + /* for now, we don't support the byte_size nor bit_size about the subrange, and pretend the two + * types are the same (FIXME) + */ + ref_type = dwarf2_lookup_type(di); + di->symt = ref_type; + if (dwarf2_get_di_children(di)) FIXME("Unsupported children\n"); + return di->symt; +} + static struct symt* dwarf2_parse_array_type(dwarf2_debug_info_t* di) { struct symt* ref_type; @@ -1682,6 +1704,9 @@ static struct symt* dwarf2_parse_udt_type(dwarf2_debug_info_t* di, case DW_TAG_const_type: dwarf2_parse_const_type(child); break; + case DW_TAG_subrange_type: + dwarf2_parse_subrange_type(child); + break; case DW_TAG_structure_type: case DW_TAG_class_type: case DW_TAG_union_type: @@ -2336,6 +2361,9 @@ static void dwarf2_load_one_entry(dwarf2_debug_info_t* di) case DW_TAG_namespace: dwarf2_parse_namespace(di); break; + case DW_TAG_subrange_type: + dwarf2_parse_subrange_type(di); + break; /* silence a couple of C++ defines */ case DW_TAG_imported_module: case DW_TAG_imported_declaration:
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/dbghelp/dwarf.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c index 2b36393b132..2c9b3a15719 100644 --- a/dlls/dbghelp/dwarf.c +++ b/dlls/dbghelp/dwarf.c @@ -1704,6 +1704,12 @@ static struct symt* dwarf2_parse_udt_type(dwarf2_debug_info_t* di, case DW_TAG_const_type: dwarf2_parse_const_type(child); break; + case DW_TAG_volatile_type: + dwarf2_parse_volatile_type(di); + break; + case DW_TAG_pointer_type: + dwarf2_parse_pointer_type(child); + break; case DW_TAG_subrange_type: dwarf2_parse_subrange_type(child); break; @@ -1713,11 +1719,13 @@ static struct symt* dwarf2_parse_udt_type(dwarf2_debug_info_t* di, case DW_TAG_typedef: /* FIXME: we need to handle nested udt definitions */ case DW_TAG_inheritance: + case DW_TAG_interface_type: case DW_TAG_template_type_param: case DW_TAG_template_value_param: case DW_TAG_variable: case DW_TAG_imported_declaration: case DW_TAG_ptr_to_member_type: + case DW_TAG_GNU_template_template_param: case DW_TAG_GNU_template_parameter_pack: case DW_TAG_GNU_formal_parameter_pack: /* FIXME: some C++ related stuff */
(as we don't handle C++ references yet, it'll be a pointer at the end)
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/dbghelp/dwarf.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c index 2c9b3a15719..f574cb6c87a 100644 --- a/dlls/dbghelp/dwarf.c +++ b/dlls/dbghelp/dwarf.c @@ -2343,6 +2343,7 @@ static void dwarf2_load_one_entry(dwarf2_debug_info_t* di) dwarf2_parse_unspecified_type(di); break; case DW_TAG_reference_type: + case DW_TAG_rvalue_reference_type: dwarf2_parse_reference_type(di); break; case DW_TAG_enumeration_type: