* [PATCH] Add sparc64-linux sigtramp support
@ 2005-04-21 3:51 David S. Miller
2005-04-21 19:23 ` Mark Kettenis
0 siblings, 1 reply; 12+ messages in thread
From: David S. Miller @ 2005-04-21 3:51 UTC (permalink / raw)
To: gdb-patches
This patch gets signal backtraces working properly on sparc64/linux
targets. The two non-straightforward parts of the implementation are:
1) proper stack bias adjusting of cache->base
2) registering the sniffer in the correct order
The issue in #2 is that we use the solaris2 sparc64 target support
as our base, then override and add things which are different for the
linux sparc64 target.
The solaris2 sparc64 osabi init which we call registers first the
solaris2 sigtramp sniffer, then the generic sparc64 frame sniffer,
via sparc64_init_abi().
Therefore we have to register the linux sparc64 sniffer before we
invoke sparc64_sol2_init_abi().
While doing this work I noticed that the signal trampoline symbols
names were wrong in the 32-bit sparc linux sigtramp support. Those
are the i386 glibc symbol names, not the sparc ones :-) So I corrected
those and also documented the "struct pt_regs" layout that we're
picking sigtramp registers from.
2005-04-20 David S. Miller <davem@davemloft.net>
* sparc-linux-tdep.c (sparc32_linux_sigtramp_p): Fix
signal return stub symbol names, __restore and __restore_rt are
the i386 symbol names not the sparc ones.
(sparc32_linux_sigtramp_frame_cache): Document the layout
of the pt_regs structure we are fishing out of the
signal frame.
* sparc64-linux-tdep.c (LINUX64_RT_SIGTRAMP_INSN0,
LINUX64_RT_SIGTRAMP_INSN1): New defines.
(sparc64_linux_sigtramp_start, sparc64_linux_sigtramp_p,
sparc64_linux_sigtramp_frame_cache,
sparc64_linux_sigtramp_frame_this_id,
sparc64_linux_sigtramp_frame_prev_register,
sparc64_linux_sigtramp_frame_sniffer): New functions.
(sparc64_linux_sigtramp_frame_unwind): New frame unwinder.
(sparc64_linux_init_abi): Register sigtramp frame sniffer.
* Makefile.in (sparc64-linux-tdep.o): Update dependencies.
--- Makefile.in 17 Apr 2005 22:20:19 -0000 1.716
+++ Makefile.in 21 Apr 2005 03:34:17 -0000
@@ -2565,8 +2565,10 @@ sparc64fbsd-tdep.o: sparc64fbsd-tdep.c $
$(sparc64_tdep_h) $(solib_svr4_h)
sparc64-linux-nat.o: sparc64-linux-nat.c $(defs_h) $(sparc64_tdep_h) \
$(sparc_nat_h)
-sparc64-linux-tdep.o: sparc64-linux-tdep.c $(defs_h) $(gdbarch_h) $(osabi_h) \
- $(solib_svr4_h) $(sparc64_tdep_h)
+sparc64-linux-tdep.o: sparc64-linux-tdep.c $(defs_h) $(frame_h) \
+ $(frame_unwind_h) $(gdbarch_h) $(osabi_h) $(solib_svr4_h) \
+ $(symtab_h) $(trad_frame_h) $(gdb_assert_h) $(gdb_string_h) \
+ $(sparc64_tdep_h)
sparc64-nat.o: sparc64-nat.c $(defs_h) $(gdbarch_h) $(sparc64_tdep_h) \
$(sparc_nat_h)
sparc64nbsd-nat.o: sparc64nbsd-nat.c $(defs_h) $(regcache_h) $(target_h) \
--- sparc-linux-tdep.c 31 Mar 2005 19:58:26 -0000 1.9
+++ sparc-linux-tdep.c 21 Apr 2005 03:34:17 -0000
@@ -144,16 +144,17 @@ sparc32_linux_sigtramp_p (struct frame_i
find_pc_partial_function (pc, &name, NULL, NULL);
/* If we have NAME, we can optimize the search. The trampolines are
- named __restore and __restore_rt. However, they aren't dynamically
- exported from the shared C library, so the trampoline may appear to
- be part of the preceding function. This should always be sigaction,
- __sigaction, or __libc_sigaction (all aliases to the same function). */
+ named __sigreturn_stub and __rt_sigreturn_stub. However, they
+ aren't dynamically exported from the shared C library, so the
+ trampoline may appear to be part of the preceding function. This
+ should always be sigaction, __sigaction, or __libc_sigaction (all
+ aliases to the same function). */
if (name == NULL || strstr (name, "sigaction") != NULL)
return (sparc32_linux_sigtramp_start (next_frame) != 0
|| sparc32_linux_rt_sigtramp_start (next_frame) != 0);
- return (strcmp ("__restore", name) == 0
- || strcmp ("__restore_rt", name) == 0);
+ return (strcmp ("__sigreturn_stub", name) == 0
+ || strcmp ("__rt_sigreturn_stub", name) == 0);
}
static struct sparc_frame_cache *
@@ -192,6 +193,14 @@ sparc32_linux_sigtramp_frame_cache (stru
cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
+ /* Layout of pt_regs on sparc is:
+ 0x00: PSR
+ 0x04: PC
+ 0x08: NPC
+ 0x0c: Y
+ 0x10: 8 global registers
+ 0x30: 8 output registers */
+
cache->saved_regs[SPARC32_PSR_REGNUM].addr = sigcontext_addr + 0;
cache->saved_regs[SPARC32_PC_REGNUM].addr = sigcontext_addr + 4;
cache->saved_regs[SPARC32_NPC_REGNUM].addr = sigcontext_addr + 8;
--- sparc64-linux-tdep.c 31 Mar 2005 19:58:26 -0000 1.4
+++ sparc64-linux-tdep.c 21 Apr 2005 03:34:17 -0000
@@ -20,17 +20,201 @@
Boston, MA 02111-1307, USA. */
#include "defs.h"
+#include "frame.h"
+#include "frame-unwind.h"
#include "gdbarch.h"
#include "osabi.h"
#include "solib-svr4.h"
+#include "symtab.h"
+#include "trad-frame.h"
+
+#include "gdb_assert.h"
+#include "gdb_string.h"
#include "sparc64-tdep.h"
+/* The instruction sequence for RT signals is
+ mov __NR_rt_sigreturn, %g1 ! hex: 0x82102065
+ ta 0x6d ! hex: 0x91d0206d
+
+ The effect is to call the system call rt_sigreturn.
+ Note that 64-bit binaries only use this RT signal return method. */
+
+#define LINUX64_RT_SIGTRAMP_INSN0 0x82102065
+#define LINUX64_RT_SIGTRAMP_INSN1 0x91d0206d
+
+/* If PC is in a sigtramp routine consisting of the instructions
+ LINUX64_RT_SIGTRAMP_INSN0 and LINUX64_RT_SIGTRAMP_INSN1, return
+ the address of the start of the routine. Otherwise, return 0. */
+
+static CORE_ADDR
+sparc64_linux_sigtramp_start (struct frame_info *next_frame)
+{
+ CORE_ADDR pc = frame_pc_unwind (next_frame);
+ ULONGEST word0, word1;
+ unsigned char buf[8]; /* Two instructions. */
+
+ /* We only recognize a signal trampoline if PC is at the start of
+ one of the instructions. We optimize for finding the PC at the
+ start of the instruction sequence, as will be the case when the
+ trampoline is not the first frame on the stack. We assume that
+ in the case where the PC is not at the start of the instruction
+ sequence, there will be a few trailing readable bytes on the
+ stack. */
+
+ if (!safe_frame_unwind_memory (next_frame, pc, buf, sizeof buf))
+ return 0;
+
+ word0 = extract_unsigned_integer (buf, 4);
+ if (word0 != LINUX64_RT_SIGTRAMP_INSN0)
+ {
+ if (word0 != LINUX64_RT_SIGTRAMP_INSN1)
+ return 0;
+
+ pc -= 4;
+ if (!safe_frame_unwind_memory (next_frame, pc, buf, sizeof buf))
+ return 0;
+
+ word0 = extract_unsigned_integer (buf, 4);
+ }
+
+ word1 = extract_unsigned_integer (buf + 4, 4);
+ if (word0 != LINUX64_RT_SIGTRAMP_INSN0
+ || word1 != LINUX64_RT_SIGTRAMP_INSN1)
+ return 0;
+
+ return pc;
+}
+
+static int
+sparc64_linux_sigtramp_p (struct frame_info *next_frame)
+{
+ CORE_ADDR pc = frame_pc_unwind (next_frame);
+ char *name;
+
+ find_pc_partial_function (pc, &name, NULL, NULL);
+
+ /* If we have NAME, we can optimize the search. The trampolines is
+ named __rt_sigreturn_stub. However, is isn't dynamically exported
+ from the shared C library, so the trampoline may appear to be part
+ of the preceding function. This should always be sigaction,
+ __sigaction, or __libc_sigaction (all aliases to the same function). */
+ if (name == NULL || strstr (name, "sigaction") != NULL)
+ return (sparc64_linux_sigtramp_start (next_frame) != 0);
+
+ return (strcmp ("__rt_sigreturn_stub", name) == 0);
+}
+
+static struct sparc_frame_cache *
+sparc64_linux_sigtramp_frame_cache (struct frame_info *next_frame,
+ void **this_cache)
+{
+ struct sparc_frame_cache *cache;
+ CORE_ADDR sigcontext_addr, addr;
+ int regnum;
+
+ if (*this_cache)
+ return *this_cache;
+
+ cache = sparc_frame_cache (next_frame, this_cache);
+ gdb_assert (cache == *this_cache);
+
+ regnum = SPARC_SP_REGNUM;
+ cache->base = frame_unwind_register_unsigned (next_frame, regnum);
+ if (cache->base & 1)
+ cache->base += BIAS;
+
+ regnum = SPARC_O1_REGNUM;
+ sigcontext_addr = frame_unwind_register_unsigned (next_frame, regnum);
+
+ /* If this is a RT signal trampoline, adjust SIGCONTEXT_ADDR
+ accordingly. */
+ addr = sparc64_linux_sigtramp_start (next_frame);
+ if (addr)
+ sigcontext_addr += 128;
+ else
+ addr = frame_func_unwind (next_frame);
+
+ cache->pc = addr;
+
+ cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
+
+ /* Layout of pt_regs on sparc64 is:
+ 0x00: 8 global registers
+ 0x40: 8 output registers
+ 0x80: TSTATE
+ 0x88: TPC
+ 0x90: TNPC
+ 0x98: Y
+ 0x9c: FPRS */
+
+ /* Since %g0 is always zero, keep the identity encoding. */
+ for (addr = sigcontext_addr + 8, regnum = SPARC_G1_REGNUM;
+ regnum <= SPARC_O7_REGNUM; regnum++, addr += 8)
+ cache->saved_regs[regnum].addr = addr;
+
+ cache->saved_regs[SPARC64_STATE_REGNUM].addr = addr + 0;
+ cache->saved_regs[SPARC64_PC_REGNUM].addr = addr + 8;
+ cache->saved_regs[SPARC64_NPC_REGNUM].addr = addr + 16;
+ cache->saved_regs[SPARC64_Y_REGNUM].addr = addr + 24;
+ cache->saved_regs[SPARC64_FPRS_REGNUM].addr = addr + 28;
+
+ for (regnum = SPARC_L0_REGNUM, addr = cache->base;
+ regnum <= SPARC_I7_REGNUM; regnum++, addr += 8)
+ cache->saved_regs[regnum].addr = addr;
+
+ return cache;
+}
+
+static void
+sparc64_linux_sigtramp_frame_this_id (struct frame_info *next_frame,
+ void **this_cache,
+ struct frame_id *this_id)
+{
+ struct sparc_frame_cache *cache =
+ sparc64_linux_sigtramp_frame_cache (next_frame, this_cache);
+
+ (*this_id) = frame_id_build (cache->base, cache->pc);
+}
+
+static void
+sparc64_linux_sigtramp_frame_prev_register (struct frame_info *next_frame,
+ void **this_cache,
+ int regnum, int *optimizedp,
+ enum lval_type *lvalp,
+ CORE_ADDR *addrp,
+ int *realnump, void *valuep)
+{
+ struct sparc_frame_cache *cache =
+ sparc64_linux_sigtramp_frame_cache (next_frame, this_cache);
+
+ trad_frame_get_prev_register (next_frame, cache->saved_regs, regnum,
+ optimizedp, lvalp, addrp, realnump, valuep);
+}
+
+static const struct frame_unwind sparc64_linux_sigtramp_frame_unwind =
+{
+ SIGTRAMP_FRAME,
+ sparc64_linux_sigtramp_frame_this_id,
+ sparc64_linux_sigtramp_frame_prev_register
+};
+
+static const struct frame_unwind *
+sparc64_linux_sigtramp_frame_sniffer (struct frame_info *next_frame)
+{
+ if (sparc64_linux_sigtramp_p (next_frame))
+ return &sparc64_linux_sigtramp_frame_unwind;
+
+ return NULL;
+}
+\f
static void
sparc64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ frame_unwind_append_sniffer (gdbarch, sparc64_linux_sigtramp_frame_sniffer);
+
/* GNU/Linux is very similar to Solaris ... */
sparc64_sol2_init_abi (info, gdbarch);
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] Add sparc64-linux sigtramp support
2005-04-21 3:51 [PATCH] Add sparc64-linux sigtramp support David S. Miller
@ 2005-04-21 19:23 ` Mark Kettenis
2005-04-21 19:29 ` David S. Miller
0 siblings, 1 reply; 12+ messages in thread
From: Mark Kettenis @ 2005-04-21 19:23 UTC (permalink / raw)
To: davem; +Cc: gdb-patches
Date: Wed, 20 Apr 2005 20:44:27 -0700
From: "David S. Miller" <davem@davemloft.net>
This patch gets signal backtraces working properly on sparc64/linux
targets. The two non-straightforward parts of the implementation are:
1) proper stack bias adjusting of cache->base
2) registering the sniffer in the correct order
The issue in #2 is that we use the solaris2 sparc64 target support
as our base, then override and add things which are different for the
linux sparc64 target.
FYI, "issue" #1 is to make sure the frame base address matches with
what the DWARF2 unwinder thinks.
The solaris2 sparc64 osabi init which we call registers first the
solaris2 sigtramp sniffer, then the generic sparc64 frame sniffer,
via sparc64_init_abi().
Therefore we have to register the linux sparc64 sniffer before we
invoke sparc64_sol2_init_abi().
Yes, indeed.
While doing this work I noticed that the signal trampoline symbols
names were wrong in the 32-bit sparc linux sigtramp support. Those
are the i386 glibc symbol names, not the sparc ones :-) So I corrected
those and also documented the "struct pt_regs" layout that we're
picking sigtramp registers from.
Ah thanks for noticing that pasto; I probably didn't notice for the
reason explained in the comment.
I'm not thrilled by documenting the "struct pt_regs" layout. The
constants already are there in the code. I think it is more important
to document where to find the offsets. I also think it is better to
point people to "struct sigcontext" instead of "struct pt_regs".
That's where I got them from. Can you change the comment in something
like:
/* Offsets from <bits/sigcontext.h>. */
?
Otherwise this is ok, so please go ahead. Oh, except for the fact
that there is a tab instead of a space between "symbol" and "names" in
the ChangeLog entry ;-).
Mark
P.S. I'm close to enabling the DWARF2 unwinder for SPARC, but there
still are a few issues that I have to solve yet. None of these affect
Linux/sparc64. I can send you a patch to test if you want.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] Add sparc64-linux sigtramp support
2005-04-21 19:23 ` Mark Kettenis
@ 2005-04-21 19:29 ` David S. Miller
2005-04-21 21:20 ` Mark Kettenis
0 siblings, 1 reply; 12+ messages in thread
From: David S. Miller @ 2005-04-21 19:29 UTC (permalink / raw)
To: Mark Kettenis; +Cc: gdb-patches
On Thu, 21 Apr 2005 21:23:17 +0200 (CEST)
Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
> FYI, "issue" #1 is to make sure the frame base address matches with
> what the DWARF2 unwinder thinks.
Right.
> I'm not thrilled by documenting the "struct pt_regs" layout. The
> constants already are there in the code. I think it is more important
> to document where to find the offsets. I also think it is better to
> point people to "struct sigcontext" instead of "struct pt_regs".
> That's where I got them from. Can you change the comment in something
> like:
>
> /* Offsets from <bits/sigcontext.h>. */
>
> ?
>
> Otherwise this is ok, so please go ahead.
Sure, I'll fix this all up. Thanks for reviewing. I'd like to convert
this stuff over to the cleaner infrastructure PPC and MIPS linux targets
use, it might mean ditching the solaris tdep sharing though since they
sniff the sigtramps slightly differently. It's kind of weird that we
let the solaris code register it's sniffer in the chain on linux targets
even though the linux sniffer is registered such that it trumps the solaris
one.
> P.S. I'm close to enabling the DWARF2 unwinder for SPARC, but there
> still are a few issues that I have to solve yet. None of these affect
> Linux/sparc64. I can send you a patch to test if you want.
Funny, I started playing around with the DWARF2 unwinder last night
as well on Sparc. It interacted badly with the signal trampoline
sniffers but otherwise mostly worked, and that's as far as I got before
I went to bed.
Please send me your test patch and what issues you are aware of, I can
likely work on fixing them today/tonight.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] Add sparc64-linux sigtramp support
2005-04-21 19:29 ` David S. Miller
@ 2005-04-21 21:20 ` Mark Kettenis
2005-04-21 21:41 ` David S. Miller
2005-04-21 21:55 ` David S. Miller
0 siblings, 2 replies; 12+ messages in thread
From: Mark Kettenis @ 2005-04-21 21:20 UTC (permalink / raw)
To: davem; +Cc: gdb-patches
Date: Thu, 21 Apr 2005 12:22:50 -0700
From: "David S. Miller" <davem@davemloft.net>
Sure, I'll fix this all up. Thanks for reviewing. I'd like to convert
this stuff over to the cleaner infrastructure PPC and MIPS linux targets
use, it might mean ditching the solaris tdep sharing though since they
sniff the sigtramps slightly differently. It's kind of weird that we
let the solaris code register it's sniffer in the chain on linux targets
even though the linux sniffer is registered such that it trumps the solaris
one.
It'd be great if you could convert things to use the tramp_frame
stuff. Should be doable for SPARC/UltraSPARC Linux without too much
effort, and simplify the code a bit.
The Solaris sniffer shouldn't really hurt the Linux stuff. But I
guess it makes sense now, to copy the SVR4-style shared library stuff
into sparcxx_linux_init_abi() and remove the call to
sparcxx_sol2_init_abi(). I'll make that change.
> P.S. I'm close to enabling the DWARF2 unwinder for SPARC, but there
> still are a few issues that I have to solve yet. None of these affect
> Linux/sparc64. I can send you a patch to test if you want.
Funny, I started playing around with the DWARF2 unwinder last night
as well on Sparc. It interacted badly with the signal trampoline
sniffers but otherwise mostly worked, and that's as far as I got before
I went to bed.
Please send me your test patch and what issues you are aware of, I can
likely work on fixing them today/tonight.
The attached patch was what I was thinking about. If it has issues
with signal handlers, take a look at
i386-linux-tdep.c:i386_linux_dwarf_signale_p(), That might help in the
case DWARF2 CFI for the signal trampoline is provided.
Mark
Index: sparc64-linux-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/sparc64-linux-tdep.c,v
retrieving revision 1.5
diff -u -p -r1.5 sparc64-linux-tdep.c
--- sparc64-linux-tdep.c 21 Apr 2005 19:38:20 -0000 1.5
+++ sparc64-linux-tdep.c 21 Apr 2005 21:06:47 -0000
@@ -206,6 +206,7 @@ sparc64_linux_init_abi (struct gdbarch_i
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer);
frame_unwind_append_sniffer (gdbarch, sparc64_linux_sigtramp_frame_sniffer);
/* GNU/Linux is very similar to Solaris ... */
Index: sparc64-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/sparc64-tdep.c,v
retrieving revision 1.21
diff -u -p -r1.21 sparc64-tdep.c
--- sparc64-tdep.c 28 Mar 2005 13:42:49 -0000 1.21
+++ sparc64-tdep.c 21 Apr 2005 21:06:48 -0000
@@ -21,6 +21,7 @@
#include "defs.h"
#include "arch-utils.h"
+#include "dwarf2-frame.h"
#include "floatformat.h"
#include "frame.h"
#include "frame-base.h"
@@ -1103,6 +1104,26 @@ sparc64_return_value (struct gdbarch *gd
}
\f
+static void
+sparc64_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
+ struct dwarf2_frame_state_reg *reg)
+{
+ switch (regnum)
+ {
+ case SPARC_SP_REGNUM:
+ reg->how = DWARF2_FRAME_REG_CFA;
+ break;
+ case SPARC64_PC_REGNUM:
+ reg->how = DWARF2_FRAME_REG_RA_OFFSET;
+ reg->loc.offset = 8;
+ break;
+ case SPARC64_NPC_REGNUM:
+ reg->how = DWARF2_FRAME_REG_RA_OFFSET;
+ reg->loc.offset = 12;
+ break;
+ }
+}
+
void
sparc64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
@@ -1137,6 +1158,12 @@ sparc64_init_abi (struct gdbarch_info in
set_gdbarch_skip_prologue (gdbarch, sparc64_skip_prologue);
+ /* Hook in the DWARF CFI frame unwinder. */
+ dwarf2_frame_set_init_reg (gdbarch, sparc64_dwarf2_frame_init_reg);
+#if notyet
+ frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer);
+#endif
+
frame_unwind_append_sniffer (gdbarch, sparc64_frame_sniffer);
frame_base_set_default (gdbarch, &sparc64_frame_base);
}
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] Add sparc64-linux sigtramp support
2005-04-21 21:20 ` Mark Kettenis
@ 2005-04-21 21:41 ` David S. Miller
2005-04-21 21:57 ` Mark Kettenis
2005-04-21 21:55 ` David S. Miller
1 sibling, 1 reply; 12+ messages in thread
From: David S. Miller @ 2005-04-21 21:41 UTC (permalink / raw)
To: Mark Kettenis; +Cc: gdb-patches
On Thu, 21 Apr 2005 23:20:11 +0200 (CEST)
Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
> It'd be great if you could convert things to use the tramp_frame
> stuff. Should be doable for SPARC/UltraSPARC Linux without too much
> effort, and simplify the code a bit.
Done. How does this look?
2005-04-21 David S. Miller <davem@davemloft.net>
* sparc-linux-tdep.c (sparc32_linux_sigframe_init): New function.
(sparc32_linux_sigframe, sparc32_linux_rt_sigframe): New tramp_frames.
(sparc_linux_sigtramp_start, sparc32_linux_sigtramp_start,
sparc32_linux_rt_sigtramp_start, sparc32_linux_sigtramp_p,
sparc32_linux_sigtramp_frame_cache,
sparc32_linux_sigtramp_frame_this_id,
sparc32_linux_sigtramp_frame_prev_register,
sparc32_linux_sigtramp_frame_unwind,
sparc32_linux_sigtramp_frame_sniffer): Delete.
(sparc32_linux_init_abi): Register new tramp unwinders. Kill
register of old sigtramp sniffer.
* sparc64-linux-tdep.c (sparc64_linux_sigframe_init): New
function.
(sparc64_linux_rt_sigframe): New tramp frame.
(sparc64_linux_sigtramp_start, sparc64_linux_sigtramp_p,
sparc64_linux_sigtramp_frame_cache,
sparc64_linux_sigtramp_frame_this_id,
sparc64_linux_sigtramp_frame_prev_register,
sparc64_linux_sigtramp_frame_unwind,
sparc64_linux_sigtramp_frame_sniffer): Delete.
(sparc64_linux_init_abi): Register new tramp unwinders. Kill
register of old sigtramp sniffer.
Makefile.in (sparc64-linux-tdep.o): Update dependencies.
(sparc-linux-tdep.o): Likewise.
--- Makefile.in 21 Apr 2005 19:38:19 -0000 1.717
+++ Makefile.in 21 Apr 2005 21:36:53 -0000
@@ -2567,7 +2567,7 @@ sparc64-linux-nat.o: sparc64-linux-nat.c
$(sparc_nat_h)
sparc64-linux-tdep.o: sparc64-linux-tdep.c $(defs_h) $(frame_h) \
$(frame_unwind_h) $(gdbarch_h) $(osabi_h) $(solib_svr4_h) \
- $(symtab_h) $(trad_frame_h) $(gdb_assert_h) $(gdb_string_h) \
+ $(symtab_h) $(trad_frame_h) \
$(sparc64_tdep_h)
sparc64-nat.o: sparc64-nat.c $(defs_h) $(gdbarch_h) $(sparc64_tdep_h) \
$(sparc_nat_h)
@@ -2590,8 +2590,8 @@ sparc64-tdep.o: sparc64-tdep.c $(defs_h)
$(sparc64_tdep_h)
sparc-linux-tdep.o: sparc-linux-tdep.c $(defs_h) $(floatformat_h) $(frame_h) \
$(frame_unwind_h) $(gdbarch_h) $(gdbcore_h) $(osabi_h) $(regcache_h) \
- $(solib_svr4_h) $(symtab_h) $(trad_frame_h) $(gdb_assert_h) \
- $(gdb_string_h) $(sparc_tdep_h)
+ $(solib_svr4_h) $(symtab_h) $(trad_frame_h) \
+ $(sparc_tdep_h)
sparc-nat.o: sparc-nat.c $(defs_h) $(inferior_h) $(regcache_h) $(target_h) \
$(gdb_assert_h) $(gdb_string_h) $(gdb_wait_h) $(sparc_tdep_h) \
$(sparc_nat_h) $(inf_ptrace_h)
--- sparc-linux-tdep.c 21 Apr 2005 19:38:20 -0000 1.10
+++ sparc-linux-tdep.c 21 Apr 2005 21:36:53 -0000
@@ -23,6 +23,7 @@
#include "floatformat.h"
#include "frame.h"
#include "frame-unwind.h"
+#include "tramp-frame.h"
#include "gdbarch.h"
#include "gdbcore.h"
#include "osabi.h"
@@ -31,12 +32,9 @@
#include "symtab.h"
#include "trad-frame.h"
-#include "gdb_assert.h"
-#include "gdb_string.h"
-
#include "sparc-tdep.h"
-/* Recognizing signal handler frames. */
+/* Signal trampoline support. */
/* GNU/Linux has two flavors of signals. Normal signal handlers, and
"realtime" (RT) signals. The RT signals can provide additional
@@ -69,195 +67,86 @@
/* The instruction sequence for RT signals is
mov __NR_rt_sigreturn, %g1 ! hex: 0x82102065
- ta {0x10,0x6d} ! hex: 0x91d02010 or 0x91d0206d
+ ta {0x10,0x6d} ! hex: 0x91d02010
- The effect is to call the system call rt_sigreturn. The trap number
- is variable based upon whether this is a 32-bit or 64-bit sparc binary.
+ The effect is to call the system call rt_sigreturn.
Note that 64-bit binaries only use this RT signal return method. */
#define LINUX32_RT_SIGTRAMP_INSN0 0x82102065
#define LINUX32_RT_SIGTRAMP_INSN1 0x91d02010
-/* If PC is in a sigtramp routine consisting of the instructions INSN0
- and INSN1, return the address of the start of the routine.
- Otherwise, return 0. */
-
-CORE_ADDR
-sparc_linux_sigtramp_start (struct frame_info *next_frame,
- ULONGEST insn0, ULONGEST insn1)
-{
- CORE_ADDR pc = frame_pc_unwind (next_frame);
- ULONGEST word0, word1;
- unsigned char buf[8]; /* Two instructions. */
-
- /* We only recognize a signal trampoline if PC is at the start of
- one of the instructions. We optimize for finding the PC at the
- start of the instruction sequence, as will be the case when the
- trampoline is not the first frame on the stack. We assume that
- in the case where the PC is not at the start of the instruction
- sequence, there will be a few trailing readable bytes on the
- stack. */
-
- if (!safe_frame_unwind_memory (next_frame, pc, buf, sizeof buf))
- return 0;
-
- word0 = extract_unsigned_integer (buf, 4);
- if (word0 != insn0)
- {
- if (word0 != insn1)
- return 0;
-
- pc -= 4;
- if (!safe_frame_unwind_memory (next_frame, pc, buf, sizeof buf))
- return 0;
-
- word0 = extract_unsigned_integer (buf, 4);
- }
-
- word1 = extract_unsigned_integer (buf + 4, 4);
- if (word0 != insn0 || word1 != insn1)
- return 0;
-
- return pc;
-}
-
-static CORE_ADDR
-sparc32_linux_sigtramp_start (struct frame_info *next_frame)
-{
- return sparc_linux_sigtramp_start (next_frame, LINUX32_SIGTRAMP_INSN0,
- LINUX32_SIGTRAMP_INSN1);
-}
-
-static CORE_ADDR
-sparc32_linux_rt_sigtramp_start (struct frame_info *next_frame)
-{
- return sparc_linux_sigtramp_start (next_frame, LINUX32_RT_SIGTRAMP_INSN0,
- LINUX32_RT_SIGTRAMP_INSN1);
-}
+static void sparc32_linux_sigframe_init (const struct tramp_frame *self,
+ struct frame_info *next_frame,
+ struct trad_frame_cache *this_cache,
+ CORE_ADDR func);
-static int
-sparc32_linux_sigtramp_p (struct frame_info *next_frame)
-{
- CORE_ADDR pc = frame_pc_unwind (next_frame);
- char *name;
-
- find_pc_partial_function (pc, &name, NULL, NULL);
-
- /* If we have NAME, we can optimize the search. The trampolines are
- named __sigreturn_stub and __rt_sigreturn_stub. However, they
- aren't dynamically exported from the shared C library, so the
- trampoline may appear to be part of the preceding function. This
- should always be sigaction, __sigaction, or __libc_sigaction (all
- aliases to the same function). */
- if (name == NULL || strstr (name, "sigaction") != NULL)
- return (sparc32_linux_sigtramp_start (next_frame) != 0
- || sparc32_linux_rt_sigtramp_start (next_frame) != 0);
+static const struct tramp_frame sparc32_linux_sigframe = {
+ SIGTRAMP_FRAME,
+ 4,
+ {
+ { LINUX32_SIGTRAMP_INSN0, -1 },
+ { LINUX32_SIGTRAMP_INSN1, -1 },
+ { TRAMP_SENTINEL_INSN, -1 }
+ },
+ sparc32_linux_sigframe_init
+};
- return (strcmp ("__sigreturn_stub", name) == 0
- || strcmp ("__rt_sigreturn_stub", name) == 0);
-}
+static const struct tramp_frame sparc32_linux_rt_sigframe = {
+ SIGTRAMP_FRAME,
+ 4,
+ {
+ { LINUX32_RT_SIGTRAMP_INSN0, -1 },
+ { LINUX32_RT_SIGTRAMP_INSN1, -1 },
+ { TRAMP_SENTINEL_INSN, -1 }
+ },
+ sparc32_linux_sigframe_init
+};
-static struct sparc_frame_cache *
-sparc32_linux_sigtramp_frame_cache (struct frame_info *next_frame,
- void **this_cache)
+static void
+sparc32_linux_sigframe_init (const struct tramp_frame *self,
+ struct frame_info *next_frame,
+ struct trad_frame_cache *this_cache,
+ CORE_ADDR func)
{
- struct sparc_frame_cache *cache;
- CORE_ADDR sigcontext_addr, addr;
+ CORE_ADDR base, addr;
int regnum;
- if (*this_cache)
- return *this_cache;
-
- cache = sparc32_frame_cache (next_frame, this_cache);
- gdb_assert (cache == *this_cache);
-
- /* ??? What about signal trampolines that aren't frameless? */
- regnum = SPARC_SP_REGNUM;
- cache->base = frame_unwind_register_unsigned (next_frame, regnum);
-
- regnum = SPARC_O1_REGNUM;
- sigcontext_addr = frame_unwind_register_unsigned (next_frame, regnum);
-
- addr = sparc32_linux_sigtramp_start (next_frame);
- if (addr == 0)
- {
- /* If this is a RT signal trampoline, adjust SIGCONTEXT_ADDR
- accordingly. */
- addr = sparc32_linux_rt_sigtramp_start (next_frame);
- if (addr)
- sigcontext_addr += 128;
- else
- addr = frame_func_unwind (next_frame);
- }
- cache->pc = addr;
-
- cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
+ base = frame_unwind_register_unsigned (next_frame, SPARC_O1_REGNUM);
+ if (self == &sparc32_linux_rt_sigframe)
+ base += 128;
/* Offsets from <bits/sigcontext.h> */
- cache->saved_regs[SPARC32_PSR_REGNUM].addr = sigcontext_addr + 0;
- cache->saved_regs[SPARC32_PC_REGNUM].addr = sigcontext_addr + 4;
- cache->saved_regs[SPARC32_NPC_REGNUM].addr = sigcontext_addr + 8;
- cache->saved_regs[SPARC32_Y_REGNUM].addr = sigcontext_addr + 12;
+ trad_frame_set_reg_addr (this_cache, SPARC32_PSR_REGNUM, base + 0x00);
+ trad_frame_set_reg_addr (this_cache, SPARC32_PC_REGNUM, base + 0x04);
+ trad_frame_set_reg_addr (this_cache, SPARC32_NPC_REGNUM, base + 0x08);
+ trad_frame_set_reg_addr (this_cache, SPARC32_Y_REGNUM, base + 0x0c);
/* Since %g0 is always zero, keep the identity encoding. */
- for (regnum = SPARC_G1_REGNUM, addr = sigcontext_addr + 20;
- regnum <= SPARC_O7_REGNUM; regnum++, addr += 4)
- cache->saved_regs[regnum].addr = addr;
-
- for (regnum = SPARC_L0_REGNUM, addr = cache->base;
- regnum <= SPARC_I7_REGNUM; regnum++, addr += 4)
- cache->saved_regs[regnum].addr = addr;
-
- return cache;
-}
-
-static void
-sparc32_linux_sigtramp_frame_this_id (struct frame_info *next_frame,
- void **this_cache,
- struct frame_id *this_id)
-{
- struct sparc_frame_cache *cache =
- sparc32_linux_sigtramp_frame_cache (next_frame, this_cache);
-
- (*this_id) = frame_id_build (cache->base, cache->pc);
-}
-
-static void
-sparc32_linux_sigtramp_frame_prev_register (struct frame_info *next_frame,
- void **this_cache,
- int regnum, int *optimizedp,
- enum lval_type *lvalp,
- CORE_ADDR *addrp,
- int *realnump, void *valuep)
-{
- struct sparc_frame_cache *cache =
- sparc32_linux_sigtramp_frame_cache (next_frame, this_cache);
+ addr = base + 0x14;
+ for (regnum = SPARC_G1_REGNUM; regnum <= SPARC_O7_REGNUM; regnum++)
+ {
+ trad_frame_set_reg_addr (this_cache, regnum, addr);
+ addr += 4;
+ }
- trad_frame_get_prev_register (next_frame, cache->saved_regs, regnum,
- optimizedp, lvalp, addrp, realnump, valuep);
+ base = addr = frame_unwind_register_unsigned (next_frame, SPARC_SP_REGNUM);
+ for (regnum = SPARC_L0_REGNUM; regnum <= SPARC_I7_REGNUM; regnum++)
+ {
+ trad_frame_set_reg_addr (this_cache, regnum, addr);
+ addr += 4;
+ }
+ trad_frame_set_id (this_cache, frame_id_build (base, func));
}
-static const struct frame_unwind sparc32_linux_sigtramp_frame_unwind =
-{
- SIGTRAMP_FRAME,
- sparc32_linux_sigtramp_frame_this_id,
- sparc32_linux_sigtramp_frame_prev_register
-};
-
-static const struct frame_unwind *
-sparc32_linux_sigtramp_frame_sniffer (struct frame_info *next_frame)
-{
- if (sparc32_linux_sigtramp_p (next_frame))
- return &sparc32_linux_sigtramp_frame_unwind;
-
- return NULL;
-}
\f
static void
sparc32_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
+ tramp_frame_prepend_unwinder (gdbarch, &sparc32_linux_sigframe);
+ tramp_frame_prepend_unwinder (gdbarch, &sparc32_linux_rt_sigframe);
+
/* GNU/Linux is very similar to Solaris ... */
sparc32_sol2_init_abi (info, gdbarch);
@@ -268,8 +157,6 @@ sparc32_linux_init_abi (struct gdbarch_i
set_gdbarch_long_double_bit (gdbarch, 64);
set_gdbarch_long_double_format (gdbarch, &floatformat_ieee_double_big);
- frame_unwind_append_sniffer (gdbarch, sparc32_linux_sigtramp_frame_sniffer);
-
/* Enable TLS support. */
set_gdbarch_fetch_tls_load_module_address (gdbarch,
svr4_fetch_objfile_link_map);
--- sparc64-linux-tdep.c 21 Apr 2005 19:38:20 -0000 1.5
+++ sparc64-linux-tdep.c 21 Apr 2005 21:36:53 -0000
@@ -22,15 +22,13 @@
#include "defs.h"
#include "frame.h"
#include "frame-unwind.h"
+#include "tramp-frame.h"
#include "gdbarch.h"
#include "osabi.h"
#include "solib-svr4.h"
#include "symtab.h"
#include "trad-frame.h"
-#include "gdb_assert.h"
-#include "gdb_string.h"
-
#include "sparc64-tdep.h"
/* The instruction sequence for RT signals is
@@ -43,162 +41,62 @@
#define LINUX64_RT_SIGTRAMP_INSN0 0x82102065
#define LINUX64_RT_SIGTRAMP_INSN1 0x91d0206d
-/* If PC is in a sigtramp routine consisting of the instructions
- LINUX64_RT_SIGTRAMP_INSN0 and LINUX64_RT_SIGTRAMP_INSN1, return
- the address of the start of the routine. Otherwise, return 0. */
-
-static CORE_ADDR
-sparc64_linux_sigtramp_start (struct frame_info *next_frame)
-{
- CORE_ADDR pc = frame_pc_unwind (next_frame);
- ULONGEST word0, word1;
- unsigned char buf[8]; /* Two instructions. */
-
- /* We only recognize a signal trampoline if PC is at the start of
- one of the instructions. We optimize for finding the PC at the
- start of the instruction sequence, as will be the case when the
- trampoline is not the first frame on the stack. We assume that
- in the case where the PC is not at the start of the instruction
- sequence, there will be a few trailing readable bytes on the
- stack. */
-
- if (!safe_frame_unwind_memory (next_frame, pc, buf, sizeof buf))
- return 0;
-
- word0 = extract_unsigned_integer (buf, 4);
- if (word0 != LINUX64_RT_SIGTRAMP_INSN0)
- {
- if (word0 != LINUX64_RT_SIGTRAMP_INSN1)
- return 0;
-
- pc -= 4;
- if (!safe_frame_unwind_memory (next_frame, pc, buf, sizeof buf))
- return 0;
-
- word0 = extract_unsigned_integer (buf, 4);
- }
-
- word1 = extract_unsigned_integer (buf + 4, 4);
- if (word0 != LINUX64_RT_SIGTRAMP_INSN0
- || word1 != LINUX64_RT_SIGTRAMP_INSN1)
- return 0;
-
- return pc;
-}
-
-static int
-sparc64_linux_sigtramp_p (struct frame_info *next_frame)
-{
- CORE_ADDR pc = frame_pc_unwind (next_frame);
- char *name;
- find_pc_partial_function (pc, &name, NULL, NULL);
+static void sparc64_linux_sigframe_init (const struct tramp_frame *self,
+ struct frame_info *next_frame,
+ struct trad_frame_cache *this_cache,
+ CORE_ADDR func);
- /* If we have NAME, we can optimize the search. The trampolines is
- named __rt_sigreturn_stub. However, is isn't dynamically exported
- from the shared C library, so the trampoline may appear to be part
- of the preceding function. This should always be sigaction,
- __sigaction, or __libc_sigaction (all aliases to the same function). */
- if (name == NULL || strstr (name, "sigaction") != NULL)
- return (sparc64_linux_sigtramp_start (next_frame) != 0);
-
- return (strcmp ("__rt_sigreturn_stub", name) == 0);
-}
+static const struct tramp_frame sparc64_linux_rt_sigframe = {
+ SIGTRAMP_FRAME,
+ 4,
+ {
+ { LINUX64_RT_SIGTRAMP_INSN0, -1 },
+ { LINUX64_RT_SIGTRAMP_INSN1, -1 },
+ { TRAMP_SENTINEL_INSN, -1 }
+ },
+ sparc64_linux_sigframe_init
+};
-static struct sparc_frame_cache *
-sparc64_linux_sigtramp_frame_cache (struct frame_info *next_frame,
- void **this_cache)
+static void
+sparc64_linux_sigframe_init (const struct tramp_frame *self,
+ struct frame_info *next_frame,
+ struct trad_frame_cache *this_cache,
+ CORE_ADDR func)
{
- struct sparc_frame_cache *cache;
- CORE_ADDR sigcontext_addr, addr;
+ CORE_ADDR base, addr;
int regnum;
- if (*this_cache)
- return *this_cache;
-
- cache = sparc_frame_cache (next_frame, this_cache);
- gdb_assert (cache == *this_cache);
-
- regnum = SPARC_SP_REGNUM;
- cache->base = frame_unwind_register_unsigned (next_frame, regnum);
- if (cache->base & 1)
- cache->base += BIAS;
-
- regnum = SPARC_O1_REGNUM;
- sigcontext_addr = frame_unwind_register_unsigned (next_frame, regnum);
-
- /* If this is a RT signal trampoline, adjust SIGCONTEXT_ADDR
- accordingly. */
- addr = sparc64_linux_sigtramp_start (next_frame);
- if (addr)
- sigcontext_addr += 128;
- else
- addr = frame_func_unwind (next_frame);
-
- cache->pc = addr;
-
- cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
+ base = frame_unwind_register_unsigned (next_frame, SPARC_O1_REGNUM);
+ base += 128;
/* Offsets from <bits/sigcontext.h> */
/* Since %g0 is always zero, keep the identity encoding. */
- for (addr = sigcontext_addr + 8, regnum = SPARC_G1_REGNUM;
- regnum <= SPARC_O7_REGNUM; regnum++, addr += 8)
- cache->saved_regs[regnum].addr = addr;
-
- cache->saved_regs[SPARC64_STATE_REGNUM].addr = addr + 0;
- cache->saved_regs[SPARC64_PC_REGNUM].addr = addr + 8;
- cache->saved_regs[SPARC64_NPC_REGNUM].addr = addr + 16;
- cache->saved_regs[SPARC64_Y_REGNUM].addr = addr + 24;
- cache->saved_regs[SPARC64_FPRS_REGNUM].addr = addr + 28;
-
- for (regnum = SPARC_L0_REGNUM, addr = cache->base;
- regnum <= SPARC_I7_REGNUM; regnum++, addr += 8)
- cache->saved_regs[regnum].addr = addr;
-
- return cache;
-}
-
-static void
-sparc64_linux_sigtramp_frame_this_id (struct frame_info *next_frame,
- void **this_cache,
- struct frame_id *this_id)
-{
- struct sparc_frame_cache *cache =
- sparc64_linux_sigtramp_frame_cache (next_frame, this_cache);
-
- (*this_id) = frame_id_build (cache->base, cache->pc);
-}
-
-static void
-sparc64_linux_sigtramp_frame_prev_register (struct frame_info *next_frame,
- void **this_cache,
- int regnum, int *optimizedp,
- enum lval_type *lvalp,
- CORE_ADDR *addrp,
- int *realnump, void *valuep)
-{
- struct sparc_frame_cache *cache =
- sparc64_linux_sigtramp_frame_cache (next_frame, this_cache);
-
- trad_frame_get_prev_register (next_frame, cache->saved_regs, regnum,
- optimizedp, lvalp, addrp, realnump, valuep);
-}
-
-static const struct frame_unwind sparc64_linux_sigtramp_frame_unwind =
-{
- SIGTRAMP_FRAME,
- sparc64_linux_sigtramp_frame_this_id,
- sparc64_linux_sigtramp_frame_prev_register
-};
+ addr = base + 0x08;
+ for (regnum = SPARC_G1_REGNUM; regnum <= SPARC_O7_REGNUM; regnum++)
+ {
+ trad_frame_set_reg_addr (this_cache, regnum, addr);
+ addr += 8;
+ }
-static const struct frame_unwind *
-sparc64_linux_sigtramp_frame_sniffer (struct frame_info *next_frame)
-{
- if (sparc64_linux_sigtramp_p (next_frame))
- return &sparc64_linux_sigtramp_frame_unwind;
+ trad_frame_set_reg_addr (this_cache, SPARC64_STATE_REGNUM, addr + 0x00);
+ trad_frame_set_reg_addr (this_cache, SPARC64_PC_REGNUM, addr + 0x08);
+ trad_frame_set_reg_addr (this_cache, SPARC64_NPC_REGNUM, addr + 0x10);
+ trad_frame_set_reg_addr (this_cache, SPARC64_Y_REGNUM, addr + 0x18);
+ trad_frame_set_reg_addr (this_cache, SPARC64_FPRS_REGNUM, addr + 0x1c);
+
+ addr = frame_unwind_register_unsigned (next_frame, SPARC_SP_REGNUM);
+ if (addr & 1)
+ addr += BIAS;
- return NULL;
+ base = addr;
+ for (regnum = SPARC_L0_REGNUM; regnum <= SPARC_I7_REGNUM; regnum++)
+ {
+ trad_frame_set_reg_addr (this_cache, regnum, addr);
+ addr += 8;
+ }
+ trad_frame_set_id (this_cache, frame_id_build (base, func));
}
\f
static void
@@ -206,7 +104,7 @@ sparc64_linux_init_abi (struct gdbarch_i
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- frame_unwind_append_sniffer (gdbarch, sparc64_linux_sigtramp_frame_sniffer);
+ tramp_frame_prepend_unwinder (gdbarch, &sparc64_linux_rt_sigframe);
/* GNU/Linux is very similar to Solaris ... */
sparc64_sol2_init_abi (info, gdbarch);
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] Add sparc64-linux sigtramp support
2005-04-21 21:20 ` Mark Kettenis
2005-04-21 21:41 ` David S. Miller
@ 2005-04-21 21:55 ` David S. Miller
2005-04-21 22:09 ` Mark Kettenis
1 sibling, 1 reply; 12+ messages in thread
From: David S. Miller @ 2005-04-21 21:55 UTC (permalink / raw)
To: Mark Kettenis; +Cc: gdb-patches
On Thu, 21 Apr 2005 23:20:11 +0200 (CEST)
Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
> The attached patch was what I was thinking about. If it has issues
> with signal handlers, take a look at
> i386-linux-tdep.c:i386_linux_dwarf_signale_p(), That might help in the
> case DWARF2 CFI for the signal trampoline is provided.
Missing dwarf2-frame.h include in sparc64-linux-tdep.c but otherwise
it did build.
It has one of the problems I ran into last night, namely that gcc
never emits data for register %g0 (which is always zero of course).
So the dwarf2 CFI unwinder spits out:
====
During symbol reading, incomplete CFI data; unspecified registers (e.g. g0)
at 0x100778
====
But besides that I can happily report that it seems to work well
even with signal handler backtraces. I'm doing this testing against
a tree with my tramp_frame Linux changes.
The temporary workaround I did last night was to make the sparc dwarf2
CIF unwinder init_reg() routine just mark G0 as UNDEFINED. I don't
know if that's what we'd like to do long term, or if GCC should output
something for this register.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] Add sparc64-linux sigtramp support
2005-04-21 21:41 ` David S. Miller
@ 2005-04-21 21:57 ` Mark Kettenis
2005-04-21 22:04 ` David S. Miller
0 siblings, 1 reply; 12+ messages in thread
From: Mark Kettenis @ 2005-04-21 21:57 UTC (permalink / raw)
To: davem; +Cc: gdb-patches
Date: Thu, 21 Apr 2005 14:34:18 -0700
From: "David S. Miller" <davem@davemloft.net>
On Thu, 21 Apr 2005 23:20:11 +0200 (CEST)
Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
> It'd be great if you could convert things to use the tramp_frame
> stuff. Should be doable for SPARC/UltraSPARC Linux without too much
> effort, and simplify the code a bit.
Done. How does this look?
Thanks. Please check this in. I hope you'll forgive me if I tweak it
bit after you've committed it ...
Mark
2005-04-21 David S. Miller <davem@davemloft.net>
* sparc-linux-tdep.c (sparc32_linux_sigframe_init): New function.
(sparc32_linux_sigframe, sparc32_linux_rt_sigframe): New tramp_frames.
(sparc_linux_sigtramp_start, sparc32_linux_sigtramp_start,
sparc32_linux_rt_sigtramp_start, sparc32_linux_sigtramp_p,
sparc32_linux_sigtramp_frame_cache,
sparc32_linux_sigtramp_frame_this_id,
sparc32_linux_sigtramp_frame_prev_register,
sparc32_linux_sigtramp_frame_unwind,
sparc32_linux_sigtramp_frame_sniffer): Delete.
(sparc32_linux_init_abi): Register new tramp unwinders. Kill
register of old sigtramp sniffer.
* sparc64-linux-tdep.c (sparc64_linux_sigframe_init): New
function.
(sparc64_linux_rt_sigframe): New tramp frame.
(sparc64_linux_sigtramp_start, sparc64_linux_sigtramp_p,
sparc64_linux_sigtramp_frame_cache,
sparc64_linux_sigtramp_frame_this_id,
sparc64_linux_sigtramp_frame_prev_register,
sparc64_linux_sigtramp_frame_unwind,
sparc64_linux_sigtramp_frame_sniffer): Delete.
(sparc64_linux_init_abi): Register new tramp unwinders. Kill
register of old sigtramp sniffer.
Makefile.in (sparc64-linux-tdep.o): Update dependencies.
(sparc-linux-tdep.o): Likewise.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] Add sparc64-linux sigtramp support
2005-04-21 21:57 ` Mark Kettenis
@ 2005-04-21 22:04 ` David S. Miller
0 siblings, 0 replies; 12+ messages in thread
From: David S. Miller @ 2005-04-21 22:04 UTC (permalink / raw)
To: Mark Kettenis; +Cc: gdb-patches
On Thu, 21 Apr 2005 23:57:31 +0200 (CEST)
Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
> Thanks. Please check this in. I hope you'll forgive me if I tweak it
> bit after you've committed it ...
No problem, committed.
By tweak I assume you're talking about moving the stuff we
want via the sol2 target osabi init calls into the linux
tdep files?
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] Add sparc64-linux sigtramp support
2005-04-21 21:55 ` David S. Miller
@ 2005-04-21 22:09 ` Mark Kettenis
2005-04-22 22:45 ` David S. Miller
0 siblings, 1 reply; 12+ messages in thread
From: Mark Kettenis @ 2005-04-21 22:09 UTC (permalink / raw)
To: davem; +Cc: gdb-patches
Date: Thu, 21 Apr 2005 14:49:01 -0700
From: "David S. Miller" <davem@davemloft.net>
The temporary workaround I did last night was to make the sparc dwarf2
CIF unwinder init_reg() routine just mark G0 as UNDEFINED. I don't
know if that's what we'd like to do long term, or if GCC should output
something for this register.
Hmm, I think it is better to mark it as SAME_VALUE; %g0 will always be
%g0. No compiler will ever be able to change that ;-).
I'm going to get some sleep now. If you'll commit that tramp_frame
diff, I'm going to do some more work on this tomorrow ;-).
Mark
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] Add sparc64-linux sigtramp support
2005-04-21 22:09 ` Mark Kettenis
@ 2005-04-22 22:45 ` David S. Miller
2005-04-23 12:33 ` Mark Kettenis
0 siblings, 1 reply; 12+ messages in thread
From: David S. Miller @ 2005-04-22 22:45 UTC (permalink / raw)
To: Mark Kettenis; +Cc: gdb-patches
Mark do you actually have a sparc-linux machine that you test
your changes on? Your solaris2 tdep removal breaks even
the most simplest debugging test case, there is no way you
tested sparc64-linux debugging.
You're not calling sparc64_init_abi() anymore. Once you
remove the call to sparc64_sol2_init_abi() it's not occuring
at all.
If you don't have a sparc*-linux machine to test your changes
on, please at least run them by me quickly so I can run the
testsuite on both 32-bit and 64-bit native Linux/Sparc.
BTW, the plt entry size stuff is wrong. It was wrong for
the solaris2 sparc64 target and it's wrong for the Linux
target as well. They are variable in size, the first 64K
of them are 16 bytes in size, then they become variable
length sections of split instructions+data.
I think we should instead either teach gdb how to really get
the correct frame even in the funny PLT entry save/restore
sequence (I had this working flawlessly a few years ago, I
could resurrect that code) or we could do something similar to
what the ppc-linux-tdep.c code does. I also think we should
integrate the "PLT breakpoint avoidance" stuff they do there
as well (and move that into a common file as the comment
above it suggests).
Thanks.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] Add sparc64-linux sigtramp support
2005-04-22 22:45 ` David S. Miller
@ 2005-04-23 12:33 ` Mark Kettenis
2005-04-23 17:47 ` David S. Miller
0 siblings, 1 reply; 12+ messages in thread
From: Mark Kettenis @ 2005-04-23 12:33 UTC (permalink / raw)
To: davem; +Cc: gdb-patches
Date: Fri, 22 Apr 2005 15:38:35 -0700
From: "David S. Miller" <davem@davemloft.net>
Mark do you actually have a sparc-linux machine that you test
your changes on? Your solaris2 tdep removal breaks even
the most simplest debugging test case, there is no way you
tested sparc64-linux debugging.
I'm working on it now ;-).
You're not calling sparc64_init_abi() anymore. Once you
remove the call to sparc64_sol2_init_abi() it's not occuring
at all.
Sorry 'bout that. Thanks for fixing this.
If you don't have a sparc*-linux machine to test your changes
on, please at least run them by me quickly so I can run the
testsuite on both 32-bit and 64-bit native Linux/Sparc.
BTW, the plt entry size stuff is wrong. It was wrong for
the solaris2 sparc64 target and it's wrong for the Linux
target as well. They are variable in size, the first 64K
of them are 16 bytes in size, then they become variable
length sections of split instructions+data.
Hmm, the SCD 2.4.1 document that I'm looking at now says there are 32K
entries of 32 bytes followed by sections of 160 24-byte entries
followed by 160 pointers. I'm not sure it really matters though.
IIRC the most important thing is to avoid thinking that the PLT is a
proper function that starts with setting up a stack frame. Did you
notice any problems with the current code.
That said, it looks like we should at least change the 16 into 32 and
add a comment about the >32K PLT entries.
I think we should instead either teach gdb how to really get
the correct frame even in the funny PLT entry save/restore
sequence (I had this working flawlessly a few years ago, I
could resurrect that code) or we could do something similar to
what the ppc-linux-tdep.c code does. I also think we should
integrate the "PLT breakpoint avoidance" stuff they do there
as well (and move that into a common file as the comment
above it suggests).
Looks to me as if the sparc PLT entries are deliberately constructed a
way to avoid the PLT breakpoint issue the ppc-linux-tdep.c code tries
to solve. That said, moving that code into a common file is probably
a good idea.
Mark
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] Add sparc64-linux sigtramp support
2005-04-23 12:33 ` Mark Kettenis
@ 2005-04-23 17:47 ` David S. Miller
0 siblings, 0 replies; 12+ messages in thread
From: David S. Miller @ 2005-04-23 17:47 UTC (permalink / raw)
To: Mark Kettenis; +Cc: gdb-patches
On Sat, 23 Apr 2005 14:32:56 +0200 (CEST)
Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
> Hmm, the SCD 2.4.1 document that I'm looking at now says there are 32K
> entries of 32 bytes followed by sections of 160 24-byte entries
> followed by 160 pointers.
The first part is correct, there are 32K pure code entries.
The latter section is "160 24-byte entries followed by
160 pointers" for every full group of 160 entries, for the
final group that has less than 160 entries (say N entries) it is
N 24-byte entries followed by N pointers.
The formulas to compute this stuff are pretty well described
in the sparc64 BFD backend support code. Search for
"h->plt.offset" and "build_plt_entry" in the current bfd/elfxx-sparc.c
code.
> I'm not sure it really matters though.
> IIRC the most important thing is to avoid thinking that the PLT is a
> proper function that starts with setting up a stack frame. Did you
> notice any problems with the current code.
Yes, there is a test case that fails on sparc32 for at least the
past 8 years that's been bugging me like crazy.
Basically it's trying to step over an integer multiply in a piece
of C code, via a watchpoint. It's 32-bit Sparc compiled code with
no hw multiply support, so to implement the multiply it calls ".umul"
in the C library via a PLT entry.
GDB outside of my own trees has never handled this test correctly
and it's because of the PLT frame handling.
The PLT trampoline _does_ have a frame, the issue is only to teach
the Sparc target dependant code where to find the restore which
releases the frame.
Anyways, let me dig through my old patches and notes I took on this
matter. I'll use that to come up with a solution proposal.
> Looks to me as if the sparc PLT entries are deliberately constructed a
> way to avoid the PLT breakpoint issue the ppc-linux-tdep.c code tries
> to solve. That said, moving that code into a common file is probably
> a good idea.
It has the same problem. If you set a breakpoint in the second instruction
of a PLT entry while we're in the dynamic linker resolve code, the dynamic
linker will write the new instructions in the PLT entry, then GDB will
restore the old out-of-date instruction when it removes the breakpoint it
had there, thus corrupting the PLT entry and causing a crash the next time
the child calls that function via that PLT entry.
Like the above, I'll come up some specific test cases and fix proposals
over the next few days for this stuff.
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2005-04-23 17:47 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-04-21 3:51 [PATCH] Add sparc64-linux sigtramp support David S. Miller
2005-04-21 19:23 ` Mark Kettenis
2005-04-21 19:29 ` David S. Miller
2005-04-21 21:20 ` Mark Kettenis
2005-04-21 21:41 ` David S. Miller
2005-04-21 21:57 ` Mark Kettenis
2005-04-21 22:04 ` David S. Miller
2005-04-21 21:55 ` David S. Miller
2005-04-21 22:09 ` Mark Kettenis
2005-04-22 22:45 ` David S. Miller
2005-04-23 12:33 ` Mark Kettenis
2005-04-23 17:47 ` David S. Miller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox