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); } }
char *get_type_str(Dwarf_Die *die) { static char buf[256] = ""; char *ptr = NULL; Dwarf_Die tdie; Dwarf_Attribute attr; if (!dwarf_attr(die, DW_AT_type, &attr)) return "void"; dwarf_formref_die(&attr, &tdie); if (dwarf_tag(&tdie) == DW_TAG_array_type) ptr = "[]"; else if (dwarf_tag(&tdie) == DW_TAG_pointer_type) ptr = "*"; else goto end_ok; dwarf_attr(&tdie, DW_AT_type, &attr); dwarf_formref_die(&attr, &tdie); end_ok: sprintf(buf, "%s%s", dwarf_diename(&tdie), (ptr) ? ptr : ""); return buf; }
/* BASE must be a base type DIE referenced by a typed DWARF expression op. */ static void print_base_type (Dwarf_Die *base) { assert (dwarf_tag (base) == DW_TAG_base_type); Dwarf_Attribute encoding; Dwarf_Word enctype; if (dwarf_attr (base, DW_AT_encoding, &encoding) == NULL || dwarf_formudata (&encoding, &enctype) != 0) error (EXIT_FAILURE, 0, "base type without encoding"); Dwarf_Attribute bsize; Dwarf_Word bits; if (dwarf_attr (base, DW_AT_byte_size, &bsize) != NULL && dwarf_formudata (&bsize, &bits) == 0) bits *= 8; else if (dwarf_attr (base, DW_AT_bit_size, &bsize) == NULL || dwarf_formudata (&bsize, &bits) != 0) error (EXIT_FAILURE, 0, "base type without byte or bit size"); printf ("{%s,%s,%" PRIu64 "@[%" PRIx64 "]}", dwarf_diename (base), dwarf_encoding_string (enctype), bits, dwarf_dieoffset (base)); }
int _dwarf_internal_get_die_comp_dir(Dwarf_Die die, const char **compdir_out, const char **compname_out, Dwarf_Error *error) { Dwarf_Attribute comp_dir_attr = 0; Dwarf_Attribute comp_name_attr = 0; int resattr = 0; Dwarf_Debug dbg = 0; dbg = die->di_cu_context->cc_dbg; resattr = dwarf_attr(die, DW_AT_name, &comp_name_attr, error); if (resattr == DW_DLV_ERROR) { return resattr; } if (resattr == DW_DLV_OK) { int cres = DW_DLV_ERROR; char *name = 0; cres = dwarf_formstring(comp_name_attr, &name, error); if (cres == DW_DLV_ERROR) { dwarf_dealloc(dbg, comp_name_attr, DW_DLA_ATTR); return cres; } else if (cres == DW_DLV_OK) { *compname_out = (const char *)name; } else { /* FALL thru */ } } if (resattr == DW_DLV_OK) { dwarf_dealloc(dbg, comp_name_attr, DW_DLA_ATTR); } resattr = dwarf_attr(die, DW_AT_comp_dir, &comp_dir_attr, error); if (resattr == DW_DLV_ERROR) { return resattr; } if (resattr == DW_DLV_OK) { int cres = DW_DLV_ERROR; char *cdir = 0; cres = dwarf_formstring(comp_dir_attr, &cdir, error); if (cres == DW_DLV_ERROR) { dwarf_dealloc(dbg, comp_dir_attr, DW_DLA_ATTR); return cres; } else if (cres == DW_DLV_OK) { *compdir_out = (const char *) cdir; } else { /* FALL thru */ } } if (resattr == DW_DLV_OK) { dwarf_dealloc(dbg, comp_dir_attr, DW_DLA_ATTR); } return resattr; }
/** * die_get_data_member_location - Get the data-member offset * @mb_die: a DIE of a member of a data structure * @offs: The offset of the member in the data structure * * Get the offset of @mb_die in the data structure including @mb_die, and * stores result offset to @offs. If any error occurs this returns errno. */ int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs) { Dwarf_Attribute attr; Dwarf_Op *expr; size_t nexpr; int ret; if (dwarf_attr(mb_die, DW_AT_data_member_location, &attr) == NULL) return -ENOENT; if (dwarf_formudata(&attr, offs) != 0) { /* DW_AT_data_member_location should be DW_OP_plus_uconst */ ret = dwarf_getlocation(&attr, &expr, &nexpr); if (ret < 0 || nexpr == 0) return -ENOENT; if (expr[0].atom != DW_OP_plus_uconst || nexpr != 1) { pr_debug("Unable to get offset:Unexpected OP %x (%zd)\n", expr[0].atom, nexpr); return -ENOTSUP; } *offs = (Dwarf_Word)expr[0].number; } return 0; }
/** * cu_get_comp_dir - Get the path of compilation directory * @cu_die: a CU DIE * * Get the path of compilation directory of given @cu_die. * Since this depends on DW_AT_comp_dir, older gcc will not * embedded it. In that case, this returns NULL. */ const char *cu_get_comp_dir(Dwarf_Die *cu_die) { Dwarf_Attribute attr; if (dwarf_attr(cu_die, DW_AT_comp_dir, &attr) == NULL) return NULL; return dwarf_formstring(&attr); }
Dwarf_Attribute DieHolder::get_attr(int attr) { Dwarf_Attribute attrib = NULL; MapAttrs::const_iterator iter = m_attrs.find(attr); if(iter == m_attrs.end()) { Dwarf_Error err = NULL; // atribute may be NULL CHECK_DWERR2(dwarf_attr(m_die, attr, &attrib, &err) == DW_DLV_ERROR, err, "cannot get DIE attribute %d", attr); if(attrib != NULL) { m_attrs[attr] = attrib; } else if(m_origin_holder.get() != NULL) { attrib = m_origin_holder->get_attr(attr); } } else { attrib = iter->second; } return attrib; }
bool supported_language(Dwarf_Die *cu) { int ret; Dwarf_Word lang; Dwarf_Attribute at; if (dwarf_attr(cu, DW_AT_language, &at) == NULL) { warn("CU %s: unknown language", dwarf_diename(cu)); return false; } ret = dwarf_formudata(&at, &lang); fail_if(ret == -1, "dwarf_formudata"); switch (lang) { case DW_LANG_C89: case DW_LANG_C: case DW_LANG_C99: /* good! */ break; case DW_LANG_C_plus_plus: warn("CU %s: C++ not supported", dwarf_diename(cu)); return false; break; default: debug("CU %s: unsupported language: 0x%lx", dwarf_diename(cu), (unsigned long)lang); return false; break; } return true; }
static int __die_walk_instances_cb(Dwarf_Die *inst, void *data) { struct __instance_walk_param *iwp = data; Dwarf_Attribute attr_mem; Dwarf_Die origin_mem; Dwarf_Attribute *attr; Dwarf_Die *origin; int tmp; attr = dwarf_attr(inst, DW_AT_abstract_origin, &attr_mem); if (attr == NULL) return DIE_FIND_CB_CONTINUE; origin = dwarf_formref_die(attr, &origin_mem); if (origin == NULL || origin->addr != iwp->addr) return DIE_FIND_CB_CONTINUE; /* Ignore redundant instances */ if (dwarf_tag(inst) == DW_TAG_inlined_subroutine) { dwarf_decl_line(origin, &tmp); if (die_get_call_lineno(inst) == tmp) { tmp = die_get_decl_fileno(origin); if (die_get_call_fileno(inst) == tmp) return DIE_FIND_CB_CONTINUE; } } iwp->retval = iwp->callback(inst, iwp->data); return (iwp->retval) ? DIE_FIND_CB_END : DIE_FIND_CB_CONTINUE; }
/* Get the size (in words) */ static int get_size(Dwarf_Debug dbg, Dwarf_Die die) { Dwarf_Attribute attr; Dwarf_Unsigned size; int ret; ret = dwarf_attr(die, DW_AT_byte_size, &attr, NULL); if (ret != DW_DLV_OK) { fprintf(stderr, "SET dwarf: Error in dwarf_attr()\n"); return 1; } ret = dwarf_formudata(attr, &size, NULL); dwarf_dealloc(dbg, attr, DW_DLA_ATTR); if (ret != DW_DLV_OK) { fprintf(stderr, "SET dwarf: Error in dwarf_formudata()\n"); return 1; } /* Increment the parameter number of the function */ func_dwarf[local_func_idx].param_size += (size + 3) >> 2; return 0; }
/** * die_is_func_def - Ensure that this DIE is a subprogram and definition * @dw_die: a DIE * * Ensure that this DIE is a subprogram and NOT a declaration. This * returns true if @dw_die is a function definition. **/ bool die_is_func_def(Dwarf_Die *dw_die) { Dwarf_Attribute attr; return (dwarf_tag(dw_die) == DW_TAG_subprogram && dwarf_attr(dw_die, DW_AT_declaration, &attr) == NULL); }
static Dwarf_Die get_cu_by_iaddr(unsigned long iaddr){ Dwarf_Unsigned cu_h_len; Dwarf_Half verstamp; Dwarf_Unsigned abbrev_offset; Dwarf_Half addrsize; Dwarf_Unsigned next_cu; Dwarf_Error error; while( dwarf_next_cu_header(d, &cu_h_len, &verstamp, &abbrev_offset, &addrsize, &next_cu, &error) == DW_DLV_OK ){ Dwarf_Die cu_die = NULL; int sibret; int dieno = 0; while((sibret = dwarf_siblingof(d,cu_die,&cu_die,&error)) != DW_DLV_NO_ENTRY && sibret != DW_DLV_ERROR){ Dwarf_Attribute lowattr; if( dwarf_attr(cu_die, DW_AT_low_pc, &lowattr, &error) != DW_DLV_OK ){ continue; } Dwarf_Attribute highattr; if( dwarf_attr(cu_die, DW_AT_high_pc, &highattr, &error) != DW_DLV_OK ){ continue; } Dwarf_Addr loval,hival; dwarf_formaddr(lowattr,&loval,&error); dwarf_formaddr(highattr,&hival,&error); if(iaddr >= loval && iaddr <= hival){ return cu_die; } } } return (Dwarf_Die)-1; }
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; }
static struct dwarf_subprogram_t *read_from_cus(Dwarf_Debug dbg) { Dwarf_Unsigned cu_header_length, abbrev_offset, next_cu_header; Dwarf_Half version_stamp, address_size; Dwarf_Error err; Dwarf_Die no_die = 0, cu_die, child_die; int ret = DW_DLV_OK; struct dwarf_subprogram_t *subprograms = NULL; Dwarf_Unsigned language = 0; Dwarf_Attribute language_attr = 0; while (ret == DW_DLV_OK) { ret = dwarf_next_cu_header( dbg, &cu_header_length, &version_stamp, &abbrev_offset, &address_size, &next_cu_header, &err); DWARF_ASSERT(ret, err); if (ret == DW_DLV_NO_ENTRY) continue; /* TODO: If the CU can provide an address range then we can skip over * all the entire die if none of our addresses match */ /* Expect the CU to have a single sibling - a DIE */ ret = dwarf_siblingof(dbg, no_die, &cu_die, &err); if (ret == DW_DLV_ERROR) { continue; } DWARF_ASSERT(ret, err); /* Get compilation unit language attribute */ ret = dwarf_attr(cu_die, DW_AT_language, &language_attr, &err); DWARF_ASSERT(ret, err); if (ret != DW_DLV_NO_ENTRY) { /* Get language attribute data */ ret = dwarf_formudata(language_attr, &language, &err); DWARF_ASSERT(ret, err); dwarf_dealloc(dbg, language_attr, DW_DLA_ATTR); } /* Expect the CU DIE to have children */ ret = dwarf_child(cu_die, &child_die, &err); DWARF_ASSERT(ret, err); handle_die(&subprograms, dbg, cu_die, child_die, language); dwarf_dealloc(dbg, cu_die, DW_DLA_DIE); } return subprograms; }
/* 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; }
/** * die_get_call_lineno - Get callsite line number of inline-function instance * @in_die: a DIE of an inlined function instance * * Get call-site line number of @in_die. This means from where the inline * function is called. */ int die_get_call_lineno(Dwarf_Die *in_die) { Dwarf_Attribute attr; Dwarf_Word ret; if (!dwarf_attr(in_die, DW_AT_call_line, &attr)) return -ENOENT; dwarf_formudata(&attr, &ret); return (int)ret; }
static int die_get_byte_size(Dwarf_Die *tp_die) { Dwarf_Attribute attr; Dwarf_Word ret; if (dwarf_attr(tp_die, DW_AT_byte_size, &attr) == NULL || dwarf_formudata(&attr, &ret) != 0) return 0; return (int)ret; }
static bool die_is_signed_type(Dwarf_Die *tp_die) { Dwarf_Attribute attr; Dwarf_Word ret; if (dwarf_attr(tp_die, DW_AT_encoding, &attr) == NULL || dwarf_formudata(&attr, &ret) != 0) return false; return (ret == DW_ATE_signed_char || ret == DW_ATE_signed || ret == DW_ATE_signed_fixed); }
/* Return DW_DLV_OK if handling this went ok. */ static int handle_attr_addr(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Half attrnum, Dwarf_Error * perr) { int res = DW_DLV_OK; Dwarf_Off offset; Dwarf_Addr addr; Dwarf_Half form; int ares; Dwarf_Attribute attr; ares = dwarf_attr(die, attrnum, &attr, perr); if (ares == DW_DLV_OK) { int formres = dwarf_whatform(attr, &form, perr); switch (formres) { case DW_DLV_OK: break; case DW_DLV_ERROR: case DW_DLV_NO_ENTRY: /* impossible. */ return formres; } switch (form) { case DW_FORM_ref_addr: case DW_FORM_addr: res = dwarf_attr_offset(die, attr, &offset, perr); if (res == DW_DLV_OK) { ares = dwarf_formaddr(attr, &addr, perr); if (ares == DW_DLV_OK) { send_addr_note(DW_SECTION_INFO, offset, addr); } else if (ares == DW_DLV_ERROR) { return ares; } /* no entry: ok. */ } else { res = DW_DLV_ERROR; /* NO_ENTRY is impossible. */ } break; default: /* surprising! An error? */ ; /* do nothing */ } dwarf_dealloc(dbg, attr, DW_DLA_ATTR); } else { res = ares; } return res; }
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; }
static int call_probe_finder(Dwarf_Die *sc_die, struct probe_finder *pf) { Dwarf_Attribute fb_attr; size_t nops; int ret; if (!sc_die) { pr_err("Caller must pass a scope DIE. Program error.\n"); return -EINVAL; } if (dwarf_tag(sc_die) != DW_TAG_subprogram) { if (!die_find_realfunc(&pf->cu_die, pf->addr, &pf->sp_die)) { pr_warning("Failed to find probe point in any " "functions.\n"); return -ENOENT; } } else memcpy(&pf->sp_die, sc_die, sizeof(Dwarf_Die)); dwarf_attr(&pf->sp_die, DW_AT_frame_base, &fb_attr); ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1); if (ret <= 0 || nops == 0) { pf->fb_ops = NULL; #if _ELFUTILS_PREREQ(0, 142) } else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa && pf->cfi != NULL) { Dwarf_Frame *frame; if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 || dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) { pr_warning("Failed to get call frame on 0x%jx\n", (uintmax_t)pf->addr); return -ENOENT; } #endif } ret = pf->callback(sc_die, pf); pf->fb_ops = NULL; return ret; }
/* Call probe_finder callback with scope DIE */ static int call_probe_finder(Dwarf_Die *sc_die, struct probe_finder *pf) { Dwarf_Attribute fb_attr; size_t nops; int ret; if (!sc_die) { pr_err("Caller must pass a scope DIE. Program error.\n"); return -EINVAL; } /* If not a real subprogram, find a real one */ if (!die_is_func_def(sc_die)) { if (!die_find_realfunc(&pf->cu_die, pf->addr, &pf->sp_die)) { pr_warning("Failed to find probe point in any " "functions.\n"); return -ENOENT; } } else memcpy(&pf->sp_die, sc_die, sizeof(Dwarf_Die)); /* Get the frame base attribute/ops from subprogram */ dwarf_attr(&pf->sp_die, DW_AT_frame_base, &fb_attr); ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1); if (ret <= 0 || nops == 0) { pf->fb_ops = NULL; #if _ELFUTILS_PREREQ(0, 142) } else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa && pf->cfi != NULL) { Dwarf_Frame *frame; if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 || dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) { pr_warning("Failed to get call frame on 0x%jx\n", (uintmax_t)pf->addr); return -ENOENT; } #endif } /* Call finder's callback handler */ ret = pf->callback(sc_die, pf); /* *pf->fb_ops will be cached in libdw. Don't free it. */ pf->fb_ops = NULL; return ret; }
/* Call probe_finder callback with real subprogram DIE */ static int call_probe_finder(Dwarf_Die *sp_die, struct probe_finder *pf) { Dwarf_Die die_mem; Dwarf_Attribute fb_attr; size_t nops; int ret; /* If no real subprogram, find a real one */ if (!sp_die || dwarf_tag(sp_die) != DW_TAG_subprogram) { sp_die = die_find_real_subprogram(&pf->cu_die, pf->addr, &die_mem); if (!sp_die) { pr_warning("Failed to find probe point in any " "functions.\n"); return -ENOENT; } } /* Get the frame base attribute/ops */ dwarf_attr(sp_die, DW_AT_frame_base, &fb_attr); ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1); if (ret <= 0 || nops == 0) { pf->fb_ops = NULL; #if _ELFUTILS_PREREQ(0, 142) } else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa && pf->cfi != NULL) { Dwarf_Frame *frame; if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 || dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) { pr_warning("Failed to get call frame on 0x%jx\n", (uintmax_t)pf->addr); return -ENOENT; } #endif } /* Call finder's callback handler */ ret = pf->callback(sp_die, pf); /* *pf->fb_ops will be cached in libdw. Don't free it. */ pf->fb_ops = NULL; return ret; }
static int probe_point_search_cb(Dwarf_Die *sp_die, void *data) { struct dwarf_callback_param *param = data; struct probe_finder *pf = param->data; struct perf_probe_point *pp = &pf->pev->point; Dwarf_Attribute attr; if (dwarf_tag(sp_die) != DW_TAG_subprogram || !die_compare_name(sp_die, pp->function) || dwarf_attr(sp_die, DW_AT_declaration, &attr)) return DWARF_CB_OK; if (pp->file && strtailcmp(pp->file, dwarf_decl_file(sp_die))) return DWARF_CB_OK; pf->fname = dwarf_decl_file(sp_die); if (pp->line) { dwarf_decl_line(sp_die, &pf->lno); pf->lno += pp->line; param->retval = find_probe_point_by_line(pf); } else if (!dwarf_func_inline(sp_die)) { if (pp->lazy_line) param->retval = find_probe_point_lazy(sp_die, pf); else { if (dwarf_entrypc(sp_die, &pf->addr) != 0) { pr_warning("Failed to get entry address of " "%s.\n", dwarf_diename(sp_die)); param->retval = -ENOENT; return DWARF_CB_ABORT; } pf->addr += pp->offset; param->retval = call_probe_finder(sp_die, pf); } } else param->retval = die_walk_instances(sp_die, probe_point_inline_cb, (void *)pf); return DWARF_CB_ABORT; }
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); }
/* Get type die, but skip qualifiers and typedef */ static Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem) { Dwarf_Attribute attr; int tag; do { if (dwarf_attr(vr_die, DW_AT_type, &attr) == NULL || dwarf_formref_die(&attr, die_mem) == NULL) return NULL; tag = dwarf_tag(die_mem); vr_die = die_mem; } while (tag == DW_TAG_const_type || tag == DW_TAG_restrict_type || tag == DW_TAG_volatile_type || tag == DW_TAG_shared_type || tag == DW_TAG_typedef); return die_mem; }
int type_off(Dwarf_Die *die, Dwarf_Off *ref_off, Dwarf_Error *err) { Dwarf_Attribute type; int status; if ((status = dwarf_attr(*die, DW_AT_type, &type, err)) != DW_DLV_OK) { if (status == DW_DLV_NO_ENTRY) { fprintf(stderr, "No type information associated with die\n"); } else { fprintf(stderr, "Error %d in getting type attribute: %s\n", status, dwarf_errmsg(*err)); } return status; } if ((status = dwarf_global_formref(type, ref_off, err)) != DW_DLV_OK) { fprintf(stderr, "Error %d in getting type offset: %s\n", status, dwarf_errmsg(*err)); return status; } return DW_DLV_OK; }
long get_location_of_scoped_variable(void *addr,const char * varname){ Dwarf_Error error; unsigned long a = (unsigned long)addr; reset_cu_header_info(); Dwarf_Die cu = get_cu_by_iaddr(a); reset_cu_header_info(); if(a != 0xffffffffffffffff && (long int)cu != -1){ Dwarf_Die v; v = (Dwarf_Die)0; DC_get_info_for_scoped_variable(cu,0,a,varname,&v); if( v != (Dwarf_Die)-1 ){ Dwarf_Attribute loc; dwarf_attr(v,DW_AT_location,&loc,&error); DC_location dloc; DC_get_location_attr_value(loc,&dloc); return dloc.offset; } }else{ fprintf(stderr,"Can't find \"%s\" in scope defined by <%x>\n",varname, a); } fprintf(stderr,"\n"); }
static Dwarf_Attribute die_attr(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, int req) { Dwarf_Attribute attr; int rc; if ((rc = dwarf_attr(die, name, &attr, &dw->dw_err)) == DW_DLV_OK) { return (attr); } else if (rc == DW_DLV_NO_ENTRY) { if (req) { terminate("die %llu: no attr 0x%x\n", die_off(dw, die), name); } else { return (NULL); } } terminate("die %llu: failed to get attribute for type: %s\n", die_off(dw, die), dwarf_errmsg(dw->dw_err)); /*NOTREACHED*/ return (NULL); }
/* Show a variables in kprobe event format */ static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf) { Dwarf_Attribute attr; Dwarf_Die die_mem; Dwarf_Op *expr; size_t nexpr; int ret; if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL) goto error; /* TODO: handle more than 1 exprs */ ret = dwarf_getlocation_addr(&attr, pf->addr, &expr, &nexpr, 1); if (ret <= 0 || nexpr == 0) goto error; ret = convert_location(expr, pf); if (ret == 0 && pf->pvar->field) { ret = convert_variable_fields(vr_die, pf->pvar->var, pf->pvar->field, &pf->tvar->ref, &die_mem); vr_die = &die_mem; } if (ret == 0) { if (pf->pvar->type) { pf->tvar->type = strdup(pf->pvar->type); if (pf->tvar->type == NULL) ret = -ENOMEM; } else ret = convert_variable_type(vr_die, pf->tvar); } /* *expr will be cached in libdw. Don't free it. */ return ret; error: /* TODO: Support const_value */ pr_err("Failed to find the location of %s at this address.\n" " Perhaps, it has been optimized out.\n", pf->pvar->var); return -ENOENT; }