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