static void DC_resolve_type(Dwarf_Die v, DC_type *t){ /*TODO: Error Handling*/ Dwarf_Error error; Dwarf_Attribute type; Dwarf_Off off; Dwarf_Die typeDie; Dwarf_Half tag = 0; /* * Start with the variable, not its type. The loop * unwraps all the types. */ dwarf_attr(v, DW_AT_type, &type, &error); dwarf_formref(type, &off, &error); DC_get_die_from_CU_relative_offset(v, off, &typeDie); int points = 0; int arrs = 0; while( 1 ){ Dwarf_Bool has; dwarf_hasattr(typeDie,DW_AT_type,&has,&error); if(!has){ /*We've reached a base or structure type*/ dwarf_diename(typeDie,&(t->name),&error); Dwarf_Attribute bsize; dwarf_attr(typeDie,DW_AT_byte_size,&bsize,&error); dwarf_formudata(bsize,(Dwarf_Unsigned*)(&t->byteSize),&error); t->indirectionLevel = points; t->arrayLevel = arrs; return; /*Note: I am assuming this must happen eventually. can there * be mutually referencing types?*/ } /*Otherwise: this type has a type, so it is a pointer or a typedef * or an array type. For now, we're only going to correctly * handle pointer types.(TODO:) */ dwarf_tag(typeDie,&tag,&error); if(tag == DW_TAG_pointer_type){ points++; } if(tag == DW_TAG_array_type){ arrs++; } dwarf_attr(typeDie, DW_AT_type, &type, &error); dwarf_formref(type, &off, &error); /*Note, the next line uses v, because it can use anything in the CU*/ DC_get_die_from_CU_relative_offset(v, off, &typeDie); } }
/** \brief Initialize the location of a member of a type * (DW_AT_data_member_location of a DW_TAG_member). * * \param type a type (struct, class) * \param member the member of the type * \param child DIE of the member (DW_TAG_member) */ static void MC_dwarf_fill_member_location( simgrid::mc::Type* type, simgrid::mc::Member* member, Dwarf_Die * child) { if (dwarf_hasattr(child, DW_AT_data_bit_offset)) xbt_die("Can't groke DW_AT_data_bit_offset."); if (not dwarf_hasattr_integrate(child, DW_AT_data_member_location)) { if (type->type == DW_TAG_union_type) return; xbt_die ("Missing DW_AT_data_member_location field in DW_TAG_member %s of type <%" PRIx64 ">%s", member->name.c_str(), (uint64_t) type->id, type->name.c_str()); } Dwarf_Attribute attr; dwarf_attr_integrate(child, DW_AT_data_member_location, &attr); int form = dwarf_whatform(&attr); simgrid::dwarf::FormClass form_class = simgrid::dwarf::classify_form(form); switch (form_class) { case simgrid::dwarf::FormClass::ExprLoc: case simgrid::dwarf::FormClass::Block: // Location expression: { Dwarf_Op *expr; size_t len; if (dwarf_getlocation(&attr, &expr, &len)) xbt_die ("Could not read location expression DW_AT_data_member_location in DW_TAG_member %s of type <%" PRIx64 ">%s", MC_dwarf_attr_integrate_string(child, DW_AT_name), (uint64_t) type->id, type->name.c_str()); member->location_expression = simgrid::dwarf::DwarfExpression(expr, expr+len); break; } case simgrid::dwarf::FormClass::Constant: // Offset from the base address of the object: { Dwarf_Word offset; if (not dwarf_formudata(&attr, &offset)) member->offset(offset); else xbt_die("Cannot get %s location <%" PRIx64 ">%s", MC_dwarf_attr_integrate_string(child, DW_AT_name), (uint64_t) type->id, type->name.c_str()); break; } default: // includes FormClass::LocListPtr (reference to a location list: TODO) and FormClass::Reference (it's supposed to be // possible in DWARF2 but I couldn't find its semantic in the spec) xbt_die("Can't handle form class (%d) / form 0x%x as DW_AT_member_location", (int)form_class, (unsigned)form); } }
static void tp_dwarf_attr_sanity(void) { Dwarf_Debug dbg; Dwarf_Error de; Dwarf_Bool has_attr; Dwarf_Half attr; Dwarf_Attribute at; int fd; result = TET_UNRESOLVED; TS_DWARF_INIT(dbg, fd, de); if (dwarf_hasattr(NULL, DW_AT_name, &has_attr, &de) != DW_DLV_ERROR) { tet_infoline("dwarf_hasattr didn't return DW_DLV_ERROR" " when called with NULL arguments"); result = TET_FAIL; goto done; } if (dwarf_attr(NULL, DW_AT_name, &at, &de) != DW_DLV_ERROR) { tet_infoline("dwarf_attr didn't return DW_DLV_ERROR" " when called with NULL arguments"); result = TET_FAIL; goto done; } if (dwarf_whatattr(NULL, &attr, &de) != DW_DLV_ERROR) { tet_infoline("dwarf_whatattr didn't return DW_DLV_ERROR" " when called with NULL arguments"); result = TET_FAIL; goto done; } if (result == TET_UNRESOLVED) result = TET_PASS; done: TS_DWARF_FINISH(dbg, de); TS_RESULT(result); }
static void print_vars (unsigned int indent, Dwarf_Die *die) { Dwarf_Die child; if (dwarf_child (die, &child) == 0) do switch (dwarf_tag (&child)) { case DW_TAG_variable: case DW_TAG_formal_parameter: printf ("%*s%-30s[%6" PRIx64 "]\n", indent, "", dwarf_diename (&child), (uint64_t) dwarf_dieoffset (&child)); break; default: break; } while (dwarf_siblingof (&child, &child) == 0); Dwarf_Attribute attr_mem; Dwarf_Die origin; if (dwarf_hasattr (die, DW_AT_abstract_origin) && dwarf_formref_die (dwarf_attr (die, DW_AT_abstract_origin, &attr_mem), &origin) != NULL && dwarf_child (&origin, &child) == 0) do switch (dwarf_tag (&child)) { case DW_TAG_variable: case DW_TAG_formal_parameter: printf ("%*s%s (abstract)\n", indent, "", dwarf_diename (&child)); break; default: break; } while (dwarf_siblingof (&child, &child) == 0); }
/* Get all the data in .debug_pubnames */ void print_pubnames(Dwarf_Debug dbg) { Dwarf_Global *globbuf = NULL; Dwarf_Signed count = 0; Dwarf_Signed i = 0; Dwarf_Off die_off = 0; Dwarf_Off cu_off = 0; /* Offset to previous CU */ Dwarf_Off prev_cu_off = elf_max_address; char *name = 0; int res = 0; current_section_id = DEBUG_PUBNAMES; if (do_print_dwarf) { printf("\n.debug_pubnames\n"); } res = dwarf_get_globals(dbg, &globbuf, &count, &err); if (res == DW_DLV_ERROR) { print_error(dbg, "dwarf_get_globals", res, err); } else if (res == DW_DLV_NO_ENTRY) { /* (err == 0 && count == DW_DLV_NOCOUNT) means there are no pubnames. */ } else { Dwarf_Unsigned maxoff = get_info_max_offset(dbg); for (i = 0; i < count; i++) { int nres = 0; int cures3 = 0; Dwarf_Off global_cu_off = 0; nres = dwarf_global_name_offsets(globbuf[i], &name, &die_off, &cu_off, &err); deal_with_name_offset_err(dbg, "dwarf_global_name_offsets", name, die_off, nres, err); cures3 = dwarf_global_cu_offset(globbuf[i], &global_cu_off, &err); if (cures3 != DW_DLV_OK) { print_error(dbg, "dwarf_global_cu_offset", cures3, err); } if (check_pubname_attr) { Dwarf_Bool has_attr; int ares; int dres; Dwarf_Die die; /* We are processing a new set of pubnames for a different CU; get the producer ID, at 'cu_off' to see if we need to skip these pubnames */ if (cu_off != prev_cu_off) { /* Record offset for previous CU */ prev_cu_off = cu_off; dres = dwarf_offdie(dbg, cu_off, &die, &err); if (dres != DW_DLV_OK) { print_error(dbg, "print pubnames: dwarf_offdie a", dres,err); } { /* Get producer name for this CU and update compiler list */ struct esb_s producername; esb_constructor(&producername); get_producer_name(dbg,die,err,&producername); update_compiler_target(esb_get_string(&producername)); esb_destructor(&producername); } dwarf_dealloc(dbg, die, DW_DLA_DIE); } /* get die at die_off */ dres = dwarf_offdie(dbg, die_off, &die, &err); if (dres != DW_DLV_OK) { print_error(dbg, "print pubnames: dwarf_offdie b", dres, err); } ares = dwarf_hasattr(die, DW_AT_external, &has_attr, &err); if (ares == DW_DLV_ERROR) { print_error(dbg, "hassattr on DW_AT_external", ares, err); } /* Check for specific compiler */ if (checking_this_compiler()) { DWARF_CHECK_COUNT(pubname_attr_result,1); if (ares == DW_DLV_OK && has_attr) { /* Should the value of flag be examined? */ } else { DWARF_CHECK_ERROR2(pubname_attr_result,name, "pubname does not have DW_AT_external"); } } dwarf_dealloc(dbg, die, DW_DLA_DIE); } /* Now print pubname, after the test */ if (do_print_dwarf || (record_dwarf_error && check_verbose_mode)) { print_pubname_style_entry(dbg, "global", name, die_off, cu_off, global_cu_off, maxoff); record_dwarf_error = FALSE; /* Clear error condition */ } } dwarf_globals_dealloc(dbg, globbuf, count); } } /* print_pubnames() */
static std::unique_ptr<simgrid::mc::Variable> MC_die_to_variable( simgrid::mc::ObjectInformation* info, Dwarf_Die * die, Dwarf_Die * unit, simgrid::mc::Frame* frame, const char *ns) { // Skip declarations: if (MC_dwarf_attr_flag(die, DW_AT_declaration, false)) return nullptr; // Skip compile time constants: if (dwarf_hasattr(die, DW_AT_const_value)) return nullptr; Dwarf_Attribute attr_location; if (dwarf_attr(die, DW_AT_location, &attr_location) == nullptr) // No location: do not add it ? return nullptr; std::unique_ptr<simgrid::mc::Variable> variable = std::unique_ptr<simgrid::mc::Variable>(new simgrid::mc::Variable()); variable->id = dwarf_dieoffset(die); variable->global = frame == nullptr; // Can be override base on DW_AT_location variable->object_info = info; const char *name = MC_dwarf_attr_integrate_string(die, DW_AT_name); if (name) variable->name = name; variable->type_id = MC_dwarf_at_type(die); int form = dwarf_whatform(&attr_location); simgrid::dwarf::FormClass form_class; if (form == DW_FORM_sec_offset) form_class = simgrid::dwarf::FormClass::Constant; else form_class = simgrid::dwarf::classify_form(form); switch (form_class) { case simgrid::dwarf::FormClass::ExprLoc: case simgrid::dwarf::FormClass::Block: // Location expression: { Dwarf_Op *expr; size_t len; if (dwarf_getlocation(&attr_location, &expr, &len)) { xbt_die( "Could not read location expression in DW_AT_location " "of variable <%" PRIx64 ">%s", (uint64_t) variable->id, variable->name.c_str()); } if (len == 1 && expr[0].atom == DW_OP_addr) { variable->global = true; uintptr_t offset = (uintptr_t) expr[0].number; uintptr_t base = (uintptr_t) info->base_address(); variable->address = (void *) (base + offset); } else variable->location_list = { simgrid::dwarf::LocationListEntry(simgrid::dwarf::DwarfExpression(expr, expr + len))}; break; } case simgrid::dwarf::FormClass::LocListPtr: case simgrid::dwarf::FormClass::Constant: // Reference to location list: variable->location_list = simgrid::dwarf::location_list( *info, attr_location); break; default: xbt_die("Unexpected form 0x%x (%i), class 0x%x (%i) list for location in <%" PRIx64 ">%s", (unsigned)form, form, (unsigned)form_class, (int)form_class, (uint64_t)variable->id, variable->name.c_str()); } // Handle start_scope: if (dwarf_hasattr(die, DW_AT_start_scope)) { Dwarf_Attribute attr; dwarf_attr(die, DW_AT_start_scope, &attr); int form = dwarf_whatform(&attr); simgrid::dwarf::FormClass form_class = simgrid::dwarf::classify_form(form); if (form_class == simgrid::dwarf::FormClass::Constant) { Dwarf_Word value; variable->start_scope = dwarf_formudata(&attr, &value) == 0 ? (size_t)value : 0; } else { // TODO: FormClass::RangeListPtr xbt_die("Unhandled form 0x%x, class 0x%X for DW_AT_start_scope of variable %s", (unsigned)form, (unsigned)form_class, name == nullptr ? "?" : name); } } if (ns && variable->global) variable->name = std::string(ns) + "::" + variable->name; // The current code needs a variable name, // generate a fake one: if (variable->name.empty()) { variable->name = "@anonymous#" + std::to_string(mc_anonymous_variable_index); mc_anonymous_variable_index++; } return variable; }
/** \brief Populate the list of members of a type * * \param info ELF object containing the type DIE * \param die DIE of the type * \param unit DIE of the compilation unit containing the type DIE * \param type the type */ static void MC_dwarf_add_members(simgrid::mc::ObjectInformation* info, Dwarf_Die * die, Dwarf_Die * unit, simgrid::mc::Type* type) { int res; Dwarf_Die child; xbt_assert(type->members.empty()); for (res = dwarf_child(die, &child); res == 0; res = dwarf_siblingof(&child, &child)) { int tag = dwarf_tag(&child); if (tag == DW_TAG_member || tag == DW_TAG_inheritance) { // Skip declarations: if (MC_dwarf_attr_flag(&child, DW_AT_declaration, false)) continue; // Skip compile time constants: if (dwarf_hasattr(&child, DW_AT_const_value)) continue; // TODO, we should use another type (because is is not a type but a member) simgrid::mc::Member member; if (tag == DW_TAG_inheritance) member.flags |= simgrid::mc::Member::INHERITANCE_FLAG; const char *name = MC_dwarf_attr_integrate_string(&child, DW_AT_name); if (name) member.name = name; // Those base names are used by GCC and clang for virtual table pointers // respectively ("__vptr$ClassName", "__vptr.ClassName"): if (boost::algorithm::starts_with(member.name, "__vptr$") || boost::algorithm::starts_with(member.name, "__vptr.")) member.flags |= simgrid::mc::Member::VIRTUAL_POINTER_FLAG; // A cleaner solution would be to check against the type: // --- // tag: DW_TAG_member // name: "_vptr$Foo" // type: // # Type for a pointer to a vtable // tag: DW_TAG_pointer_type // type: // # Type for a vtable: // tag: DW_TAG_pointer_type // name: "__vtbl_ptr_type" // type: // tag: DW_TAG_subroutine_type // type: // tag: DW_TAG_base_type // name: "int" // --- member.byte_size = MC_dwarf_attr_integrate_uint(&child, DW_AT_byte_size, 0); member.type_id = MC_dwarf_at_type(&child); if (dwarf_hasattr(&child, DW_AT_data_bit_offset)) xbt_die("Can't groke DW_AT_data_bit_offset."); MC_dwarf_fill_member_location(type, &member, &child); if (not member.type_id) xbt_die("Missing type for member %s of <%" PRIx64 ">%s", member.name.c_str(), (uint64_t) type->id, type->name.c_str()); type->members.push_back(std::move(member)); } } }
/* Get all the data in .debug_static_funcs On error, this allows some dwarf memory leaks. */ extern void print_static_funcs(Dwarf_Debug dbg) { Dwarf_Func *funcbuf = NULL; Dwarf_Signed count = 0; Dwarf_Signed i = 0; Dwarf_Off die_off = 0; Dwarf_Off cu_off = 0; int gfres = 0; printf("\n.debug_static_func\n"); gfres = dwarf_get_funcs(dbg, &funcbuf, &count, &err); if (gfres == DW_DLV_ERROR) { print_error(dbg, "dwarf_get_funcs", gfres, err); } else if (gfres == DW_DLV_NO_ENTRY) { /* no static funcs */ } else { Dwarf_Unsigned maxoff = get_info_max_offset(dbg); for (i = 0; i < count; i++) { int fnres; int cures3; Dwarf_Unsigned global_cu_off = 0; char *name = 0; fnres = dwarf_func_name_offsets(funcbuf[i], &name, &die_off, &cu_off, &err); deal_with_name_offset_err(dbg, "dwarf_func_name_offsets", name, die_off, fnres, err); cures3 = dwarf_func_cu_offset(funcbuf[i], &global_cu_off, &err); if (cures3 != DW_DLV_OK) { print_error(dbg, "dwarf_global_cu_offset", cures3, err); } print_pubname_style_entry(dbg, "static-func", name, die_off, cu_off, global_cu_off, maxoff); /* print associated die too? */ if (check_pubname_attr) { Dwarf_Bool has_attr; int ares; int dres; Dwarf_Die die; /* get die at die_off */ dres = dwarf_offdie(dbg, die_off, &die, &err); if (dres != DW_DLV_OK) { print_error(dbg, "dwarf_offdie", dres, err); } ares = dwarf_hasattr(die, DW_AT_external, &has_attr, &err); if (ares == DW_DLV_ERROR) { print_error(dbg, "hassattr on DW_AT_external", ares, err); } pubname_attr_result.checks++; if (ares == DW_DLV_OK && has_attr) { /* Should the value of flag be examined? */ } else { DWARF_CHECK_ERROR2(pubname_attr_result,name, "pubname does not have DW_AT_external") } dwarf_dealloc(dbg, die, DW_DLA_DIE); } } dwarf_funcs_dealloc(dbg, funcbuf, count); } } /* print_static_funcs() */
static void structprobe(Dwarf *dw, Dwarf_Die *structdie) { Dwarf_Die memdie; Dwarf_Word lastoff = 0, structsize; unsigned cline, members, nholes; size_t memsz, holesz; int x; (void)dw; cline = members = nholes = 0; memsz = holesz = 0; printf("struct %s {\n", dwarf_diename(structdie)); if (dwarf_aggregate_size(structdie, &structsize) == -1) dwarf_err(EX_DATAERR, "dwarf_aggregate_size"); if (dwarf_child(structdie, &memdie)) { printf("XXX ???\n"); exit(EX_DATAERR); } do { Dwarf_Attribute type_attr, base_type_attr; Dwarf_Die type_die, base_type_die; char type_name[128], mem_name[128], ptr_suffix[32] = { '\0' }; const char *type_tag = ""; const char *type = NULL; unsigned type_ptrlevel = 0; Dwarf_Word msize, off; if (dwarf_tag(&memdie) != DW_TAG_member) continue; members++; /* * TODO: Handle bitfield members. DW_AT_bit_offset, * DW_AT_bit_size; */ /* Chase down the type die of this member */ get_dwarf_attr(&memdie, DW_AT_type, &type_attr, &type_die); /* Member offset ... */ if (get_member_offset(&memdie, &off) == -1) dwarf_err(EX_DATAERR, "%s", dwarf_diename(&memdie)); /* Member size. */ if (get_member_size(&type_die, &msize) == -1) dwarf_err(EX_DATAERR, "get_member_size"); /* Format name; 'struct foo', 'enum bar', 'char **', etc. */ if (isstruct(dwarf_tag(&type_die))) { type_tag = "struct "; type = dwarf_diename(&type_die); } else if (dwarf_tag(&type_die) == DW_TAG_enumeration_type) { type_tag = "enum "; type = dwarf_diename(&type_die); } else if (dwarf_tag(&type_die) == DW_TAG_pointer_type) { unsigned i; do { if (dwarf_tag(&type_die) == DW_TAG_pointer_type) type_ptrlevel++; else if (isstruct(dwarf_tag(&type_die))) type_tag = "struct "; else if (dwarf_tag(&type_die) == DW_TAG_enumeration_type) type_tag = "enum "; else printf("!!! XXX ignored pointer qualifier TAG %#x\n", dwarf_tag(&type_die)); /* * Pointers to basic types still need some * work. Clang doesn't emit an AT_TYPE for * 'void*,' for example. */ if (!dwarf_hasattr(&type_die, DW_AT_type)) break; get_dwarf_attr(&type_die, DW_AT_type, &base_type_attr, &base_type_die); type_die = base_type_die; type_attr = base_type_attr; } while (dwarf_tag(&type_die) != DW_TAG_base_type); type = dwarf_diename(&type_die); if (type_ptrlevel > sizeof(ptr_suffix) - 2) type_ptrlevel = sizeof(ptr_suffix) - 2; ptr_suffix[0] = ' '; for (i = 1; i <= type_ptrlevel; i++) ptr_suffix[i] = '*'; ptr_suffix[i] = '\0'; } else type = dwarf_diename(&type_die); if (type == NULL) type = "<anonymous>"; snprintf(type_name, sizeof(type_name), "%s%s%s", type_tag, type, ptr_suffix); if (off != lastoff) { printf("\n\t/* XXX %ld bytes hole, try to pack */\n\n", off - lastoff); nholes++; holesz += (off - lastoff); } snprintf(mem_name, sizeof(mem_name), "%s;", dwarf_diename(&memdie)); printf("\t%-27s%-21s /* %5ld %5ld */\n", type_name, mem_name, (long)off, (long)msize); memsz += msize; lastoff = off + msize; if (lastoff / cachelinesize > cline) { int ago = lastoff % cachelinesize; cline = lastoff / cachelinesize; if (ago) printf("\t/* --- cacheline %u boundary (%ld " "bytes) was %d bytes ago --- */\n", cline, (long)cline * cachelinesize, ago); else printf("\t/* --- cacheline %u boundary (%ld " "bytes) --- */\n", cline, (long)cline * cachelinesize); } } while ((x = dwarf_siblingof(&memdie, &memdie)) == 0); if (x == -1) dwarf_err(EX_DATAERR, "dwarf_siblingof"); printf("\n\t/* size: %lu, cachelines: %u, members: %u */\n", structsize, cline + 1, members); printf("\t/* sum members: %zu, holes: %u, sum holes: %zu */\n", memsz, nholes, holesz); printf("\t/* last cacheline: %lu bytes */\n", lastoff % cachelinesize); printf("};\n"); }
void handle (Dwarf *dbg, Dwarf_Die *die, int n) { Dwarf_Die child; unsigned int tag; const char *str; char buf[30]; const char *name; Dwarf_Off off; Dwarf_Off cuoff; size_t cnt; Dwarf_Addr addr; int i; tag = dwarf_tag (die); if (tag != DW_TAG_invalid) { if (tag < ntagnames) str = tagnames[tag]; else { snprintf (buf, sizeof buf, "%#x", tag); str = buf; } } else str = "* NO TAG *"; name = dwarf_diename (die); if (name == 0) name = "* NO NAME *"; off = dwarf_dieoffset (die); cuoff = dwarf_cuoffset (die); printf ("%*s%s\n", n * 5, "", str); printf ("%*s Name : %s\n", n * 5, "", name); printf ("%*s Offset : %lld\n", n * 5, "", (long long int) off); printf ("%*s CU offset : %lld\n", n * 5, "", (long long int) cuoff); printf ("%*s Attrs :", n * 5, ""); for (cnt = 0; cnt < nattrs; ++cnt) if (dwarf_hasattr (die, attrs[cnt].code)) printf (" %s", attrs[cnt].name); puts (""); if (dwarf_hasattr (die, DW_AT_low_pc) && dwarf_lowpc (die, &addr) == 0) { Dwarf_Attribute attr; Dwarf_Addr addr2; printf ("%*s low PC : %#llx\n", n * 5, "", (unsigned long long int) addr); if (dwarf_attr (die, DW_AT_low_pc, &attr) == NULL || dwarf_formaddr (&attr, &addr2) != 0 || addr != addr2) puts ("************* DW_AT_low_pc verify failed ************"); else if (! dwarf_hasform (&attr, DW_FORM_addr)) puts ("************* DW_AT_low_pc form failed ************"); else if (dwarf_whatform (&attr) != DW_FORM_addr) puts ("************* DW_AT_low_pc form (2) failed ************"); else if (dwarf_whatattr (&attr) != DW_AT_low_pc) puts ("************* DW_AT_low_pc attr failed ************"); } if (dwarf_hasattr (die, DW_AT_high_pc) && dwarf_highpc (die, &addr) == 0) { Dwarf_Attribute attr; Dwarf_Addr addr2; printf ("%*s high PC : %#llx\n", n * 5, "", (unsigned long long int) addr); if (dwarf_attr (die, DW_AT_high_pc, &attr) == NULL || dwarf_formaddr (&attr, &addr2) != 0 || addr != addr2) puts ("************* DW_AT_high_pc verify failed ************"); else if (! dwarf_hasform (&attr, DW_FORM_addr)) puts ("************* DW_AT_high_pc form failed ************"); else if (dwarf_whatform (&attr) != DW_FORM_addr) puts ("************* DW_AT_high_pc form (2) failed ************"); else if (dwarf_whatattr (&attr) != DW_AT_high_pc) puts ("************* DW_AT_high_pc attr failed ************"); } if (dwarf_hasattr (die, DW_AT_byte_size) && (i = dwarf_bytesize (die)) != -1) { Dwarf_Attribute attr; Dwarf_Word u2; unsigned int u; printf ("%*s byte size : %d\n", n * 5, "", i); if (dwarf_attr (die, DW_AT_byte_size, &attr) == NULL || dwarf_formudata (&attr, &u2) != 0 || i != (int) u2) puts ("************* DW_AT_byte_size verify failed ************"); else if (! dwarf_hasform (&attr, DW_FORM_data1) && ! dwarf_hasform (&attr, DW_FORM_data2) && ! dwarf_hasform (&attr, DW_FORM_data4) && ! dwarf_hasform (&attr, DW_FORM_data8) && ! dwarf_hasform (&attr, DW_FORM_sdata) && ! dwarf_hasform (&attr, DW_FORM_udata)) puts ("************* DW_AT_byte_size form failed ************"); else if ((u = dwarf_whatform (&attr)) == 0 || (u != DW_FORM_data1 && u != DW_FORM_data2 && u != DW_FORM_data4 && u != DW_FORM_data8 && u != DW_FORM_sdata && u != DW_FORM_udata)) puts ("************* DW_AT_byte_size form (2) failed ************"); else if (dwarf_whatattr (&attr) != DW_AT_byte_size) puts ("************* DW_AT_byte_size attr failed ************"); } if (dwarf_hasattr (die, DW_AT_bit_size) && (i = dwarf_bitsize (die)) != -1) { Dwarf_Attribute attr; Dwarf_Word u2; unsigned int u; printf ("%*s bit size : %d\n", n * 5, "", i); if (dwarf_attr (die, DW_AT_bit_size, &attr) == NULL || dwarf_formudata (&attr, &u2) != 0 || i != (int) u2) puts ("************* DW_AT_bit_size test failed ************"); else if (! dwarf_hasform (&attr, DW_FORM_data1) && ! dwarf_hasform (&attr, DW_FORM_data2) && ! dwarf_hasform (&attr, DW_FORM_data4) && ! dwarf_hasform (&attr, DW_FORM_data8) && ! dwarf_hasform (&attr, DW_FORM_sdata) && ! dwarf_hasform (&attr, DW_FORM_udata)) puts ("************* DW_AT_bit_size form failed ************"); else if ((u = dwarf_whatform (&attr)) == 0 || (u != DW_FORM_data1 && u != DW_FORM_data2 && u != DW_FORM_data4 && u != DW_FORM_data8 && u != DW_FORM_sdata && u != DW_FORM_udata)) puts ("************* DW_AT_bit_size form (2) failed ************"); else if (dwarf_whatattr (&attr) != DW_AT_bit_size) puts ("************* DW_AT_bit_size attr failed ************"); } if (dwarf_hasattr (die, DW_AT_bit_offset) && (i = dwarf_bitoffset (die)) != -1) { Dwarf_Attribute attr; Dwarf_Word u2; unsigned int u; printf ("%*s bit offset: %d\n", n * 5, "", i); if (dwarf_attr (die, DW_AT_bit_offset, &attr) == NULL || dwarf_formudata (&attr, &u2) != 0 || i != (int) u2) puts ("************* DW_AT_bit_offset test failed ************"); else if (! dwarf_hasform (&attr, DW_FORM_data1) && ! dwarf_hasform (&attr, DW_FORM_data2) && ! dwarf_hasform (&attr, DW_FORM_data4) && ! dwarf_hasform (&attr, DW_FORM_data8) && ! dwarf_hasform (&attr, DW_FORM_sdata) && ! dwarf_hasform (&attr, DW_FORM_udata)) puts ("************* DW_AT_bit_offset form failed ************"); else if ((u = dwarf_whatform (&attr)) == 0 || (u != DW_FORM_data1 && u != DW_FORM_data2 && u != DW_FORM_data4 && u != DW_FORM_data8 && u != DW_FORM_sdata && u != DW_FORM_udata)) puts ("************* DW_AT_bit_offset form (2) failed ************"); else if (dwarf_whatattr (&attr) != DW_AT_bit_offset) puts ("************* DW_AT_bit_offset attr failed ************"); } if (dwarf_hasattr (die, DW_AT_language) && (i = dwarf_srclang (die)) != -1) { Dwarf_Attribute attr; Dwarf_Word u2; unsigned int u; printf ("%*s language : %d\n", n * 5, "", i); if (dwarf_attr (die, DW_AT_language, &attr) == NULL || dwarf_formudata (&attr, &u2) != 0 || i != (int) u2) puts ("************* DW_AT_language test failed ************"); else if (! dwarf_hasform (&attr, DW_FORM_data1) && ! dwarf_hasform (&attr, DW_FORM_data2) && ! dwarf_hasform (&attr, DW_FORM_data4) && ! dwarf_hasform (&attr, DW_FORM_data8) && ! dwarf_hasform (&attr, DW_FORM_sdata) && ! dwarf_hasform (&attr, DW_FORM_udata)) puts ("************* DW_AT_language form failed ************"); else if ((u = dwarf_whatform (&attr)) == 0 || (u != DW_FORM_data1 && u != DW_FORM_data2 && u != DW_FORM_data4 && u != DW_FORM_data8 && u != DW_FORM_sdata && u != DW_FORM_udata)) puts ("************* DW_AT_language form (2) failed ************"); else if (dwarf_whatattr (&attr) != DW_AT_language) puts ("************* DW_AT_language attr failed ************"); } if (dwarf_hasattr (die, DW_AT_ordering) && (i = dwarf_arrayorder (die)) != -1) { Dwarf_Attribute attr; Dwarf_Word u2; unsigned int u; printf ("%*s ordering : %d\n", n * 5, "", i); if (dwarf_attr (die, DW_AT_ordering, &attr) == NULL || dwarf_formudata (&attr, &u2) != 0 || i != (int) u2) puts ("************* DW_AT_ordering test failed ************"); else if (! dwarf_hasform (&attr, DW_FORM_data1) && ! dwarf_hasform (&attr, DW_FORM_data2) && ! dwarf_hasform (&attr, DW_FORM_data4) && ! dwarf_hasform (&attr, DW_FORM_data8) && ! dwarf_hasform (&attr, DW_FORM_sdata) && ! dwarf_hasform (&attr, DW_FORM_udata)) puts ("************* DW_AT_ordering failed ************"); else if ((u = dwarf_whatform (&attr)) == 0 || (u != DW_FORM_data1 && u != DW_FORM_data2 && u != DW_FORM_data4 && u != DW_FORM_data8 && u != DW_FORM_sdata && u != DW_FORM_udata)) puts ("************* DW_AT_ordering form (2) failed ************"); else if (dwarf_whatattr (&attr) != DW_AT_ordering) puts ("************* DW_AT_ordering attr failed ************"); } if (dwarf_hasattr (die, DW_AT_comp_dir)) { Dwarf_Attribute attr; if (dwarf_attr (die, DW_AT_comp_dir, &attr) == NULL || (name = dwarf_formstring (&attr)) == NULL) puts ("************* DW_AT_comp_dir attr failed ************"); else printf ("%*s directory : %s\n", n * 5, "", name); } if (dwarf_hasattr (die, DW_AT_producer)) { Dwarf_Attribute attr; if (dwarf_attr (die, DW_AT_producer, &attr) == NULL || (name = dwarf_formstring (&attr)) == NULL) puts ("************* DW_AT_comp_dir attr failed ************"); else printf ("%*s producer : %s\n", n * 5, "", name); } if (dwarf_haschildren (die) != 0 && dwarf_child (die, &child) == 0) handle (dbg, &child, n + 1); if (dwarf_siblingof (die, die) == 0) handle (dbg, die, n); }
static void _dwarf_attr(Dwarf_Die die) { Dwarf_Attribute at; Dwarf_Bool has_attr; Dwarf_Half attr; Dwarf_Error de; const char *attr_name; int i, r; for (i = 0; i < attr_array_size; i++) { if (dwarf_hasattr(die, attr_array[i], &has_attr, &de) != DW_DLV_OK) { tet_printf("dwarf_hasattr failed: %s\n", dwarf_errmsg(de)); result = TET_FAIL; } TS_CHECK_INT(has_attr); if (has_attr) { if (dwarf_get_AT_name(attr_array[i], &attr_name) != DW_DLV_OK) { tet_printf("dwarf_get_AT_name failed: %s\n", dwarf_errmsg(de)); result = TET_FAIL; continue; } if (attr_name == NULL) { tet_infoline("dwarf_get_AT_name returned " "DW_DLV_OK but didn't return string"); result = TET_FAIL; continue; } TS_CHECK_STRING(attr_name); tet_printf("DIE #%d has attribute '%s'\n", die_cnt, attr_name); r = dwarf_attr(die, attr_array[i], &at, &de); if (r == DW_DLV_ERROR) { tet_printf("dwarf_attr failed: %s", dwarf_errmsg(de)); result = TET_FAIL; continue; } else if (r == DW_DLV_NO_ENTRY) { tet_infoline("dwarf_hasattr returned true for " "attribute '%s', while dwarf_attr returned" " DW_DLV_NO_ENTRY for the same attr"); result = TET_FAIL; continue; } if (dwarf_whatattr(at, &attr, &de) != DW_DLV_OK) { tet_printf("dwarf_whatattr failed: %s", dwarf_errmsg(de)); result = TET_FAIL; continue; } if (attr != attr_array[i]) { tet_infoline("attr returned by dwarf_whatattr" " != attr_array[i]"); result = TET_FAIL; continue; } } } }
/* Return DW_DLV_OK, or DW_DLV_ERROR Handle the addrs in a single die. */ static int process_this_die_attrs(Dwarf_Debug dbg, Dwarf_Die newdie, int *errval) { Dwarf_Error err; Dwarf_Half i; Dwarf_Half newattrnum; int res; int tres; Dwarf_Half ltag; Dwarf_Off doff; int doffres = dwarf_dieoffset(newdie, &doff, &err); if (doffres != DW_DLV_OK) { if (doffres == DW_DLV_ERROR) { *errval = (int) dwarf_errno(err); } return doffres; } tres = dwarf_tag(newdie, <ag, &err); if (tres != DW_DLV_OK) { return tres; } if (DW_TAG_compile_unit == ltag) { /* because of the way the dwarf_line code works, we ** do lines only per compile unit. ** This may turn out to be wrong if we have lines ** left unconnected to a CU. ** of course such lines will not, at present, be ** used by gnome ** This is not ideal as coded due to the dwarf_line.c issue. */ int lres; lres = handle_debug_line(dbg, newdie, send_addr_note, errval); if (lres == DW_DLV_ERROR) { return lres; } } for (i = 0; i < sizeof(might_have_addr) / sizeof(int); i++) { int resattr; Dwarf_Bool hasattr; newattrnum = might_have_addr[i]; err = 0; resattr = dwarf_hasattr(newdie, newattrnum, &hasattr, &err); if (DW_DLV_OK == resattr) { if (hasattr) { res = handle_attr_addr(dbg, newdie, newattrnum, &err); if (res != DW_DLV_OK) { *errval = (int) dwarf_errno(err); return DW_DLV_ERROR; } } } else { if (resattr == DW_DLV_ERROR) { *errval = (int) dwarf_errno(err); return resattr; } } } for (i = 0; i < sizeof(might_have_locdesc) / sizeof(int); i++) { int resattr; Dwarf_Bool hasattr; newattrnum = might_have_locdesc[i]; err = 0; resattr = dwarf_hasattr(newdie, newattrnum, &hasattr, &err); if (DW_DLV_OK == resattr) { if (hasattr) { res = handle_attr_locdesc(dbg, newdie, newattrnum, &err); if (res != DW_DLV_OK) { *errval = (int) dwarf_errno(err); return DW_DLV_ERROR; } } } else { if (resattr == DW_DLV_ERROR) { *errval = (int) dwarf_errno(err); return resattr; } } } return DW_DLV_OK; }
/* Get all variables and print their value expressions. */ static void print_varlocs (Dwarf_Die *funcdie) { // Display frame base for function if it exists. // Should be used for DW_OP_fbreg. has_frame_base = dwarf_hasattr (funcdie, DW_AT_frame_base); if (has_frame_base) { Dwarf_Attribute fb_attr; if (dwarf_attr (funcdie, DW_AT_frame_base, &fb_attr) == NULL) error (EXIT_FAILURE, 0, "dwarf_attr fb: %s", dwarf_errmsg (-1)); Dwarf_Op *fb_expr; size_t fb_exprlen; if (dwarf_getlocation (&fb_attr, &fb_expr, &fb_exprlen) == 0) { // Covers all of function. Dwarf_Addr entrypc; if (dwarf_entrypc (funcdie, &entrypc) != 0) error (EXIT_FAILURE, 0, "dwarf_entrypc: %s", dwarf_errmsg (-1)); printf (" frame_base: "); if (entrypc == 0) printf ("XXX zero address"); // XXX bad DWARF? else print_expr_block (&fb_attr, fb_expr, fb_exprlen, entrypc); printf ("\n"); } else { Dwarf_Addr base, start, end; ptrdiff_t off = 0; printf (" frame_base:\n"); while ((off = dwarf_getlocations (&fb_attr, off, &base, &start, &end, &fb_expr, &fb_exprlen)) > 0) { printf (" (%" PRIx64 ",%" PRIx64 ") ", start, end); print_expr_block (&fb_attr, fb_expr, fb_exprlen, start); printf ("\n"); } if (off < 0) error (EXIT_FAILURE, 0, "dwarf_getlocations fb: %s", dwarf_errmsg (-1)); } } else if (dwarf_tag (funcdie) == DW_TAG_inlined_subroutine) { // See whether the subprogram we are inlined into has a frame // base we should use. Dwarf_Die *scopes; int n = dwarf_getscopes_die (funcdie, &scopes); if (n <= 0) error (EXIT_FAILURE, 0, "dwarf_getscopes_die: %s", dwarf_errmsg (-1)); while (n-- > 0) if (dwarf_tag (&scopes[n]) == DW_TAG_subprogram && dwarf_hasattr (&scopes[n], DW_AT_frame_base)) { has_frame_base = true; break; } free (scopes); } if (! dwarf_haschildren (funcdie)) return; Dwarf_Die child; int res = dwarf_child (funcdie, &child); if (res < 0) error (EXIT_FAILURE, 0, "dwarf_child: %s", dwarf_errmsg (-1)); /* We thought there was a child, but the child list was actually empty. This isn't technically an error in the DWARF, but it is certainly non-optimimal. */ if (res == 1) return; do { int tag = dwarf_tag (&child); if (tag == DW_TAG_variable || tag == DW_TAG_formal_parameter) { const char *what = tag == DW_TAG_variable ? "variable" : "parameter"; print_die (&child, what, 2); if (dwarf_hasattr (&child, DW_AT_location)) { Dwarf_Attribute attr; if (dwarf_attr (&child, DW_AT_location, &attr) == NULL) error (EXIT_FAILURE, 0, "dwarf_attr: %s", dwarf_errmsg (-1)); Dwarf_Op *expr; size_t exprlen; if (dwarf_getlocation (&attr, &expr, &exprlen) == 0) { // Covers all ranges of the function. // Evaluate the expression block for each range. ptrdiff_t offset = 0; Dwarf_Addr base, begin, end; do { offset = dwarf_ranges (funcdie, offset, &base, &begin, &end); if (offset < 0) error (EXIT_FAILURE, 0, "dwarf_ranges: %s", dwarf_errmsg (-1)); if (offset > 0) { if (exprlen == 0) printf (" (%" PRIx64 ",%" PRIx64 ") <empty expression>\n", begin, end); else print_expr_block_addrs (&attr, begin, end, expr, exprlen); } } while (offset > 0); if (offset < 0) error (EXIT_FAILURE, 0, "dwarf_ranges: %s", dwarf_errmsg (-1)); } else { Dwarf_Addr base, begin, end; ptrdiff_t offset = 0; while ((offset = dwarf_getlocations (&attr, offset, &base, &begin, &end, &expr, &exprlen)) > 0) if (begin >= end) printf (" (%" PRIx64 ",%" PRIx64 ") <empty range>\n", begin, end); // XXX report? else { print_expr_block_addrs (&attr, begin, end, expr, exprlen); // Extra sanity check for dwarf_getlocation_addr // Must at least find one range for begin and end-1. Dwarf_Op *expraddr; size_t expraddr_len; int locs = dwarf_getlocation_addr (&attr, begin, &expraddr, &expraddr_len, 1); assert (locs == 1); locs = dwarf_getlocation_addr (&attr, end - 1, &expraddr, &expraddr_len, 1); assert (locs == 1); } if (offset < 0) error (EXIT_FAILURE, 0, "dwarf_getlocations: %s", dwarf_errmsg (-1)); } } else if (dwarf_hasattr (&child, DW_AT_const_value)) { printf (" <constant value>\n"); // Lookup type and print. } else { printf (" <no value>\n"); } } } while (dwarf_siblingof (&child, &child) == 0); }