summaryrefslogtreecommitdiffstats
path: root/libdwfl/dwfl_addrframe.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdwfl/dwfl_addrframe.c')
-rw-r--r--libdwfl/dwfl_addrframe.c38
1 files changed, 31 insertions, 7 deletions
diff --git a/libdwfl/dwfl_addrframe.c b/libdwfl/dwfl_addrframe.c
index 21548e77..cd0a9a5b 100644
--- a/libdwfl/dwfl_addrframe.c
+++ b/libdwfl/dwfl_addrframe.c
@@ -48,7 +48,28 @@
<http://www.openinventionnetwork.com>. */
#include "libdwflP.h"
-#include "../libdw/cfi.h" /* XXX */
+#include "../libdw/cfi.h"
+
+/* Return -1 for hard error, 0 for address match, 1 for no match. */
+static int
+try_cfi (Dwarf_CFI *cfi, Dwarf_Addr *bias, bool hard,
+ Dwarf_Addr address, Dwarf_Frame **frame)
+{
+ int result = INTUSE(dwarf_cfi_addrframe) (cfi, address - *bias, frame);
+ if (result != 0)
+ {
+ if (hard)
+ __libdwfl_seterrno (DWFL_E_LIBDW);
+ else
+ {
+ int err = INTUSE(dwarf_errno) ();
+ if (err == DWARF_E_NO_MATCH)
+ return 1;
+ __libdwfl_seterrno (DWFL_E (LIBDW, err));
+ }
+ }
+ return result;
+}
int
dwfl_addrframe (dwfl, address, frame)
@@ -56,14 +77,17 @@ dwfl_addrframe (dwfl, address, frame)
Dwarf_Addr address;
Dwarf_Frame **frame;
{
- Dwarf_Addr dwbias;
Dwfl_Module *mod = INTUSE(dwfl_addrmodule) (dwfl, address);
- Dwarf_CFI *cfi = INTUSE(dwfl_module_getcfi) (mod, &dwbias);
- if (cfi == NULL)
+ if (mod == NULL)
return -1;
- int result = INTUSE(dwarf_cfi_addrframe) (cfi, address - dwbias, frame);
- if (result != 0)
- __libdwfl_seterrno (DWFL_E_LIBDW);
+ /* Try to get a .debug_frame match first, then a .eh_frame match. */
+ Dwarf_Addr bias;
+ int result = try_cfi (INTUSE(dwfl_module_dwarf_cfi) (mod, &bias), &bias,
+ false, address, frame);
+ if (result > 0)
+ result = try_cfi (INTUSE(dwfl_module_eh_cfi) (mod, &bias), &bias,
+ true, address, frame);
+
return result;
}