From 7def7fef04cd4b79b5292c6a6321902abe2367d4 Mon Sep 17 00:00:00 2001 From: Mark Kettenis Date: Mon, 12 Apr 2004 19:49:48 +0000 Subject: * 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. --- gdb/vax-tdep.c | 304 ++++++++++++++++++++++++++++++++------------------------- 1 file changed, 171 insertions(+), 133 deletions(-) (limited to 'gdb/vax-tdep.c') diff --git a/gdb/vax-tdep.c b/gdb/vax-tdep.c index cf2f86c..4aacfdf 100644 --- a/gdb/vax-tdep.c +++ b/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 . 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_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); } + /* 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); -- cgit v1.1