summaryrefslogtreecommitdiffstats
path: root/loc2c-test.c
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 /loc2c-test.c
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 'loc2c-test.c')
-rw-r--r--loc2c-test.c41
1 files changed, 37 insertions, 4 deletions
diff --git a/loc2c-test.c b/loc2c-test.c
index 688f4a8b..0c992c76 100644
--- a/loc2c-test.c
+++ b/loc2c-test.c
@@ -75,7 +75,7 @@ get_location (Dwarf_Addr dwbias, Dwarf_Addr pc, Dwarf_Attribute *loc_attr,
static void
handle_variable (Dwarf_Die *scopes, int nscopes, int out,
Dwarf_Addr cubias, Dwarf_Die *vardie, Dwarf_Addr pc,
- char **fields)
+ Dwarf_Op *cfa_ops, char **fields)
{
#define obstack_chunk_alloc malloc
#define obstack_chunk_free free
@@ -121,7 +121,7 @@ handle_variable (Dwarf_Die *scopes, int nscopes, int out,
struct location *head, *tail = NULL;
head = c_translate_location (&pool, &fail, NULL, NULL,
1, cubias, pc, locexpr, locexpr_len,
- &tail, fb_attr);
+ &tail, fb_attr, cfa_ops);
if (dwarf_attr_integrate (vardie, DW_AT_type, &attr_mem) == NULL)
error (2, 0, _("cannot get type of variable: %s"),
@@ -240,7 +240,7 @@ handle_variable (Dwarf_Die *scopes, int nscopes, int out,
&locexpr_len);
c_translate_location (&pool, NULL, NULL, NULL,
1, cubias, pc, locexpr, locexpr_len,
- &tail, NULL);
+ &tail, NULL, NULL);
break;
}
}
@@ -521,7 +521,40 @@ main (int argc, char **argv)
error (0, 0, "dwarf_getscopevar: %s (+%d, %s:%d:%d): %s",
spec, shadow, at, lineno, colno, dwarf_errmsg (-1));
else
- handle_variable (scopes, n, out, cubias, &vardie, pc, &argv[argi]);
+ {
+ Dwarf_Op *cfa_ops = NULL;
+
+#ifdef _ELFUTILS_PREREQ
+#if _ELFUTILS_PREREQ(0,142)
+ Dwarf_Addr bias;
+ Dwfl_Module *module = dwfl_addrmodule (dwfl, pc);
+ if (module != NULL)
+ {
+ // Try debug_frame first, then fall back on eh_frame.
+ 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
+
+ handle_variable (scopes, n, out, cubias, &vardie, pc, cfa_ops,
+ &argv[argi]);
+ }
}
free (scopes);