diff options
author | Mark Wielaard <mjw@redhat.com> | 2009-07-15 12:04:57 +0200 |
---|---|---|
committer | Mark Wielaard <mjw@redhat.com> | 2009-07-15 12:04:57 +0200 |
commit | 00b01a991cc4300f18c747853e85841d187b1fa4 (patch) | |
tree | 6a165d27d3e44afe1e42298d24b0c36081aa2c39 /loc2c-test.c | |
parent | d52761f89a1826b1cca29b1a63269eafe7197756 (diff) | |
download | systemtap-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.c | 41 |
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); |