1130803Smarcel/* Target-dependent mdebug code for the ALPHA architecture. 2130803Smarcel Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 3130803Smarcel Free Software Foundation, Inc. 4130803Smarcel 5130803Smarcel This file is part of GDB. 6130803Smarcel 7130803Smarcel This program is free software; you can redistribute it and/or modify 8130803Smarcel it under the terms of the GNU General Public License as published by 9130803Smarcel the Free Software Foundation; either version 2 of the License, or 10130803Smarcel (at your option) any later version. 11130803Smarcel 12130803Smarcel This program is distributed in the hope that it will be useful, 13130803Smarcel but WITHOUT ANY WARRANTY; without even the implied warranty of 14130803Smarcel MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15130803Smarcel GNU General Public License for more details. 16130803Smarcel 17130803Smarcel You should have received a copy of the GNU General Public License 18130803Smarcel along with this program; if not, write to the Free Software 19130803Smarcel Foundation, Inc., 59 Temple Place - Suite 330, 20130803Smarcel Boston, MA 02111-1307, USA. */ 21130803Smarcel 22130803Smarcel#include "defs.h" 23130803Smarcel#include "frame.h" 24130803Smarcel#include "frame-unwind.h" 25130803Smarcel#include "frame-base.h" 26130803Smarcel#include "symtab.h" 27130803Smarcel#include "gdbcore.h" 28130803Smarcel#include "block.h" 29130803Smarcel#include "gdb_assert.h" 30130803Smarcel 31130803Smarcel#include "alpha-tdep.h" 32130803Smarcel 33130803Smarcel/* FIXME: Some of this code should perhaps be merged with mips. */ 34130803Smarcel 35130803Smarcel/* *INDENT-OFF* */ 36130803Smarcel/* Layout of a stack frame on the alpha: 37130803Smarcel 38130803Smarcel | | 39130803Smarcel pdr members: | 7th ... nth arg, | 40130803Smarcel | `pushed' by caller. | 41130803Smarcel | | 42130803Smarcel----------------|-------------------------------|<-- old_sp == vfp 43130803Smarcel ^ ^ ^ ^ | | 44130803Smarcel | | | | | | 45130803Smarcel | |localoff | Copies of 1st .. 6th | 46130803Smarcel | | | | | argument if necessary. | 47130803Smarcel | | | v | | 48130803Smarcel | | | --- |-------------------------------|<-- LOCALS_ADDRESS 49130803Smarcel | | | | | 50130803Smarcel | | | | Locals and temporaries. | 51130803Smarcel | | | | | 52130803Smarcel | | | |-------------------------------| 53130803Smarcel | | | | | 54130803Smarcel |-fregoffset | Saved float registers. | 55130803Smarcel | | | | F9 | 56130803Smarcel | | | | . | 57130803Smarcel | | | | . | 58130803Smarcel | | | | F2 | 59130803Smarcel | | v | | 60130803Smarcel | | -------|-------------------------------| 61130803Smarcel | | | | 62130803Smarcel | | | Saved registers. | 63130803Smarcel | | | S6 | 64130803Smarcel |-regoffset | . | 65130803Smarcel | | | . | 66130803Smarcel | | | S0 | 67130803Smarcel | | | pdr.pcreg | 68130803Smarcel | v | | 69130803Smarcel | ----------|-------------------------------| 70130803Smarcel | | | 71130803Smarcel frameoffset | Argument build area, gets | 72130803Smarcel | | 7th ... nth arg for any | 73130803Smarcel | | called procedure. | 74130803Smarcel v | | 75130803Smarcel -------------|-------------------------------|<-- sp 76130803Smarcel | | 77130803Smarcel*/ 78130803Smarcel/* *INDENT-ON* */ 79130803Smarcel 80130803Smarcel#define PROC_LOW_ADDR(proc) ((proc)->pdr.adr) 81130803Smarcel#define PROC_FRAME_OFFSET(proc) ((proc)->pdr.frameoffset) 82130803Smarcel#define PROC_FRAME_REG(proc) ((proc)->pdr.framereg) 83130803Smarcel#define PROC_REG_MASK(proc) ((proc)->pdr.regmask) 84130803Smarcel#define PROC_FREG_MASK(proc) ((proc)->pdr.fregmask) 85130803Smarcel#define PROC_REG_OFFSET(proc) ((proc)->pdr.regoffset) 86130803Smarcel#define PROC_FREG_OFFSET(proc) ((proc)->pdr.fregoffset) 87130803Smarcel#define PROC_PC_REG(proc) ((proc)->pdr.pcreg) 88130803Smarcel#define PROC_LOCALOFF(proc) ((proc)->pdr.localoff) 89130803Smarcel 90130803Smarcel/* Locate the mdebug PDR for the given PC. Return null if one can't 91130803Smarcel be found; you'll have to fall back to other methods in that case. */ 92130803Smarcel 93130803Smarcelstatic alpha_extra_func_info_t 94130803Smarcelfind_proc_desc (CORE_ADDR pc) 95130803Smarcel{ 96130803Smarcel struct block *b = block_for_pc (pc); 97130803Smarcel alpha_extra_func_info_t proc_desc = NULL; 98130803Smarcel struct symbol *sym = NULL; 99130803Smarcel 100130803Smarcel if (b) 101130803Smarcel { 102130803Smarcel CORE_ADDR startaddr; 103130803Smarcel find_pc_partial_function (pc, NULL, &startaddr, NULL); 104130803Smarcel 105130803Smarcel if (startaddr > BLOCK_START (b)) 106130803Smarcel /* This is the "pathological" case referred to in a comment in 107130803Smarcel print_frame_info. It might be better to move this check into 108130803Smarcel symbol reading. */ 109130803Smarcel sym = NULL; 110130803Smarcel else 111130803Smarcel sym = lookup_symbol (MIPS_EFI_SYMBOL_NAME, b, LABEL_DOMAIN, 0, NULL); 112130803Smarcel } 113130803Smarcel 114130803Smarcel if (sym) 115130803Smarcel { 116130803Smarcel proc_desc = (alpha_extra_func_info_t) SYMBOL_VALUE (sym); 117130803Smarcel 118130803Smarcel /* If we never found a PDR for this function in symbol reading, 119130803Smarcel then examine prologues to find the information. */ 120130803Smarcel if (proc_desc->pdr.framereg == -1) 121130803Smarcel proc_desc = NULL; 122130803Smarcel } 123130803Smarcel 124130803Smarcel return proc_desc; 125130803Smarcel} 126130803Smarcel 127130803Smarcel/* This returns the PC of the first inst after the prologue. If we can't 128130803Smarcel find the prologue, then return 0. */ 129130803Smarcel 130130803Smarcelstatic CORE_ADDR 131130803Smarcelalpha_mdebug_after_prologue (CORE_ADDR pc, alpha_extra_func_info_t proc_desc) 132130803Smarcel{ 133130803Smarcel if (proc_desc) 134130803Smarcel { 135130803Smarcel /* If function is frameless, then we need to do it the hard way. I 136130803Smarcel strongly suspect that frameless always means prologueless... */ 137130803Smarcel if (PROC_FRAME_REG (proc_desc) == ALPHA_SP_REGNUM 138130803Smarcel && PROC_FRAME_OFFSET (proc_desc) == 0) 139130803Smarcel return 0; 140130803Smarcel } 141130803Smarcel 142130803Smarcel return alpha_after_prologue (pc); 143130803Smarcel} 144130803Smarcel 145130803Smarcel/* Return non-zero if we *might* be in a function prologue. Return zero 146130803Smarcel if we are definitively *not* in a function prologue. */ 147130803Smarcel 148130803Smarcelstatic int 149130803Smarcelalpha_mdebug_in_prologue (CORE_ADDR pc, alpha_extra_func_info_t proc_desc) 150130803Smarcel{ 151130803Smarcel CORE_ADDR after_prologue_pc = alpha_mdebug_after_prologue (pc, proc_desc); 152130803Smarcel return (after_prologue_pc == 0 || pc < after_prologue_pc); 153130803Smarcel} 154130803Smarcel 155130803Smarcel 156130803Smarcel/* Frame unwinder that reads mdebug PDRs. */ 157130803Smarcel 158130803Smarcelstruct alpha_mdebug_unwind_cache 159130803Smarcel{ 160130803Smarcel alpha_extra_func_info_t proc_desc; 161130803Smarcel CORE_ADDR vfp; 162130803Smarcel CORE_ADDR *saved_regs; 163130803Smarcel}; 164130803Smarcel 165130803Smarcel/* Extract all of the information about the frame from PROC_DESC 166130803Smarcel and store the resulting register save locations in the structure. */ 167130803Smarcel 168130803Smarcelstatic struct alpha_mdebug_unwind_cache * 169130803Smarcelalpha_mdebug_frame_unwind_cache (struct frame_info *next_frame, 170130803Smarcel void **this_prologue_cache) 171130803Smarcel{ 172130803Smarcel struct alpha_mdebug_unwind_cache *info; 173130803Smarcel alpha_extra_func_info_t proc_desc; 174130803Smarcel ULONGEST vfp; 175130803Smarcel CORE_ADDR pc, reg_position; 176130803Smarcel unsigned long mask; 177130803Smarcel int ireg, returnreg; 178130803Smarcel 179130803Smarcel if (*this_prologue_cache) 180130803Smarcel return *this_prologue_cache; 181130803Smarcel 182130803Smarcel info = FRAME_OBSTACK_ZALLOC (struct alpha_mdebug_unwind_cache); 183130803Smarcel *this_prologue_cache = info; 184130803Smarcel pc = frame_pc_unwind (next_frame); 185130803Smarcel 186130803Smarcel /* ??? We don't seem to be able to cache the lookup of the PDR 187130803Smarcel from alpha_mdebug_frame_p. It'd be nice if we could change 188130803Smarcel the arguments to that function. Oh well. */ 189130803Smarcel proc_desc = find_proc_desc (pc); 190130803Smarcel info->proc_desc = proc_desc; 191130803Smarcel gdb_assert (proc_desc != NULL); 192130803Smarcel 193130803Smarcel info->saved_regs = frame_obstack_zalloc (SIZEOF_FRAME_SAVED_REGS); 194130803Smarcel 195130803Smarcel /* The VFP of the frame is at FRAME_REG+FRAME_OFFSET. */ 196130803Smarcel frame_unwind_unsigned_register (next_frame, PROC_FRAME_REG (proc_desc), &vfp); 197130803Smarcel vfp += PROC_FRAME_OFFSET (info->proc_desc); 198130803Smarcel info->vfp = vfp; 199130803Smarcel 200130803Smarcel /* Fill in the offsets for the registers which gen_mask says were saved. */ 201130803Smarcel 202130803Smarcel reg_position = vfp + PROC_REG_OFFSET (proc_desc); 203130803Smarcel mask = PROC_REG_MASK (proc_desc); 204130803Smarcel returnreg = PROC_PC_REG (proc_desc); 205130803Smarcel 206130803Smarcel /* Note that RA is always saved first, regardless of its actual 207130803Smarcel register number. */ 208130803Smarcel if (mask & (1 << returnreg)) 209130803Smarcel { 210130803Smarcel /* Clear bit for RA so we don't save it again later. */ 211130803Smarcel mask &= ~(1 << returnreg); 212130803Smarcel 213130803Smarcel info->saved_regs[returnreg] = reg_position; 214130803Smarcel reg_position += 8; 215130803Smarcel } 216130803Smarcel 217130803Smarcel for (ireg = 0; ireg <= 31; ++ireg) 218130803Smarcel if (mask & (1 << ireg)) 219130803Smarcel { 220130803Smarcel info->saved_regs[ireg] = reg_position; 221130803Smarcel reg_position += 8; 222130803Smarcel } 223130803Smarcel 224130803Smarcel reg_position = vfp + PROC_FREG_OFFSET (proc_desc); 225130803Smarcel mask = PROC_FREG_MASK (proc_desc); 226130803Smarcel 227130803Smarcel for (ireg = 0; ireg <= 31; ++ireg) 228130803Smarcel if (mask & (1 << ireg)) 229130803Smarcel { 230130803Smarcel info->saved_regs[ALPHA_FP0_REGNUM + ireg] = reg_position; 231130803Smarcel reg_position += 8; 232130803Smarcel } 233130803Smarcel 234130803Smarcel return info; 235130803Smarcel} 236130803Smarcel 237130803Smarcel/* Given a GDB frame, determine the address of the calling function's 238130803Smarcel frame. This will be used to create a new GDB frame struct. */ 239130803Smarcel 240130803Smarcelstatic void 241130803Smarcelalpha_mdebug_frame_this_id (struct frame_info *next_frame, 242130803Smarcel void **this_prologue_cache, 243130803Smarcel struct frame_id *this_id) 244130803Smarcel{ 245130803Smarcel struct alpha_mdebug_unwind_cache *info 246130803Smarcel = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache); 247130803Smarcel 248130803Smarcel *this_id = frame_id_build (info->vfp, frame_func_unwind (next_frame)); 249130803Smarcel} 250130803Smarcel 251130803Smarcel/* Retrieve the value of REGNUM in FRAME. Don't give up! */ 252130803Smarcel 253130803Smarcelstatic void 254130803Smarcelalpha_mdebug_frame_prev_register (struct frame_info *next_frame, 255130803Smarcel void **this_prologue_cache, 256130803Smarcel int regnum, int *optimizedp, 257130803Smarcel enum lval_type *lvalp, CORE_ADDR *addrp, 258130803Smarcel int *realnump, void *bufferp) 259130803Smarcel{ 260130803Smarcel struct alpha_mdebug_unwind_cache *info 261130803Smarcel = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache); 262130803Smarcel 263130803Smarcel /* The PC of the previous frame is stored in the link register of 264130803Smarcel the current frame. Frob regnum so that we pull the value from 265130803Smarcel the correct place. */ 266130803Smarcel if (regnum == ALPHA_PC_REGNUM) 267130803Smarcel regnum = PROC_PC_REG (info->proc_desc); 268130803Smarcel 269130803Smarcel /* For all registers known to be saved in the current frame, 270130803Smarcel do the obvious and pull the value out. */ 271130803Smarcel if (info->saved_regs[regnum]) 272130803Smarcel { 273130803Smarcel *optimizedp = 0; 274130803Smarcel *lvalp = lval_memory; 275130803Smarcel *addrp = info->saved_regs[regnum]; 276130803Smarcel *realnump = -1; 277130803Smarcel if (bufferp != NULL) 278130803Smarcel get_frame_memory (next_frame, *addrp, bufferp, ALPHA_REGISTER_SIZE); 279130803Smarcel return; 280130803Smarcel } 281130803Smarcel 282130803Smarcel /* The stack pointer of the previous frame is computed by popping 283130803Smarcel the current stack frame. */ 284130803Smarcel if (regnum == ALPHA_SP_REGNUM) 285130803Smarcel { 286130803Smarcel *optimizedp = 0; 287130803Smarcel *lvalp = not_lval; 288130803Smarcel *addrp = 0; 289130803Smarcel *realnump = -1; 290130803Smarcel if (bufferp != NULL) 291130803Smarcel store_unsigned_integer (bufferp, ALPHA_REGISTER_SIZE, info->vfp); 292130803Smarcel return; 293130803Smarcel } 294130803Smarcel 295130803Smarcel /* Otherwise assume the next frame has the same register value. */ 296130803Smarcel frame_register (next_frame, regnum, optimizedp, lvalp, addrp, 297130803Smarcel realnump, bufferp); 298130803Smarcel} 299130803Smarcel 300130803Smarcelstatic const struct frame_unwind alpha_mdebug_frame_unwind = { 301130803Smarcel NORMAL_FRAME, 302130803Smarcel alpha_mdebug_frame_this_id, 303130803Smarcel alpha_mdebug_frame_prev_register 304130803Smarcel}; 305130803Smarcel 306130803Smarcelconst struct frame_unwind * 307130803Smarcelalpha_mdebug_frame_sniffer (struct frame_info *next_frame) 308130803Smarcel{ 309130803Smarcel CORE_ADDR pc = frame_pc_unwind (next_frame); 310130803Smarcel alpha_extra_func_info_t proc_desc; 311130803Smarcel 312130803Smarcel /* If this PC does not map to a PDR, then clearly this isn't an 313130803Smarcel mdebug frame. */ 314130803Smarcel proc_desc = find_proc_desc (pc); 315130803Smarcel if (proc_desc == NULL) 316130803Smarcel return NULL; 317130803Smarcel 318130803Smarcel /* If we're in the prologue, the PDR for this frame is not yet valid. 319130803Smarcel Say no here and we'll fall back on the heuristic unwinder. */ 320130803Smarcel if (alpha_mdebug_in_prologue (pc, proc_desc)) 321130803Smarcel return NULL; 322130803Smarcel 323130803Smarcel return &alpha_mdebug_frame_unwind; 324130803Smarcel} 325130803Smarcel 326130803Smarcelstatic CORE_ADDR 327130803Smarcelalpha_mdebug_frame_base_address (struct frame_info *next_frame, 328130803Smarcel void **this_prologue_cache) 329130803Smarcel{ 330130803Smarcel struct alpha_mdebug_unwind_cache *info 331130803Smarcel = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache); 332130803Smarcel 333130803Smarcel return info->vfp; 334130803Smarcel} 335130803Smarcel 336130803Smarcelstatic CORE_ADDR 337130803Smarcelalpha_mdebug_frame_locals_address (struct frame_info *next_frame, 338130803Smarcel void **this_prologue_cache) 339130803Smarcel{ 340130803Smarcel struct alpha_mdebug_unwind_cache *info 341130803Smarcel = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache); 342130803Smarcel 343130803Smarcel return info->vfp - PROC_LOCALOFF (info->proc_desc); 344130803Smarcel} 345130803Smarcel 346130803Smarcelstatic CORE_ADDR 347130803Smarcelalpha_mdebug_frame_args_address (struct frame_info *next_frame, 348130803Smarcel void **this_prologue_cache) 349130803Smarcel{ 350130803Smarcel struct alpha_mdebug_unwind_cache *info 351130803Smarcel = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache); 352130803Smarcel 353130803Smarcel return info->vfp - ALPHA_NUM_ARG_REGS * 8; 354130803Smarcel} 355130803Smarcel 356130803Smarcelstatic const struct frame_base alpha_mdebug_frame_base = { 357130803Smarcel &alpha_mdebug_frame_unwind, 358130803Smarcel alpha_mdebug_frame_base_address, 359130803Smarcel alpha_mdebug_frame_locals_address, 360130803Smarcel alpha_mdebug_frame_args_address 361130803Smarcel}; 362130803Smarcel 363130803Smarcelstatic const struct frame_base * 364130803Smarcelalpha_mdebug_frame_base_sniffer (struct frame_info *next_frame) 365130803Smarcel{ 366130803Smarcel CORE_ADDR pc = frame_pc_unwind (next_frame); 367130803Smarcel alpha_extra_func_info_t proc_desc; 368130803Smarcel 369130803Smarcel /* If this PC does not map to a PDR, then clearly this isn't an 370130803Smarcel mdebug frame. */ 371130803Smarcel proc_desc = find_proc_desc (pc); 372130803Smarcel if (proc_desc == NULL) 373130803Smarcel return NULL; 374130803Smarcel 375130803Smarcel return &alpha_mdebug_frame_base; 376130803Smarcel} 377130803Smarcel 378130803Smarcel 379130803Smarcelvoid 380130803Smarcelalpha_mdebug_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 381130803Smarcel{ 382130803Smarcel struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 383130803Smarcel 384130803Smarcel frame_unwind_append_sniffer (gdbarch, alpha_mdebug_frame_sniffer); 385130803Smarcel frame_base_append_sniffer (gdbarch, alpha_mdebug_frame_base_sniffer); 386130803Smarcel} 387