---
include/dwarf.h                   |    2 +
include/tdep-arm/libunwind_i.h    |    3 ++
include/tdep-hppa/libunwind_i.h   |    3 ++
include/tdep-ia64/libunwind_i.h   |    3 ++
include/tdep-mips/libunwind_i.h   |    3 ++
include/tdep-ppc32/libunwind_i.h  |    3 ++
include/tdep-ppc64/libunwind_i.h  |    3 ++
include/tdep-x86/libunwind_i.h    |    3 ++
include/tdep-x86_64/libunwind_i.h |   18 +++++++++
src/dwarf/Gfde.c                  |    3 ++
src/dwarf/Gparser.c               |    9 +++++
src/x86_64/Gos-linux.c            |   72 ++++++++++++++++++++++++++++++++-----
src/x86_64/Gstep.c                |    1 +
13 files changed, 117 insertions(+), 9 deletions(-)
diff --git a/include/dwarf.h b/include/dwarf.h
index 37b5ec1..53c803b 100644
--- a/include/dwarf.h
+++ b/include/dwarf.h
@@ -247,6 +247,7 @@ typedef struct dwarf_reg_state
     unsigned short lru_chain;    /* used for least-recently-used chain */
     unsigned short coll_chain; /* used for hash collisions */
     unsigned short hint;             /* hint for next rs to try (or -1) */
+    unsigned short signal_frame; /* optional machine-dependent signal info */
   }
 dwarf_reg_state_t;
 
@@ -266,6 +267,7 @@ typedef struct dwarf_cie_info
     uint8_t lsda_encoding;
     unsigned int sized_augmentation : 1;
     unsigned int have_abi_marker : 1;
+    unsigned int signal_frame : 1;
   }
 dwarf_cie_info_t;
 
diff --git a/include/tdep-arm/libunwind_i.h b/include/tdep-arm/libunwind_i.h
index 3424d86..2e1c428 100644
--- a/include/tdep-arm/libunwind_i.h
+++ b/include/tdep-arm/libunwind_i.h
@@ -217,6 +217,9 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, 
unw_word_t val)
 #define tdep_get_elf_image             UNW_ARCH_OBJ(get_elf_image)
 #define tdep_access_reg                        UNW_OBJ(access_reg)
 #define tdep_access_fpreg              UNW_OBJ(access_fpreg)
+#define tdep_fetch_frame(c,ip,n)       do {} while(0)
+#define tdep_cache_frame(c,rs)         do {} while(0)
+#define tdep_reuse_frame(c,rs)         do {} while(0)
 
 #ifdef UNW_LOCAL_ONLY
 # define tdep_find_proc_info(c,ip,n)                           \
diff --git a/include/tdep-hppa/libunwind_i.h b/include/tdep-hppa/libunwind_i.h
index 553e97d..d89cc65 100644
--- a/include/tdep-hppa/libunwind_i.h
+++ b/include/tdep-hppa/libunwind_i.h
@@ -224,6 +224,9 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, 
unw_word_t val)
 #define tdep_get_elf_image             UNW_ARCH_OBJ(get_elf_image)
 #define tdep_access_reg                        UNW_OBJ(access_reg)
 #define tdep_access_fpreg              UNW_OBJ(access_fpreg)
+#define tdep_fetch_frame(c,ip,n)       do {} while(0)
+#define tdep_cache_frame(c,rs)         do {} while(0)
+#define tdep_reuse_frame(c,rs)         do {} while(0)
 
 #ifdef UNW_LOCAL_ONLY
 # define tdep_find_proc_info(c,ip,n)                           \
diff --git a/include/tdep-ia64/libunwind_i.h b/include/tdep-ia64/libunwind_i.h
index 552c949..4936d51 100644
--- a/include/tdep-ia64/libunwind_i.h
+++ b/include/tdep-ia64/libunwind_i.h
@@ -220,6 +220,9 @@ struct ia64_global_unwind_state
 #define tdep_get_elf_image             UNW_ARCH_OBJ(get_elf_image)
 #define tdep_access_reg                        UNW_OBJ(access_reg)
 #define tdep_access_fpreg              UNW_OBJ(access_fpreg)
+#define tdep_fetch_frame(c,ip,n)       do {} while(0)
+#define tdep_cache_frame(c,rs)         do {} while(0)
+#define tdep_reuse_frame(c,rs)         do {} while(0)
 #define tdep_get_as(c)                 ((c)->as)
 #define tdep_get_as_arg(c)             ((c)->as_arg)
 #define tdep_get_ip(c)                 ((c)->ip)
diff --git a/include/tdep-mips/libunwind_i.h b/include/tdep-mips/libunwind_i.h
index c2f756a..298fae8 100644
--- a/include/tdep-mips/libunwind_i.h
+++ b/include/tdep-mips/libunwind_i.h
@@ -279,6 +279,9 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, 
unw_word_t val)
 #define tdep_get_elf_image             UNW_ARCH_OBJ(get_elf_image)
 #define tdep_access_reg                        UNW_OBJ(access_reg)
 #define tdep_access_fpreg              UNW_OBJ(access_fpreg)
+#define tdep_fetch_frame(c,ip,n)       do {} while(0)
+#define tdep_cache_frame(c,rs)         do {} while(0)
+#define tdep_reuse_frame(c,rs)         do {} while(0)
 
 #ifdef UNW_LOCAL_ONLY
 # define tdep_find_proc_info(c,ip,n)                           \
diff --git a/include/tdep-ppc32/libunwind_i.h b/include/tdep-ppc32/libunwind_i.h
index 05dd135..b963bca 100644
--- a/include/tdep-ppc32/libunwind_i.h
+++ b/include/tdep-ppc32/libunwind_i.h
@@ -256,6 +256,9 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, 
unw_word_t val)
 #define tdep_get_elf_image             UNW_ARCH_OBJ(get_elf_image)
 #define tdep_access_reg                        UNW_OBJ(access_reg)
 #define tdep_access_fpreg              UNW_OBJ(access_fpreg)
+#define tdep_fetch_frame(c,ip,n)       do {} while(0)
+#define tdep_cache_frame(c,rs)         do {} while(0)
+#define tdep_reuse_frame(c,rs)         do {} while(0)
 #define tdep_get_func_addr             UNW_OBJ(get_func_addr)
 
 #ifdef UNW_LOCAL_ONLY
diff --git a/include/tdep-ppc64/libunwind_i.h b/include/tdep-ppc64/libunwind_i.h
index 192a034..799b511 100644
--- a/include/tdep-ppc64/libunwind_i.h
+++ b/include/tdep-ppc64/libunwind_i.h
@@ -256,6 +256,9 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, 
unw_word_t val)
 #define tdep_get_elf_image             UNW_ARCH_OBJ(get_elf_image)
 #define tdep_access_reg                        UNW_OBJ(access_reg)
 #define tdep_access_fpreg              UNW_OBJ(access_fpreg)
+#define tdep_fetch_frame(c,ip,n)       do {} while(0)
+#define tdep_cache_frame(c,rs)         do {} while(0)
+#define tdep_reuse_frame(c,rs)         do {} while(0)
 #define tdep_get_func_addr             UNW_OBJ(get_func_addr)
 
 #ifdef UNW_LOCAL_ONLY
diff --git a/include/tdep-x86/libunwind_i.h b/include/tdep-x86/libunwind_i.h
index 9af007d..bed8cbf 100644
--- a/include/tdep-x86/libunwind_i.h
+++ b/include/tdep-x86/libunwind_i.h
@@ -240,6 +240,9 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, 
unw_word_t val)
 #define tdep_get_elf_image             UNW_ARCH_OBJ(get_elf_image)
 #define tdep_access_reg                        UNW_OBJ(access_reg)
 #define tdep_access_fpreg              UNW_OBJ(access_fpreg)
+#define tdep_fetch_frame(c,ip,n)       do {} while(0)
+#define tdep_cache_frame(c,rs)         do {} while(0)
+#define tdep_reuse_frame(c,rs)         do {} while(0)
 
 #ifdef UNW_LOCAL_ONLY
 # define tdep_find_proc_info(c,ip,n)                           \
diff --git a/include/tdep-x86_64/libunwind_i.h 
b/include/tdep-x86_64/libunwind_i.h
index f6a0289..c022725 100644
--- a/include/tdep-x86_64/libunwind_i.h
+++ b/include/tdep-x86_64/libunwind_i.h
@@ -163,6 +163,15 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, 
unw_word_t val)
 #define tdep_get_elf_image             UNW_ARCH_OBJ(get_elf_image)
 #define tdep_access_reg                        UNW_OBJ(access_reg)
 #define tdep_access_fpreg              UNW_OBJ(access_fpreg)
+#if __linux__
+# define tdep_fetch_frame              UNW_OBJ(fetch_frame)
+# define tdep_cache_frame              UNW_OBJ(cache_frame)
+# define tdep_reuse_frame              UNW_OBJ(reuse_frame)
+#else
+# define tdep_fetch_frame(c,ip,n)      do {} while(0)
+# define tdep_cache_frame(c,rs)                do {} while(0)
+# define tdep_reuse_frame(c,rs)                do {} while(0)
+#endif
 
 #ifdef UNW_LOCAL_ONLY
 # define tdep_find_proc_info(c,ip,n)                           \
@@ -196,5 +205,14 @@ extern int tdep_access_reg (struct cursor *c, unw_regnum_t 
reg,
                            unw_word_t *valp, int write);
 extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg,
                              unw_fpreg_t *valp, int write);
+#if __linux__
+extern void tdep_fetch_frame (struct dwarf_cursor *c, unw_word_t ip,
+                             int need_unwind_info);
+extern void tdep_cache_frame (struct dwarf_cursor *c,
+                             struct dwarf_reg_state *rs);
+extern void tdep_reuse_frame (struct dwarf_cursor *c,
+                             struct dwarf_reg_state *rs);
+#endif
+
 
 #endif /* X86_64_LIBUNWIND_I_H */
diff --git a/src/dwarf/Gfde.c b/src/dwarf/Gfde.c
index 16e36ee..8659624 100644
--- a/src/dwarf/Gfde.c
+++ b/src/dwarf/Gfde.c
@@ -187,6 +187,9 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, 
unw_word_t addr,
        break;
 
       case 'S':
+       /* This is a signal frame. */
+       dci->signal_frame = 1;
+
        /* Temporarily set it to one so dwarf_parse_fde() knows that
           it should fetch the actual ABI/TAG pair from the FDE.  */
        dci->have_abi_marker = 1;
diff --git a/src/dwarf/Gparser.c b/src/dwarf/Gparser.c
index db64b92..ccb710a 100644
--- a/src/dwarf/Gparser.c
+++ b/src/dwarf/Gparser.c
@@ -400,6 +400,11 @@ fetch_proc_info (struct dwarf_cursor *c, unw_word_t ip, 
int need_unwind_info)
 
   c->pi_valid = 1;
   c->pi_is_dynamic = dynamic;
+
+  /* Let system/machine-dependent code determine frame-specific attributes. */
+  if (ret >= 0)
+    tdep_fetch_frame (c, ip, need_unwind_info);
+
   return ret;
 }
 
@@ -604,6 +609,8 @@ rs_new (struct dwarf_rs_cache *cache, struct dwarf_cursor * 
c)
   rs->hint = 0;
   rs->ip = c->ip;
   rs->ret_addr_column = c->ret_addr_column;
+  rs->signal_frame = 0;
+  tdep_cache_frame (c, rs);
 
   return rs;
 }
@@ -818,6 +825,8 @@ dwarf_find_save_locs (struct dwarf_cursor *c)
 
   memcpy (&rs_copy, rs, sizeof (rs_copy));
   put_rs_cache (c->as, cache, &saved_mask);
+
+  tdep_reuse_frame (c, &rs_copy);
   if ((ret = apply_reg_state (c, &rs_copy)) < 0)
     return ret;
 
diff --git a/src/x86_64/Gos-linux.c b/src/x86_64/Gos-linux.c
index 1bf4ba2..8337fa5 100644
--- a/src/x86_64/Gos-linux.c
+++ b/src/x86_64/Gos-linux.c
@@ -30,10 +30,59 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
SOFTWARE.  */
 
 #include <sys/syscall.h>
 
+HIDDEN void
+tdep_fetch_frame (struct dwarf_cursor *dw, unw_word_t ip, int need_unwind_info)
+{
+  struct cursor *c = (struct cursor *) dw;
+  assert(! need_unwind_info || dw->pi_valid);
+  assert(! need_unwind_info || dw->pi.unwind_info);
+  if (dw->pi_valid
+      && dw->pi.unwind_info
+      && ((struct dwarf_cie_info *) dw->pi.unwind_info)->signal_frame)
+  {
+    c->sigcontext_format = X86_64_SCF_LINUX_RT_SIGFRAME;
+    c->sigcontext_addr = dw->cfa;
+  }
+  else
+  {
+    c->sigcontext_format = X86_64_SCF_NONE;
+    c->sigcontext_addr = 0;
+  }
+
+  Debug(15, "fetch frame ip=0x%lx cfa=0x%lx format=%d addr=0x%lx\n",
+        dw->ip, dw->cfa, c->sigcontext_format, c->sigcontext_addr);
+}
+
+HIDDEN void
+tdep_cache_frame (struct dwarf_cursor *dw, struct dwarf_reg_state *rs)
+{
+  struct cursor *c = (struct cursor *) dw;
+  rs->signal_frame = c->sigcontext_format;
+
+  Debug(15, "cache frame ip=0x%lx cfa=0x%lx format=%d addr=0x%lx\n",
+        dw->ip, dw->cfa, c->sigcontext_format, c->sigcontext_addr);
+}
+
+HIDDEN void
+tdep_reuse_frame (struct dwarf_cursor *dw, struct dwarf_reg_state *rs)
+{
+  struct cursor *c = (struct cursor *) dw;
+  c->sigcontext_format = rs->signal_frame;
+  if (c->sigcontext_format == X86_64_SCF_LINUX_RT_SIGFRAME)
+    c->sigcontext_addr = dw->cfa;
+  else
+    c->sigcontext_addr = 0;
+
+  Debug(15, "reuse frame ip=0x%lx cfa=0x%lx format=%d addr=0x%lx\n",
+        dw->ip, dw->cfa, c->sigcontext_format, c->sigcontext_addr);
+}
+
 PROTECTED int
 unw_is_signal_frame (unw_cursor_t *cursor)
 {
   struct cursor *c = (struct cursor *) cursor;
+  return c->sigcontext_format != X86_64_SCF_NONE;
+#if 0
   unw_word_t w0, w1, ip;
   unw_addr_space_t as;
   unw_accessors_t *a;
@@ -57,20 +106,24 @@ unw_is_signal_frame (unw_cursor_t *cursor)
     return 0;
   w1 &= 0xff;
   return (w0 == 0x0f0000000fc0c748 && w1 == 0x05);
+#endif
 }
 
 PROTECTED int
 unw_handle_signal_frame (unw_cursor_t *cursor)
 {
+  /* Should not get here because we now use kernel-provided dwarf
+     information for the signal trampoline and dwarf_step() works.
+     Hence dwarf_step() should never call this function. Maybe
+     restore old non-dwarf signal handling here, but then the
+     gating on unw_is_signal_frame() needs to be removed. */
   struct cursor *c = (struct cursor *) cursor;
-  int ret;
-  unw_word_t ucontext = c->dwarf.cfa;
-
-  Debug(1, "signal frame, skip over trampoline\n");
-
-  c->sigcontext_format = X86_64_SCF_LINUX_RT_SIGFRAME;
-  c->sigcontext_addr = c->dwarf.cfa;
-
+  Debug(1, "old format signal frame? format=%d addr=0x%lx cfa=0x%lx\n",
+       c->sigcontext_format, c->sigcontext_addr, c->dwarf.cfa);
+  assert(c->sigcontext_format == X86_64_SCF_LINUX_RT_SIGFRAME);
+  assert(c->sigcontext_addr == c->dwarf.cfa);
+  assert(0);
+#if 0
   struct dwarf_loc rsp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0);
   ret = dwarf_get (&c->dwarf, rsp_loc, &c->dwarf.cfa);
   if (ret < 0)
@@ -96,8 +149,9 @@ unw_handle_signal_frame (unw_cursor_t *cursor)
   c->dwarf.loc[R14] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R14, 0);
   c->dwarf.loc[R15] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R15, 0);
   c->dwarf.loc[RIP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RIP, 0);
+#endif
 
-  return 0;
+  return 1;
 }
 
 #ifndef UNW_REMOTE_ONLY
diff --git a/src/x86_64/Gstep.c b/src/x86_64/Gstep.c
index d23be8e..01022a1 100644
--- a/src/x86_64/Gstep.c
+++ b/src/x86_64/Gstep.c
@@ -38,6 +38,7 @@ unw_step (unw_cursor_t *cursor)
         c, (unsigned long long) c->dwarf.ip);
 
   /* Try DWARF-based unwinding... */
+  c->sigcontext_format = X86_64_SCF_NONE;
   ret = dwarf_step (&c->dwarf);
 
   if (ret < 0 && ret != -UNW_ENOINFO)
_______________________________________________
Libunwind-devel mailing list
[email protected]
http://lists.nongnu.org/mailman/listinfo/libunwind-devel

Reply via email to