static bool MC_dwarf_attr_flag(Dwarf_Die * die, int attribute, bool integrate) { Dwarf_Attribute attr; if ((integrate ? dwarf_attr_integrate(die, attribute, &attr) : dwarf_attr(die, attribute, &attr)) == 0) return false; bool result; if (dwarf_formflag(&attr, &result)) xbt_die("Unexpected form for attribute %s", simgrid::dwarf::attrname(attribute)); return result; }
Dwarf_Bool DieHolder::get_attr_flag(int attr) { Dwarf_Attribute attrib = get_attr(attr); Dwarf_Bool flag = (attrib != NULL); if(flag) { Dwarf_Error err = NULL; CHECK_DWERR(dwarf_formflag(attrib, &flag, &err), err, "cannot retrieve flag from attr %d", attr); } return flag; }
static int die_bool(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, Dwarf_Bool *valp, int req) { Dwarf_Attribute attr; Dwarf_Bool val; if ((attr = die_attr(dw, die, name, req)) == NULL) return (0); /* die_attr will terminate for us if necessary */ if (dwarf_formflag(attr, &val, &dw->dw_err) != DW_DLV_OK) { terminate("die %llu: failed to get bool (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 ppc_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp) { /* Start with the function's type, and get the DW_AT_type attribute, which is the type of the return value. */ Dwarf_Attribute attr_mem; Dwarf_Attribute *attr = dwarf_attr_integrate (functypedie, DW_AT_type, &attr_mem); if (attr == NULL) /* The function has no return value, like a `void' function in C. */ return 0; Dwarf_Die die_mem; Dwarf_Die *typedie = dwarf_formref_die (attr, &die_mem); int tag = dwarf_tag (typedie); /* Follow typedefs and qualifiers to get to the actual type. */ while (tag == DW_TAG_typedef || tag == DW_TAG_const_type || tag == DW_TAG_volatile_type || tag == DW_TAG_restrict_type || tag == DW_TAG_mutable_type) { attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem); typedie = dwarf_formref_die (attr, &die_mem); tag = dwarf_tag (typedie); } Dwarf_Word size; switch (tag) { case -1: return -1; case DW_TAG_subrange_type: if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size)) { attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem); typedie = dwarf_formref_die (attr, &die_mem); tag = dwarf_tag (typedie); } /* Fall through. */ case DW_TAG_base_type: case DW_TAG_enumeration_type: case DW_TAG_pointer_type: case DW_TAG_ptr_to_member_type: if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size, &attr_mem), &size) != 0) { if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type) size = 4; else return -1; } if (size <= 8) { if (tag == DW_TAG_base_type) { Dwarf_Word encoding; if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding, &attr_mem), &encoding) != 0) return -1; if (encoding == DW_ATE_float) { *locp = loc_fpreg; return nloc_fpreg; } } intreg: *locp = loc_intreg; return size <= 4 ? nloc_intreg : nloc_intregpair; } aggregate: *locp = loc_aggregate; return nloc_aggregate; case DW_TAG_array_type: { bool is_vector; if (dwarf_formflag (dwarf_attr_integrate (typedie, DW_AT_GNU_vector, &attr_mem), &is_vector) == 0 && is_vector && dwarf_aggregate_size (typedie, &size) == 0) switch (size) { case 16: if (ppc_altivec_abi ()) { *locp = loc_vmxreg; return nloc_vmxreg; } *locp = loc_intreg; return nloc_intregquad; } } /* Fall through. */ case DW_TAG_structure_type: case DW_TAG_class_type: case DW_TAG_union_type: if (SVR4_STRUCT_RETURN && dwarf_aggregate_size (typedie, &size) == 0 && size > 0 && size <= 8) goto intreg; goto aggregate; } /* XXX We don't have a good way to return specific errors from ebl calls. This value means we do not understand the type, but it is well-formed DWARF and might be valid. */ return -2; }
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); } }
static struct variable* analyze_variable(Dwarf_Die *die, Dwarf_Files *files, struct expr_context *ctx) { int ret; Dwarf_Attribute at; struct variable* var; /* ignore declarations */ if (dwarf_attr_integrate(die, DW_AT_declaration, &at) != NULL) { bool flag; ret = dwarf_formflag(&at, &flag); fail_if(ret == -1, "dwarf_formflag"); if (flag) return NULL; } var = xalloc(sizeof(struct variable)); analyze_name_location(die, files, &var->name, &var->loc); if (dwarf_attr_integrate(die, DW_AT_type, &at) != NULL) { Dwarf_Die type_die; if (dwarf_formref_die(&at, &type_die) == NULL) fail("dwarf_formref_die"); analyze_type(&type_die, &(var->type)); } if (dwarf_attr_integrate(die, DW_AT_const_value, &at) != NULL) { Dwarf_Word w; Dwarf_Block bl; unsigned int form = dwarf_whatform(&at); debug("variable %s has constant value of form %x", var->name, form); if (dwarf_formudata(&at, &w) == 0) { fail_if(sizeof(w) < var->type.width, "constant value too small"); var->value = xalloc(var->type.width); memcpy(var->value, &w, var->type.width); } else if (dwarf_formblock(&at, &bl) == 0) { fail_if(bl.length < var->type.width, "constant value too small"); var->value = xalloc(var->type.width); memcpy(var->value, bl.data, var->type.width); } else { warn("unable to get constant value of variable %x (form %x)", var->name, form); } } else if (dwarf_attr_integrate(die, DW_AT_location, &at) != NULL) { size_t exprlen; Dwarf_Op *expr; ret = dwarf_getlocation_addr(&at, ctx->ip, &expr, &exprlen, 1); if (ret != 1) { if (ret == -1) /* it seems that elfutils have some kind of problem with * DW_OP_GNU_entry_value but that operation is useless for us * anyway */ warn("cannot get location for variable %s (ip: %lx), %s", var->name, ctx->ip, dwarf_errmsg(-1)); else if (ret == 0) debug("no location available for variable %s (ip: %lx)", var->name, ctx->ip); else fail("unreachable reached"); return var; } var->value = evaluate_loc_expr(expr, exprlen, ctx, var->type.width); } return var; }