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:rs6000] Framefy rs6000 (and GNU/Linux PPC)


Hello,

The attached updates the rs6000 so that (well for NetBSD, "elf" and GNU/Linux 32+64) it uses the frame unwinder. It doesn't yet enable dwarf2-cfi.

Apart from the bug: Use right frame ID in step_over_function
http://sources.redhat.com/ml/gdb-patches/2004-02/msg00882.html
the conversion was highly mechanical..

Tested on NetBSD/PPC (which gets less failures) and GNU/Linux 32x64-bit and 64-bit (which get the same results).

ok? 6.1?

Andrew
2004-02-29  Andrew Cagney  <cagney@redhat.com>

	* ppc-linux-tdep.c: Include "trad-frame.h", and "frame-unwind.h".
	Update copyright.
	(struct ppc_linux_sigtramp_cache, ppc_linux_sigtramp_cache)
	(ppc_linux_sigtramp_this_id, ppc_linux_sigtramp_prev_register)
	(ppc_linux_sigtramp_unwind, ppc_linux_sigtramp_sniffer)
	(ppc_linux_init_abi): Add both 32- and 64-bit signal trampoline
	unwinders.  #ifdef legacy frame code.
	* rs6000-tdep.c: Include "trad-frame.h", "frame-unwind.h", and
	"frame-base.h".
	(rs6000_unwind_pc, rs6000_unwind_dummy_id)
	(struct rs6000_frame_cache, rs6000_frame_cache)
	(rs6000_frame_this_id, rs6000_frame_prev_register)
	(rs6000_frame_sniffer, rs6000_frame_unwind)
	(rs6000_frame_base_address, rs6000_frame_base_sniffer)
	(rs6000_frame_base): Implement a traditional frame unwinder.
	(rs6000_gdbarch_init): When unknown, NetBSD, or GNU/Linux use the
	frame unwinder.

Index: ppc-linux-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/ppc-linux-tdep.c,v
retrieving revision 1.50
diff -u -r1.50 ppc-linux-tdep.c
--- ppc-linux-tdep.c	16 Feb 2004 21:49:22 -0000	1.50
+++ ppc-linux-tdep.c	1 Mar 2004 01:07:57 -0000
@@ -32,6 +32,8 @@
 #include "regcache.h"
 #include "value.h"
 #include "osabi.h"
+#include "trad-frame.h"
+#include "frame-unwind.h"
 
 #include "solib-svr4.h"
 #include "ppc-tdep.h"
@@ -1034,6 +1036,110 @@
   NULL				/* next */
 };
 
+struct ppc_linux_sigtramp_cache
+{
+  CORE_ADDR base;
+  struct trad_frame_saved_reg *saved_regs;
+};
+
+static struct ppc_linux_sigtramp_cache *
+ppc_linux_sigtramp_cache (struct frame_info *next_frame, void **this_cache)
+{
+  CORE_ADDR regs;
+  CORE_ADDR gpregs;
+  CORE_ADDR fpregs;
+  int i;
+  struct ppc_linux_sigtramp_cache *cache;
+  struct gdbarch *gdbarch = get_frame_arch (next_frame);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if ((*this_cache) != NULL)
+    return (*this_cache);
+  cache = FRAME_OBSTACK_ZALLOC (struct ppc_linux_sigtramp_cache);
+  (*this_cache) = cache;
+  cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
+
+  cache->base = frame_unwind_register_unsigned (next_frame, SP_REGNUM);
+
+  /* Find the register pointer, which gives the address of the
+     register buffers.  */
+  if (tdep->wordsize == 4)
+    regs = (cache->base
+	    + 0xd0 /* Offset to ucontext_t.  */
+	    + 0x30 /* Offset to .reg.  */);
+  else
+    regs = (cache->base
+	    + 0x80 /* Offset to ucontext_t.  */
+	    + 0xe0 /* Offset to .reg.  */);
+  /* And the corresponding register buffers.  */
+  gpregs = read_memory_unsigned_integer (regs, tdep->wordsize);
+  fpregs = gpregs + 48 * tdep->wordsize;
+
+  /* General purpose.  */
+  for (i = 0; i < 32; i++)
+    {
+      int regnum = i + tdep->ppc_gp0_regnum;
+      cache->saved_regs[regnum].addr = gpregs + i * tdep->wordsize;
+    }
+  cache->saved_regs[PC_REGNUM].addr = gpregs + 32 * tdep->wordsize;
+  cache->saved_regs[tdep->ppc_ctr_regnum].addr = gpregs + 35 * tdep->wordsize;
+  cache->saved_regs[tdep->ppc_lr_regnum].addr = gpregs + 36 * tdep->wordsize;
+  cache->saved_regs[tdep->ppc_xer_regnum].addr = gpregs + 37 * tdep->wordsize;
+  cache->saved_regs[tdep->ppc_cr_regnum].addr = gpregs + 38 * tdep->wordsize;
+
+  /* Floating point registers.  */
+  for (i = 0; i < 32; i++)
+    {
+      int regnum = i + FP0_REGNUM;
+      cache->saved_regs[regnum].addr = fpregs + i * tdep->wordsize;
+    }
+  cache->saved_regs[tdep->ppc_fpscr_regnum].addr = fpregs + 32 * tdep->wordsize;
+
+  return cache;
+}
+
+static void
+ppc_linux_sigtramp_this_id (struct frame_info *next_frame, void **this_cache,
+			  struct frame_id *this_id)
+{
+  struct ppc_linux_sigtramp_cache *info
+    = ppc_linux_sigtramp_cache (next_frame, this_cache);
+  (*this_id) = frame_id_build (info->base, frame_pc_unwind (next_frame));
+}
+
+static void
+ppc_linux_sigtramp_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 ppc_linux_sigtramp_cache *info
+    = ppc_linux_sigtramp_cache (next_frame, this_cache);
+  trad_frame_prev_register (next_frame, info->saved_regs, regnum,
+			    optimizedp, lvalp, addrp, realnump, valuep);
+}
+
+static const struct frame_unwind ppc_linux_sigtramp_unwind =
+{
+  SIGTRAMP_FRAME,
+  ppc_linux_sigtramp_this_id,
+  ppc_linux_sigtramp_prev_register
+};
+
+static const struct frame_unwind *
+ppc_linux_sigtramp_sniffer (struct frame_info *next_frame)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (next_frame));
+  if (frame_pc_unwind (next_frame)
+      > frame_unwind_register_unsigned (next_frame, SP_REGNUM))
+    /* Assume anything that is vaguely on the stack is a signal
+       trampoline.  */
+    return &ppc_linux_sigtramp_unwind;
+  else
+    return NULL;
+}
+
 static void
 ppc_linux_init_abi (struct gdbarch_info info,
                     struct gdbarch *gdbarch)
@@ -1051,6 +1157,7 @@
 	 PowerOpen struct convention.  */
       set_gdbarch_return_value (gdbarch, ppc_linux_return_value);
 
+#if 0
       /* Note: kevinb/2002-04-12: See note in rs6000_gdbarch_init regarding
 	 *_push_arguments().  The same remarks hold for the methods below.  */
       set_gdbarch_deprecated_frameless_function_invocation (gdbarch, ppc_linux_frameless_function_invocation);
@@ -1061,9 +1168,11 @@
                                          ppc_linux_frame_init_saved_regs);
       set_gdbarch_deprecated_init_extra_frame_info (gdbarch,
                                          ppc_linux_init_extra_frame_info);
+#endif
 
       set_gdbarch_memory_remove_breakpoint (gdbarch,
                                             ppc_linux_memory_remove_breakpoint);
+
       /* Shared library handling.  */
       set_gdbarch_in_solib_call_trampoline (gdbarch, in_plt_section);
       set_gdbarch_skip_trampoline_code (gdbarch,
@@ -1086,6 +1195,7 @@
       /* PPC64 malloc's entry-point is called ".malloc".  */
       set_gdbarch_name_of_malloc (gdbarch, ".malloc");
     }
+  frame_unwind_append_sniffer (gdbarch, ppc_linux_sigtramp_sniffer);
 }
 
 void
Index: rs6000-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/rs6000-tdep.c,v
retrieving revision 1.182
diff -u -r1.182 rs6000-tdep.c
--- rs6000-tdep.c	1 Mar 2004 00:50:56 -0000	1.182
+++ rs6000-tdep.c	1 Mar 2004 01:07:57 -0000
@@ -50,6 +50,10 @@
 #include "gdb_assert.h"
 #include "dis-asm.h"
 
+#include "trad-frame.h"
+#include "frame-unwind.h"
+#include "frame-base.h"
+
 /* If the kernel has to deliver a signal, it pushes a sigcontext
    structure on the stack and then calls the signal handler, passing
    the address of the sigcontext in an argument register. Usually
@@ -2619,6 +2623,221 @@
     return print_insn_little_powerpc (memaddr, info);
 }
 
+static CORE_ADDR
+rs6000_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
+{
+  return frame_unwind_register_unsigned (next_frame, PC_REGNUM);
+}
+
+static struct frame_id
+rs6000_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
+{
+  return frame_id_build (frame_unwind_register_unsigned (next_frame,
+							 SP_REGNUM),
+			 frame_pc_unwind (next_frame));
+}
+
+struct rs6000_frame_cache
+{
+  CORE_ADDR base;
+  CORE_ADDR initial_sp;
+  struct trad_frame_saved_reg *saved_regs;
+};
+
+static struct rs6000_frame_cache *
+rs6000_frame_cache (struct frame_info *next_frame, void **this_cache)
+{
+  struct rs6000_frame_cache *cache;
+  struct gdbarch *gdbarch = get_frame_arch (next_frame);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  struct rs6000_framedata fdata;
+  int wordsize = tdep->wordsize;
+
+  if ((*this_cache) != NULL)
+    return (*this_cache);
+  cache = FRAME_OBSTACK_ZALLOC (struct rs6000_frame_cache);
+  (*this_cache) = cache;
+  cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
+
+  skip_prologue (frame_func_unwind (next_frame), frame_pc_unwind (next_frame),
+		 &fdata);
+
+  /* If there were any saved registers, figure out parent's stack
+     pointer.  */
+  /* The following is true only if the frame doesn't have a call to
+     alloca(), FIXME.  */
+
+  if (fdata.saved_fpr == 0
+      && fdata.saved_gpr == 0
+      && fdata.saved_vr == 0
+      && fdata.saved_ev == 0
+      && fdata.lr_offset == 0
+      && fdata.cr_offset == 0
+      && fdata.vr_offset == 0
+      && fdata.ev_offset == 0)
+    cache->base = frame_unwind_register_unsigned (next_frame, SP_REGNUM);
+  else
+    {
+      /* NOTE: cagney/2002-04-14: The ->frame points to the inner-most
+	 address of the current frame.  Things might be easier if the
+	 ->frame pointed to the outer-most address of the frame.  In
+	 the mean time, the address of the prev frame is used as the
+	 base address of this frame.  */
+      cache->base = frame_unwind_register_unsigned (next_frame, SP_REGNUM);
+      if (!fdata.frameless)
+	/* Frameless really means stackless.  */
+	cache->base = read_memory_addr (cache->base, wordsize);
+    }
+  trad_frame_set_value (cache->saved_regs, SP_REGNUM, cache->base);
+
+  /* if != -1, fdata.saved_fpr is the smallest number of saved_fpr.
+     All fpr's from saved_fpr to fp31 are saved.  */
+
+  if (fdata.saved_fpr >= 0)
+    {
+      int i;
+      CORE_ADDR fpr_addr = cache->base + fdata.fpr_offset;
+      for (i = fdata.saved_fpr; i < 32; i++)
+	{
+	  cache->saved_regs[FP0_REGNUM + i].addr = fpr_addr;
+	  fpr_addr += 8;
+	}
+    }
+
+  /* if != -1, fdata.saved_gpr is the smallest number of saved_gpr.
+     All gpr's from saved_gpr to gpr31 are saved.  */
+
+  if (fdata.saved_gpr >= 0)
+    {
+      int i;
+      CORE_ADDR gpr_addr = cache->base + fdata.gpr_offset;
+      for (i = fdata.saved_gpr; i < 32; i++)
+	{
+	  cache->saved_regs[tdep->ppc_gp0_regnum + i].addr = gpr_addr;
+	  gpr_addr += wordsize;
+	}
+    }
+
+  /* if != -1, fdata.saved_vr is the smallest number of saved_vr.
+     All vr's from saved_vr to vr31 are saved.  */
+  if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1)
+    {
+      if (fdata.saved_vr >= 0)
+	{
+	  int i;
+	  CORE_ADDR vr_addr = cache->base + fdata.vr_offset;
+	  for (i = fdata.saved_vr; i < 32; i++)
+	    {
+	      cache->saved_regs[tdep->ppc_vr0_regnum + i].addr = vr_addr;
+	      vr_addr += register_size (gdbarch, tdep->ppc_vr0_regnum);
+	    }
+	}
+    }
+
+  /* if != -1, fdata.saved_ev is the smallest number of saved_ev.
+     All vr's from saved_ev to ev31 are saved. ????? */
+  if (tdep->ppc_ev0_regnum != -1 && tdep->ppc_ev31_regnum != -1)
+    {
+      if (fdata.saved_ev >= 0)
+	{
+	  int i;
+	  CORE_ADDR ev_addr = cache->base + fdata.ev_offset;
+	  for (i = fdata.saved_ev; i < 32; i++)
+	    {
+	      cache->saved_regs[tdep->ppc_ev0_regnum + i].addr = ev_addr;
+              cache->saved_regs[tdep->ppc_gp0_regnum + i].addr = ev_addr + 4;
+	      ev_addr += register_size (gdbarch, tdep->ppc_ev0_regnum);
+            }
+	}
+    }
+
+  /* If != 0, fdata.cr_offset is the offset from the frame that
+     holds the CR.  */
+  if (fdata.cr_offset != 0)
+    cache->saved_regs[tdep->ppc_cr_regnum].addr = cache->base + fdata.cr_offset;
+
+  /* If != 0, fdata.lr_offset is the offset from the frame that
+     holds the LR.  */
+  if (fdata.lr_offset != 0)
+    cache->saved_regs[tdep->ppc_lr_regnum].addr = cache->base + fdata.lr_offset;
+  /* The PC is found in the link register.  */
+  cache->saved_regs[PC_REGNUM] = cache->saved_regs[tdep->ppc_lr_regnum];
+
+  /* If != 0, fdata.vrsave_offset is the offset from the frame that
+     holds the VRSAVE.  */
+  if (fdata.vrsave_offset != 0)
+    cache->saved_regs[tdep->ppc_vrsave_regnum].addr = cache->base + fdata.vrsave_offset;
+
+  if (fdata.alloca_reg < 0)
+    /* If no alloca register used, then fi->frame is the value of the
+       %sp for this frame, and it is good enough.  */
+    cache->initial_sp = frame_unwind_register_unsigned (next_frame, SP_REGNUM);
+  else
+    cache->initial_sp = frame_unwind_register_unsigned (next_frame,
+							fdata.alloca_reg);
+
+  return cache;
+}
+
+static void
+rs6000_frame_this_id (struct frame_info *next_frame, void **this_cache,
+		      struct frame_id *this_id)
+{
+  struct rs6000_frame_cache *info = rs6000_frame_cache (next_frame,
+							this_cache);
+  (*this_id) = frame_id_build (info->base, frame_func_unwind (next_frame));
+}
+
+static void
+rs6000_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 rs6000_frame_cache *info = rs6000_frame_cache (next_frame,
+							this_cache);
+  trad_frame_prev_register (next_frame, info->saved_regs, regnum,
+			    optimizedp, lvalp, addrp, realnump, valuep);
+}
+
+static const struct frame_unwind rs6000_frame_unwind =
+{
+  NORMAL_FRAME,
+  rs6000_frame_this_id,
+  rs6000_frame_prev_register
+};
+
+static const struct frame_unwind *
+rs6000_frame_sniffer (struct frame_info *next_frame)
+{
+  return &rs6000_frame_unwind;
+}
+
+
+
+static CORE_ADDR
+rs6000_frame_base_address (struct frame_info *next_frame,
+				void **this_cache)
+{
+  struct rs6000_frame_cache *info = rs6000_frame_cache (next_frame,
+							this_cache);
+  return info->initial_sp;
+}
+
+static const struct frame_base rs6000_frame_base = {
+  &rs6000_frame_unwind,
+  rs6000_frame_base_address,
+  rs6000_frame_base_address,
+  rs6000_frame_base_address
+};
+
+static const struct frame_base *
+rs6000_frame_base_sniffer (struct frame_info *next_frame)
+{
+  return &rs6000_frame_base;
+}
+
 /* Initialize the current architecture based on INFO.  If possible, re-use an
    architecture from ARCHES, which is a list of architectures already created
    during this debugging session.
@@ -2871,8 +3090,6 @@
        Problem is, 220 isn't frame (16 byte) aligned.  Round it up to
        224.  */
     set_gdbarch_frame_red_zone_size (gdbarch, 224);
-  set_gdbarch_deprecated_save_dummy_frame_tos (gdbarch, generic_save_dummy_frame_tos);
-  set_gdbarch_believe_pcc_promotion (gdbarch, 1);
 
   set_gdbarch_deprecated_register_convertible (gdbarch, rs6000_register_convertible);
   set_gdbarch_deprecated_register_convert_to_virtual (gdbarch, rs6000_register_convert_to_virtual);
@@ -2893,7 +3110,6 @@
     set_gdbarch_push_dummy_call (gdbarch, rs6000_push_dummy_call);
 
   set_gdbarch_deprecated_extract_struct_value_address (gdbarch, rs6000_extract_struct_value_address);
-  set_gdbarch_deprecated_pop_frame (gdbarch, rs6000_pop_frame);
 
   set_gdbarch_skip_prologue (gdbarch, rs6000_skip_prologue);
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
@@ -2915,14 +3131,6 @@
     set_gdbarch_use_struct_convention (gdbarch,
 				       rs6000_use_struct_convention);
 
-  set_gdbarch_deprecated_frameless_function_invocation (gdbarch, rs6000_frameless_function_invocation);
-  set_gdbarch_deprecated_frame_chain (gdbarch, rs6000_frame_chain);
-  set_gdbarch_deprecated_frame_saved_pc (gdbarch, rs6000_frame_saved_pc);
-
-  set_gdbarch_deprecated_frame_init_saved_regs (gdbarch, rs6000_frame_init_saved_regs);
-  set_gdbarch_deprecated_init_extra_frame_info (gdbarch, rs6000_init_extra_frame_info);
-  set_gdbarch_deprecated_init_frame_pc_first (gdbarch, rs6000_init_frame_pc_first);
-
   if (!sysv_abi)
     {
       /* Handle RS/6000 function pointers (which are really function
@@ -2930,15 +3138,38 @@
       set_gdbarch_convert_from_func_ptr_addr (gdbarch,
 	rs6000_convert_from_func_ptr_addr);
     }
-  set_gdbarch_deprecated_frame_args_address (gdbarch, rs6000_frame_args_address);
-  set_gdbarch_deprecated_frame_locals_address (gdbarch, rs6000_frame_args_address);
-  set_gdbarch_deprecated_saved_pc_after_call (gdbarch, rs6000_saved_pc_after_call);
 
   /* Helpers for function argument information.  */
   set_gdbarch_fetch_pointer_argument (gdbarch, rs6000_fetch_pointer_argument);
 
   /* Hook in ABI-specific overrides, if they have been registered.  */
   gdbarch_init_osabi (info, gdbarch);
+
+  switch (info.osabi)
+    {
+    case GDB_OSABI_NETBSD_AOUT:
+    case GDB_OSABI_NETBSD_ELF:
+    case GDB_OSABI_UNKNOWN:
+    case GDB_OSABI_LINUX:
+      set_gdbarch_unwind_pc (gdbarch, rs6000_unwind_pc);
+      frame_unwind_append_sniffer (gdbarch, rs6000_frame_sniffer);
+      set_gdbarch_unwind_dummy_id (gdbarch, rs6000_unwind_dummy_id);
+      frame_base_append_sniffer (gdbarch, rs6000_frame_base_sniffer);
+      break;
+    default:
+      set_gdbarch_deprecated_save_dummy_frame_tos (gdbarch, generic_save_dummy_frame_tos);
+      set_gdbarch_believe_pcc_promotion (gdbarch, 1);
+      set_gdbarch_deprecated_pop_frame (gdbarch, rs6000_pop_frame);
+      set_gdbarch_deprecated_frame_args_address (gdbarch, rs6000_frame_args_address);
+      set_gdbarch_deprecated_frame_locals_address (gdbarch, rs6000_frame_args_address);
+      set_gdbarch_deprecated_saved_pc_after_call (gdbarch, rs6000_saved_pc_after_call);
+      set_gdbarch_deprecated_frameless_function_invocation (gdbarch, rs6000_frameless_function_invocation);
+      set_gdbarch_deprecated_frame_chain (gdbarch, rs6000_frame_chain);
+      set_gdbarch_deprecated_frame_saved_pc (gdbarch, rs6000_frame_saved_pc);
+      set_gdbarch_deprecated_frame_init_saved_regs (gdbarch, rs6000_frame_init_saved_regs);
+      set_gdbarch_deprecated_init_extra_frame_info (gdbarch, rs6000_init_extra_frame_info);
+      set_gdbarch_deprecated_init_frame_pc_first (gdbarch, rs6000_init_frame_pc_first);
+    }
 
   if (from_xcoff_exec)
     {

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