static void HandleFunctionDIE (Dwarf_Debug dwHandle, Dwarf_Die currChildDIE) { char *funcName = NULL; Dwarf_Addr lowAddress = 0; Dwarf_Addr highAddress = 0; int dwDieNameRet = dwarf_diename (currChildDIE, &funcName, NULL); int dwDieLowAddrRet = dwarf_lowpc (currChildDIE, &lowAddress, NULL); int dwDieHighAddrRet = dwarf_highpc (currChildDIE, &highAddress, NULL); if ((dwDieNameRet == DW_DLV_OK) && (dwDieLowAddrRet == DW_DLV_OK) && (dwDieHighAddrRet == DW_DLV_OK)) { FunctionMap_Add (funcName, lowAddress, highAddress); } if ((dwDieNameRet == DW_DLV_OK) && (funcName != NULL)) { dwarf_dealloc (dwHandle, funcName, DW_DLA_STRING); } }
static void DC_show_info_for_containing_pc_ranges(Dwarf_Die die, int enclosing, unsigned long iaddr){ /*This function visits the children of a die in sequence, *applying the action() function to each*/ Dwarf_Attribute highattr; Dwarf_Attribute lowattr; Dwarf_Addr loval,hival; Dwarf_Bool has; Dwarf_Error error; Dwarf_Half tag; loval = hival = 0x0; int enc = 0; dwarf_tag(die,&tag,&error); if( tag == DW_TAG_variable || tag == DW_TAG_formal_parameter ){ if(enclosing){ char *name; dwarf_diename(die,&name,&error); fprintf(stderr,"%s, ",name); //show_all_attrs(die,0,NULL); } } if( tag == DW_TAG_lexical_block || tag == DW_TAG_subprogram ){ if( dwarf_lowpc(die,&loval,&error) == DW_DLV_OK && dwarf_highpc(die,&hival,&error) == DW_DLV_OK && iaddr >=loval && iaddr <= hival ){ enc = 1; fprintf(stderr,"\n=================================\n"); show_all_attrs(die,0,NULL); fprintf(stderr,"=================================\n"); } } Dwarf_Die kid; if( dwarf_child(die,&kid,&error) == DW_DLV_NO_ENTRY ){ return; } DC_show_info_for_containing_pc_ranges(kid, enc, iaddr); //visit_die(kid,level+1,action,adata); int chret; while( (chret = dwarf_siblingof(d,kid,&kid,&error)) != DW_DLV_NO_ENTRY && chret != DW_DLV_ERROR){ DC_show_info_for_containing_pc_ranges(kid, enc, iaddr); //visit_die(kid,level+1,action,adata); } return; }
static void DC_get_info_for_scoped_variable(Dwarf_Die die, int enclosing, unsigned long iaddr, const char *varname, Dwarf_Die *retDie){ /*This function visits the children of a die in sequence, *applying the action() function to each*/ Dwarf_Attribute highattr; Dwarf_Attribute lowattr; Dwarf_Addr loval,hival; Dwarf_Bool has; Dwarf_Error error; Dwarf_Half tag; loval = hival = 0x0; int enc = 0; dwarf_tag(die,&tag,&error); if( tag == DW_TAG_variable || tag == DW_TAG_formal_parameter ){ if(enclosing){ char *name; dwarf_diename(die,&name,&error); if(!strncmp(name,varname,strlen(name))){ *retDie = die; return; } } } if( tag == DW_TAG_lexical_block || tag == DW_TAG_subprogram ){ if( dwarf_lowpc(die,&loval,&error) == DW_DLV_OK && dwarf_highpc(die,&hival,&error) == DW_DLV_OK && iaddr >=loval && iaddr <= hival ){ enc = 1; } } Dwarf_Die kid; if( dwarf_child(die,&kid,&error) == DW_DLV_NO_ENTRY ){ return; } DC_get_info_for_scoped_variable(kid, enc, iaddr,varname,retDie); int chret; while( (chret = dwarf_siblingof(d,kid,&kid,&error)) != DW_DLV_NO_ENTRY && chret != DW_DLV_ERROR){ DC_get_info_for_scoped_variable(kid, enc, iaddr,varname,retDie); } return; }
static void HandleFunctionDIE (Dwarf_Debug dwHandle, Dwarf_Die currChildDIE) { char *funcName = NULL; Dwarf_Addr lowAddress = 0; Dwarf_Addr highAddress = 0; int dwDieNameRet, dwDieLowAddrRet, dwDieHighAddrRet; dwDieNameRet = dwarf_diename (currChildDIE, &funcName, &dw_err); if (dwDieNameRet != DW_DLV_OK) mpiPi_msg_debug("Failed to get DIE name : %s\n", dwarf_errmsg(dw_err)); dwDieLowAddrRet = dwarf_lowpc (currChildDIE, &lowAddress, &dw_err); if (dwDieLowAddrRet != DW_DLV_OK) mpiPi_msg_debug("Failed to get low PC : %s\n", dwarf_errmsg(dw_err)); dwDieHighAddrRet = dwarf_highpc (currChildDIE, &highAddress, &dw_err); if (dwDieHighAddrRet != DW_DLV_OK) mpiPi_msg_debug("Failed to get high PC : %s\n", dwarf_errmsg(dw_err)); if ((dwDieNameRet == DW_DLV_OK) && (dwDieLowAddrRet == DW_DLV_OK) && (dwDieHighAddrRet == DW_DLV_OK)) { FunctionMap_Add (funcName, lowAddress, highAddress); } if ((dwDieNameRet == DW_DLV_OK) && (funcName != NULL)) { dwarf_dealloc (dwHandle, funcName, DW_DLA_STRING); } }
/* Iterate over all the CUs in the module to find the CU containing the given * PC. */ static Dwarf_Die find_cu_die_via_iter(Dwarf_Debug dbg, Dwarf_Addr pc) { Dwarf_Die die = NULL; Dwarf_Unsigned cu_offset = 0; Dwarf_Error de = {0}; Dwarf_Die cu_die = NULL; while (dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, &cu_offset, &de) == DW_DLV_OK) { /* Scan forward in the tag soup for a CU DIE. */ die = next_die_matching_tag(dbg, DW_TAG_compile_unit); /* We found a CU die, now check if it's the one we wanted. */ if (die != NULL) { Dwarf_Addr lo_pc, hi_pc; if (dwarf_lowpc(die, &lo_pc, &de) != DW_DLV_OK || dwarf_highpc(die, &hi_pc, &de) != DW_DLV_OK) { NOTIFY_DWARF(de); break; } if (lo_pc <= pc && pc < hi_pc) { cu_die = die; break; } } } while (dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, &cu_offset, &de) == DW_DLV_OK) { /* Reset the internal CU header state. */ } return cu_die; }
/* List a function if it's in the given DIE. */ static struct dwarf_subprogram_t *read_cu_entry( struct dwarf_subprogram_t *subprograms, Dwarf_Debug dbg, Dwarf_Die cu_die, Dwarf_Die the_die) { char* die_name = 0; Dwarf_Error err; Dwarf_Half tag; Dwarf_Addr lowpc = 0; Dwarf_Addr highpc = 0; char *filename; struct dwarf_subprogram_t *subprogram = NULL; int rc; Dwarf_Attribute attrib = 0; rc = dwarf_tag(the_die, &tag, &err); if (rc != DW_DLV_OK) fatal("unable to parse dwarf tag"); /* Only interested in subprogram DIEs here */ if (tag != DW_TAG_subprogram) return subprograms; rc = dwarf_diename(the_die, &die_name, &err); if (rc == DW_DLV_ERROR) fatal("unable to parse dwarf diename"); if (rc == DW_DLV_NO_ENTRY) return subprograms; rc = dwarf_attr(cu_die, DW_AT_name, &attrib, &err); DWARF_ASSERT(rc, err); if (rc != DW_DLV_NO_ENTRY) { rc = dwarf_formstring(attrib, &filename, &err); DWARF_ASSERT(rc, err); dwarf_dealloc(dbg, attrib, DW_DLA_ATTR); } rc = dwarf_lowpc(the_die, &lowpc, &err); DWARF_ASSERT(rc, err); rc = dwarf_highpc(the_die, &highpc, &err); DWARF_ASSERT(rc, err); /* TODO: when would these not be defined? */ if (lowpc && highpc) { subprogram = malloc(sizeof(*subprogram)); if (!subprogram) fatal("unable to allocate memory"); memset(subprogram, 0, sizeof(*subprogram)); subprogram->lowpc = lowpc; subprogram->highpc = highpc; subprogram->name = die_name; subprogram->next = subprograms; subprograms = subprogram; } return subprograms; }
/* simple but too slow */ struct dwarf_subprogram_t *read_from_globals(Dwarf_Debug dbg) { Dwarf_Global *globals = NULL; Dwarf_Signed nglobals; Dwarf_Off offset; Dwarf_Die die; Dwarf_Addr lowpc = 0; Dwarf_Addr highpc = 0; Dwarf_Error err; Dwarf_Attribute attrib = 0; struct dwarf_subprogram_t *subprograms = NULL; struct dwarf_subprogram_t *subprogram = NULL; char *name; int i; int ret; ret = dwarf_get_globals(dbg, &globals, &nglobals, &err); DWARF_ASSERT(ret, err); if (ret != DW_DLV_OK) fatal("unable to get dwarf globals"); for (i = 0; i < nglobals; i++) { ret = dwarf_global_die_offset(globals[i], &offset, &err); DWARF_ASSERT(ret, err); /* TODO: this function does a linear search, making it pretty damn * slow.. see libdwarf/dwarf_die_deliv.c:_dwarf_find_CU_Context * for details */ ret = dwarf_offdie(dbg, offset, &die, &err); DWARF_ASSERT(ret, err); ret = dwarf_lowpc(die, &lowpc, &err); DWARF_ASSERT(ret, err); ret = dwarf_highpc(die, &highpc, &err); DWARF_ASSERT(ret, err); /* TODO: when would these not be defined? */ if (lowpc && highpc) { subprogram = malloc(sizeof(*subprogram)); if (!subprogram) fatal("unable to allocate memory for subprogram"); memset(subprogram, 0, sizeof(*subprogram)); ret = dwarf_attr(die, DW_AT_MIPS_linkage_name, &attrib, &err); if (ret == DW_DLV_OK) { ret = dwarf_formstring(attrib, &name, &err); DWARF_ASSERT(ret, err); dwarf_dealloc(dbg, attrib, DW_DLA_ATTR); } else { ret = dwarf_globname(globals[i], &name, &err); DWARF_ASSERT(ret, err); } subprogram->lowpc = lowpc; subprogram->highpc = highpc; subprogram->name = name; subprogram->next = subprograms; subprograms = subprogram; } dwarf_dealloc(dbg, die, DW_DLA_DIE); } return subprograms; }
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 DC_show_vars_for_containing_pc_ranges(Dwarf_Die die, int enclosing, unsigned long iaddr){ /*This function visits the children of a die in sequence, *applying the action() function to each*/ Dwarf_Attribute highattr; Dwarf_Attribute lowattr; Dwarf_Addr loval,hival; Dwarf_Bool has; Dwarf_Error error; Dwarf_Half tag; loval = hival = 0x0; int enc = 0; dwarf_tag(die,&tag,&error); if( tag == DW_TAG_variable || tag == DW_TAG_formal_parameter ){ if(enclosing){ char *name; dwarf_diename(die,&name,&error); DC_type t; DC_resolve_type(die,&t); fprintf(stderr,"%s ",t.name); int i; for(i = 0; i < t.indirectionLevel; i++){ fprintf(stderr,"*"); } fprintf(stderr,"%s",name); for(i = 0; i < t.arrayLevel; i++){ fprintf(stderr,"[]"); } fprintf(stderr,","); } } if( tag == DW_TAG_lexical_block || tag == DW_TAG_subprogram ){ if( dwarf_lowpc(die,&loval,&error) == DW_DLV_OK && dwarf_highpc(die,&hival,&error) == DW_DLV_OK && iaddr >=loval && iaddr <= hival ){ enc = 1; } } Dwarf_Die kid; if( dwarf_child(die,&kid,&error) == DW_DLV_NO_ENTRY ){ return; } DC_show_vars_for_containing_pc_ranges(kid, enc, iaddr); int chret; while( (chret = dwarf_siblingof(d,kid,&kid,&error)) != DW_DLV_NO_ENTRY && chret != DW_DLV_ERROR){ DC_show_vars_for_containing_pc_ranges(kid, enc, iaddr); } return; }
/** * Get the name of the function containing a given address within a * given compile unit (CU). * * If found, the out parameter `func_name` is set on success. On * failure, it remains unchanged. * * @param cu bt_dwarf_cu instance which may contain the address * @param addr Virtual memory address for which to find the * function name * @param func_name Out parameter, the function name * @returns 0 on success, -1 on failure */ static int bin_info_lookup_cu_function_name(struct bt_dwarf_cu *cu, uint64_t addr, char **func_name) { int ret = 0; bool found = false; struct bt_dwarf_die *die = NULL; if (!cu || !func_name) { goto error; } die = bt_dwarf_die_create(cu); if (!die) { goto error; } while (bt_dwarf_die_next(die) == 0) { int tag; ret = bt_dwarf_die_get_tag(die, &tag); if (ret) { goto error; } if (tag == DW_TAG_subprogram) { ret = bt_dwarf_die_contains_addr(die, addr, &found); if (ret) { goto error; } if (found) { break; } } } if (found) { uint64_t low_addr = 0; char *die_name = NULL; ret = bt_dwarf_die_get_name(die, &die_name); if (ret) { goto error; } ret = dwarf_lowpc(die->dwarf_die, &low_addr); if (ret) { free(die_name); goto error; } ret = bin_info_append_offset_str(die_name, low_addr, addr, func_name); free(die_name); if (ret) { goto error; } } bt_dwarf_die_destroy(die); return 0; error: bt_dwarf_die_destroy(die); return -1; }