int dwarf_object_init(Dwarf_Obj_Access_Interface *iface, Dwarf_Handler errhand, Dwarf_Ptr errarg, Dwarf_Debug *ret_dbg, Dwarf_Error *error) { Dwarf_Debug dbg; if (iface == NULL || ret_dbg == NULL) { DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT); return (DW_DLV_ERROR); } if (_dwarf_alloc(&dbg, DW_DLC_READ, error) != DW_DLE_NONE) return (DW_DLV_ERROR); dbg->dbg_iface = iface; if (_dwarf_init(dbg, 0, errhand, errarg, error) != DW_DLE_NONE) { free(dbg); return (DW_DLV_ERROR); } *ret_dbg = dbg; return (DW_DLV_OK); }
int dwarf_init(int fd, int mode, Dwarf_Handler errhand, Dwarf_Ptr errarg, Dwarf_Debug *ret_dbg, Dwarf_Error *error) { Dwarf_Debug dbg; Elf *elf; int ret; if (fd < 0 || ret_dbg == NULL) { DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT); return (DW_DLV_ERROR); } if (mode != DW_DLC_READ) { DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT); return (DW_DLV_ERROR); } if (elf_version(EV_CURRENT) == EV_NONE) { DWARF_SET_ELF_ERROR(NULL, error); return (DW_DLV_ERROR); } if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { DWARF_SET_ELF_ERROR(NULL, error); return (DW_DLV_ERROR); } if (_dwarf_alloc(&dbg, mode, error) != DW_DLE_NONE) return (DW_DLV_ERROR); if (_dwarf_elf_init(dbg, elf, error) != DW_DLE_NONE) { free(dbg); return (DW_DLV_ERROR); } if ((ret = _dwarf_init(dbg, 0, errhand, errarg, error)) != DW_DLE_NONE) { _dwarf_elf_deinit(dbg); free(dbg); if (ret == DW_DLE_DEBUG_INFO_NULL) return (DW_DLV_NO_ENTRY); else return (DW_DLV_ERROR); } *ret_dbg = dbg; return (DW_DLV_OK); }
int dwarf_elf_init(Elf *elf, int mode, Dwarf_Handler errhand, Dwarf_Ptr errarg, Dwarf_Debug *ret_dbg, Dwarf_Error *error) { Dwarf_Debug dbg; int ret; if (elf == NULL || ret_dbg == NULL) { DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT); return (DW_DLV_ERROR); } if (mode != DW_DLC_READ) { DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT); return (DW_DLV_ERROR); } if (_dwarf_alloc(&dbg, mode, error) != DW_DLE_NONE) return (DW_DLV_ERROR); if (_dwarf_elf_init(dbg, elf, error) != DW_DLE_NONE) { free(dbg); return (DW_DLV_ERROR); } if ((ret = _dwarf_init(dbg, 0, errhand, errarg, error)) != DW_DLE_NONE) { _dwarf_elf_deinit(dbg); free(dbg); if (ret == DW_DLE_DEBUG_INFO_NULL) return (DW_DLV_NO_ENTRY); else return (DW_DLV_ERROR); } *ret_dbg = 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; }