BT_HIDDEN int bt_dwarf_die_get_call_file(struct bt_dwarf_die *die, char **filename) { int ret; Dwarf_Sword file_no; const char *_filename = NULL; Dwarf_Files *src_files = NULL; Dwarf_Attribute *file_attr = NULL; struct bt_dwarf_die *cu_die = NULL; if (!die || !filename) { goto error; } file_attr = g_new0(Dwarf_Attribute, 1); if (!file_attr) { goto error; } file_attr = dwarf_attr(die->dwarf_die, DW_AT_call_file, file_attr); if (!file_attr) { goto error; } ret = dwarf_formsdata(file_attr, &file_no); if (ret) { goto error; } cu_die = bt_dwarf_die_create(die->cu); if (!cu_die) { goto error; } ret = dwarf_getsrcfiles(cu_die->dwarf_die, &src_files, NULL); if (ret) { goto error; } _filename = dwarf_filesrc(src_files, file_no, NULL, NULL); if (!_filename) { goto error; } *filename = strdup(_filename); bt_dwarf_die_destroy(cu_die); g_free(file_attr); return 0; error: bt_dwarf_die_destroy(cu_die); g_free(file_attr); return -1; }
/* Get attribute and translate it as a sdata */ static int die_get_attr_sdata(Dwarf_Die *tp_die, unsigned int attr_name, Dwarf_Sword *result) { Dwarf_Attribute attr; if (dwarf_attr(tp_die, attr_name, &attr) == NULL || dwarf_formsdata(&attr, result) != 0) return -ENOENT; return 0; }
static void get_number(Dwarf_Attribute attr,Dwarf_Unsigned *val) { Dwarf_Error error = 0; int res; Dwarf_Signed sval = 0; Dwarf_Unsigned uval = 0; res = dwarf_formudata(attr,&uval,&error); if(res == DW_DLV_OK) { *val = uval; return; } res = dwarf_formsdata(attr,&sval,&error); if(res == DW_DLV_OK) { *val = sval; return; } return; }
static int die_signed(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, Dwarf_Signed *valp, int req) { Dwarf_Attribute attr; Dwarf_Signed val; if ((attr = die_attr(dw, die, name, req)) == NULL) return (0); /* die_attr will terminate for us if necessary */ if (dwarf_formsdata(attr, &val, &dw->dw_err) != DW_DLV_OK) { terminate("die %llu: failed to get signed (form 0x%x)\n", die_off(dw, die), die_attr_form(dw, attr)); } dwarf_dealloc(dw->dw_dw, attr, DW_DLA_ATTR); *valp = val; return (1); }
int get_small_encoding_value(Dwarf_Attribute attrib, Dwarf_Signed *val, Dwarf_Error *err) { Dwarf_Unsigned uval = 0; int ret = dwarf_formudata(attrib, &uval, err); if(ret != DW_DLV_OK) { Dwarf_Signed sval = 0; ret = dwarf_formsdata(attrib, &sval, err); if(ret == DW_DLV_OK) { *val = sval; } } else { *val = uval; } return ret; }
static void MC_dwarf_handle_scope_die(simgrid::mc::ObjectInformation* info, Dwarf_Die * die, Dwarf_Die * unit, simgrid::mc::Frame* parent_frame, const char *ns) { // TODO, handle DW_TAG_type/DW_TAG_location for DW_TAG_with_stmt int tag = dwarf_tag(die); simgrid::dwarf::TagClass klass = simgrid::dwarf::classify_tag(tag); // (Template) Subprogram declaration: if (klass == simgrid::dwarf::TagClass::Subprogram && MC_dwarf_attr_flag(die, DW_AT_declaration, false)) return; if (klass == simgrid::dwarf::TagClass::Scope) xbt_assert(parent_frame, "No parent scope for this scope"); simgrid::mc::Frame frame; frame.tag = tag; frame.id = dwarf_dieoffset(die); frame.object_info = info; if (klass == simgrid::dwarf::TagClass::Subprogram) { const char *name = MC_dwarf_attr_integrate_string(die, DW_AT_name); if (name && ns) frame.name = std::string(ns) + "::" + name; else if (name) frame.name = name; } frame.abstract_origin_id = MC_dwarf_attr_dieoffset(die, DW_AT_abstract_origin); // This is the base address for DWARF addresses. // Relocated addresses are offset from this base address. // See DWARF4 spec 7.5 std::uint64_t base = (std::uint64_t) info->base_address(); // TODO, support DW_AT_ranges uint64_t low_pc = MC_dwarf_attr_integrate_addr(die, DW_AT_low_pc); frame.range.begin() = low_pc ? (std::uint64_t) base + low_pc : 0; if (low_pc) { // DW_AT_high_pc: Dwarf_Attribute attr; if (not dwarf_attr_integrate(die, DW_AT_high_pc, &attr)) xbt_die("Missing DW_AT_high_pc matching with DW_AT_low_pc"); Dwarf_Sword offset; Dwarf_Addr high_pc; switch (simgrid::dwarf::classify_form(dwarf_whatform(&attr))) { // DW_AT_high_pc if an offset from the low_pc: case simgrid::dwarf::FormClass::Constant: if (dwarf_formsdata(&attr, &offset) != 0) xbt_die("Could not read constant"); frame.range.end() = frame.range.begin() + offset; break; // DW_AT_high_pc is a relocatable address: case simgrid::dwarf::FormClass::Address: if (dwarf_formaddr(&attr, &high_pc) != 0) xbt_die("Could not read address"); frame.range.end() = base + high_pc; break; default: xbt_die("Unexpected class for DW_AT_high_pc"); } } if (klass == simgrid::dwarf::TagClass::Subprogram) { Dwarf_Attribute attr_frame_base; if (dwarf_attr_integrate(die, DW_AT_frame_base, &attr_frame_base)) frame.frame_base_location = simgrid::dwarf::location_list(*info, attr_frame_base); } // Handle children: MC_dwarf_handle_children(info, die, unit, &frame, ns); // We sort them in order to have an (somewhat) efficient by name // lookup: boost::range::sort(frame.variables, MC_compare_variable); // Register it: if (klass == simgrid::dwarf::TagClass::Subprogram) info->subprograms[frame.id] = std::move(frame); else if (klass == simgrid::dwarf::TagClass::Scope) parent_frame->scopes.push_back(std::move(frame)); }
QVariant DwarfDie::attributeLocal(Dwarf_Half attributeType) const { Dwarf_Attribute attr; auto res = dwarf_attr(m_die, attributeType, &attr, nullptr); if (res != DW_DLV_OK) return {}; Dwarf_Half formType; res = dwarf_whatform(attr, &formType, nullptr); if (res != DW_DLV_OK) return {}; QVariant value; switch (formType) { case DW_FORM_data1: case DW_FORM_data2: case DW_FORM_data4: case DW_FORM_data8: case DW_FORM_udata: { Dwarf_Unsigned n; res = dwarf_formudata(attr, &n, nullptr); value = n; break; } case DW_FORM_sdata: { Dwarf_Signed n; res = dwarf_formsdata(attr, &n, nullptr); value = n; break; } case DW_FORM_string: case DW_FORM_strp: { char *str; res = dwarf_formstring(attr, &str, nullptr); value = QByteArray(str); break; } case DW_FORM_flag: case DW_FORM_flag_present: { Dwarf_Bool b; res = dwarf_formflag(attr, &b, nullptr); value = b ? true : false; break; } case DW_FORM_ref1: case DW_FORM_ref2: case DW_FORM_ref4: case DW_FORM_ref8: { Dwarf_Off offset; res = dwarf_global_formref(attr, &offset, nullptr); value = QVariant::fromValue(dwarfInfo()->dieAtOffset(offset)); break; } case DW_FORM_sec_offset: { Dwarf_Off offset; res = dwarf_global_formref(attr, &offset, nullptr); value = offset; break; } case DW_FORM_addr: { Dwarf_Addr addr; res = dwarf_formaddr(attr, &addr, nullptr); value = addr; break; } case DW_FORM_exprloc: { Dwarf_Unsigned len; Dwarf_Ptr block; res = dwarf_formexprloc(attr, &len, &block, nullptr); value = QVariant::fromValue(DwarfExpression(block, len, dwarfInfo()->elfFile()->addressSize())); break; } default: { const char* formName; res = dwarf_get_FORM_name(formType, &formName); if (res != DW_DLV_OK) return {}; value = QStringLiteral("TODO: ") + QString::fromLocal8Bit(formName); break; } } // post-process some well-known types switch (attributeType) { case DW_AT_decl_file: case DW_AT_call_file: { const auto fileIndex = value.value<Dwarf_Unsigned>(); // index 0 means not present, TODO handle that value = compilationUnit()->sourceFileForIndex(fileIndex -1); break; } case DW_AT_ranges: value = QVariant::fromValue(DwarfRanges(this, value.toLongLong())); break; case DW_AT_accessibility: stringifyEnum(value, &dwarf_get_ACCESS_name); break; case DW_AT_language: stringifyEnum(value, &dwarf_get_LANG_name); break; case DW_AT_virtuality: value = QVariant::fromValue(static_cast<DwarfVirtuality>(value.toInt())); break; case DW_AT_visibility: stringifyEnum(value, &dwarf_get_VIS_name); break; case DW_AT_identifier_case: stringifyEnum(value, &dwarf_get_ID_name); break; case DW_AT_inline: stringifyEnum(value, &dwarf_get_INL_name); break; case DW_AT_encoding: stringifyEnum(value, &dwarf_get_ATE_name); break; case DW_AT_ordering: stringifyEnum(value, &dwarf_get_ORD_name); break; case DW_AT_calling_convention: stringifyEnum(value, &dwarf_get_CC_name); break; case DW_AT_discr_list: stringifyEnum(value, &dwarf_get_DSC_name); break; default: break; } return value; }
static void show_all_attrs(Dwarf_Die die, unsigned long level, void *ndata){ Dwarf_Error error; Dwarf_Half tag; dwarf_tag(die,&tag,&error); const char *stag; dwarf_get_TAG_name(tag,&stag); Dwarf_Off off = 0x0; dwarf_die_CU_offset(die,&off,&error); fprintf(stderr,"[%u]<%x>%s\n",level,off,stag); char **sourceFiles; Dwarf_Signed num; int res; if( (res = dwarf_srcfiles(die,&sourceFiles,&num,&error)) == DW_DLV_OK){ fprintf(stderr,"Source Files Referenced:\n"); int i; for(i = 0; i < num; i++){ fprintf(stderr,"%s\n",sourceFiles[i]); dwarf_dealloc(d, sourceFiles[i],DW_DLA_STRING); } dwarf_dealloc(d, sourceFiles,DW_DLA_LIST); } Dwarf_Unsigned atcnt; Dwarf_Attribute *atlist; int errv; if((errv = dwarf_attrlist(die, &atlist, &atcnt, &error)) == DW_DLV_OK){ int i; for(i = 0; i < atcnt; i++){ Dwarf_Half attr; if(dwarf_whatattr(atlist[i],&attr,&error) == DW_DLV_OK){ const char *sattr; dwarf_get_AT_name(attr,&sattr); fprintf(stderr,"\t%s => ",sattr); }else{ fprintf(stderr,"\tCouldn't Get Attr Type!\n"); continue; } Dwarf_Half form; if(dwarf_whatform(atlist[i],&form,&error) == DW_DLV_OK){ //const char *formname; //dwarf_get_FORM_name(form,&formname); //fprintf(stderr,"[%s] ",formname); switch(form){ case DW_FORM_ref1: case DW_FORM_ref2: case DW_FORM_ref4: case DW_FORM_ref8: case DW_FORM_ref_udata: {Dwarf_Off offset; dwarf_formref(atlist[i],&offset,&error); fprintf(stderr,"%x\n",offset);} break; case DW_FORM_ref_addr: {Dwarf_Off offset; dwarf_global_formref(atlist[i],&offset,&error); fprintf(stderr,"%x\n",offset);} break; case DW_FORM_addr: {Dwarf_Addr addr; dwarf_formaddr(atlist[i],&addr,&error); fprintf(stderr,"%x\n",addr);} break; case DW_FORM_flag: {Dwarf_Bool flag; dwarf_formflag(atlist[i],&flag,&error); fprintf(stderr,"%s\n",flag ? "True" : "False");} break; case DW_FORM_udata: case DW_FORM_data1: case DW_FORM_data2: case DW_FORM_data4: case DW_FORM_data8: {Dwarf_Unsigned val; dwarf_formudata(atlist[i],&val,&error); fprintf(stderr,"%u\n",val);} break; case DW_FORM_sdata: {Dwarf_Signed val; dwarf_formsdata(atlist[i],&val,&error); fprintf(stderr,"%d\n",val);} break; case DW_FORM_block: case DW_FORM_block1: if(attr == DW_AT_location || attr == DW_AT_data_member_location || attr == DW_AT_vtable_elem_location || attr == DW_AT_string_length || attr == DW_AT_use_location || attr == DW_AT_return_addr){ /* Dwarf_Locdesc *locationList; Dwarf_Signed listLength; int ret = dwarf_loclist( atlist[i], &locationList, &listLength, &error ); int frameRel = 0; long offset = 0; decode_location(locationList,listLength,&offset,NULL,&frameRel); int i; for( i = 0; i < listLength; ++i){ dwarf_dealloc(d,locationList[i].ld_s,DW_DLA_LOC_BLOCK); } dwarf_dealloc(d,locationList,DW_DLA_LOCDESC); */ DC_location dcl; DC_get_location_attr_value(atlist[i],&dcl); fprintf(stderr," %s:",dcl.isFrameOffset ? "FP Offset" : "Address"); fprintf(stderr," %ld\n",dcl.offset); }else{ fprintf(stderr,"UNSUPPORTED ATTRIBUTE TYPE\n"); } break; case DW_FORM_string: {char *val; dwarf_formstring(atlist[i],&val,&error); fprintf(stderr,"%s\n",val);} break; case DW_FORM_strp: {char *str; if( (dwarf_formstring(atlist[i],&str,&error) == DW_DLV_OK) ){ fprintf(stderr,"%s\n",str); } } break; default: fprintf(stderr,"Unhandled Attribute Form!\n"); break; }; } dwarf_dealloc(d, atlist[i], DW_DLA_ATTR); } dwarf_dealloc(d, atlist, DW_DLA_LIST); } }
/* get_compiler_info */ int get_compiler_info(void) { Dwarf_Unsigned cu_header_length, abbrev_offset, next_cu_header; Dwarf_Half version, address_size; Dwarf_Signed attrcount, i, language; Dwarf_Die no_die = 0, cu_die; Dwarf_Attribute *attrs; Dwarf_Half attrcode; Dwarf_Debug dbg = 0; Dwarf_Error err; char *compiler = NULL; int fd = -1; OUTPUT_VERBOSE((5, "%s", _BLUE("Extracting DWARF info"))); /* Open the binary */ if (0 > (fd = open(globals.program_full, O_RDONLY))) { OUTPUT(("%s [%s]", _ERROR("opening program binary"), globals.program_full)); return PERFEXPERT_ERROR; } /* Initialize DWARF library */ if (DW_DLV_OK != dwarf_init(fd, DW_DLC_READ, 0, 0, &dbg, &err)) { OUTPUT(("%s", _ERROR("failed DWARF initialization"))); return PERFEXPERT_ERROR; } /* Find compilation unit header */ if (DW_DLV_ERROR == dwarf_next_cu_header(dbg, &cu_header_length, &version, &abbrev_offset, &address_size, &next_cu_header, &err)) { OUTPUT(("%s", _ERROR("reading DWARF CU header"))); return PERFEXPERT_ERROR; } /* Expect the CU to have a single sibling, a DIE */ if (DW_DLV_ERROR == dwarf_siblingof(dbg, no_die, &cu_die, &err)) { OUTPUT(("%s", _ERROR("getting sibling of CU"))); return PERFEXPERT_ERROR; } /* Find the DIEs attributes */ if (DW_DLV_OK != dwarf_attrlist(cu_die, &attrs, &attrcount, &err)) { OUTPUT(("%s", _ERROR("in dwarf_attlist"))); return PERFEXPERT_ERROR; } /* For each attribute... */ for (i = 0; i < attrcount; ++i) { if (DW_DLV_OK != dwarf_whatattr(attrs[i], &attrcode, &err)) { OUTPUT(("%s [%s]", _ERROR("in dwarf_whatattr"))); return PERFEXPERT_ERROR; } if (DW_AT_producer == attrcode) { if (DW_DLV_OK != dwarf_formstring(attrs[i], &compiler, &err)) { OUTPUT(("%s [%s]", _ERROR("in dwarf_formstring"))); return PERFEXPERT_ERROR; } else { OUTPUT_VERBOSE((5, " Compiler: %s", _CYAN(compiler))); } } if (DW_AT_language == attrcode) { if (DW_DLV_OK != dwarf_formsdata(attrs[i], &language, &err)) { OUTPUT(("%s [%s]", _ERROR("in dwarf_formsdata"))); return PERFEXPERT_ERROR; } else { OUTPUT_VERBOSE((5, " Language: %d", language)); } } } if (PERFEXPERT_SUCCESS != database_write(compiler, language)) { OUTPUT(("%s", _ERROR("writing to database"))); return PERFEXPERT_ERROR; } /* Finalize DWARF library */ if (DW_DLV_OK != dwarf_finish(dbg, &err)) { OUTPUT(("%s", _ERROR("failed DWARF finalization"))); return PERFEXPERT_ERROR; } close(fd); return PERFEXPERT_SUCCESS; }
static VALUE rd_attr_raw_value(VALUE self) { rd_attr_t *attr = GetAttr(self); Dwarf_Half form; Dwarf_Error err; union { Dwarf_Addr addr; Dwarf_Off off; Dwarf_Unsigned udata; Dwarf_Signed sdata; Dwarf_Bool bool; char *str; } val; VALUE top; chkerr1(dwarf_whatform(attr->attr, &form, &err), &err, self); switch (form) { case DW_FORM_addr: chkerr1(dwarf_formaddr(attr->attr, &val.addr, &err), &err, self); return ULL2NUM(val.addr); case DW_FORM_ref1: case DW_FORM_ref2: case DW_FORM_ref4: case DW_FORM_ref8: case DW_FORM_ref_udata: chkerr1(dwarf_global_formref(attr->attr, &val.off, &err), &err, self); top = rb_ivar_get(self, id_at_top); return rdwarf_die_at(top, LL2NUM(val.off)); case DW_FORM_data1: case DW_FORM_data2: case DW_FORM_data4: case DW_FORM_data8: case DW_FORM_udata: chkerr1(dwarf_formudata(attr->attr, &val.udata, &err), &err, self); return ULL2NUM(val.udata); case DW_FORM_sdata: chkerr1(dwarf_formsdata(attr->attr, &val.sdata, &err), &err, self); return LL2NUM(val.sdata); case DW_FORM_flag: chkerr1(dwarf_formflag(attr->attr, &val.bool, &err), &err, self); return val.bool ? Qtrue : Qfalse; case DW_FORM_strp: case DW_FORM_string: chkerr1(dwarf_formstring(attr->attr, &val.str, &err), &err, self); return rb_str_new_cstr(val.str); } return sym_unsupported_type; }