* vax-tdep.c: Include "frame-base.h", "frame-unwind.h" and
authorMark Kettenis <kettenis@gnu.org>
Mon, 12 Apr 2004 19:49:48 +0000 (19:49 +0000)
committerMark Kettenis <kettenis@gnu.org>
Mon, 12 Apr 2004 19:49:48 +0000 (19:49 +0000)
"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.

gdb/ChangeLog
gdb/Makefile.in
gdb/vax-tdep.c

index d4ff9f4caaf94a344f4a00768c6e8c8427561bca..58ce1bc99ca0ec065ca6f5c77ba3c0b1adebe91b 100644 (file)
@@ -1,5 +1,34 @@
 2004-04-12  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.
+
        * vaxbsd-nat.c: New file.
 
        * vax-tdep.h: Update copyright year.  Adjust comments.
index fd182606e7009535152a4f94ae89909318e8755d..78db6736b4575259c63e97882172691445588d5d 100644 (file)
@@ -2492,8 +2492,9 @@ values.o: values.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
 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 cf2f86c8a641111a2fe6e02b759644ec8858f0c4..4aacfdf918c3dd66e15b3090145629769648f8f0 100644 (file)
@@ -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"
 
 #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;
-\f
-
 /* Return the name of register REGNUM.  */
 
 static const char *
@@ -71,111 +65,7 @@ vax_register_type (struct gdbarch *gdbarch, int regnum)
   return builtin_type_int;
 }
 \f
-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));
-}
-\f
 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;
 }
+\f
+
+/* 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;
+}
+\f
+
+static CORE_ADDR
+vax_frame_base_address (struct frame_info *next_frame, void **this_cache)
+{
+  struct vax_frame_cache *cache = vax_frame_cache (next_frame, this_cache);
+
+  return cache->base;
+}
 
 static CORE_ADDR
-vax_saved_pc_after_call (struct frame_info *frame)
+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 =
 {
-  return (DEPRECATED_FRAME_SAVED_PC(frame));
+  &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);
 }
 \f
+
 /* 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 info, struct gdbarch_list *arches)
 
   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,9 +417,15 @@ vax_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   /* 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);
 
   return (gdbarch);