X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Falpha-tdep.c;h=f3ba0eb3e83616417a06c4f11ec0dd866d4b9488;hb=03165292c0383a5bcaf2230b82683d74140cb381;hp=81061d35ae677cc9c79a0e33cfd0c45359e03d8f;hpb=0434c1a0c91e92d7a73affd5332583266b20b158;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/alpha-tdep.c b/gdb/alpha-tdep.c index 81061d35ae..f3ba0eb3e8 100644 --- a/gdb/alpha-tdep.c +++ b/gdb/alpha-tdep.c @@ -1,5 +1,5 @@ /* Target-dependent code for the ALPHA architecture, for GDB, the GNU Debugger. - Copyright 1993, 1994 Free Software Foundation, Inc. + Copyright 1993, 1994, 1995 Free Software Foundation, Inc. This file is part of GDB. @@ -15,7 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "defs.h" #include "frame.h" @@ -25,31 +25,41 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "gdbcmd.h" #include "gdbcore.h" #include "dis-asm.h" +#include "symfile.h" +#include "objfiles.h" +#include "gdb_string.h" /* FIXME: Some of this code should perhaps be merged with mips-tdep.c. */ -#define VM_MIN_ADDRESS (CORE_ADDR)0x120000000 +/* FIXME: Put this declaration in frame.h. */ +extern struct obstack frame_cache_obstack; /* Forward declarations. */ -static CORE_ADDR -read_next_frame_reg PARAMS ((FRAME, int)); +static CORE_ADDR read_next_frame_reg PARAMS ((struct frame_info *, int)); -static CORE_ADDR -heuristic_proc_start PARAMS ((CORE_ADDR)); +static CORE_ADDR heuristic_proc_start PARAMS ((CORE_ADDR)); -static alpha_extra_func_info_t -heuristic_proc_desc PARAMS ((CORE_ADDR, CORE_ADDR, FRAME)); +static alpha_extra_func_info_t heuristic_proc_desc PARAMS ((CORE_ADDR, + CORE_ADDR, + struct frame_info *)); -static alpha_extra_func_info_t -find_proc_desc PARAMS ((CORE_ADDR, FRAME)); +static alpha_extra_func_info_t find_proc_desc PARAMS ((CORE_ADDR, + struct frame_info *)); -static int -alpha_in_lenient_prologue PARAMS ((CORE_ADDR, CORE_ADDR)); +#if 0 +static int alpha_in_lenient_prologue PARAMS ((CORE_ADDR, CORE_ADDR)); +#endif -static void -reinit_frame_cache_sfunc PARAMS ((char *, int, struct cmd_list_element *)); +static void reinit_frame_cache_sfunc PARAMS ((char *, int, + struct cmd_list_element *)); + +static CORE_ADDR after_prologue PARAMS ((CORE_ADDR pc, + alpha_extra_func_info_t proc_desc)); + +static int in_prologue PARAMS ((CORE_ADDR pc, + alpha_extra_func_info_t proc_desc)); /* Heuristic_proc_start may hunt through the text section for a long time across a 2400 baud serial line. Allows the user to limit this @@ -122,53 +132,135 @@ struct linked_proc_info } *linked_proc_desc_table = NULL; -#define READ_FRAME_REG(fi, regno) read_next_frame_reg((fi)->next, regno) +/* Guaranteed to set fci->saved_regs to some values (it never leaves it + NULL). */ -static CORE_ADDR -read_next_frame_reg(fi, regno) - FRAME fi; - int regno; +void +alpha_find_saved_regs (frame) + struct frame_info *frame; { - /* If it is the frame for sigtramp we have a pointer to the sigcontext - on the stack. - If the stack layout for __sigtramp changes or if sigcontext offsets - change we might have to update this code. */ + int ireg; + CORE_ADDR reg_position; + unsigned long mask; + alpha_extra_func_info_t proc_desc; + int returnreg; + + frame->saved_regs = (struct frame_saved_regs *) + obstack_alloc (&frame_cache_obstack, sizeof(struct frame_saved_regs)); + memset (frame->saved_regs, 0, sizeof (struct frame_saved_regs)); + + /* If it is the frame for __sigtramp, the saved registers are located + in a sigcontext structure somewhere on the stack. __sigtramp + passes a pointer to the sigcontext structure on the stack. + If the stack layout for __sigtramp changes, or if sigcontext offsets + change, we might have to update this code. */ #ifndef SIGFRAME_PC_OFF #define SIGFRAME_PC_OFF (2 * 8) #define SIGFRAME_REGSAVE_OFF (4 * 8) +#define SIGFRAME_FPREGSAVE_OFF (SIGFRAME_REGSAVE_OFF + 32 * 8 + 8) #endif - for (; fi; fi = fi->next) + if (frame->signal_handler_caller) { - if (fi->signal_handler_caller) + CORE_ADDR sigcontext_pointer_addr; + CORE_ADDR sigcontext_addr; + + if (frame->next) + sigcontext_pointer_addr = frame->next->frame; + else + sigcontext_pointer_addr = frame->frame; + sigcontext_addr = read_memory_integer(sigcontext_pointer_addr, 8); + for (ireg = 0; ireg < 32; ireg++) + { + reg_position = sigcontext_addr + SIGFRAME_REGSAVE_OFF + ireg * 8; + frame->saved_regs->regs[ireg] = reg_position; + } + for (ireg = 0; ireg < 32; ireg++) { - int offset; - CORE_ADDR sigcontext_addr = read_memory_integer(fi->frame, 8); - - if (regno == PC_REGNUM) - offset = SIGFRAME_PC_OFF; - else if (regno < 32) - offset = SIGFRAME_REGSAVE_OFF + regno * 8; - else - return 0; - return read_memory_integer(sigcontext_addr + offset, 8); - } - else if (regno == SP_REGNUM) + reg_position = sigcontext_addr + SIGFRAME_FPREGSAVE_OFF + ireg * 8; + frame->saved_regs->regs[FP0_REGNUM + ireg] = reg_position; + } + frame->saved_regs->regs[PC_REGNUM] = sigcontext_addr + SIGFRAME_PC_OFF; + return; + } + + proc_desc = frame->proc_desc; + if (proc_desc == NULL) + /* I'm not sure how/whether this can happen. Normally when we can't + find a proc_desc, we "synthesize" one using heuristic_proc_desc + and set the saved_regs right away. */ + return; + + /* Fill in the offsets for the registers which gen_mask says + were saved. */ + + reg_position = frame->frame + PROC_REG_OFFSET (proc_desc); + mask = PROC_REG_MASK (proc_desc); + + returnreg = PROC_PC_REG (proc_desc); + + /* Note that RA is always saved first, regardless of its actual + register number. */ + if (mask & (1 << returnreg)) + { + frame->saved_regs->regs[returnreg] = reg_position; + reg_position += 8; + mask &= ~(1 << returnreg); /* Clear bit for RA so we + don't save again later. */ + } + + for (ireg = 0; ireg <= 31 ; ++ireg) + if (mask & (1 << ireg)) + { + frame->saved_regs->regs[ireg] = reg_position; + reg_position += 8; + } + + /* Fill in the offsets for the registers which float_mask says + were saved. */ + + reg_position = frame->frame + PROC_FREG_OFFSET (proc_desc); + mask = PROC_FREG_MASK (proc_desc); + + for (ireg = 0; ireg <= 31 ; ++ireg) + if (mask & (1 << ireg)) + { + frame->saved_regs->regs[FP0_REGNUM+ireg] = reg_position; + reg_position += 8; + } + + frame->saved_regs->regs[PC_REGNUM] = frame->saved_regs->regs[returnreg]; +} + +static CORE_ADDR +read_next_frame_reg(fi, regno) + struct frame_info *fi; + int regno; +{ + for (; fi; fi = fi->next) + { + /* We have to get the saved sp from the sigcontext + if it is a signal handler frame. */ + if (regno == SP_REGNUM && !fi->signal_handler_caller) return fi->frame; - else if (fi->saved_regs->regs[regno]) - return read_memory_integer(fi->saved_regs->regs[regno], 8); + else + { + if (fi->saved_regs == NULL) + alpha_find_saved_regs (fi); + if (fi->saved_regs->regs[regno]) + return read_memory_integer(fi->saved_regs->regs[regno], 8); + } } return read_register(regno); } CORE_ADDR alpha_frame_saved_pc(frame) - FRAME frame; + struct frame_info *frame; { alpha_extra_func_info_t proc_desc = frame->proc_desc; /* We have to get the saved pc from the sigcontext if it is a signal handler frame. */ - int pcreg = frame->signal_handler_caller ? PC_REGNUM - : (proc_desc ? PROC_PC_REG(proc_desc) : RA_REGNUM); + int pcreg = frame->signal_handler_caller ? PC_REGNUM : frame->pc_reg; if (proc_desc && PROC_DESC_IS_DUMMY(proc_desc)) return read_memory_integer(frame->frame - 8, 8); @@ -178,10 +270,20 @@ alpha_frame_saved_pc(frame) CORE_ADDR alpha_saved_pc_after_call (frame) - FRAME frame; + struct frame_info *frame; { - alpha_extra_func_info_t proc_desc = find_proc_desc (frame->pc, frame->next); - int pcreg = proc_desc ? PROC_PC_REG (proc_desc) : RA_REGNUM; + CORE_ADDR pc = frame->pc; + CORE_ADDR tmp; + alpha_extra_func_info_t proc_desc; + int pcreg; + + /* Skip over shared library trampoline if necessary. */ + tmp = SKIP_TRAMPOLINE_CODE (pc); + if (tmp != 0) + pc = tmp; + + proc_desc = find_proc_desc (pc, frame->next); + pcreg = proc_desc ? PROC_PC_REG (proc_desc) : RA_REGNUM; return read_register (pcreg); } @@ -250,9 +352,9 @@ Otherwise, you told GDB there was a function where there isn't one, or\n\ static alpha_extra_func_info_t heuristic_proc_desc(start_pc, limit_pc, next_frame) CORE_ADDR start_pc, limit_pc; - FRAME next_frame; + struct frame_info *next_frame; { - CORE_ADDR sp = next_frame ? next_frame->frame : read_register (SP_REGNUM); + CORE_ADDR sp = read_next_frame_reg (next_frame, SP_REGNUM); CORE_ADDR cur_pc; int frame_size; int has_frame_reg = 0; @@ -260,9 +362,9 @@ heuristic_proc_desc(start_pc, limit_pc, next_frame) if (start_pc == 0) return NULL; - memset(&temp_proc_desc, '\0', sizeof(temp_proc_desc)); - memset(&temp_saved_regs, '\0', sizeof(struct frame_saved_regs)); - PROC_LOW_ADDR(&temp_proc_desc) = start_pc; + memset (&temp_proc_desc, '\0', sizeof(temp_proc_desc)); + memset (&temp_saved_regs, '\0', sizeof(struct frame_saved_regs)); + PROC_LOW_ADDR (&temp_proc_desc) = start_pc; if (start_pc + 200 < limit_pc) limit_pc = start_pc + 200; @@ -297,13 +399,70 @@ heuristic_proc_desc(start_pc, limit_pc, next_frame) PROC_FRAME_OFFSET(&temp_proc_desc) = frame_size; PROC_REG_MASK(&temp_proc_desc) = reg_mask; PROC_PC_REG(&temp_proc_desc) = RA_REGNUM; + PROC_LOCALOFF(&temp_proc_desc) = 0; /* XXX - bogus */ return &temp_proc_desc; } +/* This returns the PC of the first inst after the prologue. If we can't + find the prologue, then return 0. */ + +static CORE_ADDR +after_prologue (pc, proc_desc) + CORE_ADDR pc; + alpha_extra_func_info_t proc_desc; +{ + struct symtab_and_line sal; + CORE_ADDR func_addr, func_end; + + if (!proc_desc) + proc_desc = find_proc_desc (pc, NULL); + + if (proc_desc) + { + /* If function is frameless, then we need to do it the hard way. I + strongly suspect that frameless always means prologueless... */ + if (PROC_FRAME_REG (proc_desc) == SP_REGNUM + && PROC_FRAME_OFFSET (proc_desc) == 0) + return 0; + } + + if (!find_pc_partial_function (pc, NULL, &func_addr, &func_end)) + return 0; /* Unknown */ + + sal = find_pc_line (func_addr, 0); + + if (sal.end < func_end) + return sal.end; + + /* The line after the prologue is after the end of the function. In this + case, tell the caller to find the prologue the hard way. */ + + return 0; +} + +/* Return non-zero if we *might* be in a function prologue. Return zero if we + are definatly *not* in a function prologue. */ + +static int +in_prologue (pc, proc_desc) + CORE_ADDR pc; + alpha_extra_func_info_t proc_desc; +{ + CORE_ADDR after_prologue_pc; + + after_prologue_pc = after_prologue (pc, proc_desc); + + if (after_prologue_pc == 0 + || pc < after_prologue_pc) + return 1; + else + return 0; +} + static alpha_extra_func_info_t -find_proc_desc(pc, next_frame) +find_proc_desc (pc, next_frame) CORE_ADDR pc; - FRAME next_frame; + struct frame_info *next_frame; { alpha_extra_func_info_t proc_desc; struct block *b; @@ -317,10 +476,11 @@ find_proc_desc(pc, next_frame) as it will be contained in the proc_desc we are searching for. So we have to find the proc_desc whose frame is closest to the current stack pointer. */ + if (PC_IN_CALL_DUMMY (pc, 0, 0)) { struct linked_proc_info *link; - CORE_ADDR sp = next_frame ? next_frame->frame : read_register (SP_REGNUM); + CORE_ADDR sp = read_next_frame_reg (next_frame, SP_REGNUM); alpha_extra_func_info_t found_proc_desc = NULL; long min_distance = LONG_MAX; @@ -338,6 +498,7 @@ find_proc_desc(pc, next_frame) } b = block_for_pc(pc); + find_pc_partial_function (pc, NULL, &startaddr, NULL); if (b == NULL) sym = NULL; @@ -353,47 +514,50 @@ find_proc_desc(pc, next_frame) 0, NULL); } + /* If we never found a PDR for this function in symbol reading, then + examine prologues to find the information. */ + if (sym && ((mips_extra_func_info_t) SYMBOL_VALUE (sym))->pdr.framereg == -1) + sym = NULL; + if (sym) { - /* IF (this is the topmost frame OR a frame interrupted by a signal) - * AND (this proc does not have debugging information OR + /* IF this is the topmost frame AND + * (this proc does not have debugging information OR * the PC is in the procedure prologue) * THEN create a "heuristic" proc_desc (by analyzing * the actual code) to replace the "official" proc_desc. */ proc_desc = (alpha_extra_func_info_t)SYMBOL_VALUE(sym); - if (next_frame == NULL || next_frame->signal_handler_caller) { - struct symtab_and_line val; - struct symbol *proc_symbol = - PROC_DESC_IS_DUMMY(proc_desc) ? 0 : PROC_SYMBOL(proc_desc); - - if (proc_symbol) { - val = find_pc_line (BLOCK_START - (SYMBOL_BLOCK_VALUE(proc_symbol)), - 0); - val.pc = val.end ? val.end : pc; - } - if (!proc_symbol || pc < val.pc) { + if (next_frame == NULL) + { + if (PROC_DESC_IS_DUMMY (proc_desc) || in_prologue (pc, proc_desc)) + { alpha_extra_func_info_t found_heuristic = - heuristic_proc_desc(PROC_LOW_ADDR(proc_desc), - pc, next_frame); + heuristic_proc_desc (PROC_LOW_ADDR (proc_desc), + pc, next_frame); if (found_heuristic) { - /* The call to heuristic_proc_desc determines - which registers have been saved so far and if the - frame is already set up. - The heuristic algorithm doesn't work well for other - information in the procedure descriptor, so copy - it from the found procedure descriptor. */ - PROC_LOCALOFF(found_heuristic) = PROC_LOCALOFF(proc_desc); - PROC_PC_REG(found_heuristic) = PROC_PC_REG(proc_desc); + PROC_LOCALOFF (found_heuristic) = + PROC_LOCALOFF (proc_desc); + PROC_PC_REG (found_heuristic) = PROC_PC_REG (proc_desc); proc_desc = found_heuristic; } - } - } + } + } } else { + /* Is linked_proc_desc_table really necessary? It only seems to be used + by procedure call dummys. However, the procedures being called ought + to have their own proc_descs, and even if they don't, + heuristic_proc_desc knows how to create them! */ + + register struct linked_proc_info *link; + for (link = linked_proc_desc_table; link; link = link->next) + if (PROC_LOW_ADDR(&link->info) <= pc + && PROC_HIGH_ADDR(&link->info) > pc) + return &link->info; + if (startaddr == 0) startaddr = heuristic_proc_start (pc); @@ -405,9 +569,9 @@ find_proc_desc(pc, next_frame) alpha_extra_func_info_t cached_proc_desc; -FRAME_ADDR +CORE_ADDR alpha_frame_chain(frame) - FRAME frame; + struct frame_info *frame; { alpha_extra_func_info_t proc_desc; CORE_ADDR saved_pc = FRAME_SAVED_PC(frame); @@ -424,7 +588,7 @@ alpha_frame_chain(frame) /* Fetch the frame pointer for a dummy frame from the procedure descriptor. */ if (PROC_DESC_IS_DUMMY(proc_desc)) - return (FRAME_ADDR) PROC_DUMMY_FRAME(proc_desc); + return (CORE_ADDR) PROC_DUMMY_FRAME(proc_desc); /* If no frame pointer and frame size is zero, we must be at end of stack (or otherwise hosed). If we don't check frame size, @@ -451,107 +615,49 @@ alpha_frame_chain(frame) } void -init_extra_frame_info(fci) - struct frame_info *fci; +init_extra_frame_info (frame) + struct frame_info *frame; { - extern struct obstack frame_cache_obstack; /* Use proc_desc calculated in frame_chain */ alpha_extra_func_info_t proc_desc = - fci->next ? cached_proc_desc : find_proc_desc(fci->pc, fci->next); + frame->next ? cached_proc_desc : find_proc_desc(frame->pc, frame->next); - fci->saved_regs = (struct frame_saved_regs*) - obstack_alloc (&frame_cache_obstack, sizeof(struct frame_saved_regs)); - memset (fci->saved_regs, 0, sizeof (struct frame_saved_regs)); - fci->proc_desc = - proc_desc == &temp_proc_desc ? 0 : proc_desc; + frame->saved_regs = NULL; + frame->localoff = 0; + frame->pc_reg = RA_REGNUM; + frame->proc_desc = proc_desc == &temp_proc_desc ? 0 : proc_desc; if (proc_desc) { - int ireg; - CORE_ADDR reg_position; - unsigned long mask; - int returnreg; - - /* Get the locals offset from the procedure descriptor, it is valid - even if we are in the middle of the prologue. */ - fci->localoff = PROC_LOCALOFF(proc_desc); + /* Get the locals offset and the saved pc register from the + procedure descriptor, they are valid even if we are in the + middle of the prologue. */ + frame->localoff = PROC_LOCALOFF(proc_desc); + frame->pc_reg = PROC_PC_REG(proc_desc); /* Fixup frame-pointer - only needed for top frame */ + /* Fetch the frame pointer for a dummy frame from the procedure descriptor. */ if (PROC_DESC_IS_DUMMY(proc_desc)) - fci->frame = (FRAME_ADDR) PROC_DUMMY_FRAME(proc_desc); + frame->frame = (CORE_ADDR) PROC_DUMMY_FRAME(proc_desc); + /* This may not be quite right, if proc has a real frame register. Get the value of the frame relative sp, procedure might have been interrupted by a signal at it's very start. */ - else if (fci->pc == PROC_LOW_ADDR(proc_desc)) - fci->frame = READ_FRAME_REG(fci, SP_REGNUM); + else if (frame->pc == PROC_LOW_ADDR (proc_desc) && !PROC_DESC_IS_DUMMY (proc_desc)) + frame->frame = read_next_frame_reg (frame->next, SP_REGNUM); else - fci->frame = READ_FRAME_REG(fci, PROC_FRAME_REG(proc_desc)) - + PROC_FRAME_OFFSET(proc_desc); - - /* If this is the innermost frame, and we are still in the - prologue (loosely defined), then the registers may not have - been saved yet. */ - if (fci->next == NULL - && !PROC_DESC_IS_DUMMY(proc_desc) - && alpha_in_lenient_prologue (PROC_LOW_ADDR (proc_desc), fci->pc)) - { - /* Can't just say that the registers are not saved, because they - might get clobbered halfway through the prologue. - heuristic_proc_desc already has the right code to figure out - exactly what has been saved, so use it. As far as I know we - could be doing this (as we do on the 68k, for example) - regardless of whether we are in the prologue; I'm leaving in - the check for being in the prologue only out of conservatism - (I'm not sure whether heuristic_proc_desc handles all cases, - for example). - - This stuff is ugly (and getting uglier by the minute). Probably - the best way to clean it up is to ignore the proc_desc's from - the symbols altogher, and get all the information we need by - examining the prologue (provided we can make the prologue - examining code good enough to get all the cases...). */ - proc_desc = - heuristic_proc_desc (PROC_LOW_ADDR (proc_desc), - fci->pc, - fci->next); - } + frame->frame = read_next_frame_reg (frame->next, PROC_FRAME_REG (proc_desc)) + + PROC_FRAME_OFFSET (proc_desc); if (proc_desc == &temp_proc_desc) - *fci->saved_regs = temp_saved_regs; - else { - /* Find which general-purpose registers were saved. - The return address register is the first saved register, - the other registers follow in ascending order. */ - reg_position = fci->frame + PROC_REG_OFFSET(proc_desc); - mask = PROC_REG_MASK(proc_desc) & 0xffffffffL; - returnreg = PROC_PC_REG(proc_desc); - if (mask & (1 << returnreg)) - { - fci->saved_regs->regs[returnreg] = reg_position; - reg_position += 8; - } - for (ireg = 0; mask; ireg++, mask >>= 1) - if (mask & 1) - { - if (ireg == returnreg) - continue; - fci->saved_regs->regs[ireg] = reg_position; - reg_position += 8; - } - /* find which floating-point registers were saved */ - reg_position = fci->frame + PROC_FREG_OFFSET(proc_desc); - mask = PROC_FREG_MASK(proc_desc) & 0xffffffffL; - for (ireg = 0; mask; ireg++, mask >>= 1) - if (mask & 1) - { - fci->saved_regs->regs[FP0_REGNUM+ireg] = reg_position; - reg_position += 8; - } + frame->saved_regs = (struct frame_saved_regs*) + obstack_alloc (&frame_cache_obstack, + sizeof (struct frame_saved_regs)); + *frame->saved_regs = temp_saved_regs; + frame->saved_regs->regs[PC_REGNUM] = frame->saved_regs->regs[RA_REGNUM]; } - - fci->saved_regs->regs[PC_REGNUM] = fci->saved_regs->regs[PROC_PC_REG(proc_desc)]; } } @@ -570,10 +676,10 @@ init_extra_frame_info(fci) cache. This allows the rest of info frame to extract the important arguments without difficulty. */ -FRAME +struct frame_info * setup_arbitrary_frame (argc, argv) int argc; - FRAME_ADDR *argv; + CORE_ADDR *argv; { if (argc != 2) error ("ALPHA frame specifications require two arguments: sp and pc"); @@ -593,11 +699,11 @@ setup_arbitrary_frame (argc, argv) CORE_ADDR alpha_push_arguments (nargs, args, sp, struct_return, struct_addr) - int nargs; - value *args; - CORE_ADDR sp; - int struct_return; - CORE_ADDR struct_addr; + int nargs; + value_ptr *args; + CORE_ADDR sp; + int struct_return; + CORE_ADDR struct_addr; { register i; int accumulate_size = struct_return ? 8 : 0; @@ -611,10 +717,21 @@ alpha_push_arguments (nargs, args, sp, struct_return, struct_addr) for (i = 0, m_arg = alpha_args; i < nargs; i++, m_arg++) { - value arg = value_arg_coerce (args[i]); + value_ptr arg = args[i]; /* Cast argument to long if necessary as the compiler does it too. */ - if (TYPE_LENGTH (VALUE_TYPE (arg)) < TYPE_LENGTH (builtin_type_long)) - arg = value_cast (builtin_type_long, arg); + switch (TYPE_CODE (VALUE_TYPE (arg))) + { + case TYPE_CODE_INT: + case TYPE_CODE_BOOL: + case TYPE_CODE_CHAR: + case TYPE_CODE_RANGE: + case TYPE_CODE_ENUM: + if (TYPE_LENGTH (VALUE_TYPE (arg)) < TYPE_LENGTH (builtin_type_long)) + arg = value_cast (builtin_type_long, arg); + break; + default: + break; + } m_arg->len = TYPE_LENGTH (VALUE_TYPE (arg)); m_arg->offset = accumulate_size; accumulate_size = (accumulate_size + m_arg->len + 7) & ~7; @@ -661,16 +778,18 @@ void alpha_push_dummy_frame() { int ireg; - struct linked_proc_info *link = (struct linked_proc_info*) - xmalloc(sizeof (struct linked_proc_info)); - alpha_extra_func_info_t proc_desc = &link->info; + struct linked_proc_info *link; + alpha_extra_func_info_t proc_desc; CORE_ADDR sp = read_register (SP_REGNUM); CORE_ADDR save_address; char raw_buffer[MAX_REGISTER_RAW_SIZE]; unsigned long mask; + link = (struct linked_proc_info *) xmalloc(sizeof (struct linked_proc_info)); link->next = linked_proc_desc_table; linked_proc_desc_table = link; + + proc_desc = &link->info; /* * The registers we must save are all those not preserved across @@ -764,7 +883,7 @@ alpha_push_dummy_frame() sp += PROC_REG_OFFSET(proc_desc); write_register (SP_REGNUM, sp); - PROC_LOW_ADDR(proc_desc) = entry_point_address (); + PROC_LOW_ADDR(proc_desc) = CALL_DUMMY_ADDRESS (); PROC_HIGH_ADDR(proc_desc) = PROC_LOW_ADDR(proc_desc) + 4; SET_PROC_DESC_IS_DUMMY(proc_desc); @@ -775,12 +894,14 @@ void alpha_pop_frame() { register int regnum; - FRAME frame = get_current_frame (); + struct frame_info *frame = get_current_frame (); CORE_ADDR new_sp = frame->frame; alpha_extra_func_info_t proc_desc = frame->proc_desc; write_register (PC_REGNUM, FRAME_SAVED_PC(frame)); + if (frame->saved_regs == NULL) + alpha_find_saved_regs (frame); if (proc_desc) { for (regnum = 32; --regnum >= 0; ) @@ -795,8 +916,6 @@ alpha_pop_frame() } write_register (SP_REGNUM, new_sp); flush_cached_frames (); - /* We let init_extra_frame_info figure out the frame pointer */ - set_current_frame (create_new_frame (0, read_pc ())); if (proc_desc && PROC_DESC_IS_DUMMY(proc_desc)) { @@ -838,13 +957,37 @@ alpha_skip_prologue (pc, lenient) { unsigned long inst; int offset; + CORE_ADDR post_prologue_pc; + char buf[4]; + +#ifdef GDB_TARGET_HAS_SHARED_LIBS + /* Silently return the unaltered pc upon memory errors. + This could happen on OSF/1 if decode_line_1 tries to skip the + prologue for quickstarted shared library functions when the + shared library is not yet mapped in. + Reading target memory is slow over serial lines, so we perform + this check only if the target has shared libraries. */ + if (target_read_memory (pc, buf, 4)) + return pc; +#endif + + /* See if we can determine the end of the prologue via the symbol table. + If so, then return either PC, or the PC after the prologue, whichever + is greater. */ + + post_prologue_pc = after_prologue (pc, NULL); + + if (post_prologue_pc != 0) + return max (pc, post_prologue_pc); + + /* Can't determine prologue from the symbol table, need to examine + instructions. */ /* Skip the typical prologue instructions. These are the stack adjustment instruction and the instructions that save registers on the stack or in the gcc frame. */ for (offset = 0; offset < 100; offset += 4) { - char buf[4]; int status; status = read_memory_nobpt (pc + offset, buf, 4); @@ -879,6 +1022,7 @@ alpha_skip_prologue (pc, lenient) return pc + offset; } +#if 0 /* Is address PC in the prologue (loosely defined) for function at STARTADDR? */ @@ -890,6 +1034,7 @@ alpha_in_lenient_prologue (startaddr, pc) CORE_ADDR end_prologue = alpha_skip_prologue (startaddr, 1); return pc >= startaddr && pc < end_prologue; } +#endif /* The alpha needs a conversion between register and memory format if the register is a floating point register and @@ -960,52 +1105,48 @@ alpha_register_convert_to_raw (valtype, regnum, virtual_buffer, raw_buffer) /* Given a return value in `regbuf' with a type `valtype', extract and copy its value into `valbuf'. */ + void alpha_extract_return_value (valtype, regbuf, valbuf) struct type *valtype; char regbuf[REGISTER_BYTES]; char *valbuf; { - int regnum; - - regnum = TYPE_CODE (valtype) == TYPE_CODE_FLT ? FP0_REGNUM : V0_REGNUM; - - memcpy (valbuf, regbuf + REGISTER_BYTE (regnum), TYPE_LENGTH (valtype)); + if (TYPE_CODE (valtype) == TYPE_CODE_FLT) + alpha_register_convert_to_virtual (FP0_REGNUM, valtype, + regbuf + REGISTER_BYTE (FP0_REGNUM), + valbuf); + else + memcpy (valbuf, regbuf + REGISTER_BYTE (V0_REGNUM), TYPE_LENGTH (valtype)); } /* Given a return value in `regbuf' with a type `valtype', - write it's value into the appropriate register. */ + write its value into the appropriate register. */ + void alpha_store_return_value (valtype, valbuf) struct type *valtype; char *valbuf; { - int regnum; char raw_buffer[MAX_REGISTER_RAW_SIZE]; + int regnum = V0_REGNUM; + int length = TYPE_LENGTH (valtype); - regnum = TYPE_CODE (valtype) == TYPE_CODE_FLT ? FP0_REGNUM : V0_REGNUM; - memcpy(raw_buffer, valbuf, TYPE_LENGTH (valtype)); - - write_register_bytes(REGISTER_BYTE (regnum), raw_buffer, TYPE_LENGTH (valtype)); -} - -/* Print the instruction at address MEMADDR in debugged memory, - on STREAM. Returns length of the instruction, in bytes. */ - -int -print_insn (memaddr, stream) - CORE_ADDR memaddr; - GDB_FILE *stream; -{ - disassemble_info info; - - GDB_INIT_DISASSEMBLE_INFO(info, stream); + if (TYPE_CODE (valtype) == TYPE_CODE_FLT) + { + regnum = FP0_REGNUM; + length = REGISTER_RAW_SIZE (regnum); + alpha_register_convert_to_raw (valtype, regnum, valbuf, raw_buffer); + } + else + memcpy (raw_buffer, valbuf, length); - return print_insn_alpha (memaddr, &info); + write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, length); } /* Just like reinit_frame_cache, but with the right arguments to be callable as an sfunc. */ + static void reinit_frame_cache_sfunc (args, from_tty, c) char *args; @@ -1015,11 +1156,37 @@ reinit_frame_cache_sfunc (args, from_tty, c) reinit_frame_cache (); } +/* This is the definition of CALL_DUMMY_ADDRESS. It's a heuristic that is used + to find a convenient place in the text segment to stick a breakpoint to + detect the completion of a target function call (ala call_function_by_hand). + */ + +CORE_ADDR +alpha_call_dummy_address () +{ + CORE_ADDR entry; + struct minimal_symbol *sym; + + entry = entry_point_address (); + + if (entry != 0) + return entry; + + sym = lookup_minimal_symbol ("_Prelude", NULL, symfile_objfile); + + if (!sym || MSYMBOL_TYPE (sym) != mst_text) + return 0; + else + return SYMBOL_VALUE_ADDRESS (sym) + 4; +} + void _initialize_alpha_tdep () { struct cmd_list_element *c; + tm_print_insn = print_insn_alpha; + /* Let the user set the fence post for heuristic_proc_start. */ /* We really would like to have both "0" and "unlimited" work, but