Hi, On Monday 10 October 2005 09:06, Raphael wrote: > Changelog: > - begin of dwarf debug lines parsing > - better robustness > - support of unamed syms > - better traces > > TODO: > - find a clean way to handle forward declarations > - debug lines parsing >
as Eric wanted: without type.c modification I'll try to improve it for next patch Regards, Raphael
Index: dbghelp_private.h =================================================================== RCS file: /home/wine/wine/dlls/dbghelp/dbghelp_private.h,v retrieving revision 1.16 diff -u -r1.16 dbghelp_private.h --- dbghelp_private.h 17 May 2005 14:32:55 -0000 1.16 +++ dbghelp_private.h 13 Oct 2005 21:51:16 -0000 @@ -360,7 +360,8 @@ extern BOOL dwarf2_parse(struct module* module, unsigned long load_offset, const unsigned char* debug, unsigned int debug_size, const unsigned char* abbrev, unsigned int abbrev_size, - const unsigned char* str, unsigned int str_sz); + const unsigned char* str, unsigned int str_sz, + const unsigned char* lines, unsigned int lines_sz); /* symbol.c */ extern const char* symt_get_name(const struct symt* sym); @@ -436,10 +437,10 @@ extern BOOL symt_set_udt_size(struct module* module, struct symt_udt* type, unsigned size); extern BOOL symt_add_udt_element(struct module* module, - struct symt_udt* udt_type, - const char* name, - struct symt* elt_type, unsigned offset, - unsigned size); + struct symt_udt* udt_type, + const char* name, + struct symt* elt_type, unsigned offset, + unsigned size); extern struct symt_enum* symt_new_enum(struct module* module, const char* typename); extern BOOL symt_add_enum_element(struct module* module, @@ -452,8 +453,8 @@ symt_new_function_signature(struct module* module, struct symt* ret_type); extern BOOL symt_add_function_signature_parameter(struct module* module, - struct symt_function_signature* sig, - struct symt* param); + struct symt_function_signature* sig, + struct symt* param); extern struct symt_pointer* symt_new_pointer(struct module* module, struct symt* ref_type); Index: dwarf.c =================================================================== RCS file: /home/wine/wine/dlls/dbghelp/dwarf.c,v retrieving revision 1.7 diff -u -r1.7 dwarf.c --- dwarf.c 27 Jun 2005 09:53:47 -0000 1.7 +++ dwarf.c 13 Oct 2005 21:51:18 -0000 @@ -90,6 +90,10 @@ * example of projects who do dwarf2 parsing: * http://www.x86-64.org/cgi-bin/cvsweb.cgi/binutils.dead/binutils/readelf.c?rev=1.1.1.2 * http://elis.ugent.be/diota/log/ltrace_elf.c + * + * dwarf3: + * http://cvs.sourceforge.net/viewcvs.py/linux-vax/tools/src/binutils/readelf.c?rev=2.10.0.2&view=markup + * http://cvs.sourceforge.net/viewcvs.py/linux-vax/tools/src/include/elf/dwarf2.h?rev=2.10.0.2&view=auto */ typedef struct { @@ -107,12 +111,23 @@ } dwarf2_comp_unit_t; typedef struct { + unsigned char length[4]; + unsigned char version[2]; + unsigned char prologue_length[4]; + unsigned char min_insn_length[1]; + unsigned char default_is_stmt[1]; + unsigned char line_base[1]; + unsigned char line_range[1]; + unsigned char opcode_base[1]; +} dwarf2_line_info_stream_t; + +typedef struct { unsigned int length; unsigned short version; unsigned int prologue_length; unsigned char min_insn_length; unsigned char default_is_stmt; - int line_base; + char line_base; unsigned char line_range; unsigned char opcode_base; } dwarf2_line_info_t; @@ -166,11 +181,20 @@ DW_TAG_variant_part = 0x33, DW_TAG_variable = 0x34, DW_TAG_volatile_type = 0x35, + /* DWARF 3 */ + DW_TAG_dwarf_procedure = 0x36, + DW_TAG_restrict_type = 0x37, + DW_TAG_interface_type = 0x38, + DW_TAG_namespace = 0x39, + DW_TAG_imported_module = 0x3a, + DW_TAG_unspecified_type = 0x3b, + DW_TAG_partial_unit = 0x3c, + DW_TAG_imported_unit = 0x3d, /** extensions */ DW_TAG_MIPS_loop = 0x4081, DW_TAG_format_label = 0x4101, DW_TAG_function_template = 0x4102, - DW_TAG_class_template = 0x4103 + DW_TAG_class_template = 0x4103 } dwarf_tag_t; typedef enum dwarf_attribute_e { @@ -236,8 +260,19 @@ DW_AT_variable_parameter = 0x4b, DW_AT_virtuality = 0x4c, DW_AT_vtable_elem_location = 0x4d, - + /* DWARF 3 */ + DW_AT_allocated = 0x4e, + DW_AT_associated = 0x4f, + DW_AT_data_location = 0x50, + DW_AT_stride = 0x51, + DW_AT_entry_pc = 0x52, + DW_AT_use_UTF8 = 0x53, + DW_AT_extension = 0x54, DW_AT_ranges = 0x55, + DW_AT_trampoline = 0x56, + DW_AT_call_column = 0x57, + DW_AT_call_file = 0x58, + DW_AT_call_line = 0x59, /* extensions */ DW_AT_MIPS_fde = 0x2001, DW_AT_MIPS_loop_begin = 0x2002, @@ -255,7 +290,8 @@ DW_AT_mac_info = 0x2103, DW_AT_src_coords = 0x2104, DW_AT_body_begin = 0x2105, - DW_AT_body_end = 0x2106 + DW_AT_body_end = 0x2106, + DW_AT_GNU_vector = 0x2107 } dwarf_attribute_t; typedef enum dwarf_form_e { @@ -292,7 +328,9 @@ DW_ATE_signed = 0x5, DW_ATE_signed_char = 0x6, DW_ATE_unsigned = 0x7, - DW_ATE_unsigned_char = 0x8 + DW_ATE_unsigned_char = 0x8, + /* DWARF 3 */ + DW_ATE_imaginary_float = 0x9 } dwarf_type_t; typedef enum dwarf_operation_e { @@ -447,6 +485,123 @@ * Parsers */ +typedef struct ref_hash_table_elt_forwards_s { + struct symt** fw; + struct ref_hash_table_elt_forwards_s* next; +} ref_hash_table_elt_forwards_t; + +typedef struct ref_hash_table_elt_s { + struct symt* sym; + unsigned long ref; + ref_hash_table_elt_forwards_t* fws; + struct ref_hash_table_elt_s* next; +} ref_hash_table_elt_t; + +typedef struct ref_hash_table_s { + unsigned num_buckets; + ref_hash_table_elt_t** buckets; +} ref_hash_table_t; + +unsigned ref_hash_table_hash(unsigned long ref, unsigned num_buckets) +{ + unsigned hash = 0; + hash = ref % num_buckets; + return 0; +} + +int ref_hash_table_cmp(unsigned long ref1, unsigned long ref2) +{ + return ref1 != ref2; +} + +void ref_hash_table_init(struct pool* pool, ref_hash_table_t* ht, unsigned num_buckets) +{ + ht->buckets = pool_alloc(pool, num_buckets * sizeof(ref_hash_table_elt_t*)); + assert( NULL != ht->buckets ); + ht->num_buckets = num_buckets; + memset(ht->buckets, 0, num_buckets * sizeof(ref_hash_table_elt_t*)); +} + +void ref_hash_table_destroy(struct pool* pool, ref_hash_table_t* ht) +{ + ht->num_buckets = 0; + ht->buckets = NULL; +} + +void ref_hash_table_insert_fw(struct pool* pool, ref_hash_table_t* ht, unsigned long ref, struct symt** fw) +{ + unsigned hash = ref_hash_table_hash(ref, ht->num_buckets); + ref_hash_table_elt_t** p = NULL; + ref_hash_table_elt_forwards_t* fw_elt = NULL; + + fw_elt = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ref_hash_table_elt_forwards_t)); + fw_elt->fw = fw; + fw_elt->next = NULL; + + for (p = &ht->buckets[hash]; NULL != *p; p = &((*p)->next)) { + if (!ref_hash_table_cmp((*p)->ref, ref)) { + assert( NULL == (*p)->sym ); + fw_elt->next = (*p)->fws; + (*p)->fws = fw_elt->next; + return ; + } + } + *p = pool_alloc(pool, sizeof(ref_hash_table_elt_t)); + assert( NULL != *p ); + (*p)->ref = ref; + (*p)->next = NULL; + (*p)->fws = fw_elt; + (*p)->sym = NULL; +} + +struct symt* ref_hash_table_insert(struct pool* pool, ref_hash_table_t* ht, unsigned long ref, struct symt* sym) +{ + unsigned hash = ref_hash_table_hash(ref, ht->num_buckets); + ref_hash_table_elt_t** p = NULL; + struct symt* ret = NULL; + + for (p = &ht->buckets[hash]; NULL != *p; p = &((*p)->next)) { + if (!ref_hash_table_cmp((*p)->ref, ref)) { + ret = (*p)->sym; + (*p)->sym = sym; + if (NULL != (*p)->fws) { + ref_hash_table_elt_forwards_t* it = NULL; + ref_hash_table_elt_forwards_t* prev_it = NULL; + assert( NULL == ret ); + assert( NULL != sym ); + /** resolve forward as we are now adding the long waiting symt ;) */ + it = (*p)->fws; + (*p)->fws = NULL; + while (NULL != it) { + *(it->fw) = sym; + prev_it = it; + it = it->next; + HeapFree(GetProcessHeap(), 0, prev_it); + } + } + return ret; + } + } + *p = pool_alloc(pool, sizeof(ref_hash_table_elt_t)); + assert( NULL != *p ); + (*p)->ref = ref; + (*p)->next = NULL; + (*p)->fws = NULL; + (*p)->sym = sym; + return ret; +} + +struct symt* ref_hash_table_find(ref_hash_table_t* ht, unsigned long ref) +{ + unsigned hash = ref_hash_table_hash(ref, ht->num_buckets); + ref_hash_table_elt_t* p = NULL; + + for (p = ht->buckets[hash]; NULL != p; p = p->next) { + if (!ref_hash_table_cmp(p->ref, ref)) return p->sym; + } + return NULL; +} + typedef struct dwarf2_abbrev_entry_attr_s { unsigned long attribute; unsigned long form; @@ -473,6 +628,7 @@ const unsigned char* start_data; const unsigned char* end_data; const unsigned char* str_section; + ref_hash_table_t* ht_ref; unsigned long offset; unsigned char word_size; unsigned char level; @@ -696,6 +852,7 @@ break; default: ERR("Unsupported string format 0x%lx for attr 0x%lx\n", attr->form, attr->attribute); + assert( 0 ); } return ret; } @@ -744,6 +901,10 @@ */ ctx->data += 8; break; + + default: + FIXME("Unsupported ref format 0x%lx support\n", attr->form); + assert( 0 ); } return uvalue; } @@ -773,6 +934,10 @@ FIXME("Unsupported 64bits support\n"); ctx->data += 8; break; + + default: + FIXME("Unsupported data format 0x%lx support\n", attr->form); + assert( 0 ); } return uvalue; } @@ -839,7 +1004,7 @@ case DW_FORM_string: case DW_FORM_strp: str = dwarf2_parse_attr_as_string(attr, ctx); - TRACE("string<%s>\n", str); + TRACE("string<%p>\n", str); break; case DW_FORM_block: @@ -867,18 +1032,44 @@ } } -static struct symt* dwarf2_find_symt_by_ref(struct module* module, unsigned long ref) +static const char* dwarf2_clean_name(const char* name) { - TRACE("want ref<0x%lx>\n", ref); - return NULL; + static unsigned cnt = 0; + static char buffer[255]; + if (NULL == name) { + /*name = "unamed";*/ + ++cnt; + snprintf(buffer, sizeof(buffer), "unamed_%u", cnt); + return buffer; + } + return name; } -static struct symt* dwarf2_add_symt_ref(struct module* module, unsigned long ref, struct symt* symt) +static struct symt* dwarf2_find_symt_by_ref(struct module* module, dwarf2_parse_context_t* ctx, unsigned long ref) { - if (NULL != symt) return NULL; - return NULL; + struct symt* ret = NULL; + ret = ref_hash_table_find(ctx->ht_ref, ref); + TRACE("want ref<0x%lx> found %p\n", ref, ret); + return ret; +} + +static struct symt* dwarf2_add_symt_ref(struct module* module, dwarf2_parse_context_t* ctx, unsigned long ref, struct symt* symt) +{ + struct symt* ret = NULL; + if (NULL == symt) return NULL; + ret = ref_hash_table_insert(&module->pool, ctx->ht_ref, ref, symt); + TRACE("(hash:%p) ref<0x%lx> symt(%p) -> %p\n", ctx->ht_ref, ref, symt, ret); + return ret; } +static void dwarf2_add_symt_ref_fw(struct module* module, dwarf2_parse_context_t* ctx, unsigned long ref, struct symt** fw) +{ + if (NULL == fw) return ; + ref_hash_table_insert_fw(&module->pool, ctx->ht_ref, ref, fw); + TRACE("(hash:%p) ref<0x%lx> fw(%p)\n", ctx->ht_ref, ref, fw); +} + + 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; @@ -935,6 +1126,7 @@ struct symt* ref_type = NULL; const char* name = NULL; dwarf2_abbrev_entry_attr_t* attr = NULL; + unsigned long ref_ref_type = 0; TRACE("%s, for %lu\n", dwarf2_debug_ctx(ctx), entry->entry_code); @@ -945,10 +1137,8 @@ TRACE("found name %s\n", name); break; case DW_AT_type: - { - unsigned long ref = dwarf2_parse_attr_as_ref(attr, ctx); - ref_type = dwarf2_find_symt_by_ref(module, ref); - } + ref_ref_type = dwarf2_parse_attr_as_ref(attr, ctx); + ref_type = dwarf2_find_symt_by_ref(module, ctx, ref_ref_type); break; case DW_AT_decl_file: case DW_AT_decl_line: @@ -959,8 +1149,10 @@ dwarf2_parse_attr(attr, ctx); } } - if (NULL != name) { - symt = symt_new_typedef(module, ref_type, name); + name = dwarf2_clean_name(name); + symt = symt_new_typedef(module, ref_type, name); + if (NULL == ref_type) { + dwarf2_add_symt_ref_fw(module, ctx, ref_ref_type, &(symt->type)); } if (entry->have_child) { @@ -975,6 +1167,7 @@ struct symt* ref_type = NULL; unsigned size = 0; dwarf2_abbrev_entry_attr_t* attr = NULL; + unsigned long ref_ref_type = 0; TRACE("%s, for %lu\n", dwarf2_debug_ctx(ctx), entry->entry_code); @@ -984,10 +1177,8 @@ size = dwarf2_parse_byte(ctx); break; case DW_AT_type: - { - unsigned long ref = dwarf2_parse_attr_as_ref(attr, ctx); - ref_type = dwarf2_find_symt_by_ref(module, ref); - } + ref_ref_type = dwarf2_parse_attr_as_ref(attr, ctx); + ref_type = dwarf2_find_symt_by_ref(module, ctx, ref_ref_type); break; default: TRACE("Unhandled attr at %s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_attr(attr)); @@ -995,6 +1186,9 @@ } } symt = symt_new_pointer(module, ref_type); + if (NULL == ref_type) { + dwarf2_add_symt_ref_fw(module, ctx, ref_ref_type, &(symt->pointsto)); + } if (entry->have_child) { FIXME("Unsupported children\n"); @@ -1008,16 +1202,18 @@ unsigned max = 0; struct symt* idx_type = NULL; dwarf2_abbrev_entry_attr_t* attr = NULL; + unsigned long ref_ref_type = 0; TRACE("%s, for %lu\n", dwarf2_debug_ctx(ctx), entry->entry_code); for (attr = entry->attrs; NULL != attr; attr = attr->next) { switch (attr->attribute) { case DW_AT_type: - { - unsigned long ref = dwarf2_parse_attr_as_ref(attr, ctx); - idx_type = dwarf2_find_symt_by_ref(module, ref); - /** check if idx_type is a basic_type integer */ + ref_ref_type = dwarf2_parse_attr_as_ref(attr, ctx); + idx_type = dwarf2_find_symt_by_ref(module, ctx, ref_ref_type); + /** check if idx_type is a basic_type integer */ + if (NULL == idx_type) { + /*dwarf2_add_symt_ref_fw(module, ctx, ref_ref_type, &(symt->pointsto));*/ } break; case DW_AT_lower_bound: @@ -1056,6 +1252,7 @@ unsigned max = 0; dwarf2_abbrev_entry_attr_t* attr = NULL; unsigned long next_sibling = 0; + unsigned long ref_ref_type = 0; TRACE("%s, for %lu\n", dwarf2_debug_ctx(ctx), entry->entry_code); @@ -1065,10 +1262,8 @@ next_sibling = dwarf2_parse_attr_as_ref(attr, ctx); break; case DW_AT_type: - { - unsigned long ref = dwarf2_parse_attr_as_ref(attr, ctx); - ref_type = dwarf2_find_symt_by_ref(module, ref); - } + ref_ref_type = dwarf2_parse_attr_as_ref(attr, ctx); + ref_type = dwarf2_find_symt_by_ref(module, ctx, ref_ref_type); break; default: TRACE("Unhandled attr at %s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_attr(attr)); @@ -1077,6 +1272,9 @@ } symt = symt_new_array(module, min, max, ref_type); + if (NULL == ref_type) { + dwarf2_add_symt_ref_fw(module, ctx, ref_ref_type, &(symt->basetype)); + } if (entry->have_child) { /** any interest to not have child ? */ ++ctx->level; @@ -1088,7 +1286,7 @@ entry_ref = ctx->data - ctx->data_stream; entry_code = dwarf2_leb128_as_unsigned(ctx); - TRACE("found entry_code %lu at 0x%lx\n", entry_code, entry_ref); + TRACE("found entry_code %lu at ref<0x%lx>\n", entry_code, entry_ref); if (0 == entry_code) { break ; } @@ -1126,24 +1324,26 @@ struct symt* ref_type = NULL; dwarf2_abbrev_entry_attr_t* attr = NULL; unsigned long next_sibling = 0; + unsigned long ref_ref_type = 0; TRACE("%s, for %lu\n", dwarf2_debug_ctx(ctx), entry->entry_code); for (attr = entry->attrs; NULL != attr; attr = attr->next) { switch (attr->attribute) { case DW_AT_type: - { - unsigned long ref = dwarf2_parse_attr_as_ref(attr, ctx); - ref_type = dwarf2_find_symt_by_ref(module, ref); - } + ref_ref_type = dwarf2_parse_attr_as_ref(attr, ctx); + ref_type = dwarf2_find_symt_by_ref(module, ctx, ref_ref_type); break; default: TRACE("Unhandled attr at %s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_attr(attr)); dwarf2_parse_attr(attr, ctx); } } - FIXME("need to generate a name\n"); - symt = symt_new_typedef(module, ref_type, ""); + TRACE("need to generate a better name\n"); + symt = symt_new_typedef(module, ref_type, dwarf2_clean_name(NULL)); + if (NULL == ref_type) { + dwarf2_add_symt_ref_fw(module, ctx, ref_ref_type, &(symt->type)); + } if (entry->have_child) { FIXME("Unsupported children\n"); @@ -1161,6 +1361,7 @@ struct symt* ref_type = NULL; dwarf2_abbrev_entry_attr_t* attr = NULL; unsigned long next_sibling = 0; + unsigned long ref_ref_type = 0; TRACE("%s, for %lu\n", dwarf2_debug_ctx(ctx), entry->entry_code); @@ -1170,18 +1371,19 @@ next_sibling = dwarf2_parse_attr_as_ref(attr, ctx); break; case DW_AT_type: - { - unsigned long ref = dwarf2_parse_attr_as_ref(attr, ctx); - ref_type = dwarf2_find_symt_by_ref(module, ref); - } + ref_ref_type = dwarf2_parse_attr_as_ref(attr, ctx); + ref_type = dwarf2_find_symt_by_ref(module, ctx, ref_ref_type); break; default: TRACE("Unhandled attr at %s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_attr(attr)); dwarf2_parse_attr(attr, ctx); } } - FIXME("need to generate a name\n"); - symt = symt_new_typedef(module, ref_type, ""); + FIXME("need to generate a better name\n"); + symt = symt_new_typedef(module, ref_type, dwarf2_clean_name(NULL)); + if (NULL == ref_type) { + dwarf2_add_symt_ref_fw(module, ctx, ref_ref_type, &(symt->type)); + } if (entry->have_child) { FIXME("Unsupported children\n"); @@ -1195,12 +1397,14 @@ static void dwarf2_parse_udt_member(struct module* module, dwarf2_abbrev_entry_t* entry, dwarf2_parse_context_t* ctx, struct symt_udt* parent) { + /*struct symt_data* symt = NULL;*/ struct symt* elt_type = NULL; const char* name = NULL; unsigned long offset = 0; unsigned size = 0; dwarf2_abbrev_entry_attr_t* attr = NULL; unsigned long next_sibling = 0; + unsigned long ref_ref_type = 0; assert( NULL != parent ); @@ -1216,10 +1420,8 @@ TRACE("found name %s\n", name); break; case DW_AT_type: - { - unsigned long ref = dwarf2_parse_attr_as_ref(attr, ctx); - elt_type = dwarf2_find_symt_by_ref(module, ref); - } + ref_ref_type = dwarf2_parse_attr_as_ref(attr, ctx); + elt_type = dwarf2_find_symt_by_ref(module, ctx, ref_ref_type); break; case DW_AT_data_member_location: { @@ -1267,7 +1469,14 @@ dwarf2_parse_attr(attr, ctx); } } + name = dwarf2_clean_name(name); symt_add_udt_element(module, parent, name, elt_type, offset, size); + /* + assert( NULL != symt ); + if (NULL == elt_type) { + dwarf2_add_symt_ref_fw(module, ctx, ref_ref_type, &(symt->type)); + } + */ if (entry->have_child) { FIXME("Unsupported children\n"); @@ -1289,7 +1498,7 @@ entry_ref = ctx->data - ctx->data_stream; entry_code = dwarf2_leb128_as_unsigned(ctx); - TRACE("found entry_code %lu at 0x%lx\n", entry_code, entry_ref); + TRACE("found entry_code %lu at ref<0x%lx>\n", entry_code, entry_ref); if (0 == entry_code) { break ; } @@ -1376,7 +1585,7 @@ TRACE("found name %s\n", name); break; case DW_AT_byte_size: - size = dwarf2_parse_byte(ctx); + size = dwarf2_parse_attr_as_data(attr, ctx); break; case DW_AT_decl_file: case DW_AT_decl_line: @@ -1387,6 +1596,7 @@ dwarf2_parse_attr(attr, ctx); } } + name = dwarf2_clean_name(name); symt = symt_new_udt(module, name, size, UdtStruct); dwarf2_parse_udt_members(module, entry, ctx, symt); @@ -1427,6 +1637,7 @@ dwarf2_parse_attr(attr, ctx); } } + name = dwarf2_clean_name(name); symt = symt_new_udt(module, name, size, UdtUnion); dwarf2_parse_udt_members(module, entry, ctx, symt); @@ -1508,6 +1719,7 @@ dwarf2_parse_attr(attr, ctx); } } + name = dwarf2_clean_name(name); symt = symt_new_enum(module, name); if (entry->have_child) { /** any interest to not have child ? */ @@ -1520,7 +1732,7 @@ entry_ref = ctx->data - ctx->data_stream; entry_code = dwarf2_leb128_as_unsigned(ctx); - TRACE("found entry_code %lu at 0x%lx\n", entry_code, entry_ref); + TRACE("found entry_code %lu at ref<0x%lx>\n", entry_code, entry_ref); if (0 == entry_code) { break ; } @@ -1560,6 +1772,7 @@ dwarf2_abbrev_entry_attr_t* attr = NULL; const char* name = NULL; unsigned long next_sibling = 0; + unsigned long ref_ref_type = 0; TRACE("%s, for %lu\n", dwarf2_debug_ctx(ctx), entry->entry_code); @@ -1569,10 +1782,8 @@ next_sibling = dwarf2_parse_attr_as_ref(attr, ctx); break; case DW_AT_type: - { - unsigned long ref = dwarf2_parse_attr_as_ref(attr, ctx); - var_type = dwarf2_find_symt_by_ref(module, ref); - } + ref_ref_type = dwarf2_parse_attr_as_ref(attr, ctx); + var_type = dwarf2_find_symt_by_ref(module, ctx, ref_ref_type); break; case DW_AT_name: name = dwarf2_parse_attr_as_string(attr, ctx); @@ -1602,10 +1813,12 @@ struct symt_function_signature* sig_type, struct symt_function* func_type) { + /*struct symt** psymt = NULL;*/ struct symt* param_type = NULL; const char* name = NULL; dwarf2_abbrev_entry_attr_t* attr = NULL; unsigned long next_sibling = 0; + unsigned long ref_ref_type = 0; TRACE("%s, for %lu\n", dwarf2_debug_ctx(ctx), entry->entry_code); @@ -1615,10 +1828,8 @@ next_sibling = dwarf2_parse_attr_as_ref(attr, ctx); break; case DW_AT_type: - { - unsigned long ref = dwarf2_parse_attr_as_ref(attr, ctx); - param_type = dwarf2_find_symt_by_ref(module, ref); - } + ref_ref_type = dwarf2_parse_attr_as_ref(attr, ctx); + param_type = dwarf2_find_symt_by_ref(module, ctx, ref_ref_type); break; case DW_AT_name: name = dwarf2_parse_attr_as_string(attr, ctx); @@ -1638,6 +1849,11 @@ } if (NULL != sig_type) { symt_add_function_signature_parameter(module, sig_type, param_type); + /* + if (NULL == param_type) { + dwarf2_add_symt_ref_fw(module, ctx, ref_ref_type, psymt); + } + */ } if (entry->have_child) { @@ -1697,7 +1913,7 @@ entry_ref = ctx->data - ctx->data_stream; entry_code = dwarf2_leb128_as_unsigned(ctx); - TRACE("found entry_code %lu at 0x%lx\n", entry_code, entry_ref); + TRACE("found entry_code %lu at ref<0x%lx>\n", entry_code, entry_ref); if (0 == entry_code) { break ; } @@ -1776,7 +1992,7 @@ entry_ref = ctx->data - ctx->data_stream; entry_code = dwarf2_leb128_as_unsigned(ctx); - TRACE("found entry_code %lu at 0x%lx\n", entry_code, entry_ref); + TRACE("found entry_code %lu at ref<0x%lx>\n", entry_code, entry_ref); if (0 == entry_code) { break ; } @@ -1826,7 +2042,7 @@ entry_ref = ctx->data - ctx->data_stream; entry_code = dwarf2_leb128_as_unsigned(ctx); - TRACE("found entry_code %lu at 0x%lx\n", entry_code, entry_ref); + TRACE("found entry_code %lu at ref<0x%lx>\n", entry_code, entry_ref); if (0 == entry_code) { break ; } @@ -1876,6 +2092,7 @@ unsigned char decl_line = 0; dwarf2_abbrev_entry_attr_t* attr = NULL; unsigned long next_sibling = 0; + unsigned long ref_ref_type = 0; TRACE("%s, for %lu\n", dwarf2_debug_ctx(ctx), entry->entry_code); @@ -1897,10 +2114,8 @@ TRACE("found name %s\n", name); break; case DW_AT_type: - { - unsigned long ref = dwarf2_parse_attr_as_ref(attr, ctx); - ret_type = dwarf2_find_symt_by_ref(module, ref); - } + ref_ref_type = dwarf2_parse_attr_as_ref(attr, ctx); + ret_type = dwarf2_find_symt_by_ref(module, ctx, ref_ref_type); break; case DW_AT_declaration: is_decl = dwarf2_parse_byte(ctx); @@ -1922,8 +2137,13 @@ } } sig_type = symt_new_function_signature(module, ret_type); + assert( NULL != sig_type ); + if (NULL == ret_type) { + dwarf2_add_symt_ref_fw(module, ctx, ref_ref_type, &(sig_type->rettype)); + } if (!is_decl) { func_type = symt_new_function(module, compiland, name, addr, size, &sig_type->symt); + assert( NULL != func_type ); if (low_pc && high_pc) { symt_add_function_point(module, func_type, SymTagFuncDebugStart, low_pc, NULL); symt_add_function_point(module, func_type, SymTagFuncDebugEnd, high_pc, NULL); @@ -1953,7 +2173,7 @@ entry_ref = ctx->data - ctx->data_stream; entry_code = dwarf2_leb128_as_unsigned(ctx); - TRACE("found entry_code %lu at 0x%lx\n", entry_code, entry_ref); + TRACE("found entry_code %lu at ref<0x%lx>\n", entry_code, entry_ref); if (0 == entry_code) { break ; } @@ -1965,67 +2185,67 @@ case DW_TAG_typedef: { struct symt_typedef* symt = dwarf2_parse_typedef(module, entry, ctx); - dwarf2_add_symt_ref(module, entry_ref, &symt->symt); + dwarf2_add_symt_ref(module, ctx, entry_ref, &symt->symt); } break; case DW_TAG_base_type: { struct symt_basic* symt = dwarf2_parse_base_type(module, entry, ctx); - dwarf2_add_symt_ref(module, entry_ref, &symt->symt); + dwarf2_add_symt_ref(module, ctx, entry_ref, &symt->symt); } break; case DW_TAG_pointer_type: { struct symt_pointer* symt = dwarf2_parse_pointer_type(module, entry, ctx); - dwarf2_add_symt_ref(module, entry_ref, &symt->symt); + dwarf2_add_symt_ref(module, ctx, entry_ref, &symt->symt); } break; case DW_TAG_class_type: { struct symt_udt* symt = dwarf2_parse_class_type(module, entry, ctx); - if (NULL != symt) dwarf2_add_symt_ref(module, entry_ref, &symt->symt); + if (NULL != symt) dwarf2_add_symt_ref(module, ctx, entry_ref, &symt->symt); } break; case DW_TAG_structure_type: { struct symt_udt* symt = dwarf2_parse_struct_type(module, entry, ctx); - if (NULL != symt) dwarf2_add_symt_ref(module, entry_ref, &symt->symt); + if (NULL != symt) dwarf2_add_symt_ref(module, ctx, entry_ref, &symt->symt); } break; case DW_TAG_union_type: { struct symt_udt* symt = dwarf2_parse_union_type(module, entry, ctx); - if (NULL != symt) dwarf2_add_symt_ref(module, entry_ref, &symt->symt); + if (NULL != symt) dwarf2_add_symt_ref(module, ctx, entry_ref, &symt->symt); } break; case DW_TAG_array_type: { struct symt_array* symt = dwarf2_parse_array_type(module, entry, ctx); - dwarf2_add_symt_ref(module, entry_ref, &symt->symt); + dwarf2_add_symt_ref(module, ctx, entry_ref, &symt->symt); } break; case DW_TAG_const_type: { struct symt_typedef* symt = dwarf2_parse_const_type(module, entry, ctx); - dwarf2_add_symt_ref(module, entry_ref, &symt->symt); + dwarf2_add_symt_ref(module, ctx, entry_ref, &symt->symt); } break; case DW_TAG_reference_type: { struct symt_typedef* symt = dwarf2_parse_reference_type(module, entry, ctx); - dwarf2_add_symt_ref(module, entry_ref, &symt->symt); + dwarf2_add_symt_ref(module, ctx, entry_ref, &symt->symt); } break; case DW_TAG_enumeration_type: { struct symt_enum* symt = dwarf2_parse_enumeration_type(module, entry, ctx); - dwarf2_add_symt_ref(module, entry_ref, &symt->symt); + dwarf2_add_symt_ref(module, ctx, entry_ref, &symt->symt); } break; case DW_TAG_subprogram: { struct symt_function* symt = dwarf2_parse_subprogram(module, entry, ctx, compiland); - if (NULL != symt) dwarf2_add_symt_ref(module, entry_ref, &symt->symt); + if (NULL != symt) dwarf2_add_symt_ref(module, ctx, entry_ref, &symt->symt); } break; @@ -2075,14 +2295,81 @@ return compiland; } +/** + * Machine State Registers for DW line parsing + */ +typedef struct dwarf2_state_machine_regs_s { + unsigned long address; + unsigned int file; + unsigned int line; + unsigned int column; + unsigned char is_stmt; /** BOOL */ + unsigned char basic_block; /** BOOL */ + unsigned char end_sequence; /** BOOL */ +} dwarf2_state_machine_regs_t; + +static void dwarf2_reset_sm_regs(dwarf2_state_machine_regs_t* regs, int is_stmt) +{ + regs->address = 0; + regs->file = 1; + regs->line = 1; + regs->column = 0; + regs->is_stmt = is_stmt; + regs->basic_block = 0; + regs->end_sequence = 0; +} + +BOOL dwarf2_parse_lines(struct module* module, dwarf2_parse_context_t* ctx) +{ + dwarf2_state_machine_regs_t sm_regs; + const unsigned char* end_seq = NULL; + const unsigned char* std_opcodes = NULL; + + /** TO BE DONE */ + return FALSE; + + while (ctx->data < ctx->end_data) { + dwarf2_line_info_stream_t* line_info_stream; + dwarf2_line_info_t line_info; + + line_info_stream = (dwarf2_line_info_stream_t*) ctx->data; + + line_info.length = *(unsigned long*) line_info_stream->length; + line_info.version = *(unsigned short*) line_info_stream->version; + line_info.prologue_length = *(unsigned long*) line_info_stream->prologue_length; + line_info.min_insn_length = *(unsigned char*) line_info_stream->min_insn_length; + line_info.default_is_stmt = *(unsigned char*) line_info_stream->default_is_stmt; + line_info.line_base = *(unsigned char*) line_info_stream->line_base; + line_info.line_range = *(unsigned char*) line_info_stream->line_range; + line_info.opcode_base = *(unsigned char*) line_info_stream->opcode_base; + + if (2 != line_info.version) { + WARN("%u DWARF version unsupported. Wine dbghelp only support DWARF 2.\n", line_info.version); + break ; + } + + + dwarf2_reset_sm_regs(&sm_regs, line_info.default_is_stmt); + + end_seq = ctx->data + line_info.length + sizeof(line_info_stream->length); + std_opcodes = ctx->data + sizeof(dwarf2_line_info_stream_t); + + } + return FALSE; +} + BOOL dwarf2_parse(struct module* module, unsigned long load_offset, const unsigned char* debug, unsigned int debug_size, const unsigned char* abbrev, unsigned int abbrev_size, - const unsigned char* str, unsigned int str_sz) + const unsigned char* str, unsigned int str_sz, + const unsigned char* lines, unsigned int lines_size) { const unsigned char* comp_unit_cursor = debug; const unsigned char* end_debug = debug + debug_size; BOOL bRet = TRUE; + ref_hash_table_t ht_ref; + + ref_hash_table_init(&module->pool, &ht_ref, 4097); while (comp_unit_cursor < end_debug) { dwarf2_abbrev_table_t* abbrev_table; @@ -2090,6 +2377,7 @@ dwarf2_comp_unit_t comp_unit; dwarf2_parse_context_t ctx; dwarf2_parse_context_t abbrev_ctx; + dwarf2_parse_context_t lines_ctx; struct symt_compiland* compiland = NULL; comp_unit_stream = (const dwarf2_comp_unit_stream_t*) comp_unit_cursor; @@ -2111,6 +2399,7 @@ ctx.word_size = comp_unit.word_size; ctx.str_section = str; ctx.level = 0; + ctx.ht_ref = &ht_ref; comp_unit_cursor += comp_unit.length + sizeof(unsigned); ctx.end_data = comp_unit_cursor; @@ -2120,13 +2409,22 @@ continue ; } + lines_ctx.abbrev_table = NULL; + lines_ctx.data_stream = lines; + lines_ctx.data = lines_ctx.start_data = lines; + lines_ctx.end_data = lines + lines_size; + lines_ctx.offset = 0; + lines_ctx.word_size = comp_unit.word_size; + lines_ctx.str_section = str; + dwarf2_parse_lines(module, &lines_ctx); + abbrev_ctx.abbrev_table = NULL; abbrev_ctx.data_stream = abbrev; abbrev_ctx.data = abbrev_ctx.start_data = abbrev + comp_unit.abbrev_offset; abbrev_ctx.end_data = abbrev + abbrev_size; abbrev_ctx.offset = comp_unit.abbrev_offset; abbrev_ctx.str_section = str; - abbrev_table = dwarf2_parse_abbrev_set(&abbrev_ctx); + abbrev_table = dwarf2_parse_abbrev_set(&abbrev_ctx); ctx.abbrev_table = abbrev_table; @@ -2138,7 +2436,7 @@ entry_ref = ctx.data - ctx.data_stream; entry_code = dwarf2_leb128_as_unsigned(&ctx); - TRACE("found entry_code %lu at 0x%lx\n", entry_code, entry_ref); + TRACE("found entry_code %lu at ref<0x%lx>\n", entry_code, entry_ref); if (0 == entry_code) { continue ; } @@ -2153,7 +2451,7 @@ case DW_TAG_compile_unit: { struct symt_compiland* symt = dwarf2_parse_compiland(module, entry, &ctx); - dwarf2_add_symt_ref(module, entry_ref, &symt->symt); + dwarf2_add_symt_ref(module, &ctx, entry_ref, &symt->symt); compiland = symt; } break; @@ -2170,5 +2468,7 @@ } dwarf2_abbrev_table_free(abbrev_table); } + ref_hash_table_destroy(&module->pool, &ht_ref); return bRet; } + Index: elf_module.c =================================================================== RCS file: /home/wine/wine/dlls/dbghelp/elf_module.c,v retrieving revision 1.25 diff -u -r1.25 elf_module.c --- elf_module.c 2 Sep 2005 14:47:36 -0000 1.25 +++ elf_module.c 13 Oct 2005 21:51:19 -0000 @@ -854,8 +854,8 @@ if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY)) { - if (stab_sect != -1 && stabstr_sect != -1) - { + if (stab_sect != -1 && stabstr_sect != -1) + { const char* stab; const char* stabstr; @@ -885,23 +885,28 @@ const BYTE* dw2_debug; const BYTE* dw2_debug_abbrev; const BYTE* dw2_debug_str; + const BYTE* dw2_debug_line; FIXME("Alpha-support for Dwarf2 information for %s\n", module->module.ModuleName); + if (dw2_debug != NO_MAP && NO_MAP != dw2_debug_abbrev && dw2_debug_str != NO_MAP && dw2_debug_line != NO_MAP) dw2_debug = (const BYTE*) elf_map_section(fmap, debug_sect); dw2_debug_abbrev = (const BYTE*) elf_map_section(fmap, debug_abbrev_sect); dw2_debug_str = (const BYTE*) elf_map_section(fmap, debug_str_sect); + dw2_debug_line = (const BYTE*) elf_map_section(fmap, debug_line_sect); if (dw2_debug != NO_MAP && NO_MAP != dw2_debug_abbrev && dw2_debug_str != NO_MAP) { /* OK, now just parse dwarf2 debug infos. */ ret = dwarf2_parse(module, module->elf_info->elf_addr, dw2_debug, fmap->sect[debug_sect].shdr.sh_size, dw2_debug_abbrev, fmap->sect[debug_abbrev_sect].shdr.sh_size, - dw2_debug_str, fmap->sect[debug_str_sect].shdr.sh_size); + dw2_debug_str, fmap->sect[debug_str_sect].shdr.sh_size, + dw2_debug_line,fmap->sect[debug_line_sect].shdr.sh_size); } elf_unmap_section(fmap, debug_sect); elf_unmap_section(fmap, debug_abbrev_sect); elf_unmap_section(fmap, debug_str_sect); + elf_unmap_section(fmap, debug_line_sect); if (!ret) { WARN("Couldn't correctly read stabs\n");
pgpOvbQCGB2EG.pgp
Description: PGP signature