On Tue, Nov 22, 2011 at 12:12 PM, Lassi Tuura <[email protected]> wrote:

> The new patch looks good. I've tested on RHEL5-derived x86_64 system with
> GCC 4.6.1 build, and things look good in a couple of test applications I
> tried on.

Thanks!

> There's one new compilation warning in release mode, because 'uc' is only
> used in assert() in the new tdep_stash_frame(). Maybe protect the entire
> signal frame 'else if' body in tdep_stash_frame() #if UNW_DEBUG?
>
> ../../../libunwind/src/x86_64/Gstash_frame.c: In function 
> '_ULx86_64_stash_frame':
> ../../../libunwind/src/x86_64/Gstash_frame.c:84:22: warning: unused variable 
> 'uc' [-Wunused-variable]

The UNW_DEBUG could be true and assert() could still be empty.

How about this:

diff --git a/src/x86_64/Gstash_frame.c b/src/x86_64/Gstash_frame.c
index 92477e0..43695d6 100644
--- a/src/x86_64/Gstash_frame.c
+++ b/src/x86_64/Gstash_frame.c
@@ -81,11 +81,13 @@ tdep_stash_frame (struct dwarf_cursor *d, struct
dwarf_reg_state *rs)
        their ucontext_t offsets.  Confirm DWARF info agrees with the
        offsets we expect.  */

+#ifndef NDEBUG
     const unw_word_t uc = c->sigcontext_addr;

     assert (DWARF_GET_LOC(d->loc[RIP]) == uc + UC_MCONTEXT_GREGS_RIP);
     assert (DWARF_GET_LOC(d->loc[RBP]) == uc + UC_MCONTEXT_GREGS_RBP);
     assert (DWARF_GET_LOC(d->loc[RSP]) == uc + UC_MCONTEXT_GREGS_RSP);
+#endif

     Debug (4, " sigreturn frame\n");
   }

I've also changed the assert slightly (moving 'uc' to the right): I think
it's slightly easier to understand that way.

Full patch attached.


Thanks,
-- 
Paul Pluzhnikov
diff --git a/src/x86_64/Gos-linux.c b/src/x86_64/Gos-linux.c
index a315ea1..a0ecce2 100644
--- a/src/x86_64/Gos-linux.c
+++ b/src/x86_64/Gos-linux.c
@@ -64,10 +64,9 @@ tdep_reuse_frame (struct dwarf_cursor *dw, struct 
dwarf_reg_state *rs)
   c->sigcontext_format = rs->signal_frame;
   if (c->sigcontext_format == X86_64_SCF_LINUX_RT_SIGFRAME)
   {
-    /* Rest will be filled by tdep_stash_frame(), save what it needs. */
     c->frame_info.frame_type = UNW_X86_64_FRAME_SIGRETURN;
-    c->frame_info.cfa_reg_offset = -1;
-    c->frame_info.cfa_reg_rsp = -1;
+    /* Offset from cfa to ucontext_t in signal frame.  */
+    c->frame_info.cfa_reg_offset = 0;
     c->sigcontext_addr = dw->cfa;
   }
   else
diff --git a/src/x86_64/Gstash_frame.c b/src/x86_64/Gstash_frame.c
index 2f81cc0..43695d6 100644
--- a/src/x86_64/Gstash_frame.c
+++ b/src/x86_64/Gstash_frame.c
@@ -74,19 +74,22 @@ tdep_stash_frame (struct dwarf_cursor *d, struct 
dwarf_reg_state *rs)
     Debug (4, " standard frame\n");
   }
 
-  /* Signal frame was detected via augmentation in tdep_fetch_frame()
-     and partially filled in tdep_reuse_frame().  Now that we have
-     the delta between inner and outer CFAs available to use, fill in
-     the offsets for CFA and stored registers.  We don't have space
-     for RIP, it's location is calculated relative to RBP location. */
+  /* Signal frame was detected via augmentation in tdep_fetch_frame()  */
   else if (f->frame_type == UNW_X86_64_FRAME_SIGRETURN)
   {
-    assert (f->cfa_reg_offset == -1);
-    f->cfa_reg_offset = d->cfa - c->sigcontext_addr;
-    f->rbp_cfa_offset = DWARF_GET_LOC(d->loc[RBP]) - d->cfa;
-    f->rsp_cfa_offset = DWARF_GET_LOC(d->loc[RSP]) - d->cfa;
-    Debug (4, " sigreturn frame rbpoff %d rspoff %d\n",
-          f->rbp_cfa_offset, f->rsp_cfa_offset);
+    /* Later we are going to fish out {RBP,RSP,RIP} from sigcontext via
+       their ucontext_t offsets.  Confirm DWARF info agrees with the
+       offsets we expect.  */
+
+#ifndef NDEBUG
+    const unw_word_t uc = c->sigcontext_addr;
+
+    assert (DWARF_GET_LOC(d->loc[RIP]) == uc + UC_MCONTEXT_GREGS_RIP);
+    assert (DWARF_GET_LOC(d->loc[RBP]) == uc + UC_MCONTEXT_GREGS_RBP);
+    assert (DWARF_GET_LOC(d->loc[RSP]) == uc + UC_MCONTEXT_GREGS_RSP);
+#endif
+
+    Debug (4, " sigreturn frame\n");
   }
 
   /* PLT and guessed RBP-walked frames are handled in unw_step(). */
diff --git a/src/x86_64/Gtrace.c b/src/x86_64/Gtrace.c
index f10737f..2d78729 100644
--- a/src/x86_64/Gtrace.c
+++ b/src/x86_64/Gtrace.c
@@ -35,12 +35,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
SOFTWARE.  */
 /* Initial hash table size. Table expands by 2 bits (times four). */
 #define HASH_MIN_BITS 14
 
-/* There's not enough space to store RIP's location in a signal
-   frame, but we can calculate it relative to RBP's (or RSP's)
-   position in mcontext structure.  Note we don't want to use
-   the UC_MCONTEXT_GREGS_* directly since we rely on DWARF info. */
-#define dRIP (UC_MCONTEXT_GREGS_RIP - UC_MCONTEXT_GREGS_RBP)
-
 typedef struct
 {
   unw_tdep_frame_t *frames;
@@ -496,16 +490,13 @@ tdep_trace (unw_cursor_t *cursor, void **buffer, int 
*size)
       break;
 
     case UNW_X86_64_FRAME_SIGRETURN:
-      /* Advance standard signal frame, whose CFA points above saved
-         registers (ucontext) among other things.  We know the info
-        is stored at some unknown constant offset off inner frame's
-        CFA.  We determine the actual offset from DWARF unwind info. */
-      cfa = cfa + f->cfa_reg_offset;
-      ACCESS_MEM_FAST(ret, c->validate, d, cfa + f->rbp_cfa_offset + dRIP, 
rip);
+      cfa = cfa + f->cfa_reg_offset; /* cfa now points to ucontext_t.  */
+
+      ACCESS_MEM_FAST(ret, c->validate, d, cfa + UC_MCONTEXT_GREGS_RIP, rip);
       if (likely(ret >= 0))
-        ACCESS_MEM_FAST(ret, c->validate, d, cfa + f->rbp_cfa_offset, rbp);
+        ACCESS_MEM_FAST(ret, c->validate, d, cfa + UC_MCONTEXT_GREGS_RBP, rbp);
       if (likely(ret >= 0))
-        ACCESS_MEM_FAST(ret, c->validate, d, cfa + f->rsp_cfa_offset, rsp);
+        ACCESS_MEM_FAST(ret, c->validate, d, cfa + UC_MCONTEXT_GREGS_RSP, rsp);
 
       /* Resume stack at signal restoration point. The stack is not
          necessarily continuous here, especially with sigaltstack(). */
_______________________________________________
Libunwind-devel mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/libunwind-devel

Reply via email to