dbghelp: merge dwarf code from ntdll/signal_x86_64.c

André Hentschel nerv at dawncrow.de
Sun Jan 10 10:44:47 CST 2010


thanks Eric Pouech for the reviews
---
 dlls/dbghelp/dwarf.c |  229 +++++++++++++++++++++++++++++++++++++++++---------
 dlls/dbghelp/dwarf.h |   15 ++++
 2 files changed, 204 insertions(+), 40 deletions(-)

diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c
index 48e6351..d7f4f50 100644
--- a/dlls/dbghelp/dwarf.c
+++ b/dlls/dbghelp/dwarf.c
@@ -241,6 +241,13 @@ static DWORD64 dwarf2_get_u8(const unsigned char* ptr)
     return *(const UINT64*)ptr;
 }
 
+static DWORD64 dwarf2_parse_u8(dwarf2_traverse_context_t* ctx)
+{
+    unsigned long uvalue = dwarf2_get_u8(ctx->data);
+    ctx->data += 8;
+    return uvalue;
+}
+
 static unsigned long dwarf2_get_leb128_as_unsigned(const unsigned char* ptr, const unsigned char** end)
 {
     unsigned long ret = 0;
@@ -344,6 +351,58 @@ static unsigned long dwarf2_parse_addr(dwarf2_traverse_context_t* ctx)
     return ret;
 }
 
+static ULONG_PTR dwarf2_get_ptr( const unsigned char **p, unsigned char encoding, unsigned word_size)
+{
+    ULONG_PTR base;
+
+    if (encoding == DW_EH_PE_omit) return 0;
+
+    switch (encoding & 0xf0)
+    {
+    case DW_EH_PE_abs:
+        base = 0;
+        break;
+    case DW_EH_PE_pcrel:
+        base = (ULONG_PTR)*p;
+        break;
+    default:
+        FIXME( "unsupported encoding %02x\n", encoding );
+        return 0;
+    }
+
+    switch (encoding & 0x0f)
+    {
+    case DW_EH_PE_native:
+        return base + dwarf2_get_addr( *p, word_size );
+    case DW_EH_PE_leb128:
+        return base + dwarf2_get_leb128_as_unsigned(*p, p);
+    case DW_EH_PE_data2:
+        return base + dwarf2_get_u2( *p );
+    case DW_EH_PE_data4:
+        return base + dwarf2_get_u4( *p );
+    case DW_EH_PE_data8:
+        return base + dwarf2_get_u8( *p );
+    case DW_EH_PE_signed|DW_EH_PE_leb128:
+        return base + dwarf2_get_leb128_as_signed(*p, p);
+    case DW_EH_PE_signed|DW_EH_PE_data2:
+        return base + (signed short)dwarf2_get_u2( *p );
+    case DW_EH_PE_signed|DW_EH_PE_data4:
+        return base + (signed int)dwarf2_get_u4( *p );
+    case DW_EH_PE_signed|DW_EH_PE_data8:
+        return base + (LONG64)dwarf2_get_u8( *p );
+    default:
+        FIXME( "unsupported encoding %02x\n", encoding );
+        return 0;
+    }
+}
+
+static unsigned long dwarf2_parse_ptr(dwarf2_traverse_context_t* ctx)
+{
+    unsigned long ret = dwarf2_get_ptr(&(ctx->data), *(ctx->data++), ctx->word_size);
+    ctx->data++;
+    return ret;
+}
+
 static const char* dwarf2_debug_traverse_ctx(const dwarf2_traverse_context_t* ctx) 
 {
     return wine_dbg_sprintf("ctx(%p)", ctx->data); 
@@ -666,7 +725,7 @@ static enum location_error
 compute_location(dwarf2_traverse_context_t* ctx, struct location* loc,
                  HANDLE hproc, const struct location* frame)
 {
-    DWORD_PTR stack[64];
+    DWORD_PTR tmp, stack[64];
     unsigned stk;
     unsigned char op;
     BOOL piece_found = FALSE;
@@ -679,36 +738,11 @@ compute_location(dwarf2_traverse_context_t* ctx, struct location* loc,
     while (ctx->data < ctx->end_data)
     {
         op = dwarf2_parse_byte(ctx);
-        switch (op)
+
+        if (op >= DW_OP_lit0 && op <= DW_OP_lit31)
+            stack[++stk] = op - DW_OP_lit0;
+        else if (op >= DW_OP_reg0 && op <= DW_OP_reg31)
         {
-        case DW_OP_lit0:  case DW_OP_lit1:  case DW_OP_lit2:  case DW_OP_lit3:
-        case DW_OP_lit4:  case DW_OP_lit5:  case DW_OP_lit6:  case DW_OP_lit7:
-        case DW_OP_lit8:  case DW_OP_lit9:  case DW_OP_lit10: case DW_OP_lit11:
-        case DW_OP_lit12: case DW_OP_lit13: case DW_OP_lit14: case DW_OP_lit15:
-        case DW_OP_lit16: case DW_OP_lit17: case DW_OP_lit18: case DW_OP_lit19:
-        case DW_OP_lit20: case DW_OP_lit21: case DW_OP_lit22: case DW_OP_lit23:
-        case DW_OP_lit24: case DW_OP_lit25: case DW_OP_lit26: case DW_OP_lit27:
-        case DW_OP_lit28: case DW_OP_lit29: case DW_OP_lit30: case DW_OP_lit31:
-            stack[++stk] = op - DW_OP_lit0; break;
-        case DW_OP_addr:    stack[++stk] = dwarf2_parse_addr(ctx); break;
-        case DW_OP_const1u: stack[++stk] = dwarf2_parse_byte(ctx); break;
-        case DW_OP_const1s: stack[++stk] = (long)(signed char)dwarf2_parse_byte(ctx); break;
-        case DW_OP_const2u: stack[++stk] = dwarf2_parse_u2(ctx); break;
-        case DW_OP_const2s: stack[++stk] = (long)(short)dwarf2_parse_u2(ctx); break;
-        case DW_OP_const4u: stack[++stk] = dwarf2_parse_u4(ctx); break;
-        case DW_OP_const4s: stack[++stk] = dwarf2_parse_u4(ctx); break;
-        case DW_OP_constu:  stack[++stk] = dwarf2_leb128_as_unsigned(ctx); break;
-        case DW_OP_consts:  stack[++stk] = dwarf2_leb128_as_signed(ctx); break;
-        case DW_OP_plus_uconst:
-            stack[stk] += dwarf2_leb128_as_unsigned(ctx); 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:
             /* 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)
@@ -721,15 +755,9 @@ compute_location(dwarf2_traverse_context_t* ctx, struct location* loc,
                 loc->reg = dwarf2_map_register(op - DW_OP_reg0);
             }
             loc->kind = loc_register;
-            break;
-        case DW_OP_breg0:  case DW_OP_breg1:  case DW_OP_breg2:  case DW_OP_breg3:
-        case DW_OP_breg4:  case DW_OP_breg5:  case DW_OP_breg6:  case DW_OP_breg7:
-        case DW_OP_breg8:  case DW_OP_breg9:  case DW_OP_breg10: case DW_OP_breg11:
-        case DW_OP_breg12: case DW_OP_breg13: case DW_OP_breg14: case DW_OP_breg15:
-        case DW_OP_breg16: case DW_OP_breg17: case DW_OP_breg18: case DW_OP_breg19:
-        case DW_OP_breg20: case DW_OP_breg21: case DW_OP_breg22: case DW_OP_breg23:
-        case DW_OP_breg24: case DW_OP_breg25: case DW_OP_breg26: case DW_OP_breg27:
-        case DW_OP_breg28: case DW_OP_breg29: case DW_OP_breg30: case DW_OP_breg31:
+        }
+        else if (op >= DW_OP_breg0 && op <= DW_OP_breg31)
+        {
             /* 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)
@@ -737,13 +765,72 @@ compute_location(dwarf2_traverse_context_t* ctx, struct location* loc,
             if (!piece_found)
             {
                 if (loc->reg != Wine_DW_no_register)
-                    FIXME("Only supporting one reg (%d -> %d)\n",
+                    FIXME("Only supporting one breg (%d -> %d)\n",
                           loc->reg, dwarf2_map_register(op - DW_OP_breg0));
                 loc->reg = dwarf2_map_register(op - DW_OP_breg0);
             }
             stack[++stk] = dwarf2_leb128_as_signed(ctx);
             loc->kind = loc_regrel;
             break;
+        }
+        else switch (op)
+        {
+        case DW_OP_nop:         break;
+        case DW_OP_addr:        stack[++stk] = dwarf2_parse_addr(ctx); break;
+        case DW_OP_const1u:     stack[++stk] = dwarf2_parse_byte(ctx); break;
+        case DW_OP_const1s:     stack[++stk] = (long)(signed char)dwarf2_parse_byte(ctx); break;
+        case DW_OP_const2u:     stack[++stk] = dwarf2_parse_u2(ctx); break;
+        case DW_OP_const2s:     stack[++stk] = (long)(short)dwarf2_parse_u2(ctx); break;
+        case DW_OP_const4u:     stack[++stk] = dwarf2_parse_u4(ctx); break;
+        case DW_OP_const4s:     stack[++stk] = (long)(signed int)dwarf2_parse_u4(ctx); break;
+        case DW_OP_const8u:     stack[++stk] = dwarf2_parse_u8(ctx); break;
+        case DW_OP_const8s:     stack[++stk] = (long)dwarf2_parse_u8(ctx); break;
+        case DW_OP_constu:      stack[++stk] = dwarf2_leb128_as_unsigned(ctx); break;
+        case DW_OP_consts:      stack[++stk] = dwarf2_leb128_as_signed(ctx); break;
+        case DW_OP_dup:         stack[stk + 1] = stack[stk]; stk++; break;
+        case DW_OP_drop:        stk--; break;
+        case DW_OP_over:        stack[stk + 1] = stack[stk - 1]; stk++; break;
+        case DW_OP_pick:        stack[stk + 1] = stack[stk - dwarf2_parse_byte(ctx)]; stk++; break;
+        case DW_OP_swap:        tmp = stack[stk]; stack[stk] = stack[stk-1]; stack[stk-1] = tmp; break;
+        case DW_OP_rot:         tmp = stack[stk]; stack[stk] = stack[stk-1]; stack[stk-1] = stack[stk-2]; stack[stk-2] = tmp; break;
+        case DW_OP_abs:         stack[stk] = labs(stack[stk]); break;
+        case DW_OP_neg:         stack[stk] = -stack[stk]; break;
+        case DW_OP_not:         stack[stk] = ~stack[stk]; break;
+        case DW_OP_and:         stack[stk-1] &= stack[stk]; stk--; break;
+        case DW_OP_or:          stack[stk-1] |= stack[stk]; stk--; break;
+        case DW_OP_minus:       stack[stk-1] -= stack[stk]; stk--; break;
+        case DW_OP_mul:         stack[stk-1] *= stack[stk]; stk--; break;
+        case DW_OP_plus:        stack[stk-1] += stack[stk]; stk--; break;
+        case DW_OP_xor:         stack[stk-1] ^= stack[stk]; stk--; break;
+        case DW_OP_shl:         stack[stk-1] <<= stack[stk]; stk--; break;
+        case DW_OP_shr:         stack[stk-1] >>= stack[stk]; stk--; break;
+        case DW_OP_plus_uconst: stack[stk] += dwarf2_leb128_as_unsigned(ctx); break;
+        case DW_OP_shra:        stack[stk-1] = (LONG_PTR)stack[stk-1] / (1 << stack[stk]); stk--; break;
+        case DW_OP_div:         stack[stk-1] = (LONG_PTR)stack[stk-1] / (LONG_PTR)stack[stk]; stk--; break;
+        case DW_OP_mod:         stack[stk-1] = (LONG_PTR)stack[stk-1] % (LONG_PTR)stack[stk]; stk--; break;
+        case DW_OP_ge:          stack[stk-1] = ((LONG_PTR)stack[stk-1] >= (LONG_PTR)stack[stk]); stk--; break;
+        case DW_OP_gt:          stack[stk-1] = ((LONG_PTR)stack[stk-1] >  (LONG_PTR)stack[stk]); stk--; break;
+        case DW_OP_le:          stack[stk-1] = ((LONG_PTR)stack[stk-1] <= (LONG_PTR)stack[stk]); stk--; break;
+        case DW_OP_lt:          stack[stk-1] = ((LONG_PTR)stack[stk-1] <  (LONG_PTR)stack[stk]); stk--; break;
+        case DW_OP_eq:          stack[stk-1] = (stack[stk-1] == stack[stk]); stk--; break;
+        case DW_OP_ne:          stack[stk-1] = (stack[stk-1] != stack[stk]); stk--; break;
+        case DW_OP_skip:        tmp = (short)dwarf2_parse_u2(ctx); ctx->data += tmp; break;
+        case DW_OP_bra:         tmp = (short)dwarf2_parse_u2(ctx); if (!stack[stk--]) ctx->data += tmp; break;
+        case DW_OP_GNU_encoded_addr: stack[++stk] = dwarf2_parse_ptr(ctx); break;
+        case DW_OP_regx:
+            if (loc->reg != Wine_DW_no_register)
+                FIXME("Only supporting one regx\n");
+            loc->reg = dwarf2_map_register(dwarf2_leb128_as_unsigned(ctx));
+            loc->kind = loc_register;
+            break;
+        case DW_OP_bregx:
+            tmp = dwarf2_leb128_as_unsigned(ctx);
+            ctx->data++;
+            if (loc->reg != Wine_DW_no_register)
+                FIXME("Only supporting one regx\n");
+            loc->reg = dwarf2_map_register(tmp) + dwarf2_leb128_as_signed(ctx);
+            loc->kind = loc_register;
+            break;
         case DW_OP_fbreg:
             if (loc->reg != Wine_DW_no_register)
                 FIXME("Only supporting one reg (%d -> -2)\n", loc->reg);
@@ -803,6 +890,68 @@ compute_location(dwarf2_traverse_context_t* ctx, struct location* loc,
                loc->kind = loc_dwarf2_block;
             }
             break;
+        case DW_OP_deref_size:
+            if (!stk)
+            {
+                FIXME("Unexpected empty stack\n");
+                return loc_err_internal;
+            }
+            if (loc->reg != Wine_DW_no_register)
+            {
+                WARN("Too complex expression for deref\n");
+                return loc_err_too_complex;
+            }
+            if (hproc)
+            {
+                DWORD_PTR addr = stack[stk--];
+                BYTE derefsize = dwarf2_parse_byte(ctx);
+
+                if (derefsize == 1)
+                {
+                    unsigned char deref;
+                    if (!ReadProcessMemory(hproc, (void*)addr, &deref, sizeof(deref), NULL))
+                    {
+                        WARN("Couldn't read memory at %lx\n", addr);
+                        return loc_err_cant_read;
+                    }
+                    stack[++stk] = deref;
+                }
+                else if (derefsize == 2)
+                {
+                    unsigned short deref;
+                    if (!ReadProcessMemory(hproc, (void*)addr, &deref, sizeof(deref), NULL))
+                    {
+                        WARN("Couldn't read memory at %lx\n", addr);
+                        return loc_err_cant_read;
+                    }
+                    stack[++stk] = deref;
+                }
+                else if (derefsize == 4)
+                {
+                    unsigned int deref;
+                    if (!ReadProcessMemory(hproc, (void*)addr, &deref, sizeof(deref), NULL))
+                    {
+                        WARN("Couldn't read memory at %lx\n", addr);
+                        return loc_err_cant_read;
+                    }
+                    stack[++stk] = deref;
+                }
+                else if (derefsize == 8 && ctx->word_size >= derefsize)
+                {
+                    DWORD64 deref;
+                    if (!ReadProcessMemory(hproc, (void*)addr, &deref, sizeof(deref), NULL))
+                    {
+                        WARN("Couldn't read memory at %lx\n", addr);
+                        return loc_err_cant_read;
+                    }
+                    stack[++stk] = deref;
+                }
+            }
+            else
+            {
+               loc->kind = loc_dwarf2_block;
+            }
+            break;
         default:
             if (op < DW_OP_lo_user) /* as DW_OP_hi_user is 0xFF, we don't need to test against it */
                 FIXME("Unhandled attr op: %x\n", op);
diff --git a/dlls/dbghelp/dwarf.h b/dlls/dbghelp/dwarf.h
index a590df2..e1247fb 100644
--- a/dlls/dbghelp/dwarf.h
+++ b/dlls/dbghelp/dwarf.h
@@ -400,6 +400,21 @@ enum dwarf_calling_convention
 #define DW_CC_lo_user 0x40
 #define DW_CC_hi_user 0xff
 
+#define DW_EH_PE_native                 0x00
+#define DW_EH_PE_leb128                 0x01
+#define DW_EH_PE_data2                  0x02
+#define DW_EH_PE_data4                  0x03
+#define DW_EH_PE_data8                  0x04
+#define DW_EH_PE_signed                 0x08
+#define DW_EH_PE_abs                    0x00
+#define DW_EH_PE_pcrel                  0x10
+#define DW_EH_PE_textrel                0x20
+#define DW_EH_PE_datarel                0x30
+#define DW_EH_PE_funcrel                0x40
+#define DW_EH_PE_aligned                0x50
+#define DW_EH_PE_indirect               0x80
+#define DW_EH_PE_omit                   0xff
+
 #define DW_LNS_extended_op              0x00
 #define DW_LNS_copy                     0x01
 #define DW_LNS_advance_pc               0x02
-- 

Best Regards, André Hentschel



More information about the wine-patches mailing list