dbghelp: Dwarf & debug info entries.
- now loading the debug info entries into specific structures - this will help writing new functions - this will allow handling of forward references
This commit is contained in:
parent
b51cd5750f
commit
c571b8506e
|
@ -113,9 +113,26 @@ typedef struct dwarf2_abbrev_entry_s
|
||||||
dwarf2_abbrev_entry_attr_t* attrs;
|
dwarf2_abbrev_entry_attr_t* attrs;
|
||||||
} dwarf2_abbrev_entry_t;
|
} dwarf2_abbrev_entry_t;
|
||||||
|
|
||||||
|
union attribute
|
||||||
|
{
|
||||||
|
unsigned long uvalue;
|
||||||
|
long svalue;
|
||||||
|
const char* string;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct dwarf2_debug_info_s
|
||||||
|
{
|
||||||
|
unsigned long offset;
|
||||||
|
const dwarf2_abbrev_entry_t*abbrev;
|
||||||
|
struct symt* symt;
|
||||||
|
union attribute* attributes;
|
||||||
|
struct vector children;
|
||||||
|
} dwarf2_debug_info_t;
|
||||||
|
|
||||||
typedef struct dwarf2_parse_context_s {
|
typedef struct dwarf2_parse_context_s {
|
||||||
struct pool pool;
|
struct pool pool;
|
||||||
struct sparse_array abbrev_table;
|
struct sparse_array abbrev_table;
|
||||||
|
struct sparse_array debug_info_table;
|
||||||
const unsigned char* data_stream;
|
const unsigned char* data_stream;
|
||||||
const unsigned char* data;
|
const unsigned char* data;
|
||||||
const unsigned char* start_data;
|
const unsigned char* start_data;
|
||||||
|
@ -191,6 +208,22 @@ static long dwarf2_leb128_as_signed(dwarf2_parse_context_t* ctx)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned long dwarf2_parse_addr(dwarf2_parse_context_t* ctx)
|
||||||
|
{
|
||||||
|
unsigned long ret;
|
||||||
|
|
||||||
|
switch (ctx->word_size)
|
||||||
|
{
|
||||||
|
case 4:
|
||||||
|
ret = dwarf2_parse_u4(ctx);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
FIXME("Unsupported Word Size %u\n", ctx->word_size);
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static const char* dwarf2_debug_ctx(dwarf2_parse_context_t* ctx)
|
static const char* dwarf2_debug_ctx(dwarf2_parse_context_t* ctx)
|
||||||
{
|
{
|
||||||
/*return wine_dbg_sprintf("ctx(0x%x,%u)", ctx->data - ctx->start_data, ctx->level); */
|
/*return wine_dbg_sprintf("ctx(0x%x,%u)", ctx->data - ctx->start_data, ctx->level); */
|
||||||
|
@ -471,6 +504,116 @@ static void dwarf2_parse_attr(dwarf2_abbrev_entry_attr_t* attr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dwarf2_parse_attr_into_di(dwarf2_parse_context_t* ctx,
|
||||||
|
const dwarf2_abbrev_entry_attr_t* abbrev_attr,
|
||||||
|
union attribute* attr)
|
||||||
|
|
||||||
|
{
|
||||||
|
TRACE("(attr:0x%lx,form:0x%lx)\n", abbrev_attr->attribute, abbrev_attr->form);
|
||||||
|
|
||||||
|
switch (abbrev_attr->form) {
|
||||||
|
case DW_FORM_ref_addr:
|
||||||
|
case DW_FORM_addr:
|
||||||
|
attr->uvalue = dwarf2_parse_addr(ctx);
|
||||||
|
TRACE("addr<0x%lx>\n", attr->uvalue);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DW_FORM_flag:
|
||||||
|
attr->uvalue = dwarf2_parse_byte(ctx);
|
||||||
|
TRACE("flag<0x%lx>\n", attr->uvalue);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DW_FORM_data1:
|
||||||
|
attr->uvalue = dwarf2_parse_byte(ctx);
|
||||||
|
TRACE("data1<%lu>\n", attr->uvalue);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DW_FORM_data2:
|
||||||
|
attr->uvalue = dwarf2_parse_u2(ctx);
|
||||||
|
TRACE("data2<%lu>\n", attr->uvalue);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DW_FORM_data4:
|
||||||
|
attr->uvalue = dwarf2_parse_u4(ctx);
|
||||||
|
TRACE("data4<%lu>\n", attr->uvalue);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DW_FORM_data8:
|
||||||
|
FIXME("Unhandled 64bits support\n");
|
||||||
|
ctx->data += 8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DW_FORM_ref1:
|
||||||
|
attr->uvalue = ctx->offset + dwarf2_parse_byte(ctx);
|
||||||
|
TRACE("ref1<0x%lx>\n", attr->uvalue);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DW_FORM_ref2:
|
||||||
|
attr->uvalue = ctx->offset + dwarf2_parse_u2(ctx);
|
||||||
|
TRACE("ref2<0x%lx>\n", attr->uvalue);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DW_FORM_ref4:
|
||||||
|
attr->uvalue = ctx->offset + dwarf2_parse_u4(ctx);
|
||||||
|
TRACE("ref4<0x%lx>\n", attr->uvalue);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DW_FORM_ref8:
|
||||||
|
FIXME("Unhandled 64 bit support\n");
|
||||||
|
ctx->data += 8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DW_FORM_sdata:
|
||||||
|
attr->svalue = dwarf2_leb128_as_signed(ctx);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DW_FORM_ref_udata:
|
||||||
|
attr->uvalue = dwarf2_leb128_as_unsigned(ctx);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DW_FORM_udata:
|
||||||
|
attr->uvalue = dwarf2_leb128_as_unsigned(ctx);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DW_FORM_string:
|
||||||
|
attr->string = (const char*)ctx->data;
|
||||||
|
ctx->data += strlen(attr->string) + 1;
|
||||||
|
TRACE("string<%s>\n", attr->string);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DW_FORM_strp:
|
||||||
|
{
|
||||||
|
unsigned long offset = dwarf2_parse_u4(ctx);
|
||||||
|
attr->string = (const char*)ctx->str_section + offset;
|
||||||
|
}
|
||||||
|
TRACE("strp<%s>\n", attr->string);
|
||||||
|
break;
|
||||||
|
case DW_FORM_block:
|
||||||
|
attr->uvalue = dwarf2_leb128_as_unsigned(ctx);
|
||||||
|
ctx->data += attr->uvalue;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DW_FORM_block1:
|
||||||
|
attr->uvalue = dwarf2_parse_byte(ctx);
|
||||||
|
ctx->data += attr->uvalue;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DW_FORM_block2:
|
||||||
|
attr->uvalue = dwarf2_parse_u2(ctx);
|
||||||
|
ctx->data += attr->uvalue;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DW_FORM_block4:
|
||||||
|
attr->uvalue = dwarf2_parse_u4(ctx);
|
||||||
|
ctx->data += attr->uvalue;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
FIXME("Unhandled attribute form %lx\n", abbrev_attr->form);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static struct symt* dwarf2_find_symt_by_ref(struct module* module, unsigned long ref)
|
static struct symt* dwarf2_find_symt_by_ref(struct module* module, unsigned long ref)
|
||||||
{
|
{
|
||||||
WARN("want ref<0x%lx>\n", ref);
|
WARN("want ref<0x%lx>\n", ref);
|
||||||
|
@ -483,6 +626,69 @@ static struct symt* dwarf2_add_symt_ref(struct module* module, unsigned long ref
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* dwarf2_read_one_debug_info
|
||||||
|
*
|
||||||
|
* Loads into memory one debug info entry, and recursively its children (if any)
|
||||||
|
*/
|
||||||
|
static BOOL dwarf2_read_one_debug_info(dwarf2_parse_context_t* ctx,
|
||||||
|
dwarf2_debug_info_t** pdi)
|
||||||
|
{
|
||||||
|
const dwarf2_abbrev_entry_t*abbrev;
|
||||||
|
unsigned long entry_code;
|
||||||
|
unsigned long offset;
|
||||||
|
dwarf2_debug_info_t* di;
|
||||||
|
dwarf2_debug_info_t* child;
|
||||||
|
dwarf2_debug_info_t** where;
|
||||||
|
dwarf2_abbrev_entry_attr_t* attr;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
offset = ctx->data - ctx->data_stream;
|
||||||
|
entry_code = dwarf2_leb128_as_unsigned(ctx);
|
||||||
|
TRACE("found entry_code %lu at 0x%lx\n", entry_code, offset);
|
||||||
|
if (!entry_code)
|
||||||
|
{
|
||||||
|
*pdi = NULL;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
abbrev = dwarf2_abbrev_table_find_entry(&ctx->abbrev_table, entry_code);
|
||||||
|
if (!abbrev)
|
||||||
|
{
|
||||||
|
WARN("Cannot find abbrev entry for %lu at 0x%lx\n", entry_code, offset);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
di = sparse_array_add(&ctx->debug_info_table, offset, &ctx->pool);
|
||||||
|
if (!di) return FALSE;
|
||||||
|
di->offset = offset;
|
||||||
|
di->abbrev = abbrev;
|
||||||
|
di->symt = NULL;
|
||||||
|
|
||||||
|
if (abbrev->num_attr)
|
||||||
|
{
|
||||||
|
di->attributes = pool_alloc(&ctx->pool,
|
||||||
|
abbrev->num_attr * sizeof(union attribute));
|
||||||
|
for (i = 0, attr = abbrev->attrs; attr; i++, attr = attr->next)
|
||||||
|
{
|
||||||
|
dwarf2_parse_attr_into_di(ctx, attr, &di->attributes[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else di->attributes = NULL;
|
||||||
|
if (abbrev->have_child)
|
||||||
|
{
|
||||||
|
vector_init(&di->children, sizeof(dwarf2_debug_info_t*), 16);
|
||||||
|
while (ctx->data < ctx->end_data)
|
||||||
|
{
|
||||||
|
if (!dwarf2_read_one_debug_info(ctx, &child)) return FALSE;
|
||||||
|
if (!child) break;
|
||||||
|
where = vector_add(&di->children, &ctx->pool);
|
||||||
|
if (!where) return FALSE;
|
||||||
|
*where = child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*pdi = di;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static struct symt_basic* dwarf2_parse_base_type(struct module* module, dwarf2_abbrev_entry_t* entry, dwarf2_parse_context_t* ctx)
|
static struct symt_basic* dwarf2_parse_base_type(struct module* module, dwarf2_abbrev_entry_t* entry, dwarf2_parse_context_t* ctx)
|
||||||
{
|
{
|
||||||
struct symt_basic* symt = NULL;
|
struct symt_basic* symt = NULL;
|
||||||
|
@ -1694,6 +1900,7 @@ BOOL dwarf2_parse(struct module* module, unsigned long load_offset,
|
||||||
dwarf2_parse_context_t ctx;
|
dwarf2_parse_context_t ctx;
|
||||||
dwarf2_parse_context_t abbrev_ctx;
|
dwarf2_parse_context_t abbrev_ctx;
|
||||||
struct symt_compiland* compiland = NULL;
|
struct symt_compiland* compiland = NULL;
|
||||||
|
dwarf2_debug_info_t* di;
|
||||||
|
|
||||||
comp_unit_stream = (const dwarf2_comp_unit_stream_t*) comp_unit_cursor;
|
comp_unit_stream = (const dwarf2_comp_unit_stream_t*) comp_unit_cursor;
|
||||||
|
|
||||||
|
@ -1730,6 +1937,10 @@ BOOL dwarf2_parse(struct module* module, unsigned long load_offset,
|
||||||
abbrev_ctx.str_section = str;
|
abbrev_ctx.str_section = str;
|
||||||
dwarf2_parse_abbrev_set(&abbrev_ctx, &ctx.abbrev_table, &ctx.pool);
|
dwarf2_parse_abbrev_set(&abbrev_ctx, &ctx.abbrev_table, &ctx.pool);
|
||||||
|
|
||||||
|
sparse_array_init(&ctx.debug_info_table, sizeof(dwarf2_debug_info_t), 128);
|
||||||
|
dwarf2_read_one_debug_info(&ctx, &di);
|
||||||
|
ctx.data = ctx.start_data; /* FIXME */
|
||||||
|
|
||||||
while (ctx.data < ctx.end_data) {
|
while (ctx.data < ctx.end_data) {
|
||||||
const dwarf2_abbrev_entry_t* entry = NULL;
|
const dwarf2_abbrev_entry_t* entry = NULL;
|
||||||
unsigned long entry_code;
|
unsigned long entry_code;
|
||||||
|
|
Loading…
Reference in New Issue