|
|
@@ -145,7 +145,7 @@ static Dwarf_Frame *get_dwarf_frame(Dwfl_Module *mod, Dwarf_Addr pc)
|
|
|
* yet used)
|
|
|
* -1 in case of errors
|
|
|
*/
|
|
|
-static int check_return_addr(const char *exec_file, Dwarf_Addr pc)
|
|
|
+static int check_return_addr(struct dso *dso, Dwarf_Addr pc)
|
|
|
{
|
|
|
int rc = -1;
|
|
|
Dwfl *dwfl;
|
|
|
@@ -156,15 +156,27 @@ static int check_return_addr(const char *exec_file, Dwarf_Addr pc)
|
|
|
Dwarf_Addr end = pc;
|
|
|
bool signalp;
|
|
|
|
|
|
- dwfl = dwfl_begin(&offline_callbacks);
|
|
|
- if (!dwfl) {
|
|
|
- pr_debug("dwfl_begin() failed: %s\n", dwarf_errmsg(-1));
|
|
|
- return -1;
|
|
|
- }
|
|
|
+ dwfl = dso->dwfl;
|
|
|
|
|
|
- if (dwfl_report_offline(dwfl, "", exec_file, -1) == NULL) {
|
|
|
- pr_debug("dwfl_report_offline() failed %s\n", dwarf_errmsg(-1));
|
|
|
- goto out;
|
|
|
+ if (!dwfl) {
|
|
|
+ dwfl = dwfl_begin(&offline_callbacks);
|
|
|
+ if (!dwfl) {
|
|
|
+ pr_debug("dwfl_begin() failed: %s\n", dwarf_errmsg(-1));
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (dwfl_report_offline(dwfl, "", dso->long_name, -1) == NULL) {
|
|
|
+ pr_debug("dwfl_report_offline() 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);
|
|
|
@@ -194,7 +206,6 @@ static int check_return_addr(const char *exec_file, Dwarf_Addr pc)
|
|
|
rc = check_return_reg(ra_regno, frame);
|
|
|
|
|
|
out:
|
|
|
- dwfl_end(dwfl);
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
|
@@ -246,7 +257,7 @@ int arch_skip_callchain_idx(struct machine *machine, struct thread *thread,
|
|
|
return skip_slot;
|
|
|
}
|
|
|
|
|
|
- rc = check_return_addr(dso->long_name, ip);
|
|
|
+ rc = check_return_addr(dso, ip);
|
|
|
|
|
|
pr_debug("DSO %s, nr %" PRIx64 ", ip 0x%" PRIx64 "rc %d\n",
|
|
|
dso->long_name, chain->nr, ip, rc);
|