---
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