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