* 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:
parent
53284fc17d
commit
7def7fef04
3 changed files with 204 additions and 136 deletions
|
@ -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.
|
||||
|
|
|
@ -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) \
|
||||
|
|
306
gdb/vax-tdep.c
306
gdb/vax-tdep.c
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue