Eric Pouech : dbghelp: Use AT_range attribute (for function, block... addresses) when AT_low_pc and AT_high_pc are not present.

Alexandre Julliard julliard at winehq.org
Wed Jan 19 11:46:10 CST 2011


Module: wine
Branch: master
Commit: 60fbda43cb92f4574f96383eeefc734e1dbf0fc2
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=60fbda43cb92f4574f96383eeefc734e1dbf0fc2

Author: Eric Pouech <eric.pouech at orange.fr>
Date:   Tue Jan 18 21:49:05 2011 +0100

dbghelp: Use AT_range attribute (for function, block... addresses) when AT_low_pc and AT_high_pc are not present.

---

 dlls/dbghelp/dwarf.c |  108 +++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 84 insertions(+), 24 deletions(-)

diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c
index 2130c71..d60a5fd 100644
--- a/dlls/dbghelp/dwarf.c
+++ b/dlls/dbghelp/dwarf.c
@@ -163,7 +163,7 @@ typedef struct dwarf2_section_s
     DWORD_PTR                   rva;
 } dwarf2_section_t;
 
-enum dwarf2_sections {section_debug, section_string, section_abbrev, section_line, section_max};
+enum dwarf2_sections {section_debug, section_string, section_abbrev, section_line, section_ranges, section_max};
 
 typedef struct dwarf2_traverse_context_s
 {
@@ -945,6 +945,61 @@ static struct symt* dwarf2_lookup_type(dwarf2_parse_context_t* ctx,
 }
 
 /******************************************************************
+ *		dwarf2_read_range
+ *
+ * read a range for a given debug_info (either using AT_range attribute, in which
+ * case we don't return all the details, or using AT_low_pc & AT_high_pc attributes)
+ * in all cases, range is relative to beginning of compilation unit
+ */
+static BOOL dwarf2_read_range(dwarf2_parse_context_t* ctx, const dwarf2_debug_info_t* di,
+                              unsigned long* plow, unsigned long* phigh)
+{
+    struct attribute            range;
+
+    if (dwarf2_find_attribute(ctx, di, DW_AT_ranges, &range))
+    {
+        dwarf2_traverse_context_t   traverse;
+        unsigned long               low, high;
+
+        traverse.data = ctx->sections[section_ranges].address + range.u.uvalue;
+        traverse.end_data = ctx->sections[section_ranges].address +
+            ctx->sections[section_ranges].size;
+        traverse.word_size = ctx->module->format_info[DFI_DWARF]->u.dwarf2_info->word_size;
+
+        *plow  = ULONG_MAX;
+        *phigh = 0;
+        while (traverse.data + 2 * traverse.word_size < traverse.end_data)
+        {
+            low = dwarf2_parse_addr(&traverse);
+            high = dwarf2_parse_addr(&traverse);
+            if (low == 0 && high == 0) break;
+            if (low == ULONG_MAX) FIXME("unsupported yet (base address selection)\n");
+            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 == *phigh) {FIXME("entry found, but low=high\n"); return FALSE;}
+
+        return TRUE;
+    }
+    else
+    {
+        struct attribute            low_pc;
+        struct attribute            high_pc;
+
+        if (!dwarf2_find_attribute(ctx, di, DW_AT_low_pc, &low_pc) ||
+            !dwarf2_find_attribute(ctx, di, DW_AT_high_pc, &high_pc))
+        {
+            FIXME("missing low or high value\n");
+            return FALSE;
+        }
+        *plow = low_pc.u.uvalue;
+        *phigh = high_pc.u.uvalue;
+        return TRUE;
+    }
+}
+
+/******************************************************************
  *		dwarf2_read_one_debug_info
  *
  * Loads into memory one debug info entry, and recursively its children (if any)
@@ -1563,17 +1618,19 @@ static void dwarf2_parse_inlined_subroutine(dwarf2_subprogram_t* subpgm,
                                             const dwarf2_debug_info_t* di)
 {
     struct symt_block*  block;
-    struct attribute    low_pc;
-    struct attribute    high_pc;
+    unsigned long       low_pc, high_pc;
 
     TRACE("%s, for %s\n", dwarf2_debug_ctx(subpgm->ctx), dwarf2_debug_di(di));
 
-    if (!dwarf2_find_attribute(subpgm->ctx, di, DW_AT_low_pc, &low_pc)) low_pc.u.uvalue = 0;
-    if (!dwarf2_find_attribute(subpgm->ctx, di, DW_AT_high_pc, &high_pc)) high_pc.u.uvalue = 0;
+    if (!dwarf2_read_range(subpgm->ctx, di, &low_pc, &high_pc))
+    {
+        FIXME("cannot read range\n");
+        return;
+    }
 
     block = symt_open_func_block(subpgm->ctx->module, subpgm->func, parent_block,
-                                 subpgm->ctx->load_offset + low_pc.u.uvalue - subpgm->func->address,
-                                 high_pc.u.uvalue - low_pc.u.uvalue);
+                                 subpgm->ctx->load_offset + low_pc - subpgm->func->address,
+                                 high_pc - low_pc);
 
     if (di->abbrev->have_child) /** any interest to not have child ? */
     {
@@ -1614,19 +1671,19 @@ static void dwarf2_parse_subprogram_block(dwarf2_subprogram_t* subpgm,
 					  const dwarf2_debug_info_t* di)
 {
     struct symt_block*  block;
-    struct attribute    low_pc;
-    struct attribute    high_pc;
+    unsigned long       low_pc, high_pc;
 
     TRACE("%s, for %s\n", dwarf2_debug_ctx(subpgm->ctx), dwarf2_debug_di(di));
 
-    if (!dwarf2_find_attribute(subpgm->ctx, di, DW_AT_low_pc, &low_pc))
-        low_pc.u.uvalue = 0;
-    if (!dwarf2_find_attribute(subpgm->ctx, di, DW_AT_high_pc, &high_pc))
-        high_pc.u.uvalue = 0;
+    if (!dwarf2_read_range(subpgm->ctx, di, &low_pc, &high_pc))
+    {
+        FIXME("no range\n");
+        return;
+    }
 
     block = symt_open_func_block(subpgm->ctx->module, subpgm->func, parent_block,
-                                 subpgm->ctx->load_offset + low_pc.u.uvalue - subpgm->func->address,
-                                 high_pc.u.uvalue - low_pc.u.uvalue);
+                                 subpgm->ctx->load_offset + low_pc - subpgm->func->address,
+                                 high_pc - low_pc);
 
     if (di->abbrev->have_child) /** any interest to not have child ? */
     {
@@ -1683,8 +1740,7 @@ static struct symt* dwarf2_parse_subprogram(dwarf2_parse_context_t* ctx,
                                             struct symt_compiland* compiland)
 {
     struct attribute name;
-    struct attribute low_pc;
-    struct attribute high_pc;
+    unsigned long low_pc, high_pc;
     struct attribute is_decl;
     struct attribute inline_flags;
     struct symt* ret_type;
@@ -1710,14 +1766,17 @@ static struct symt* dwarf2_parse_subprogram(dwarf2_parse_context_t* ctx,
         return NULL;
     }
 
-    if (!dwarf2_find_attribute(ctx, di, DW_AT_low_pc, &low_pc)) low_pc.u.uvalue = 0;
-    if (!dwarf2_find_attribute(ctx, di, DW_AT_high_pc, &high_pc)) high_pc.u.uvalue = 0;
+    if (!dwarf2_read_range(ctx, di, &low_pc, &high_pc))
+    {
+        FIXME("cannot get range\n");
+        return NULL;
+    }
+
     /* As functions (defined as inline assembly) get debug info with dwarf
      * (not the case for stabs), we just drop Wine's thunks here...
      * Actual thunks will be created in elf_module from the symbol table
      */
-    if (elf_is_in_thunk_area(ctx->load_offset + low_pc.u.uvalue,
-                             ctx->thunks) >= 0)
+    if (elf_is_in_thunk_area(ctx->load_offset + low_pc, ctx->thunks) >= 0)
         return NULL;
     if (!dwarf2_find_attribute(ctx, di, DW_AT_declaration, &is_decl))
         is_decl.u.uvalue = 0;
@@ -1733,8 +1792,7 @@ static struct symt* dwarf2_parse_subprogram(dwarf2_parse_context_t* ctx,
     if (!is_decl.u.uvalue)
     {
         subpgm.func = symt_new_function(ctx->module, compiland, name.u.string,
-                                        ctx->load_offset + low_pc.u.uvalue,
-                                        high_pc.u.uvalue - low_pc.u.uvalue,
+                                        ctx->load_offset + low_pc, high_pc - low_pc,
                                         &sig_type->symt);
         di->symt = &subpgm.func->symt;
     }
@@ -3119,7 +3177,7 @@ BOOL dwarf2_parse(struct module* module, unsigned long load_offset,
     dwarf2_section_t    section[section_max];
     dwarf2_traverse_context_t   mod_ctx;
     struct image_section_map    debug_sect, debug_str_sect, debug_abbrev_sect,
-                                debug_line_sect;
+                                debug_line_sect, debug_ranges_sect;
     BOOL                ret = TRUE;
     struct module_format* dwarf2_modfmt;
 
@@ -3130,6 +3188,7 @@ BOOL dwarf2_parse(struct module* module, unsigned long load_offset,
     dwarf2_init_section(&section[section_abbrev], fmap, ".debug_abbrev", &debug_abbrev_sect);
     dwarf2_init_section(&section[section_string], fmap, ".debug_str",    &debug_str_sect);
     dwarf2_init_section(&section[section_line],   fmap, ".debug_line",   &debug_line_sect);
+    dwarf2_init_section(&section[section_ranges], fmap, ".debug_ranges", &debug_ranges_sect);
 
     if (section[section_debug].address == IMAGE_NO_MAP ||
         section[section_abbrev].address == IMAGE_NO_MAP ||
@@ -3192,6 +3251,7 @@ leave:
     image_unmap_section(&debug_abbrev_sect);
     image_unmap_section(&debug_str_sect);
     image_unmap_section(&debug_line_sect);
+    image_unmap_section(&debug_ranges_sect);
 
     return ret;
 }




More information about the wine-cvs mailing list