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]

[PATCH] Modernize VAX target; frameification


Preliminary testing shows that backtraces are much more reliable now.

Committed,

Mark


Index: ChangeLog
from  Mark Kettenis  <kettenis@gnu.org>
 
	* vax-tdep.c: Include "frame-base.h", "frame-unwind.h" and
	"trad-frame.h".
	(vax_frame_init_saved_regs): Remove function.
	(vax_sigtramp_saved_pc): Remove function.
	(vax_frame_saved_pc): Remove function.
	(vax_frame_args_address): Remove function.
	(vax_frame_num_args): Rewrite.
	(vax_frame_chain): Remove function.
	(vax_push_dummy_frame): Replace DEPRECATED_FP_REGNUM with
	VAX_FP_REGNUM.
	(vax_pop_frame): Likewise.
	(vax_saved_pc_after_call): Remove function.
	(struct vax_frame_cache): New structure.
	(vax_frame_cache): New function.
	(vax_frame_this_id): New function.
	(vax_frame_prev_register): New function.
	(vax_frame_unwind): New variable.
	(vax_frame_sniffer): New function.
	(vax_frame_base_address): New function.
	(vax_frame_args_address): New function.
	(vax_frame_base): New variable.
	(vax_unwind_pc): New function.
	(vax_gdbarch_init): Don't set deprecated_init_frame_pc,
	deprecated_fp_regnum, deprecated_saved_pc_after_call,
	deprecated_frame_chain, deprecated_frame_saved_pc,
	deprecated_frame_args_address and
	deprecated_frame_init_saved_regs.
	* Makefile.in (vax-tdep.o): Update dependencies.

 
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.537
diff -u -p -r1.537 Makefile.in
--- Makefile.in 9 Apr 2004 23:15:53 -0000 1.537
+++ Makefile.in 12 Apr 2004 19:45:56 -0000
@@ -2492,8 +2492,9 @@ values.o: values.c $(defs_h) $(gdb_strin
 varobj.o: varobj.c $(defs_h) $(value_h) $(expression_h) $(frame_h) \
 	$(language_h) $(wrapper_h) $(gdbcmd_h) $(gdb_string_h) $(varobj_h)
 vax-tdep.o: vax-tdep.c $(defs_h) $(symtab_h) $(opcode_vax_h) $(gdbcore_h) \
-	$(inferior_h) $(regcache_h) $(frame_h) $(value_h) $(arch_utils_h) \
-	$(gdb_string_h) $(osabi_h) $(dis_asm_h) $(vax_tdep_h)
+	$(inferior_h) $(regcache_h) $(frame_h) $(frame_base_h) \
+	$(frame_unwind_h) $(value_h) $(arch_utils_h) $(gdb_string_h) \
+	$(osabi_h) $(dis_asm_h) $(vax_tdep_h)
 win32-nat.o: win32-nat.c $(defs_h) $(frame_h) $(inferior_h) $(target_h) \
 	$(gdbcore_h) $(command_h) $(completer_h) $(regcache_h) $(top_h) \
 	$(buildsym_h) $(symfile_h) $(objfiles_h) $(gdb_string_h) \
Index: vax-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/vax-tdep.c,v
retrieving revision 1.71
diff -u -p -r1.71 vax-tdep.c
--- vax-tdep.c 12 Apr 2004 16:49:35 -0000 1.71
+++ vax-tdep.c 12 Apr 2004 19:45:56 -0000
@@ -27,6 +27,9 @@
 #include "inferior.h"
 #include "regcache.h"
 #include "frame.h"
+#include "frame-base.h"
+#include "frame-unwind.h"
+#include "trad-frame.h"
 #include "value.h"
 #include "arch-utils.h"
 #include "gdb_string.h"
@@ -35,15 +38,6 @@
 
 #include "vax-tdep.h"
 
-static gdbarch_skip_prologue_ftype vax_skip_prologue;
-static gdbarch_frame_num_args_ftype vax_frame_num_args;
-static gdbarch_deprecated_frame_chain_ftype vax_frame_chain;
-
-static gdbarch_deprecated_extract_return_value_ftype vax_extract_return_value;
-
-static gdbarch_deprecated_push_dummy_frame_ftype vax_push_dummy_frame;
-
-
 /* Return the name of register REGNUM.  */
 
 static const char *
@@ -71,111 +65,7 @@ vax_register_type (struct gdbarch *gdbar
   return builtin_type_int;
 }
 
-static void
-vax_frame_init_saved_regs (struct frame_info *frame)
-{
-  int regnum, regmask;
-  CORE_ADDR next_addr;
-
-  if (deprecated_get_frame_saved_regs (frame))
-    return;
-
-  frame_saved_regs_zalloc (frame);
-
-  regmask = read_memory_integer (get_frame_base (frame) + 4, 4) >> 16;
-
-  next_addr = get_frame_base (frame) + 16;
-
-  /* regmask's low bit is for register 0, which is the first one
-     what would be pushed.  */
-  for (regnum = 0; regnum < VAX_AP_REGNUM; regnum++)
-    {
-      if (regmask & (1 << regnum))
-        deprecated_get_frame_saved_regs (frame)[regnum] = next_addr += 4;
-    }
-
-  deprecated_get_frame_saved_regs (frame)[SP_REGNUM] = next_addr + 4;
-  if (regmask & (1 << DEPRECATED_FP_REGNUM))
-    deprecated_get_frame_saved_regs (frame)[SP_REGNUM] +=
-      4 + (4 * read_memory_integer (next_addr + 4, 4));
-
-  deprecated_get_frame_saved_regs (frame)[PC_REGNUM] = get_frame_base (frame) + 16;
-  deprecated_get_frame_saved_regs (frame)[DEPRECATED_FP_REGNUM] = get_frame_base (frame) + 12;
-  deprecated_get_frame_saved_regs (frame)[VAX_AP_REGNUM] = get_frame_base (frame) + 8;
-  deprecated_get_frame_saved_regs (frame)[PS_REGNUM] = get_frame_base (frame) + 4;
-}
-
-/* Get saved user PC for sigtramp from sigcontext for BSD style sigtramp.  */
-
-static CORE_ADDR
-vax_sigtramp_saved_pc (struct frame_info *frame)
-{
-  CORE_ADDR sigcontext_addr;
-  char *buf;
-  int ptrbytes = TYPE_LENGTH (builtin_type_void_func_ptr);
-  int sigcontext_offs = (2 * TARGET_INT_BIT) / TARGET_CHAR_BIT;
-
-  buf = alloca (ptrbytes);
-  /* Get sigcontext address, it is the third parameter on the stack.  */
-  if (get_next_frame (frame))
-    sigcontext_addr = read_memory_typed_address
-      (DEPRECATED_FRAME_ARGS_ADDRESS (get_next_frame (frame))
-       + FRAME_ARGS_SKIP + sigcontext_offs,
-       builtin_type_void_data_ptr);
-  else
-    sigcontext_addr = read_memory_typed_address
-      (read_register (SP_REGNUM) + sigcontext_offs, builtin_type_void_data_ptr);
-
-  /* Offset to saved PC in sigcontext, from <sys/signal.h>.  Don't
-     cause a memory_error when accessing sigcontext in case the stack
-     layout has changed or the stack is corrupt.  */
-  target_read_memory (sigcontext_addr + 12, buf, ptrbytes);
-  return extract_typed_address (buf, builtin_type_void_func_ptr);
-}
-
-static CORE_ADDR
-vax_frame_saved_pc (struct frame_info *frame)
-{
-  if ((get_frame_type (frame) == SIGTRAMP_FRAME))
-    return (vax_sigtramp_saved_pc (frame)); /* XXXJRT */
 
-  return (read_memory_integer (get_frame_base (frame) + 16, 4));
-}
-
-static CORE_ADDR
-vax_frame_args_address (struct frame_info *frame)
-{
-  /* In most of GDB, getting the args address is too important to just
-     say "I don't know".  This is sometimes wrong for functions that
-     aren't on top of the stack, but c'est la vie.  */
-  if (get_next_frame (frame))
-    return (read_memory_integer (get_frame_base (get_next_frame (frame)) + 8, 4));
-  /* Cannot find the AP register value directly from the FP value.
-     Must find it saved in the frame called by this one, or in the AP
-     register for the innermost frame.  However, there is no way to
-     tell the difference between the innermost frame and a frame for
-     which we just don't know the frame that it called (e.g. "info
-     frame 0x7ffec789").  For the sake of argument, suppose that the
-     stack is somewhat trashed (which is one reason that "info frame"
-     exists).  So, return 0 (indicating we don't know the address of
-     the arglist) if we don't know what frame this frame calls.  */
-  return 0;
-}
-
-static int
-vax_frame_num_args (struct frame_info *fi)
-{
-  return (0xff & read_memory_integer (DEPRECATED_FRAME_ARGS_ADDRESS (fi), 1));
-}
-
-static CORE_ADDR
-vax_frame_chain (struct frame_info *frame)
-{
-  /* In the case of the VAX, the frame's nominal address is the FP value,
-     and 12 bytes later comes the saved previous FP value as a 4-byte word.  */
-  return (read_memory_integer (get_frame_base (frame) + 12, 4));
-}
-
 static void
 vax_push_dummy_frame (void)
 {
@@ -186,19 +76,19 @@ vax_push_dummy_frame (void)
   for (regnum = 11; regnum >= 0; regnum--)
     sp = push_word (sp, read_register (regnum));
   sp = push_word (sp, read_register (PC_REGNUM));
-  sp = push_word (sp, read_register (DEPRECATED_FP_REGNUM));
+  sp = push_word (sp, read_register (VAX_FP_REGNUM));
   sp = push_word (sp, read_register (VAX_AP_REGNUM));
   sp = push_word (sp, (read_register (PS_REGNUM) & 0xffef) + 0x2fff0000);
   sp = push_word (sp, 0);
   write_register (SP_REGNUM, sp);
-  write_register (DEPRECATED_FP_REGNUM, sp);
+  write_register (VAX_FP_REGNUM, sp);
   write_register (VAX_AP_REGNUM, sp + (17 * 4));
 }
 
 static void
 vax_pop_frame (void)
 {
-  CORE_ADDR fp = read_register (DEPRECATED_FP_REGNUM);
+  CORE_ADDR fp = read_register (VAX_FP_REGNUM);
   int regnum;
   int regmask = read_memory_integer (fp + 4, 4);
 
@@ -206,7 +96,7 @@ vax_pop_frame (void)
 		  (regmask & 0xffff)
 		  | (read_register (PS_REGNUM) & 0xffff0000));
   write_register (PC_REGNUM, read_memory_integer (fp + 16, 4));
-  write_register (DEPRECATED_FP_REGNUM, read_memory_integer (fp + 12, 4));
+  write_register (VAX_FP_REGNUM, read_memory_integer (fp + 12, 4));
   write_register (VAX_AP_REGNUM, read_memory_integer (fp + 8, 4));
   fp += 16;
   for (regnum = 0; regnum < 12; regnum++)
@@ -302,13 +192,169 @@ vax_skip_prologue (CORE_ADDR pc)
     pc += 7;			/* skip movab */
   return pc;
 }
+
+
+/* Unwinding the stack is relatively easy since the VAX has a
+   dedicated frame pointer, and frames are set up automatically as the
+   result of a function call.  Most of the relevant information can be
+   inferred from the documentation of the Procedure Call Instructions
+   in the VAX MACRO and Instruction Set Reference Manual.  */
+
+struct vax_frame_cache
+{
+  /* Base address.  */
+  CORE_ADDR base;
+
+  /* Table of saved registers.  */
+  struct trad_frame_saved_reg *saved_regs;
+};
+
+struct vax_frame_cache *
+vax_frame_cache (struct frame_info *next_frame, void **this_cache)
+{
+  struct vax_frame_cache *cache;
+  CORE_ADDR addr;
+  ULONGEST mask;
+  int regnum;
+
+  if (*this_cache)
+    return *this_cache;
+
+  /* Allocate a new cache.  */
+  cache = FRAME_OBSTACK_ZALLOC (struct vax_frame_cache);
+  cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
+
+  /* The frame pointer is used as the base for the frame.  */
+  cache->base = frame_unwind_register_unsigned (next_frame, VAX_FP_REGNUM);
+  if (cache->base == 0)
+    return cache;
+
+  /* The register save mask and control bits determine the layout of
+     the stack frame.  */
+  mask = get_frame_memory_unsigned (next_frame, cache->base + 4, 4) >> 16;
+
+  /* These are always saved.  */
+  cache->saved_regs[VAX_PC_REGNUM].addr = cache->base + 16;
+  cache->saved_regs[VAX_FP_REGNUM].addr = cache->base + 12;
+  cache->saved_regs[VAX_AP_REGNUM].addr = cache->base + 8;
+  cache->saved_regs[VAX_PS_REGNUM].addr = cache->base + 4;
+
+  /* Scan the register save mask and record the location of the saved
+     registers.  */
+  addr = cache->base + 20;
+  for (regnum = 0; regnum < VAX_AP_REGNUM; regnum++)
+    {
+      if (mask & (1 << regnum))
+	{
+	  cache->saved_regs[regnum].addr = addr;
+	  addr += 4;
+	}
+    }
+
+  /* The CALLS/CALLG flag determines whether this frame has a General
+     Argument List or a Stack Argument List.  */
+  if (mask & (1 << 13))
+    {
+      ULONGEST numarg;
+
+      /* This is a procedure with Stack Argument List.  Adjust the
+         stack address for the arguments thet were pushed onto the
+         stack.  The return instruction will automatically pop the
+         arguments from the stack.  */
+      numarg = get_frame_memory_unsigned (next_frame, addr, 1);
+      addr += 4 + numarg * 4;
+    }
+
+  /* Bits 1:0 of the stack pointer were saved in the control bits.  */
+  trad_frame_set_value (cache->saved_regs, VAX_SP_REGNUM, addr + (mask >> 14));
+
+  return cache;
+}
+
+static void
+vax_frame_this_id (struct frame_info *next_frame, void **this_cache,
+		   struct frame_id *this_id)
+{
+  struct vax_frame_cache *cache = vax_frame_cache (next_frame, this_cache);
+
+  /* This marks the outermost frame.  */
+  if (cache->base == 0)
+    return;
+
+  (*this_id) = frame_id_build (cache->base, frame_pc_unwind (next_frame));
+}
+
+static void
+vax_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 vax_frame_cache *cache = vax_frame_cache (next_frame, this_cache);
+
+  trad_frame_prev_register (next_frame, cache->saved_regs, regnum,
+			    optimizedp, lvalp, addrp, realnump, valuep);
+}
+
+static const struct frame_unwind vax_frame_unwind =
+{
+  NORMAL_FRAME,
+  vax_frame_this_id,
+  vax_frame_prev_register
+};
+
+static const struct frame_unwind *
+vax_frame_sniffer (struct frame_info *next_frame)
+{
+  return &vax_frame_unwind;
+}
+
 
 static CORE_ADDR
-vax_saved_pc_after_call (struct frame_info *frame)
+vax_frame_base_address (struct frame_info *next_frame, void **this_cache)
 {
-  return (DEPRECATED_FRAME_SAVED_PC(frame));
+  struct vax_frame_cache *cache = vax_frame_cache (next_frame, this_cache);
+
+  return cache->base;
+}
+
+static CORE_ADDR
+vax_frame_args_address (struct frame_info *next_frame, void **this_cache)
+{
+  return frame_unwind_register_unsigned (next_frame, VAX_AP_REGNUM);
+}
+
+static const struct frame_base vax_frame_base =
+{
+  &vax_frame_unwind,
+  vax_frame_base_address,
+  vax_frame_base_address,
+  vax_frame_args_address
+};
+
+/* Return number of arguments for FRAME.  */
+
+static int
+vax_frame_num_args (struct frame_info *frame)
+{
+  CORE_ADDR args;
+
+  /* Assume that the argument pointer for the outermost frame is
+     hosed, as is the case on NetBSD/vax ELF.  */
+  if (get_frame_base (frame) == 0)
+    return 0;
+
+  args = get_frame_register_unsigned (frame, VAX_AP_REGNUM);
+  return get_frame_memory_unsigned (frame, args, 1);
+}
+
+static CORE_ADDR
+vax_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
+{
+  return frame_unwind_register_unsigned (next_frame, VAX_PC_REGNUM);
 }
 
+
 /* 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.
@@ -328,32 +374,18 @@ vax_gdbarch_init (struct gdbarch_info in
 
   gdbarch = gdbarch_alloc (&info, NULL);
 
-  /* NOTE: cagney/2002-12-06: This can be deleted when this arch is
-     ready to unwind the PC first (see frame.c:get_prev_frame()).  */
-  set_gdbarch_deprecated_init_frame_pc (gdbarch, deprecated_init_frame_pc_default);
-
   /* Register info */
   set_gdbarch_num_regs (gdbarch, VAX_NUM_REGS);
   set_gdbarch_register_name (gdbarch, vax_register_name);
   set_gdbarch_register_type (gdbarch, vax_register_type);
   set_gdbarch_sp_regnum (gdbarch, VAX_SP_REGNUM);
-  set_gdbarch_deprecated_fp_regnum (gdbarch, VAX_FP_REGNUM);
   set_gdbarch_pc_regnum (gdbarch, VAX_PC_REGNUM);
   set_gdbarch_ps_regnum (gdbarch, VAX_PS_REGNUM);
 
   /* Frame and stack info */
   set_gdbarch_skip_prologue (gdbarch, vax_skip_prologue);
-  set_gdbarch_deprecated_saved_pc_after_call (gdbarch, vax_saved_pc_after_call);
-
   set_gdbarch_frame_num_args (gdbarch, vax_frame_num_args);
 
-  set_gdbarch_deprecated_frame_chain (gdbarch, vax_frame_chain);
-  set_gdbarch_deprecated_frame_saved_pc (gdbarch, vax_frame_saved_pc);
-
-  set_gdbarch_deprecated_frame_args_address (gdbarch, vax_frame_args_address);
-
-  set_gdbarch_deprecated_frame_init_saved_regs (gdbarch, vax_frame_init_saved_regs);
-
   set_gdbarch_frame_args_skip (gdbarch, 4);
 
   /* Stack grows downward.  */
@@ -385,8 +417,14 @@ vax_gdbarch_init (struct gdbarch_info in
   /* Should be using push_dummy_call.  */
   set_gdbarch_deprecated_dummy_write_sp (gdbarch, deprecated_write_sp);
 
+  set_gdbarch_unwind_pc (gdbarch, vax_unwind_pc);
+
+  frame_base_set_default (gdbarch, &vax_frame_base);
+
   /* Hook in ABI-specific overrides, if they have been registered.  */
   gdbarch_init_osabi (info, gdbarch);
+
+  frame_unwind_append_sniffer (gdbarch, vax_frame_sniffer);
 
   set_gdbarch_print_insn (gdbarch, print_insn_vax);
 


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