static VALUE rd_die_attributes(VALUE self) { rd_die_t *die = GetDie(self); Dwarf_Attribute *list; Dwarf_Signed count; Dwarf_Error err; Dwarf_Signed idx; VALUE top; VALUE cu; VALUE ary; if (die->attributes != Qfalse) { return die->attributes; } top = rb_ivar_get(self, id_at_top); cu = rb_ivar_get(self, id_at_cu); if (chkerr2(dwarf_attrlist(die->die, &list, &count, &err), &err)) { ary = rb_ary_new_capa(count); for (idx = 0; idx < count; idx++) { rb_ary_store(ary, idx, rd_attr_new(die->shared_data, top, cu, list[idx])); } } else { ary = rb_ary_new(); } die->attributes = ary; return ary; }
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); }
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; }
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; }
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 }
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; }
Dwarf_Signed DieHolder::get_nb_attrs(void) { Dwarf_Attribute *attrlist = NULL; Dwarf_Signed nb_attrs = 0; Dwarf_Error err = NULL; CHECK_DWERR2(dwarf_attrlist(m_die, &attrlist, &nb_attrs, &err) == DW_DLV_ERROR, err, "error when getting the list of attributes"); // do not use the attributes // TODO: maybe we can put them in the attributes map later... if(nb_attrs != 0) { for(Dwarf_Signed idx = 0; idx < nb_attrs; ++idx) { dwarf_dealloc(m_dbg, attrlist[idx], DW_DLA_ATTR); } dwarf_dealloc(m_dbg, attrlist, DW_DLA_LIST); } return nb_attrs; }
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; }
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; }