* 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.
This commit is contained in:
Mark Kettenis 2004-04-12 19:49:48 +00:00
parent 53284fc17d
commit 7def7fef04
3 changed files with 204 additions and 136 deletions

View 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.

View 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) \

View 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"
@ -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 *gdbarch, int regnum)
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;
}
static CORE_ADDR
vax_saved_pc_after_call (struct frame_info *frame)
/* 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
{
return (DEPRECATED_FRAME_SAVED_PC(frame));
/* 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_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_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 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);