static int __report_module(struct addr_location *al, u64 ip, struct unwind_info *ui) { Dwfl_Module *mod; struct dso *dso = NULL; thread__find_addr_location(ui->thread, ui->machine, PERF_RECORD_MISC_USER, MAP__FUNCTION, ip, al); if (al->map) dso = al->map->dso; if (!dso) return 0; mod = dwfl_addrmodule(ui->dwfl, ip); if (!mod) mod = dwfl_report_elf(ui->dwfl, dso->short_name, dso->long_name, -1, al->map->start, false); return mod && dwfl_addrmodule(ui->dwfl, ip) == mod ? 0 : -1; }
/* * Return: * 0 if return address for the program counter @pc is on stack * 1 if return address is in LR and no new stack frame was allocated * 2 if return address is in LR and a new frame was allocated (but not * yet used) * -1 in case of errors */ static int check_return_addr(struct dso *dso, u64 map_start, Dwarf_Addr pc) { int rc = -1; Dwfl *dwfl; Dwfl_Module *mod; Dwarf_Frame *frame; int ra_regno; Dwarf_Addr start = pc; Dwarf_Addr end = pc; bool signalp; const char *exec_file = dso->long_name; dwfl = dso->dwfl; if (!dwfl) { dwfl = dwfl_begin(&offline_callbacks); if (!dwfl) { pr_debug("dwfl_begin() failed: %s\n", dwarf_errmsg(-1)); return -1; } mod = dwfl_report_elf(dwfl, exec_file, exec_file, -1, map_start, false); if (!mod) { pr_debug("dwfl_report_elf() failed %s\n", dwarf_errmsg(-1)); /* * We normally cache the DWARF debug info and never * call dwfl_end(). But to prevent fd leak, free in * case of error. */ dwfl_end(dwfl); goto out; } dso->dwfl = dwfl; } mod = dwfl_addrmodule(dwfl, pc); if (!mod) { pr_debug("dwfl_addrmodule() failed, %s\n", dwarf_errmsg(-1)); goto out; } /* * To work with split debug info files (eg: glibc), check both * .eh_frame and .debug_frame sections of the ELF header. */ frame = get_eh_frame(mod, pc); if (!frame) { frame = get_dwarf_frame(mod, pc); if (!frame) goto out; } ra_regno = dwarf_frame_info(frame, &start, &end, &signalp); if (ra_regno < 0) { pr_debug("Return address register unavailable: %s\n", dwarf_errmsg(-1)); goto out; } rc = check_return_reg(ra_regno, frame); out: return rc; }