This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFA] Add sparc-linux-tdep



[ Assuming the Sparc OS tdep changes get approved. ]

This makes use of Sparc OS tdep for Linux/Sparc.  It adds signal frame
recognition and also dynamic linker support.  It also takes care of
the "long double is 8 bytes" issue.

Everything that can be multi-arch'd is.  I've noted the in comments
labelled "TODO" in sparc-linux-tdep.c which routines still cannot be
generically multi-arch'd so that I can take care of this later.

2002-04-20  David S. Miller  <davem@redhat.com>

	* sparc-linux-tdep.c: New file.
	* Makefile.in (ALLDEPFILES): Add sparc-linux-tdep.c
	(sparc-linux-tdep.o): New dependencies.
	(sparc-tdep.o): Add sparc-tdep.h dependency
	* config/sparc/tm-linux.h (SIGCONTEXT_PC_OFFSET): Don't define.
	(IN_SIGTRAMP, SKIP_SOLIB_RESOLVER, SKIP_PROLOGUE_FRAMELESS_P):
	Define.
	(sparc_linux_skip_prologue_frameless_p,
	sparc_linux_skip_solib_resolver, sparc_linux_in_sigtramp):
	Declare.
	* config/sparc/tm-sp64linux.h (tm-sysv4.h): Don't include.
	(tm-linux.h): Include this instead.
	(SIGCONTEXT_PC_OFFSET, GDB_PTRACE_REGS64): Don't define.
	(IN_SIGTRAMP, SKIP_SOLIB_RESOLVER, SKIP_PROLOGUE_FRAMELESS_P):
	Define.
	(sparc_linux_skip_prologue_frameless_p,
	sparc_linux_skip_solib_resolver, sparc_linux_in_sigtramp):
	Declare.

--- sparc-linux-tdep.c.~1~	Sat Apr 20 20:55:07 2002
+++ sparc-linux-tdep.c	Sat Apr 20 21:50:48 2002
@@ -0,0 +1,508 @@
+/* Target-dependent code for GNU/Linux running on Sparc's, for GDB.
+
+   Copyright 2002 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "defs.h"
+#include "arch-utils.h"
+#include "frame.h"
+#include "inferior.h"
+#include "obstack.h"
+#include "target.h"
+#include "value.h"
+#include "bfd.h"
+#include "gdb_string.h"
+#include "regcache.h"
+
+#include "gdbcore.h"
+
+#include "elf-bfd.h"
+
+#include "sparc-tdep.h"
+
+/* For sparc_linux_skip_solib_resolver.  */
+#include "symtab.h"
+#include "symfile.h"
+#include "objfiles.h"
+
+#include "solib-svr4.h"		/* For struct link_map_offsets.  */
+
+/* Recognizing signal handler frames.  */
+
+/* GNU/Linux has two flavors of signals.  Normal signal handlers, and
+   "realtime" (RT) signals.  The RT signals can provide additional
+   information to the signal handler if the SA_SIGINFO flag is set
+   when establishing a signal handler using `sigaction'.  It is not
+   unlikely that future versions of GNU/Linux will support SA_SIGINFO
+   for normal signals too.  */
+
+/* When the sparc Linux kernel calls a signal handler and the
+   SA_RESTORER flag isn't set, the return address points to a bit of
+   code on the stack.  This function returns whether the PC appears to
+   be within this bit of code.
+
+   The instruction sequence for normal signals is
+	mov __NR_sigreturn, %g1		! hex: 0x821020d8
+	ta  0x10			! hex: 0x91d02010
+
+   Checking for the code sequence should be somewhat reliable, because
+   the effect is to call the system call sigreturn.  This is unlikely
+   to occur anywhere other than a signal trampoline.
+
+   It kind of sucks that we have to read memory from the process in
+   order to identify a signal trampoline, but there doesn't seem to be
+   any other way.  The IN_SIGTRAMP macro in tm-linux.h arranges to
+   only call us if no function name could be identified, which should
+   be the case since the code is on the stack.  */
+
+#define LINUX_SIGTRAMP_WORD0	(0x821020d8)	/* mov __NR_sigreturn, %g1 */
+#define LINUX_SIGTRAMP_WORD1	(0x91d02010)	/* ta  0x10 */
+
+#define LINUX_SIGTRAMP_LEN	(0x8)
+
+/* If PC is in a sigtramp routine, return the address of the start of
+   the routine.  Otherwise, return 0.  */
+
+static CORE_ADDR
+sparc_linux_sigtramp_start (CORE_ADDR pc)
+{
+  unsigned int buf[LINUX_SIGTRAMP_LEN / sizeof(unsigned int)];
+
+  /* We only recognize a signal trampoline if PC is at the start of
+     one of the three instructions.  We optimize for finding the PC at
+     the start, 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 (read_memory_nobpt (pc, (char *) buf, LINUX_SIGTRAMP_LEN) != 0)
+    return 0;
+
+  if (buf[0] != LINUX_SIGTRAMP_WORD0)
+    {
+      if (buf[0] != LINUX_SIGTRAMP_WORD1)
+	return 0;
+
+      pc -= 4;
+
+      if (read_memory_nobpt(pc, (char *) buf, LINUX_SIGTRAMP_LEN) != 0)
+	return 0;
+    }
+
+  if (buf[0] != LINUX_SIGTRAMP_WORD0
+      || buf[1] != LINUX_SIGTRAMP_WORD1)
+    return 0;
+
+  return pc;
+}
+
+/* This function does the same for RT signals.  Here the instruction
+   sequence is
+       mov __NR_rt_sigreturn, %g1	! hex: 0x82102065
+       ta  {0x10,0x6d}			! hex: 0x91d02010 or 0x91d0206d
+
+   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.
+   Note that 64-bit binaries only use this RT signal return method.  */
+
+#define LINUX_RT_SIGTRAMP_WORD0		(0x82102065)
+#define LINUX_RT_SIGTRAMP_WORD1_32	(0x91d02010)
+#define LINUX_RT_SIGTRAMP_WORD1_64	(0x91d0206d)
+
+#define LINUX_RT_SIGTRAMP_LEN		8
+
+/* If PC is in a RT sigtramp routine, return the address of the start
+   of the routine.  Otherwise, return 0.  */
+
+static CORE_ADDR
+sparc_linux_rt_sigtramp_start (CORE_ADDR pc)
+{
+  unsigned int buf[LINUX_RT_SIGTRAMP_LEN / sizeof(unsigned int)];
+
+  /* We only recognize a signal trampoline if PC is at the start of
+     one of the two instructions.  We optimize for finding the PC at
+     the start, 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 (read_memory_nobpt (pc, (char *) buf, LINUX_RT_SIGTRAMP_LEN) != 0)
+    return 0;
+
+  if (buf[0] != LINUX_RT_SIGTRAMP_WORD0)
+    {
+      if (buf[0] != LINUX_RT_SIGTRAMP_WORD1_32
+	  && buf[0] != LINUX_RT_SIGTRAMP_WORD1_64)
+	return 0;
+
+      pc -= 4;
+
+      if (read_memory_nobpt (pc, (char *) buf, LINUX_RT_SIGTRAMP_LEN) != 0)
+	return 0;
+    }
+
+  if (buf[0] != LINUX_RT_SIGTRAMP_WORD0
+      || (buf[1] != LINUX_RT_SIGTRAMP_WORD1_32
+	  && buf[1] != LINUX_RT_SIGTRAMP_WORD1_64))
+    return 0;
+
+  return pc;
+}
+
+/* Return whether PC is in a GNU/Linux sigtramp routine.
+
+   TODO Need to generically multi-arch this. */
+
+int
+sparc_linux_in_sigtramp (CORE_ADDR pc, char *name)
+{
+  int ret;
+
+  if (name)
+    ret = (STREQ ("__sigreturn_stub", name) || STREQ ("__rt_sigreturn_stub", name));
+  else
+    ret = (sparc_linux_sigtramp_start (pc) != 0
+	   || sparc_linux_rt_sigtramp_start (pc) != 0);
+
+  return ret;
+}
+
+/* Assuming FRAME is for a GNU/Linux sigtramp routine, return the
+   PC/SP of the associated sigcontext structure.  */
+
+static CORE_ADDR
+sparc_linux_sigtramp_saved_pc (struct frame_info *frame)
+{
+  CORE_ADDR ret;
+  char *buf;
+
+  if (!frame->next)
+    return 0;
+
+  buf = alloca(SPARC_INTREG_SIZE);
+
+  if (sparc_linux_sigtramp_start (frame->pc) != 0)
+    {
+      /* Stack frame is:
+           standard 32-bit register window + slack	96 bytes
+           siginfo_t					PC at offset 4  */
+
+      read_memory(frame->next->frame + (96 + 4), buf, SPARC_INTREG_SIZE);
+
+      ret = PC_ADJUST (extract_address (buf, SPARC_INTREG_SIZE));
+
+      return ret;
+    }
+
+  if (sparc_linux_rt_sigtramp_start (frame->pc) != 0)
+    {
+      /* For 32-bit task, same as non-rt frame.  For 64-bit task
+	 the layout is:
+	      standard 64-bit register window + slack	192 bytes
+	      siginfo_t					128 bytes
+	      pt_regs					PC at offset 136  */
+      if (! GDB_TARGET_IS_SPARC64)
+	{
+	  read_memory(frame->next->frame + (96 + 4), buf, SPARC_INTREG_SIZE);
+	}
+      else
+	{
+	  read_memory(frame->next->frame + (192 + 128 + 136), buf, SPARC_INTREG_SIZE);
+	}
+
+      ret = PC_ADJUST (extract_address (buf, SPARC_INTREG_SIZE));
+
+      return ret;
+    }
+
+  error ("Couldn't recognize signal trampoline.");
+  return 0;
+}
+
+extern CORE_ADDR sparc_frame_chain (struct frame_info *);
+
+static CORE_ADDR
+sparc_linux_frame_chain (struct frame_info *frame)
+{
+  if (frame->signal_handler_caller)
+    return frame->frame;
+
+  return sparc_frame_chain (frame);
+}
+
+extern CORE_ADDR sparc_frame_saved_pc (struct frame_info *);
+
+/* Return the saved program counter for FRAME.  */
+
+static CORE_ADDR
+sparc_linux_frame_saved_pc (struct frame_info *frame)
+{
+  CORE_ADDR ret;
+
+  if (frame->signal_handler_caller)
+    ret = sparc_linux_sigtramp_saved_pc (frame);
+  else
+    ret = sparc_frame_saved_pc (frame);
+
+  return ret;
+}
+
+static CORE_ADDR
+sparc_linux_saved_pc_after_call (struct frame_info *frame)
+{
+  CORE_ADDR ret;
+
+  if (frame->signal_handler_caller)
+    ret = sparc_linux_sigtramp_saved_pc (frame);
+  else
+    ret = sparc_pc_adjust (read_register (RP_REGNUM));
+
+  return ret;
+}
+
+/* Calling functions in shared libraries.  */
+
+/* Find the minimal symbol named NAME, and return both the minsym
+   struct and its objfile.  This probably ought to be in minsym.c, but
+   everything there is trying to deal with things like C++ and
+   SOFUN_ADDRESS_MAYBE_TURQUOISE, ...  Since this is so simple, it may
+   be considered too special-purpose for general consumption.  */
+
+static struct minimal_symbol *
+find_minsym_and_objfile (char *name, struct objfile **objfile_p)
+{
+  struct objfile *objfile;
+
+  ALL_OBJFILES (objfile)
+    {
+      struct minimal_symbol *msym;
+
+      ALL_OBJFILE_MSYMBOLS (objfile, msym)
+	{
+	  if (SYMBOL_NAME (msym)
+	      && STREQ (SYMBOL_NAME (msym), name))
+	    {
+	      *objfile_p = objfile;
+	      return msym;
+	    }
+	}
+    }
+
+  return 0;
+}
+
+static CORE_ADDR
+skip_hurd_resolver (CORE_ADDR pc)
+{
+  /* The HURD dynamic linker is part of the GNU C library, so many
+     GNU/Linux distributions use it.  (All ELF versions, as far as I
+     know.)  An unresolved PLT entry points to "_dl_runtime_resolve",
+     which calls "fixup" to patch the PLT, and then passes control to
+     the function.
+
+     We look for the symbol `_dl_runtime_resolve', and find `fixup' in
+     the same objfile.  If we are at the entry point of `fixup', then
+     we set a breakpoint at the return address (at the top of the
+     stack), and continue.
+  
+     It's kind of gross to do all these checks every time we're
+     called, since they don't change once the executable has gotten
+     started.  But this is only a temporary hack --- upcoming versions
+     of GNU/Linux will provide a portable, efficient interface for
+     debugging programs that use shared libraries.  */
+
+  struct objfile *objfile;
+  struct minimal_symbol *resolver 
+    = find_minsym_and_objfile ("_dl_runtime_resolve", &objfile);
+
+  if (resolver)
+    {
+      struct minimal_symbol *fixup
+	= lookup_minimal_symbol ("fixup", NULL, objfile);
+
+      if (fixup && SYMBOL_VALUE_ADDRESS (fixup) == pc)
+	return (SAVED_PC_AFTER_CALL (get_current_frame ()));
+
+      fixup = lookup_minimal_symbol("profile_fixup", NULL, objfile);
+      if (fixup && SYMBOL_VALUE_ADDRESS (fixup) == pc)
+	return (SAVED_PC_AFTER_CALL (get_current_frame ()));
+    }
+
+  return 0;
+}      
+
+/* See the comments for SKIP_SOLIB_RESOLVER at the top of infrun.c.
+   This function:
+   1) decides whether a PLT has sent us into the linker to resolve
+      a function reference, and 
+   2) if so, tells us where to set a temporary breakpoint that will
+      trigger when the dynamic linker is done.
+
+   TODO Need to generically multi-arch this thing.  */
+
+CORE_ADDR
+sparc_linux_skip_solib_resolver (CORE_ADDR pc)
+{
+  CORE_ADDR result;
+
+  /* Plug in functions for other kinds of resolvers here.  */
+  result = skip_hurd_resolver (pc);
+  if (result)
+    return result;
+
+  return 0;
+}
+
+/* We need special processing here because 'fixup' in the dynamic linker
+   looks like it is frameless, but it really does get a frame from its
+   caller in the PLT (which does save).
+
+   Actually, any piece of code which has the same pettern, ie.:
+
+	place1:		save
+			call place2
+			 nop
+
+	place2:		call place3
+			 nop
+			jmp  %reg
+			restore
+
+	place3:		save
+			...
+			ret
+			 restore
+
+   is going to confuse SKIP_PROLOGUE_FRAMELESS_P.  It is hard to
+   formulate a generic fix for this that would not break on sibcalls.
+
+   TODO Need to generically multi-arch this.  */
+
+CORE_ADDR
+sparc_linux_skip_prologue_frameless_p (CORE_ADDR pc)
+{
+  struct objfile *objfile;
+  struct minimal_symbol *resolver 
+    = find_minsym_and_objfile ((GDB_TARGET_IS_SPARC64 ?
+				"_dl_runtime_resolve_0" :
+				"_dl_runtime_resolve"), &objfile);
+
+  if (resolver)
+    {
+      CORE_ADDR rpc = SYMBOL_VALUE_ADDRESS (resolver);
+      int resolver_size = 0x60;
+
+      /* This size includes all of the resolver instances present.
+	 For example on sparc32 it includes _dl_runtime_resolve
+	 and _dl_profile_resolve, and on sparc64 it includes
+	 _dl_runtime_resolve_0 _dl_runtime_resolve_1 and
+	 _dl_profile_resolve.  It works because they are present
+	 one right after another in the dynamic linker.  */
+      if (GDB_TARGET_IS_SPARC64)
+	resolver_size = 0x100;
+
+      if (pc >= rpc && pc < (rpc + resolver_size))
+	return pc + 4;
+    }
+  return sparc_skip_prologue (pc, 1);
+}
+
+/* Fetch (and possibly build) an appropriate link_map_offsets
+   structure for native GNU/Linux Sparc targets using the struct offsets
+   defined in link.h (but without actual reference to that file).
+
+   This makes it possible to access GNU/Linux Sparc shared libraries from a
+   GDB that was built on a different host platform (for cross debugging).
+
+   It also is needed to handle GDB multi-arch properly.  */
+
+static struct link_map_offsets *
+sparc_linux_svr4_fetch_link_map_offsets (void)
+{ 
+  static struct link_map_offsets lmo;
+  static struct link_map_offsets *lmp = NULL;
+
+  if (lmp == NULL)
+    { 
+      lmp = &lmo;
+
+      if (! GDB_TARGET_IS_SPARC64)
+	{
+	  lmo.r_debug_size = 8;	/* The actual size is 20 bytes, but
+				   this is all we need.  */
+	  lmo.r_map_offset = 4;
+	  lmo.r_map_size   = 4;
+	  lmo.link_map_size = 20;
+	  lmo.l_addr_offset = 0;
+	  lmo.l_addr_size   = 4;
+	  lmo.l_name_offset = 4;
+	  lmo.l_name_size   = 4;
+	  lmo.l_next_offset = 12;
+	  lmo.l_next_size   = 4;
+	  lmo.l_prev_offset = 16;
+	  lmo.l_prev_size   = 4;
+	}
+      else
+	{
+	  lmo.r_debug_size = 16; /* The actual size is 40 bytes, but
+				    this is all we need.  */
+	  lmo.r_map_offset = 8;
+	  lmo.r_map_size   = 8;
+	  lmo.link_map_size = 40;
+	  lmo.l_addr_offset = 0;
+	  lmo.l_addr_size   = 8;
+	  lmo.l_name_offset = 8;
+	  lmo.l_name_size   = 8;
+	  lmo.l_next_offset = 24;
+	  lmo.l_next_size   = 8;
+	  lmo.l_prev_offset = 32;
+	  lmo.l_prev_size   = 8;
+	}
+    }
+
+  return lmp;
+}
+
+static void
+sparc_linux_gdbarch_os_init(struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  set_gdbarch_frame_chain (gdbarch, sparc_linux_frame_chain);
+  set_gdbarch_frame_saved_pc (gdbarch, sparc_linux_frame_saved_pc);
+  set_gdbarch_saved_pc_after_call (gdbarch, sparc_linux_saved_pc_after_call);
+
+  if (gdbarch_tdep (gdbarch)->intreg_size == 4)
+    {
+      /* Contrary to the v8 ABI, we use an 8-byte long double
+	 in this configuration.  */
+      set_gdbarch_long_double_bit (gdbarch, 8 * TARGET_CHAR_BIT);
+    }
+  else
+    {
+      set_gdbarch_long_double_bit (gdbarch, 16 * TARGET_CHAR_BIT);
+    }
+
+  set_solib_svr4_fetch_link_map_offsets (gdbarch,
+					 sparc_linux_svr4_fetch_link_map_offsets);
+}
+
+void
+_initialize_sparc_linux_tdep (void)
+{
+  sparc_gdbarch_register_os_abi (ELFOSABI_LINUX, sparc_linux_gdbarch_os_init);
+}
--- Makefile.in.~2~	Sat Apr 20 20:04:36 2002
+++ Makefile.in	Sat Apr 20 21:04:24 2002
@@ -1213,7 +1213,7 @@
 	ser-go32.c ser-pipe.c ser-tcp.c \
 	sh-tdep.c solib.c solib-svr4.c solib-sunos.c sparc-linux-nat.c \
 	sparc-nat.c \
-	sparc-tdep.c sparcl-tdep.c sun3-nat.c \
+	sparc-tdep.c sparcl-tdep.c sparc-linux-tdep.c sun3-nat.c \
 	symm-tdep.c symm-nat.c \
 	vax-tdep.c \
 	vx-share/xdr_ld.c vx-share/xdr_ptrace.c vx-share/xdr_rdb.c \
@@ -2048,12 +2048,17 @@
 
 sparc-linux-nat.o: sparc-linux-nat.c $(defs_h) $(regcache_h)
 
+sparc-linux-tdep.o: sparc-linux-tdep.c $(defs_h) $(arch_utils_h) $(frame_h) \
+	$(inferior_h) $(obstack_h) $(target_h) $(value_h) $(bfd_h) \
+	$(gdb_string_h) $(regcache_h) $(gdbcore_h) $(symtab_h) $(symfile_h) \
+	$(objdiles_h) $(solib_svr4_h) $(BFD_SRC)/elf-bfd.h sparc-tdep.h
+
 sparc-nat.o: sparc-nat.c $(bfd_h) $(defs_h) $(inferior_h) $(gdbcore_h) \
 	$(target_h) $(regcache_h)
 
 sparc-tdep.o: sparc-tdep.c $(floatformat_h) $(defs_h) $(gdbcore_h) \
 	$(inferior_h) $(objfiles_h) $(symfile_h) $(target_h) $(gdb_string_h) \
-	$(arch_utils_h) $(regcache_h) $(BFD_SRC)/elf-bfd.h
+	$(arch_utils_h) $(regcache_h) $(BFD_SRC)/elf-bfd.h sparc-tdep.h
 
 sparcl-tdep.o: sparcl-tdep.c $(defs_h) $(gdbcore_h) $(target_h) $(regcache_h)
 
--- config/sparc/tm-linux.h.~1~	Sat Apr 20 18:47:06 2002
+++ config/sparc/tm-linux.h	Sat Apr 20 20:53:49 2002
@@ -27,8 +27,26 @@
 
 #include "sparc/tm-sparc.h"
 
-#define SIGCONTEXT_PC_OFFSET 12
-
 #include "tm-linux.h"
+
+/* When the sparc Linux kernel calls a signal handler, the return
+   address points to a bit of code on the stack.  These definitions
+   are used to identify this bit of code as a signal trampoline in
+   order to support backtracing through calls to signal handlers.  */
+
+#define IN_SIGTRAMP(pc, name) sparc_linux_in_sigtramp (pc, name)
+extern int sparc_linux_in_sigtramp (CORE_ADDR, char *);
+
+/* When we call a function in a shared library, and the PLT sends us
+   into the dynamic linker to find the function's real address, we
+   need to skip over the dynamic linker call.  This function decides
+   when to skip, and where to skip to.  See the comments for
+   SKIP_SOLIB_RESOLVER at the top of infrun.c.  */
+#define SKIP_SOLIB_RESOLVER sparc_linux_skip_solib_resolver
+extern CORE_ADDR sparc_linux_skip_solib_resolver (CORE_ADDR pc);
+
+#undef SKIP_PROLOGUE_FRAMELESS_P
+#define SKIP_PROLOGUE_FRAMELESS_P(PC) sparc_linux_skip_prologue_frameless_p (PC)
+extern CORE_ADDR sparc_linux_skip_prologue_frameless_p (CORE_ADDR pc);
 
 #endif /* TM_SPARCLINUX_H */
--- config/sparc/tm-sp64linux.h.~1~	Sat Apr 20 18:47:06 2002
+++ config/sparc/tm-sp64linux.h	Sat Apr 20 20:54:24 2002
@@ -23,14 +23,31 @@ Foundation, Inc., 59 Temple Place - Suit
 
 #include "sparc/tm-sp64.h"
 
-#define SIGCONTEXT_PC_OFFSET 16  /* See asm-sparc64/sigcontext.h */
-
 /* We always want full V9 + Ultra VIS stuff... */
 #undef TM_PRINT_INSN_MACH
 #define TM_PRINT_INSN_MACH bfd_mach_sparc_v9a
 
-#define GDB_PTRACE_REGS64
+#include "tm-linux.h"
+
+
+/* When the sparc Linux kernel calls a signal handler, the return
+   address points to a bit of code on the stack.  These definitions
+   are used to identify this bit of code as a signal trampoline in
+   order to support backtracing through calls to signal handlers.  */
+
+#define IN_SIGTRAMP(pc, name) sparc_linux_in_sigtramp (pc, name)
+extern int sparc_linux_in_sigtramp (CORE_ADDR, char *);
+
+/* When we call a function in a shared library, and the PLT sends us
+   into the dynamic linker to find the function's real address, we
+   need to skip over the dynamic linker call.  This function decides
+   when to skip, and where to skip to.  See the comments for
+   SKIP_SOLIB_RESOLVER at the top of infrun.c.  */
+#define SKIP_SOLIB_RESOLVER sparc_linux_skip_solib_resolver
+extern CORE_ADDR sparc_linux_skip_solib_resolver (CORE_ADDR pc);
 
-#include "tm-sysv4.h"
+#undef SKIP_PROLOGUE_FRAMELESS_P
+#define SKIP_PROLOGUE_FRAMELESS_P(PC) sparc_linux_skip_prologue_frameless_p (PC)
+extern CORE_ADDR sparc_linux_skip_prologue_frameless_p (CORE_ADDR pc);
 
-#endif TM_SPARC_LIN64_H
+#endif /* TM_SPARC_LIN64_H */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]