int dwarf_get_str(Dwarf_Debug dbg, Dwarf_Off offset, char **string, Dwarf_Signed *ret_strlen, Dwarf_Error *error) { Dwarf_Section *ds; if (dbg == NULL || offset < 0 || string == NULL || ret_strlen == NULL) { DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); return (DW_DLV_ERROR); } ds = _dwarf_find_section(dbg, ".debug_str"); if (ds == NULL) { DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY); return (DW_DLV_NO_ENTRY); } if ((Dwarf_Unsigned) offset > ds->ds_size) { DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); return (DW_DLV_ERROR); } if ((Dwarf_Unsigned) offset == ds->ds_size) { DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY); return (DW_DLV_NO_ENTRY); } *string = (char *) ds->ds_data + offset; *ret_strlen = strlen(*string); return (DW_DLV_OK); }
int dwarf_get_vars(Dwarf_Debug dbg, Dwarf_Var **vars, Dwarf_Signed *ret_count, Dwarf_Error *error) { Dwarf_Section *ds; int ret; if (dbg == NULL || vars == NULL || ret_count == NULL) { DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); return (DW_DLV_ERROR); } if (dbg->dbg_vars == NULL) { if ((ds = _dwarf_find_section(dbg, ".debug_static_vars")) != NULL) { ret = _dwarf_nametbl_init(dbg, &dbg->dbg_vars, ds, error); if (ret != DW_DLE_NONE) return (DW_DLV_ERROR); } if (dbg->dbg_vars == NULL) { DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY); return (DW_DLV_NO_ENTRY); } } *vars = dbg->dbg_vars->ns_array; *ret_count = dbg->dbg_vars->ns_len; return (DW_DLV_OK); }
int dwarf_get_loclist_entry(Dwarf_Debug dbg, Dwarf_Unsigned offset, Dwarf_Addr *hipc, Dwarf_Addr *lopc, Dwarf_Ptr *data, Dwarf_Unsigned *entry_len, Dwarf_Unsigned *next_entry, Dwarf_Error *error) { Dwarf_Loclist ll, next_ll; Dwarf_Locdesc *ld; Dwarf_Section *ds; int i, ret; if (dbg == NULL || hipc == NULL || lopc == NULL || data == NULL || entry_len == NULL || next_entry == NULL) { DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); return (DW_DLV_ERROR); } ret = _dwarf_loclist_find(dbg, STAILQ_FIRST(&dbg->dbg_cu), offset, &ll, error); if (ret == DW_DLE_NO_ENTRY) { DWARF_SET_ERROR(dbg, error, DW_DLV_NO_ENTRY); return (DW_DLV_NO_ENTRY); } else if (ret != DW_DLE_NONE) return (DW_DLV_ERROR); *hipc = *lopc = 0; for (i = 0; i < ll->ll_ldlen; i++) { ld = ll->ll_ldlist[i]; if (i == 0) { *hipc = ld->ld_hipc; *lopc = ld->ld_lopc; } else { if (ld->ld_lopc < *lopc) *lopc = ld->ld_lopc; if (ld->ld_hipc > *hipc) *hipc = ld->ld_hipc; } } ds = _dwarf_find_section(dbg, ".debug_loc"); assert(ds != NULL); *data = (uint8_t *) ds->ds_data + ll->ll_offset; *entry_len = ll->ll_length; next_ll = TAILQ_NEXT(ll, ll_next); if (next_ll != NULL) *next_entry = next_ll->ll_offset; else *next_entry = ds->ds_size; return (DW_DLV_OK); }
int dwarf_get_loclist_entry(Dwarf_Debug dbg, Dwarf_Unsigned offset, Dwarf_Addr *hipc, Dwarf_Addr *lopc, Dwarf_Ptr *data, Dwarf_Unsigned *entry_len, Dwarf_Unsigned *next_entry, Dwarf_Error *error) { Dwarf_Locdesc *ld, **llbuf; Dwarf_Section *ds; Dwarf_Signed listlen; int i, ret; /* * Note that this API sometimes will not work correctly because * it assumes that all units have the same pointer size and offset * size. */ if (dbg == NULL || hipc == NULL || lopc == NULL || data == NULL || entry_len == NULL || next_entry == NULL) { DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); return (DW_DLV_ERROR); } ret = _dwarf_loclist_find(dbg, STAILQ_FIRST(&dbg->dbg_cu), offset, &llbuf, &listlen, entry_len, error); if (ret == DW_DLE_NO_ENTRY) { DWARF_SET_ERROR(dbg, error, DW_DLV_NO_ENTRY); return (DW_DLV_NO_ENTRY); } else if (ret != DW_DLE_NONE) return (DW_DLV_ERROR); *hipc = *lopc = 0; for (i = 0; i < listlen; i++) { ld = llbuf[i]; if (i == 0) { *hipc = ld->ld_hipc; *lopc = ld->ld_lopc; } else { if (ld->ld_lopc < *lopc) *lopc = ld->ld_lopc; if (ld->ld_hipc > *hipc) *hipc = ld->ld_hipc; } } ds = _dwarf_find_section(dbg, ".debug_loc"); assert(ds != NULL); *data = (uint8_t *) ds->ds_data + offset; *next_entry = offset + *entry_len; return (DW_DLV_OK); }
int _dwarf_strtab_init(Dwarf_Debug dbg, Dwarf_Error *error) { Dwarf_Section *ds; assert(dbg != NULL); if (dbg->dbg_mode == DW_DLC_READ || dbg->dbg_mode == DW_DLC_RDWR) { ds = _dwarf_find_section(dbg, ".debug_str"); if (ds == NULL) { dbg->dbg_strtab = NULL; dbg->dbg_strtab_cap = dbg->dbg_strtab_size = 0; return (DW_DLE_NONE); } dbg->dbg_strtab_cap = dbg->dbg_strtab_size = ds->ds_size; if (dbg->dbg_mode == DW_DLC_RDWR) { if ((dbg->dbg_strtab = malloc((size_t) ds->ds_size)) == NULL) { DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); return (DW_DLE_MEMORY); } memcpy(dbg->dbg_strtab, ds->ds_data, ds->ds_size); } else dbg->dbg_strtab = (char *) ds->ds_data; } else { /* DW_DLC_WRITE */ dbg->dbg_strtab_cap = _INIT_DWARF_STRTAB_SIZE; dbg->dbg_strtab_size = 0; if ((dbg->dbg_strtab = malloc((size_t) dbg->dbg_strtab_cap)) == NULL) { DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); return (DW_DLE_MEMORY); } dbg->dbg_strtab[0] = '\0'; } return (DW_DLE_NONE); }
static int _dwarf_consumer_init(Dwarf_Debug dbg, Dwarf_Error *error) { const Dwarf_Obj_Access_Methods *m; Dwarf_Obj_Access_Section sec; void *obj; Dwarf_Unsigned cnt; Dwarf_Half i; int ret; assert(dbg != NULL); assert(dbg->dbg_iface != NULL); m = dbg->dbg_iface->methods; obj = dbg->dbg_iface->object; assert(m != NULL); assert(obj != NULL); if (m->get_byte_order(obj) == DW_OBJECT_MSB) { dbg->read = _dwarf_read_msb; dbg->write = _dwarf_write_msb; dbg->decode = _dwarf_decode_msb; } else { dbg->read = _dwarf_read_lsb; dbg->write = _dwarf_write_lsb; dbg->decode = _dwarf_decode_lsb; } dbg->dbg_pointer_size = m->get_pointer_size(obj); dbg->dbg_offset_size = m->get_length_size(obj); cnt = m->get_section_count(obj); if (cnt == 0) { DWARF_SET_ERROR(dbg, error, DW_DLE_DEBUG_INFO_NULL); return (DW_DLE_DEBUG_INFO_NULL); } dbg->dbg_seccnt = cnt; if ((dbg->dbg_section = calloc(cnt, sizeof(Dwarf_Section))) == NULL) { DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); return (DW_DLE_MEMORY); } for (i = 0; i < cnt; i++) { if (m->get_section_info(obj, i, &sec, &ret) != DW_DLV_OK) { free(dbg->dbg_section); DWARF_SET_ERROR(dbg, error, ret); return (ret); } dbg->dbg_section[i].ds_addr = sec.addr; dbg->dbg_section[i].ds_size = sec.size; dbg->dbg_section[i].ds_name = sec.name; if (m->load_section(obj, i, &dbg->dbg_section[i].ds_data, &ret) != DW_DLV_OK) { free(dbg->dbg_section); DWARF_SET_ERROR(dbg, error, ret); return (ret); } } if (_dwarf_find_section(dbg, ".debug_abbrev") == NULL || ((dbg->dbg_info_sec = _dwarf_find_section(dbg, ".debug_info")) == NULL)) { free(dbg->dbg_section); DWARF_SET_ERROR(dbg, error, DW_DLE_DEBUG_INFO_NULL); return (DW_DLE_DEBUG_INFO_NULL); } /* Initialise call frame API related parameters. */ _dwarf_frame_params_init(dbg); return (DW_DLV_OK); }
// debuginfo_rip(addr, info) // // Fill in the 'info' structure with information about the specified // instruction address, 'addr'. Returns 0 if information was found, and // negative if not. But even if it returns negative it has stored some // information into '*info'. // int debuginfo_rip(uintptr_t addr, struct Ripdebuginfo *info) { static struct Env* lastenv = NULL; void* elf; Dwarf_Section *sect; Dwarf_CU cu; Dwarf_Die die, cudie, die2; Dwarf_Regtable *rt = NULL; //Set up initial pc uint64_t pc = (uintptr_t)addr; // Initialize *info info->rip_file = "<unknown>"; info->rip_line = 0; info->rip_fn_name = "<unknown>"; info->rip_fn_namelen = 9; info->rip_fn_addr = addr; info->rip_fn_narg = 0; // Find the relevant set of stabs if (addr >= ULIM) { elf = (void *)0x10000 + KERNBASE; } else { // Can't search for user-level addresses yet! panic("User address"); } _dwarf_init(dbg, elf); sect = _dwarf_find_section(".debug_info"); dbg->dbg_info_offset_elf = (uint64_t)sect->ds_data; dbg->dbg_info_size = sect->ds_size; assert(dbg->dbg_info_size); while(_get_next_cu(dbg, &cu) == 0) { if(dwarf_siblingof(dbg, NULL, &cudie, &cu) == DW_DLE_NO_ENTRY) { continue; } cudie.cu_header = &cu; cudie.cu_die = NULL; if(dwarf_child(dbg, &cu, &cudie, &die) == DW_DLE_NO_ENTRY) { continue; } die.cu_header = &cu; die.cu_die = &cudie; while(1) { if(list_func_die(info, &die, addr)) goto find_done; if(dwarf_siblingof(dbg, &die, &die2, &cu) < 0) break; die = die2; die.cu_header = &cu; die.cu_die = &cudie; } } return -1; find_done: return 0; }