summaryrefslogtreecommitdiffstats
path: root/dwflpp.cxx
diff options
context:
space:
mode:
authorMark Wielaard <mjw@redhat.com>2009-07-15 12:04:57 +0200
committerMark Wielaard <mjw@redhat.com>2009-07-15 12:04:57 +0200
commit00b01a991cc4300f18c747853e85841d187b1fa4 (patch)
tree6a165d27d3e44afe1e42298d24b0c36081aa2c39 /dwflpp.cxx
parentd52761f89a1826b1cca29b1a63269eafe7197756 (diff)
downloadsystemtap-steved-00b01a991cc4300f18c747853e85841d187b1fa4.tar.gz
systemtap-steved-00b01a991cc4300f18c747853e85841d187b1fa4.tar.xz
systemtap-steved-00b01a991cc4300f18c747853e85841d187b1fa4.zip
PR10388 Support DW_OP_call_frame_cfa.
Depends on elfutils 0.142 cfi support. * loc2c.h (c_translate_location): Take (optional) Dwarf_Op *cfa_ops. * loc2c.c (translate): Recognize DW_OP_call_frame_cfa. (location_from_address): Take cfa_ops, examine fb_ops, if it is DW_OP_call_frame_cfa, pass cfa_ops to translate instead. (location_relative): Take cfa_ops, pass to location_from_address. (c_translate_location): Take cfa_ops, pass to location_from_address. * loc2c-test.c (handle_variable): Take cfa_ops, pass to c_translate_location when needed. (main): Fetch cfa_ops, pass to handle_variable. * dwflpp.h (struct dwflpp): Add new method get_cfa_ops. * dwflpp.cxx: Include elfutils/version.h. (translate_location): Fetch cfa_ops when necessary. (get_cfa_ops): New method.
Diffstat (limited to 'dwflpp.cxx')
-rw-r--r--dwflpp.cxx39
1 files changed, 37 insertions, 2 deletions
diff --git a/dwflpp.cxx b/dwflpp.cxx
index 3f30e3a8..dc7af5d8 100644
--- a/dwflpp.cxx
+++ b/dwflpp.cxx
@@ -41,6 +41,9 @@ extern "C" {
#include <fcntl.h>
#include <elfutils/libdwfl.h>
#include <elfutils/libdw.h>
+#ifdef HAVE_ELFUTILS_VERSION_H
+#include <elfutils/version.h>
+#endif
#include <dwarf.h>
#include <elf.h>
#include <obstack.h>
@@ -1497,10 +1500,11 @@ dwflpp::translate_location(struct obstack *pool,
e->tok);
}
+ Dwarf_Op *cfa_ops = get_cfa_ops (pc);
return c_translate_location (pool, &loc2c_error, this,
&loc2c_emit_address,
1, 0 /* PR9768 */,
- pc, expr, len, tail, fb_attr);
+ pc, expr, len, tail, fb_attr, cfa_ops);
}
@@ -2085,7 +2089,7 @@ dwflpp::literal_stmt_for_return (Dwarf_Die *scope_die,
&loc2c_emit_address,
1, 0 /* PR9768 */,
pc, locops, nlocops,
- &tail, NULL);
+ &tail, NULL, NULL);
/* Translate the ->bar->baz[NN] parts. */
@@ -2489,5 +2493,36 @@ dwflpp::dwarf_getscopes_cached (Dwarf_Addr pc, Dwarf_Die **scopes)
return num_cached_scopes;
}
+Dwarf_Op *
+dwflpp::get_cfa_ops (Dwarf_Addr pc)
+{
+ Dwarf_Op *cfa_ops = NULL;
+
+#ifdef _ELFUTILS_PREREQ
+#if _ELFUTILS_PREREQ(0,142)
+ // Try debug_frame first, then fall back on eh_frame.
+ Dwarf_Addr bias;
+ Dwarf_CFI *cfi = dwfl_module_dwarf_cfi (module, &bias);
+ if (cfi != NULL)
+ {
+ Dwarf_Frame *frame = NULL;
+ if (dwarf_cfi_addrframe (cfi, pc, &frame) == 0)
+ dwarf_frame_cfa (frame, &cfa_ops);
+ }
+ if (cfa_ops == NULL)
+ {
+ cfi = dwfl_module_eh_cfi (module, &bias);
+ if (cfi != NULL)
+ {
+ Dwarf_Frame *frame = NULL;
+ if (dwarf_cfi_addrframe (cfi, pc, &frame) == 0)
+ dwarf_frame_cfa (frame, &cfa_ops);
+ }
+ }
+#endif
+#endif
+
+ return cfa_ops;
+}
/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */