Eric Pouech : dbghelp: Dwarf & locations.

Alexandre Julliard julliard at wine.codeweavers.com
Tue Jun 20 05:23:37 CDT 2006


Module: wine
Branch: refs/heads/master
Commit: ae67326863246fc19e30cb3e8a3c4bd4562a9eae
URL:    http://source.winehq.org/git/?p=wine.git;a=commit;h=ae67326863246fc19e30cb3e8a3c4bd4562a9eae

Author: Eric Pouech <eric.pouech at wanadoo.fr>
Date:   Sun Jun 18 21:31:39 2006 +0200

dbghelp: Dwarf & locations.

- put back the block attribute parsing
- added dwarf2_compute_location to properly decode a location (at
  least starting it)

---

 dlls/dbghelp/dwarf.c |  146 ++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 118 insertions(+), 28 deletions(-)

diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c
index 6c354b7..60c86f2 100644
--- a/dlls/dbghelp/dwarf.c
+++ b/dlls/dbghelp/dwarf.c
@@ -113,11 +113,18 @@ typedef struct dwarf2_abbrev_entry_s
     dwarf2_abbrev_entry_attr_t* attrs;
 } dwarf2_abbrev_entry_t;
 
+struct dwarf2_block
+{
+    unsigned                    size;
+    const unsigned char*        ptr;
+};
+
 union attribute
 {
     unsigned long                   uvalue;
     long                            svalue;
     const char*                     string;
+    struct dwarf2_block*            block;
 };
 
 typedef struct dwarf2_debug_info_s
@@ -391,23 +398,31 @@ static void dwarf2_parse_attr_into_di(dw
         TRACE("strp<%s>\n", attr->string);
         break;
     case DW_FORM_block:
-        attr->uvalue = dwarf2_leb128_as_unsigned(ctx);
-        ctx->data += attr->uvalue;
+        attr->block = pool_alloc(&ctx->pool, sizeof(struct dwarf2_block));
+        attr->block->size = dwarf2_leb128_as_unsigned(ctx);
+        attr->block->ptr  = ctx->data;
+        ctx->data += attr->block->size;
         break;
 
     case DW_FORM_block1:
-        attr->uvalue = dwarf2_parse_byte(ctx);
-        ctx->data += attr->uvalue;
+        attr->block = pool_alloc(&ctx->pool, sizeof(struct dwarf2_block));
+        attr->block->size = dwarf2_parse_byte(ctx);
+        attr->block->ptr  = ctx->data;
+        ctx->data += attr->block->size;
         break;
 
     case DW_FORM_block2:
-        attr->uvalue = dwarf2_parse_u2(ctx);
-        ctx->data += attr->uvalue;
+        attr->block = pool_alloc(&ctx->pool, sizeof(struct dwarf2_block));
+        attr->block->size = dwarf2_parse_u2(ctx);
+        attr->block->ptr  = ctx->data;
+        ctx->data += attr->block->size;
         break;
 
     case DW_FORM_block4:
-        attr->uvalue = dwarf2_parse_u4(ctx);
-        ctx->data += attr->uvalue;
+        attr->block = pool_alloc(&ctx->pool, sizeof(struct dwarf2_block));
+        attr->block->size = dwarf2_parse_u4(ctx);
+        attr->block->ptr  = ctx->data;
+        ctx->data += attr->block->size;
         break;
 
     default:
@@ -450,6 +465,96 @@ static void dwarf2_find_name(dwarf2_pars
 static void dwarf2_load_one_entry(dwarf2_parse_context_t*, dwarf2_debug_info_t*,
                                   struct symt_compiland*);
 
+#define Wine_DW_no_register     -1
+#define Wine_DW_frame_register  -2
+
+static unsigned long dwarf2_compute_location(dwarf2_parse_context_t* ctx,
+                                             struct dwarf2_block* block,
+                                             int* in_register)
+{
+    unsigned long loc[64];
+    unsigned stk;
+
+    if (in_register) *in_register = Wine_DW_no_register;
+    loc[stk = 0] = 0;
+
+    if (block->size)
+    {
+        /* FIXME: would require better definition of contexts */
+        dwarf2_parse_context_t  lctx;
+        unsigned char op;
+        BOOL piece_found = FALSE;
+
+        lctx.data = block->ptr;
+        lctx.end_data = block->ptr + block->size;
+        lctx.word_size = ctx->word_size;
+
+        while (lctx.data < lctx.end_data)
+        {
+            op = dwarf2_parse_byte(&lctx);
+            switch (op)
+            {
+            case DW_OP_addr:    loc[++stk] = dwarf2_parse_addr(&lctx); break;
+            case DW_OP_const1u: loc[++stk] = dwarf2_parse_byte(&lctx); break;
+            case DW_OP_const1s: loc[++stk] = (long)(char)dwarf2_parse_byte(&lctx); break;
+            case DW_OP_const2u: loc[++stk] = dwarf2_parse_u2(&lctx); break;
+            case DW_OP_const2s: loc[++stk] = (long)(short)dwarf2_parse_u2(&lctx); break;
+            case DW_OP_const4u: loc[++stk] = dwarf2_parse_u4(&lctx); break;
+            case DW_OP_const4s: loc[++stk] = dwarf2_parse_u4(&lctx); break;
+            case DW_OP_constu:  loc[++stk] = dwarf2_leb128_as_unsigned(&lctx); break;
+            case DW_OP_consts:  loc[++stk] = dwarf2_leb128_as_signed(&lctx); break;
+            case DW_OP_plus_uconst:
+                                loc[stk] += dwarf2_leb128_as_unsigned(&lctx); break;
+            case DW_OP_reg0:  case DW_OP_reg1:  case DW_OP_reg2:  case DW_OP_reg3:
+            case DW_OP_reg4:  case DW_OP_reg5:  case DW_OP_reg6:  case DW_OP_reg7:
+            case DW_OP_reg8:  case DW_OP_reg9:  case DW_OP_reg10: case DW_OP_reg11:
+            case DW_OP_reg12: case DW_OP_reg13: case DW_OP_reg14: case DW_OP_reg15:
+            case DW_OP_reg16: case DW_OP_reg17: case DW_OP_reg18: case DW_OP_reg19:
+            case DW_OP_reg20: case DW_OP_reg21: case DW_OP_reg22: case DW_OP_reg23:
+            case DW_OP_reg24: case DW_OP_reg25: case DW_OP_reg26: case DW_OP_reg27:
+            case DW_OP_reg28: case DW_OP_reg29: case DW_OP_reg30: case DW_OP_reg31:
+                if (in_register)
+                {
+                    /* dbghelp APIs don't know how to cope with this anyway
+                     * (for example 'long long' stored in two registers)
+                     * FIXME: We should tell winedbg how to deal with it (sigh)
+                     */
+                    if (!piece_found || (op - DW_OP_reg0 != *in_register + 1))
+                    {
+                        if (*in_register != Wine_DW_no_register)
+                            FIXME("Only supporting one reg (%d -> %d)\n", 
+                                  *in_register, op - DW_OP_reg0);
+                        *in_register = op - DW_OP_reg0;
+                    }
+                }
+                else FIXME("Found register, while not expecting it\n");
+                break;
+            case DW_OP_fbreg:
+                if (in_register)
+                {
+                    if (*in_register != Wine_DW_no_register)
+                        FIXME("Only supporting one reg (%d -> -2)\n", *in_register);
+                    *in_register = Wine_DW_frame_register;
+                }
+                else FIXME("Found register, while not expecting it\n");
+                loc[++stk] = dwarf2_leb128_as_signed(&lctx);
+                break;
+            case DW_OP_piece:
+                {
+                    unsigned sz = dwarf2_leb128_as_unsigned(&lctx);
+                    WARN("Not handling OP_piece directly (size=%d)\n", sz);
+                    piece_found = TRUE;
+                }
+                break;
+            default:
+                FIXME("Unhandled attr op: %x\n", op);
+                return loc[stk];
+            }
+        }
+    }
+    return loc[stk];
+}
+
 static struct symt* dwarf2_lookup_type(dwarf2_parse_context_t* ctx,
                                        const dwarf2_debug_info_t* di)
 {
@@ -699,8 +804,8 @@ static void dwarf2_parse_udt_member(dwar
 {
     struct symt* elt_type;
     union attribute name;
-/*    union attribute loc; */
-    unsigned long offset;
+    union attribute loc;
+    unsigned long offset = 0;
 
     assert(parent);
 
@@ -708,27 +813,12 @@ static void dwarf2_parse_udt_member(dwar
 
     dwarf2_find_name(ctx, di, &name, "udt_member");
     elt_type = dwarf2_lookup_type(ctx, di);
-#if 0
     if (dwarf2_find_attribute(di, DW_AT_data_member_location, &loc))
     {
-	TRACE("found member_location at %s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_attr(attr));
-	if (loc.uvalue) {
-	  unsigned char op = dwarf2_parse_byte(ctx);
-	  --uvalue;
-	  switch (op) {
-	  case DW_OP_plus_uconst:
-	    offset = dwarf2_leb128_as_unsigned(ctx);
-	    break;
-	  default:
-	    WARN("Unhandled attr op at %s, for %s, op:%u\n", dwarf2_debug_ctx(ctx), dwarf2_debug_attr(attr), op);
-	    ctx->data += uvalue;
-	  }
-	  TRACE("found offset:%lu\n", offset); 		  
-	}
+	TRACE("found member_location at %s\n", dwarf2_debug_ctx(ctx));
+        offset = dwarf2_compute_location(ctx, loc.block, NULL);
+        TRACE("found offset:%lu\n", offset); 		  
     }
-#endif
-    FIXME("still to be implemented proper member location\n");
-    offset = 0;
     
     symt_add_udt_element(ctx->module, parent, name.string, elt_type, offset, 0);
 




More information about the wine-cvs mailing list