static void print_comp_dir(Dwarf_Debug dbg,Dwarf_Die die,int level, struct srcfilesdata *sf) { int res; Dwarf_Error error = 0; Dwarf_Attribute *attrbuf = 0; Dwarf_Signed attrcount = 0; Dwarf_Unsigned i; res = dwarf_attrlist(die,&attrbuf,&attrcount,&error); if(res != DW_DLV_OK) { return; } sf->srcfilesres = dwarf_srcfiles(die,&sf->srcfiles,&sf->srcfilescount, &error); for(i = 0; i < attrcount ; ++i) { Dwarf_Half aform; res = dwarf_whatattr(attrbuf[i],&aform,&error); if(res == DW_DLV_OK) { if(aform == DW_AT_comp_dir) { char *name = 0; res = dwarf_formstring(attrbuf[i],&name,&error); if(res == DW_DLV_OK) { printf( "<%3d> compilation directory : \"%s\"\n", level,name); } } if(aform == DW_AT_stmt_list) { /* Offset of stmt list for this CU in .debug_line */ } } dwarf_dealloc(dbg,attrbuf[i],DW_DLA_ATTR); } dwarf_dealloc(dbg,attrbuf,DW_DLA_LIST); }
Dwarf_Loc dwarf_get_variable_location(Dwarf_Die die, struct dwarf_compilation_unit * unit){ Dwarf_Error error = 0; Dwarf_Attribute *attrbuf = 0; Dwarf_Signed attrcount = 0; Dwarf_Unsigned i; Dwarf_Locdesc *llbuf = 0; Dwarf_Locdesc **llbufarray = 0; Dwarf_Signed no_of_elements; int lres = 0; Dwarf_Loc first_loc; int res = dwarf_attrlist(die,&attrbuf,&attrcount,&error); if(res != DW_DLV_OK) { return first_loc; } for(i = 0; i < attrcount ; ++i) { Dwarf_Half aform; res = dwarf_whatattr(attrbuf[i],&aform,&error); if(aform == DW_AT_location) { lres = dwarf_loclist_n(attrbuf[i], &llbufarray, &no_of_elements, &error); if (llbufarray[0]->ld_s){ first_loc = (llbufarray[0]->ld_s)[0]; return first_loc; } } } return first_loc; }
QVector< Dwarf_Half > DwarfDie::attributes() const { Dwarf_Attribute* attrList; Dwarf_Signed attrCount; auto res = dwarf_attrlist(m_die, &attrList, &attrCount, nullptr); if (res != DW_DLV_OK) return {}; QVector<Dwarf_Half> attrs; attrs.reserve(attrCount); for (int i = 0; i < attrCount; ++i) { Dwarf_Half attrType; res = dwarf_whatattr(attrList[i], &attrType, nullptr); if (res != DW_DLV_OK) continue; attrs.push_back(attrType); } dwarf_dealloc(dwarfHandle(), attrList, DW_DLA_LIST); if (const auto die = inheritedFrom()) { auto inheritedAttrs = die->attributes(); // remove attributes that must not be inherited inheritedAttrs.erase( std::remove_if(inheritedAttrs.begin(), inheritedAttrs.end(), [](Dwarf_Half at) { return at == DW_AT_declaration || at == DW_AT_sibling; }), inheritedAttrs.end()); attrs += inheritedAttrs; std::sort(attrs.begin(), attrs.end()); attrs.erase(std::unique(attrs.begin(), attrs.end()), attrs.end()); } return attrs; }
static void print_subprog(Dwarf_Debug dbg,Dwarf_Die die, int level, struct srcfilesdata *sf) { int res; Dwarf_Error error = 0; Dwarf_Attribute *attrbuf = 0; Dwarf_Addr lowpc = 0; Dwarf_Addr highpc = 0; Dwarf_Signed attrcount = 0; Dwarf_Unsigned i; Dwarf_Unsigned filenum = 0; Dwarf_Unsigned linenum = 0; char *filename = 0; res = dwarf_attrlist(die,&attrbuf,&attrcount,&error); if(res != DW_DLV_OK) { return; } for(i = 0; i < attrcount ; ++i) { Dwarf_Half aform; res = dwarf_whatattr(attrbuf[i],&aform,&error); if(res == DW_DLV_OK) { if(aform == DW_AT_decl_file) { get_number(attrbuf[i],&filenum); if((filenum > 0) && (sf->srcfilescount > (filenum-1))) { filename = sf->srcfiles[filenum-1]; } } if(aform == DW_AT_decl_line) { get_number(attrbuf[i],&linenum); } if(aform == DW_AT_low_pc) { get_addr(attrbuf[i],&lowpc); } if(aform == DW_AT_high_pc) { get_addr(attrbuf[i],&highpc); } } dwarf_dealloc(dbg,attrbuf[i],DW_DLA_ATTR); } if(filenum || linenum) { printf("<%3d> file: %" DW_PR_DUu " %s line %" DW_PR_DUu "\n",level,filenum,filename?filename:"",linenum); } if(lowpc) { printf("<%3d> low_pc : 0x%" DW_PR_DUx "\n", level, (Dwarf_Unsigned)lowpc); } if(highpc) { printf("<%3d> high_pc: 0x%" DW_PR_DUx "\n", level, (Dwarf_Unsigned)highpc); } dwarf_dealloc(dbg,attrbuf,DW_DLA_LIST); }
static int get_attributes(Dwarf_Debug dbg,Dwarf_Die die, int level, struct srcfilesdata *sf, struct attributes *attr) { int res; Dwarf_Error error = 0; Dwarf_Attribute *attrbuf = 0; Dwarf_Addr lowpc = 0; Dwarf_Addr highpc = 0; Dwarf_Signed attrcount = 0; Dwarf_Unsigned i; Dwarf_Unsigned filenum = 0; Dwarf_Unsigned linenum = 0; char *filename = 0; int ret = 1; res = dwarf_attrlist(die,&attrbuf,&attrcount,&error); if(res != DW_DLV_OK) { return ret; } for(i = 0; i < attrcount ; ++i) { Dwarf_Half aform; res = dwarf_whatattr(attrbuf[i],&aform,&error); if(res == DW_DLV_OK) { if(aform == DW_AT_decl_file) { get_number(attrbuf[i],&filenum); if((filenum > 0) && (sf->srcfilescount > (filenum-1))) { filename = sf->srcfiles[filenum-1]; attr->filename = filename; } } if(aform == DW_AT_declaration) { Dwarf_Unsigned size=0; get_number(attrbuf[i],&size); ret =0; } if(aform == DW_AT_byte_size) { attr->size=0; get_number(attrbuf[i],&attr->size); } if(aform == DW_AT_data_member_location) { attr->member_location=0; get_number(attrbuf[i],&attr->member_location); } if(aform == DW_AT_type) { attr->type_offset = 0; dwarf_global_formref(attrbuf[i],&(attr->type_offset),&error); } } dwarf_dealloc(dbg,attrbuf[i],DW_DLA_ATTR); } dwarf_dealloc(dbg,attrbuf,DW_DLA_LIST); return ret; }
/* List a function if it's in the given DIE. */ void list_func_in_die(Dwarf_Debug dgb, Dwarf_Die the_die, FILE *fp) { char* die_name = 0; const char* tag_name = 0; Dwarf_Error err; Dwarf_Half tag; Dwarf_Attribute* attrs; Dwarf_Addr lowpc, highpc; Dwarf_Signed attrcount, i; int rc = dwarf_diename(the_die, &die_name, &err); if (rc == DW_DLV_ERROR) die("Error in dwarf_diename\n"); else if (rc == DW_DLV_NO_ENTRY) return; if (dwarf_tag(the_die, &tag, &err) != DW_DLV_OK) die("Error in dwarf_tag\n"); /* Only interested in subprogram DIEs here */ if (tag != DW_TAG_subprogram) return; if (dwarf_get_TAG_name(tag, &tag_name) != DW_DLV_OK) die("Error in dwarf_get_TAG_name\n"); //printf("DW_TAG_subprogram: '%s'\n", die_name); fprintf(fp, "%s\t", die_name); /* Grab the DIEs attributes for display */ if (dwarf_attrlist(the_die, &attrs, &attrcount, &err) != DW_DLV_OK) die("Error in dwarf_attlist\n"); for (i = 0; i < attrcount; ++i) { Dwarf_Half attrcode; if (dwarf_whatattr(attrs[i], &attrcode, &err) != DW_DLV_OK) die("Error in dwarf_whatattr\n"); /* We only take some of the attributes for display here. ** More can be picked with appropriate tag constants. */ if (attrcode == DW_AT_low_pc) dwarf_formaddr(attrs[i], &lowpc, 0); else if (attrcode == DW_AT_high_pc) dwarf_formaddr(attrs[i], &highpc, 0); } fprintf(fp, "%08llx\n", lowpc); // printf("low pc : 0x%08llx\n", lowpc); // printf("high pc : 0x%08llx\n", highpc); }
//print_cmd helper funcs error_t ip_in_func(Dwarf_Die the_die, size_t rip, bool* res){ char* die_name = 0; Dwarf_Error err; Dwarf_Half tag; Dwarf_Attribute* attrs; Dwarf_Addr lowpc, highpc; Dwarf_Signed attrcount, i; int rc = dwarf_diename(the_die, &die_name, &err); if (rc == DW_DLV_ERROR) return E_FATAL; else if (rc == DW_DLV_NO_ENTRY) return E_NONE; if (dwarf_tag(the_die, &tag, &err) != DW_DLV_OK) return E_FATAL; /* Only interested in subprogram DIEs here */ if (tag != DW_TAG_subprogram) return E_NONE; /* Grab the DIEs attributes for display */ if (dwarf_attrlist(the_die, &attrs, &attrcount, &err) != DW_DLV_OK) return E_FATAL; for (i = 0; i < attrcount; ++i) { Dwarf_Half attrcode; if (dwarf_whatattr(attrs[i], &attrcode, &err) != DW_DLV_OK) return E_FATAL; /* We only take some of the attributes for display here. ** More can be picked with appropriate tag constants. */ if (attrcode == DW_AT_low_pc) dwarf_formaddr(attrs[i], &lowpc, 0); else if (attrcode == DW_AT_high_pc) dwarf_formaddr(attrs[i], &highpc, 0); } if( rip >= lowpc && rip <= highpc){ *res = true; return E_NONE; } return E_NONE; }
error_t is_right_var(Dwarf_Die var_die, char* var_name, bool* found){ char* die_name = 0; Dwarf_Error err; Dwarf_Half tag; Dwarf_Attribute* attrs; Dwarf_Signed attrcount, i; int rc = dwarf_diename(var_die, &die_name, &err); if (rc == DW_DLV_ERROR) return E_FATAL; else if (rc == DW_DLV_NO_ENTRY) return E_NONE; if (dwarf_tag(var_die, &tag, &err) != DW_DLV_OK) return E_FATAL; /* Only interested in variable DIEs here */ if (tag != DW_TAG_variable) return E_NONE; /* Grab the DIEs attributes for display */ if (dwarf_attrlist(var_die, &attrs, &attrcount, &err) != DW_DLV_OK) return E_FATAL; for (i = 0; i < attrcount; ++i) { Dwarf_Half attrcode; if (dwarf_whatattr(attrs[i], &attrcode, &err) != DW_DLV_OK) return E_FATAL; if (attrcode == DW_AT_name){ char* die_var_name; dwarf_formstring(attrs[i], &die_var_name, &err); if( strcmp(die_var_name, var_name) == 0 ){ *found = true; return E_NONE; } } } return E_NONE; //Not var_die being searched for }
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); }
unsigned long dwarf_function_ending_address(Dwarf_Die function_die, struct dwarf_compilation_unit * unit){ Dwarf_Error error = 0; Dwarf_Attribute *attrbuf = 0; Dwarf_Addr highpc = 0; Dwarf_Signed attrcount = 0; Dwarf_Unsigned i; int res = dwarf_attrlist(function_die,&attrbuf,&attrcount,&error); if(res != DW_DLV_OK) { return 0; } for(i = 0; i < attrcount ; ++i) { Dwarf_Half aform; res = dwarf_whatattr(attrbuf[i],&aform,&error); if(aform == DW_AT_high_pc) { get_addr(attrbuf[i],&highpc); return highpc; } } return 0; }
char * dwarf_get_name(Dwarf_Die function_die, struct dwarf_compilation_unit * unit){ Dwarf_Error error = 0; Dwarf_Attribute *attrbuf = 0; Dwarf_Addr highpc = 0; Dwarf_Signed attrcount = 0; Dwarf_Unsigned i; int res = dwarf_attrlist(function_die,&attrbuf,&attrcount,&error); if(res != DW_DLV_OK) { return 0; } for(i = 0; i < attrcount ; ++i) { Dwarf_Half aform; res = dwarf_whatattr(attrbuf[i],&aform,&error); if (aform == DW_AT_name) { char * tmpName; res = dwarf_formstring(attrbuf[i], &tmpName, &error); return tmpName; } } return NULL; }
static VALUE rd_attr_new(rd_shared_data_t *sd, VALUE top, VALUE cu, Dwarf_Attribute attr) { rd_attr_t *rd_attr; Dwarf_Error err; VALUE obj; VALUE klass; Dwarf_Half attr_type = 0; chkerr1(dwarf_whatattr(attr, &attr_type, &err), &err, Qnil); klass = rb_hash_aref(rdwarf_at2class, INT2FIX(attr_type)); if (NIL_P(klass)) { rb_raise(rb_eRuntimeError, "unknown attribute %d\n", attr_type); } obj = rd_attr_s_alloc(klass); rd_attr = GetAttr(obj); rd_attr->shared_data = rd_shared_data_ref(sd); rd_attr->attr = attr; rd_attr->attr_type = attr_type; rb_ivar_set(obj, id_at_top, top); rb_ivar_set(obj, id_at_cu, cu); return obj; }
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 print_expr (Dwarf_Attribute *attr, Dwarf_Op *expr, Dwarf_Addr addr) { uint8_t atom = expr->atom; const char *opname = dwarf_opcode_string (atom); assert (opname != NULL); switch (atom) { case DW_OP_deref: case DW_OP_dup: case DW_OP_drop: case DW_OP_over: case DW_OP_swap: case DW_OP_rot: case DW_OP_xderef: case DW_OP_abs: case DW_OP_and: case DW_OP_div: case DW_OP_minus: case DW_OP_mod: case DW_OP_mul: case DW_OP_neg: case DW_OP_not: case DW_OP_or: case DW_OP_plus: case DW_OP_shl: case DW_OP_shr: case DW_OP_shra: case DW_OP_xor: case DW_OP_eq: case DW_OP_ge: case DW_OP_gt: case DW_OP_le: case DW_OP_lt: case DW_OP_ne: case DW_OP_lit0 ... DW_OP_lit31: case DW_OP_reg0 ... DW_OP_reg31: case DW_OP_nop: case DW_OP_stack_value: /* No arguments. */ printf ("%s", opname); break; case DW_OP_form_tls_address: /* No arguments. Special. Pops an address and pushes the corresponding address in the current thread local storage. Uses the thread local storage block of the defining module (executable, shared library). */ printf ("%s", opname); break; case DW_OP_GNU_push_tls_address: /* No arguments. Special. Not the same as DW_OP_form_tls_address. Pops an offset into the current thread local strorage and pushes back the actual address. */ printf ("%s", opname); break; case DW_OP_call_frame_cfa: /* No arguments. Special. Pushes Call Frame Address as computed by CFI data (dwarf_cfi_addrframe will fetch that info (either from the .eh_frame or .debug_frame CFI) and dwarf_frame_cfa translatesr the CFI instructions into a plain DWARF expression. Never used in CFI itself. */ if (attr == NULL) error (EXIT_FAILURE, 0, "%s used in CFI", opname); printf ("%s ", opname); if (cfi_eh == NULL && cfi_debug == NULL) error (EXIT_FAILURE, 0, "DW_OP_call_frame_cfa used but no cfi found."); Dwarf_Frame *frame; if (dwarf_cfi_addrframe (cfi_eh, addr + cfi_eh_bias, &frame) != 0 && dwarf_cfi_addrframe (cfi_debug, addr, &frame) != 0) error (EXIT_FAILURE, 0, "dwarf_cfi_addrframe 0x%" PRIx64 ": %s", addr, dwarf_errmsg (-1)); Dwarf_Op *cfa_ops; size_t cfa_nops; if (dwarf_frame_cfa (frame, &cfa_ops, &cfa_nops) != 0) error (EXIT_FAILURE, 0, "dwarf_frame_cfa 0x%" PRIx64 ": %s", addr, dwarf_errmsg (-1)); if (cfa_nops < 1) error (EXIT_FAILURE, 0, "dwarf_frame_cfa no ops"); print_expr_block (NULL, cfa_ops, cfa_nops, 0); free (frame); break; case DW_OP_push_object_address: /* No arguments. Special. Pushes object address explicitly. Normally only done implicitly by DW_AT_data_member_location. Never used in CFI. */ if (attr == NULL) error (EXIT_FAILURE, 0, "%s used in CFI", opname); printf ("%s", opname); break; case DW_OP_addr: /* 1 address argument. */ printf ("%s(0x%" PRIx64 ")", opname, (Dwarf_Addr) expr->number); break; case DW_OP_const1u: case DW_OP_const2u: case DW_OP_const4u: case DW_OP_const8u: case DW_OP_constu: case DW_OP_pick: case DW_OP_plus_uconst: case DW_OP_regx: case DW_OP_piece: case DW_OP_deref_size: case DW_OP_xderef_size: /* 1 numeric unsigned argument. */ printf ("%s(%" PRIu64 ")", opname, expr->number); break; case DW_OP_call2: case DW_OP_call4: case DW_OP_call_ref: /* 1 DIE offset argument for more ops in location attribute of DIE. Never used in CFI. */ { if (attr == NULL) error (EXIT_FAILURE, 0, "%s used in CFI", opname); Dwarf_Attribute call_attr; if (dwarf_getlocation_attr (attr, expr, &call_attr) != 0) error (EXIT_FAILURE, 0, "dwarf_getlocation_attr for %s error %s", opname, dwarf_errmsg (-1)); Dwarf_Die call_die; if (dwarf_getlocation_die (attr, expr, &call_die) != 0) error (EXIT_FAILURE, 0, "dwarf_getlocation_die for %s error %s", opname, dwarf_errmsg (-1)); Dwarf_Op *call_ops; size_t call_len; if (dwarf_getlocation (&call_attr, &call_ops, &call_len) != 0) error (EXIT_FAILURE, 0, "dwarf_getlocation for entry: %s", dwarf_errmsg (-1)); printf ("%s([%" PRIx64 "]) ", opname, dwarf_dieoffset (&call_die)); print_expr_block (&call_attr, call_ops, call_len, addr); } break; case DW_OP_const1s: case DW_OP_const2s: case DW_OP_const4s: case DW_OP_const8s: case DW_OP_consts: case DW_OP_skip: case DW_OP_bra: case DW_OP_breg0 ... DW_OP_breg31: /* 1 numeric signed argument. */ printf ("%s(%" PRId64 ")", opname, (Dwarf_Sword) expr->number); break; case DW_OP_fbreg: /* 1 numeric signed argument. Offset from frame base. */ if (attr == NULL) error (EXIT_FAILURE, 0, "%s used in CFI", opname); if (! has_frame_base) error (EXIT_FAILURE, 0, "DW_OP_fbreg used without a frame base"); printf ("%s(%" PRId64 ")", opname, (Dwarf_Sword) expr->number); break; case DW_OP_bregx: /* 2 arguments, unsigned register number, signed offset. */ printf ("%s(%" PRIu64 ",%" PRId64 ")", opname, expr->number, (Dwarf_Sword) expr->number2); break; case DW_OP_bit_piece: /* 2 arguments, unsigned size, unsigned offset. */ printf ("%s(%" PRIu64 ",%" PRIu64 ")", opname, expr->number, expr->number2); break; case DW_OP_implicit_value: /* Special, unsigned size plus block. */ { Dwarf_Attribute const_attr; Dwarf_Block block; if (dwarf_getlocation_attr (attr, expr, &const_attr) != 0) error (EXIT_FAILURE, 0, "dwarf_getlocation_attr: %s", dwarf_errmsg (-1)); if (dwarf_formblock (&const_attr, &block) != 0) error (EXIT_FAILURE, 0, "dwarf_formblock: %s", dwarf_errmsg (-1)); /* This is the "old" way. Check they result in the same. */ Dwarf_Block block_impl; if (dwarf_getlocation_implicit_value (attr, expr, &block_impl) != 0) error (EXIT_FAILURE, 0, "dwarf_getlocation_implicit_value: %s", dwarf_errmsg (-1)); assert (expr->number == block.length); assert (block.length == block_impl.length); printf ("%s(%" PRIu64 "){", opname, block.length); for (size_t i = 0; i < block.length; i++) { printf ("%02x", block.data[i]); assert (block.data[i] == block_impl.data[i]); } printf("}"); } break; case DW_OP_GNU_implicit_pointer: /* Special, DIE offset, signed offset. Referenced DIE has a location or const_value attribute. */ { if (attr == NULL) error (EXIT_FAILURE, 0, "%s used in CFI", opname); Dwarf_Attribute attrval; if (dwarf_getlocation_implicit_pointer (attr, expr, &attrval) != 0) error (EXIT_FAILURE, 0, "dwarf_getlocation_implicit_pointer: %s", dwarf_errmsg (-1)); // Sanity check, results should be the same. Dwarf_Attribute attrval2; if (dwarf_getlocation_attr (attr, expr, &attrval2) != 0) error (EXIT_FAILURE, 0, "dwarf_getlocation_attr: %s", dwarf_errmsg (-1)); assert (dwarf_whatattr (&attrval) == dwarf_whatattr (&attrval2)); assert (dwarf_whatform (&attrval) == dwarf_whatform (&attrval2)); // In theory two different valp pointers could point to the same // value. But here we really expect them to be the equal. assert (attrval.valp == attrval2.valp); Dwarf_Die impl_die; if (dwarf_getlocation_die (attr, expr, &impl_die) != 0) error (EXIT_FAILURE, 0, "dwarf_getlocation_due: %s", dwarf_errmsg (-1)); printf ("%s([%" PRIx64 "],%" PRId64 ") ", opname, dwarf_dieoffset (&impl_die), expr->number2); if (dwarf_whatattr (&attrval) == DW_AT_const_value) printf ("<constant value>"); // Lookup type... else { // Lookup the location description at the current address. Dwarf_Op *exprval; size_t exprval_len; int locs = dwarf_getlocation_addr (&attrval, addr, &exprval, &exprval_len, 1); if (locs == 0) printf ("<no location>"); // This means "optimized out". else if (locs == 1) print_expr_block (&attrval, exprval, exprval_len, addr); else error (EXIT_FAILURE, 0, "dwarf_getlocation_addr attrval at addr 0x%" PRIx64 ", locs (%d): %s", addr, locs, dwarf_errmsg (-1)); } } break; case DW_OP_GNU_entry_value: /* Special, unsigned size plus expression block. All registers inside the block should be interpreted as they had on entering the function. dwarf_getlocation_attr will return an attribute containing the block as locexpr which can be retrieved with dwarf_getlocation. */ { Dwarf_Attribute entry_attr; if (dwarf_getlocation_attr (attr, expr, &entry_attr) != 0) error (EXIT_FAILURE, 0, "dwarf_getlocation_attr: %s", dwarf_errmsg (-1)); Dwarf_Op *entry_ops; size_t entry_len; if (dwarf_getlocation (&entry_attr, &entry_ops, &entry_len) != 0) error (EXIT_FAILURE, 0, "dwarf_getlocation for entry: %s", dwarf_errmsg (-1)); printf ("%s(%zd) ", opname, entry_len); print_expr_block (attr, entry_ops, entry_len, addr); } break; case DW_OP_GNU_parameter_ref: /* Special, unsigned CU relative DIE offset pointing to a DW_TAG_formal_parameter. The value that parameter had at the call site of the current function will be put on the DWARF stack. The value can be retrieved by finding the DW_TAG_GNU_call_site_parameter which has as DW_AT_abstract_origin the same formal parameter DIE. */ { Dwarf_Die param; if (dwarf_getlocation_die (attr, expr, ¶m) != 0) error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s", dwarf_errmsg (-1)); // XXX actually lookup DW_TAG_GNU_call_site_parameter printf ("%s[%" PRIx64 "]", opname, dwarf_dieoffset (¶m)); assert (expr->number == dwarf_cuoffset (¶m)); assert (dwarf_tag (¶m) == DW_TAG_formal_parameter); } break; case DW_OP_GNU_convert: case DW_OP_GNU_reinterpret: /* Special, unsigned CU relative DIE offset pointing to a DW_TAG_base_type. Pops a value, converts or reinterprets the value to the given type. When the argument is zero the value becomes untyped again. */ { Dwarf_Die type; Dwarf_Off off = expr->number; if (off != 0) { if (dwarf_getlocation_die (attr, expr, &type) != 0) error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s", dwarf_errmsg (-1)); off = dwarf_dieoffset (&type); assert (expr->number == dwarf_cuoffset (&type)); printf ("%s", opname); print_base_type (&type); } else printf ("%s[%" PRIu64 "]", opname, off); } break; case DW_OP_GNU_regval_type: /* Special, unsigned register number plus unsigned CU relative DIE offset pointing to a DW_TAG_base_type. */ { Dwarf_Die type; if (dwarf_getlocation_die (attr, expr, &type) != 0) error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s", dwarf_errmsg (-1)); assert (expr->number2 == dwarf_cuoffset (&type)); // XXX check size against base_type size? printf ("%s(reg%" PRIu64 ")", opname, expr->number); print_base_type (&type); } break; case DW_OP_GNU_deref_type: /* Special, unsigned size plus unsigned CU relative DIE offset pointing to a DW_TAG_base_type. */ { Dwarf_Die type; if (dwarf_getlocation_die (attr, expr, &type) != 0) error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s", dwarf_errmsg (-1)); assert (expr->number2 == dwarf_cuoffset (&type)); // XXX check size against base_type size? printf ("%s(%" PRIu64 ")", opname, expr->number); print_base_type (&type); } break; case DW_OP_GNU_const_type: /* Special, unsigned CU relative DIE offset pointing to a DW_TAG_base_type, an unsigned size length plus a block with the constant value. */ { Dwarf_Die type; if (dwarf_getlocation_die (attr, expr, &type) != 0) error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s", dwarf_errmsg (-1)); assert (expr->number == dwarf_cuoffset (&type)); Dwarf_Attribute const_attr; if (dwarf_getlocation_attr (attr, expr, &const_attr) != 0) error (EXIT_FAILURE, 0, "dwarf_getlocation_attr for type: %s", dwarf_errmsg (-1)); Dwarf_Block block; if (dwarf_formblock (&const_attr, &block) != 0) error (EXIT_FAILURE, 0, "dwarf_formblock for type: %s", dwarf_errmsg (-1)); printf ("%s", opname); print_base_type (&type); printf ("(%" PRIu64 ")[", block.length); for (size_t i = 0; i < block.length; i++) printf ("%02x", block.data[i]); printf("]"); } break; default: error (EXIT_FAILURE, 0, "unhandled opcode: DW_OP_%s (0x%x)", opname, atom); } }
/* 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 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; } } } }
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); } }
error_t print_local_var(mygdb_info_t* gdb_info, Dwarf_Die var_die, char* var_name){ Dwarf_Half tag; Dwarf_Error err; unsigned long var_addr; Dwarf_Attribute* attrs; Dwarf_Locdesc* locs_var; Dwarf_Signed attrcount, i, cnt_var; if (dwarf_tag(var_die, &tag, &err) != DW_DLV_OK) return E_FATAL; /* Make sure to only have a var die */ if (tag != DW_TAG_variable) return E_FATAL; /* Grab the DIEs attributes */ if (dwarf_attrlist(var_die, &attrs, &attrcount, &err) != DW_DLV_OK) return E_FATAL; for (i = 0; i < attrcount; ++i) { Dwarf_Half attrcode; if (dwarf_whatattr(attrs[i], &attrcode, &err) != DW_DLV_OK) return E_FATAL; if (attrcode == DW_AT_location) break; } if( attrs[i] == NULL ){ printf("Failed to find the DW_AT_location attribute\n"); return E_NON_FATAL; } if( dwarf_loclist(attrs[i], &locs_var, &cnt_var, &err) != DW_DLV_OK){ printf("dwarf_loclist failed\n"); return E_FATAL; } if((cnt_var != 1) || (locs_var[0].ld_cents != 1) || (locs_var[0].ld_s[0].lr_atom != DW_OP_fbreg)){ fprintf(stderr, "Unexpected location information\n"); return E_NON_FATAL; } struct user_regs_struct regs; if( ptrace(PTRACE_GETREGS, gdb_info->child_pid, NULL, ®s ) < 0 ) return E_FATAL; var_addr = (unsigned long)(regs.rbp + (long)locs_var[0].ld_s[0].lr_number + 16); errno = 0; unsigned long data; data = ptrace(PTRACE_PEEKTEXT, gdb_info->child_pid, (void*)var_addr); if(errno){ printf("peektext failed\n"); return E_FATAL; } printf("%s = %lu\n", var_name, data); return E_NONE; }