Technically, I don't think the cfa is absolutely guaranteed to be the SP just before the call. That's just the most common and straightforward way to set it up; the dwarf cfi can set it to whatever it wants as long as it can get to the saved state from it. It's rather unlikely to be anything but a constant offset from that SP.
As I recall, the spec has confusing language like "the cfa is commonly defined as the SP just before the call", which isn't a definition at all.
Sent via DroidX2 on Verizon Wireless™
From: Arun Sharma <address@hidden>
To: Lassi Tuura <address@hidden>
Cc: Steve Fink <address@hidden>, address@hidden
Sent: 2011 Oct, Sat, 29 01:02:56 GMT+00:00
Subject: Re: [Libunwind-devel] local vars
On Fri, Oct 28, 2011 at 9:25 AM, Lassi Tuura wrote:
> Hi,
>
>> I can't think of anything obvious that'd break if we returned a
>> different answer for UNW_X86_64_CFA. Let me think about this a bit
>> more before attempting to implement something.
>
> Hm, are you certain about this?
>
After this patch:
--- a/tests/Gtest-bt.c
+++ b/tests/Gtest-bt.c
@@ -59,7 +59,7 @@ ucontext_t uc;
static void
do_backtrace (void)
{
- unw_word_t ip, sp, off;
+ unw_word_t ip, sp, off, cfa;
unw_proc_info_t pi;
int ret;
@@ -74,6 +74,8 @@ do_backtrace (void)
{
unw_get_reg (&cursor, UNW_REG_IP, &ip);
unw_get_reg (&cursor, UNW_REG_SP, &sp);
+ unw_get_reg (&cursor, UNW_X86_64_CFA, &cfa);
+ printf("ip=%lx sp=%lx cfa=%lx\n", ip, sp, cfa);
buf[0] = '\0';
if (unw_get_proc_name (&cursor, name, sizeof (name), &off) == 0)
{
I get:
ip=400c59 sp=7fffffffd900 cfa=7fffffffd900
ip=40195b sp=7fffffffda40 cfa=7fffffffda40 <-- bar()'s frame
ip=40199b sp=7fffffffde30 cfa=7fffffffde30
ip=332d01d8b4 sp=7fffffffdf00 cfa=7fffffffdf00
ip=400b69 sp=7fffffffdfc0 cfa=7fffffffdfc0
note how (cfa == sp) is always true. Whereas DWARF defines cfa to be
the sp *before* the call.
gdb shows:
Breakpoint 1, bar (v=1) at Gtest-bt.c:139
139 {
(gdb) info frame
Stack level 0, frame at 0x7fffffffde30:
rip = 0x400f50 in bar (Gtest-bt.c:139); saved rip 0x40199b
called by frame at 0x7fffffffdf00
source language c.
Arglist at 0x7fffffffde20, args: v=1
Locals at 0x7fffffffde20, Previous frame's sp is 0x7fffffffde30
Saved registers:
rip at 0x7fffffffde28
I'm essentially thinking of changing the return value of unw_get_reg
(&cursor, UNW_X86_64_CFA, &cfa), without touching any other
implementation details. Does that affect the fast trace
implementation?
-Arun