alpha-mdebug-tdep.c revision 130803
118730Ssteve/* Target-dependent mdebug code for the ALPHA architecture. 294589Sobrien Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 350477Speter Free Software Foundation, Inc. 41590Srgrimes 51590Srgrimes This file is part of GDB. 6143657Sharti 7146056Sharti This program is free software; you can redistribute it and/or modify 8146574Sharti it under the terms of the GNU General Public License as published by 9146574Sharti the Free Software Foundation; either version 2 of the License, or 101590Srgrimes (at your option) any later version. 11139112Sru 1276801Ssobomax This program is distributed in the hope that it will be useful, 13228157Sfjoe but WITHOUT ANY WARRANTY; without even the implied warranty of 14228157Sfjoe MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15228157Sfjoe GNU General Public License for more details. 16134843Sjmg 17104475Sphk You should have received a copy of the GNU General Public License 18104475Sphk along with this program; if not, write to the Free Software 19146608Sharti Foundation, Inc., 59 Temple Place - Suite 330, 20146608Sharti Boston, MA 02111-1307, USA. */ 21146608Sharti 22146608Sharti#include "defs.h" 23146608Sharti#include "frame.h" 24146608Sharti#include "frame-unwind.h" 25146579Sharti#include "frame-base.h" 2697121Sru#include "symtab.h" 27145616Sharti#include "gdbcore.h" 28150598Sphk#include "block.h" 29145616Sharti#include "gdb_assert.h" 30145616Sharti 31145612Sharti#include "alpha-tdep.h" 32145612Sharti 33145612Sharti/* FIXME: Some of this code should perhaps be merged with mips. */ 34145616Sharti 35145616Sharti/* *INDENT-OFF* */ 36145612Sharti/* Layout of a stack frame on the alpha: 37145612Sharti 38145612Sharti | | 39145612Sharti pdr members: | 7th ... nth arg, | 40145612Sharti | `pushed' by caller. | 41145616Sharti | | 42145616Sharti----------------|-------------------------------|<-- old_sp == vfp 43145612Sharti ^ ^ ^ ^ | | 44145612Sharti | | | | | | 45145612Sharti | |localoff | Copies of 1st .. 6th | 46145612Sharti | | | | | argument if necessary. | 47145612Sharti | | | v | | 48145612Sharti | | | --- |-------------------------------|<-- LOCALS_ADDRESS 49145616Sharti | | | | | 50145612Sharti | | | | Locals and temporaries. | 51145612Sharti | | | | | 52145612Sharti | | | |-------------------------------| 53145614Sharti | | | | | 54145612Sharti |-fregoffset | Saved float registers. | 55145612Sharti | | | | F9 | 56145612Sharti | | | | . | 57145612Sharti | | | | . | 58145612Sharti | | | | F2 | 59145612Sharti | | v | | 60145612Sharti | | -------|-------------------------------| 61145683Sharti | | | | 62145612Sharti | | | Saved registers. | 63145612Sharti | | | S6 | 64145612Sharti |-regoffset | . | 65145612Sharti | | | . | 66145612Sharti | | | S0 | 67145612Sharti | | | pdr.pcreg | 68145612Sharti | v | | 69145612Sharti | ----------|-------------------------------| 70145612Sharti | | | 71145612Sharti frameoffset | Argument build area, gets | 72145612Sharti | | 7th ... nth arg for any | 73145612Sharti | | called procedure. | 74145612Sharti v | | 75145612Sharti -------------|-------------------------------|<-- sp 76145612Sharti | | 77145612Sharti*/ 78145612Sharti/* *INDENT-ON* */ 79145616Sharti 80145616Sharti#define PROC_LOW_ADDR(proc) ((proc)->pdr.adr) 81145616Sharti#define PROC_FRAME_OFFSET(proc) ((proc)->pdr.frameoffset) 82145616Sharti#define PROC_FRAME_REG(proc) ((proc)->pdr.framereg) 83145616Sharti#define PROC_REG_MASK(proc) ((proc)->pdr.regmask) 84145616Sharti#define PROC_FREG_MASK(proc) ((proc)->pdr.fregmask) 85145616Sharti#define PROC_REG_OFFSET(proc) ((proc)->pdr.regoffset) 86145616Sharti#define PROC_FREG_OFFSET(proc) ((proc)->pdr.fregoffset) 87145616Sharti#define PROC_PC_REG(proc) ((proc)->pdr.pcreg) 88145616Sharti#define PROC_LOCALOFF(proc) ((proc)->pdr.localoff) 89145616Sharti 90145616Sharti/* Locate the mdebug PDR for the given PC. Return null if one can't 91145616Sharti be found; you'll have to fall back to other methods in that case. */ 92145616Sharti 93145616Shartistatic alpha_extra_func_info_t 94145616Shartifind_proc_desc (CORE_ADDR pc) 95145616Sharti{ 96145683Sharti struct block *b = block_for_pc (pc); 97145612Sharti alpha_extra_func_info_t proc_desc = NULL; 9864739Sgreen struct symbol *sym = NULL; 9964739Sgreen 10064739Sgreen if (b) 10164739Sgreen { 10264739Sgreen CORE_ADDR startaddr; 10364739Sgreen find_pc_partial_function (pc, NULL, &startaddr, NULL); 104146571Sharti 105146571Sharti if (startaddr > BLOCK_START (b)) 10664739Sgreen /* This is the "pathological" case referred to in a comment in 10764739Sgreen print_frame_info. It might be better to move this check into 10864739Sgreen symbol reading. */ 10964739Sgreen sym = NULL; 1101590Srgrimes else 111 sym = lookup_symbol (MIPS_EFI_SYMBOL_NAME, b, LABEL_DOMAIN, 0, NULL); 112 } 113 114 if (sym) 115 { 116 proc_desc = (alpha_extra_func_info_t) SYMBOL_VALUE (sym); 117 118 /* If we never found a PDR for this function in symbol reading, 119 then examine prologues to find the information. */ 120 if (proc_desc->pdr.framereg == -1) 121 proc_desc = NULL; 122 } 123 124 return proc_desc; 125} 126 127/* This returns the PC of the first inst after the prologue. If we can't 128 find the prologue, then return 0. */ 129 130static CORE_ADDR 131alpha_mdebug_after_prologue (CORE_ADDR pc, alpha_extra_func_info_t proc_desc) 132{ 133 if (proc_desc) 134 { 135 /* If function is frameless, then we need to do it the hard way. I 136 strongly suspect that frameless always means prologueless... */ 137 if (PROC_FRAME_REG (proc_desc) == ALPHA_SP_REGNUM 138 && PROC_FRAME_OFFSET (proc_desc) == 0) 139 return 0; 140 } 141 142 return alpha_after_prologue (pc); 143} 144 145/* Return non-zero if we *might* be in a function prologue. Return zero 146 if we are definitively *not* in a function prologue. */ 147 148static int 149alpha_mdebug_in_prologue (CORE_ADDR pc, alpha_extra_func_info_t proc_desc) 150{ 151 CORE_ADDR after_prologue_pc = alpha_mdebug_after_prologue (pc, proc_desc); 152 return (after_prologue_pc == 0 || pc < after_prologue_pc); 153} 154 155 156/* Frame unwinder that reads mdebug PDRs. */ 157 158struct alpha_mdebug_unwind_cache 159{ 160 alpha_extra_func_info_t proc_desc; 161 CORE_ADDR vfp; 162 CORE_ADDR *saved_regs; 163}; 164 165/* Extract all of the information about the frame from PROC_DESC 166 and store the resulting register save locations in the structure. */ 167 168static struct alpha_mdebug_unwind_cache * 169alpha_mdebug_frame_unwind_cache (struct frame_info *next_frame, 170 void **this_prologue_cache) 171{ 172 struct alpha_mdebug_unwind_cache *info; 173 alpha_extra_func_info_t proc_desc; 174 ULONGEST vfp; 175 CORE_ADDR pc, reg_position; 176 unsigned long mask; 177 int ireg, returnreg; 178 179 if (*this_prologue_cache) 180 return *this_prologue_cache; 181 182 info = FRAME_OBSTACK_ZALLOC (struct alpha_mdebug_unwind_cache); 183 *this_prologue_cache = info; 184 pc = frame_pc_unwind (next_frame); 185 186 /* ??? We don't seem to be able to cache the lookup of the PDR 187 from alpha_mdebug_frame_p. It'd be nice if we could change 188 the arguments to that function. Oh well. */ 189 proc_desc = find_proc_desc (pc); 190 info->proc_desc = proc_desc; 191 gdb_assert (proc_desc != NULL); 192 193 info->saved_regs = frame_obstack_zalloc (SIZEOF_FRAME_SAVED_REGS); 194 195 /* The VFP of the frame is at FRAME_REG+FRAME_OFFSET. */ 196 frame_unwind_unsigned_register (next_frame, PROC_FRAME_REG (proc_desc), &vfp); 197 vfp += PROC_FRAME_OFFSET (info->proc_desc); 198 info->vfp = vfp; 199 200 /* Fill in the offsets for the registers which gen_mask says were saved. */ 201 202 reg_position = vfp + PROC_REG_OFFSET (proc_desc); 203 mask = PROC_REG_MASK (proc_desc); 204 returnreg = PROC_PC_REG (proc_desc); 205 206 /* Note that RA is always saved first, regardless of its actual 207 register number. */ 208 if (mask & (1 << returnreg)) 209 { 210 /* Clear bit for RA so we don't save it again later. */ 211 mask &= ~(1 << returnreg); 212 213 info->saved_regs[returnreg] = reg_position; 214 reg_position += 8; 215 } 216 217 for (ireg = 0; ireg <= 31; ++ireg) 218 if (mask & (1 << ireg)) 219 { 220 info->saved_regs[ireg] = reg_position; 221 reg_position += 8; 222 } 223 224 reg_position = vfp + PROC_FREG_OFFSET (proc_desc); 225 mask = PROC_FREG_MASK (proc_desc); 226 227 for (ireg = 0; ireg <= 31; ++ireg) 228 if (mask & (1 << ireg)) 229 { 230 info->saved_regs[ALPHA_FP0_REGNUM + ireg] = reg_position; 231 reg_position += 8; 232 } 233 234 return info; 235} 236 237/* Given a GDB frame, determine the address of the calling function's 238 frame. This will be used to create a new GDB frame struct. */ 239 240static void 241alpha_mdebug_frame_this_id (struct frame_info *next_frame, 242 void **this_prologue_cache, 243 struct frame_id *this_id) 244{ 245 struct alpha_mdebug_unwind_cache *info 246 = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache); 247 248 *this_id = frame_id_build (info->vfp, frame_func_unwind (next_frame)); 249} 250 251/* Retrieve the value of REGNUM in FRAME. Don't give up! */ 252 253static void 254alpha_mdebug_frame_prev_register (struct frame_info *next_frame, 255 void **this_prologue_cache, 256 int regnum, int *optimizedp, 257 enum lval_type *lvalp, CORE_ADDR *addrp, 258 int *realnump, void *bufferp) 259{ 260 struct alpha_mdebug_unwind_cache *info 261 = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache); 262 263 /* The PC of the previous frame is stored in the link register of 264 the current frame. Frob regnum so that we pull the value from 265 the correct place. */ 266 if (regnum == ALPHA_PC_REGNUM) 267 regnum = PROC_PC_REG (info->proc_desc); 268 269 /* For all registers known to be saved in the current frame, 270 do the obvious and pull the value out. */ 271 if (info->saved_regs[regnum]) 272 { 273 *optimizedp = 0; 274 *lvalp = lval_memory; 275 *addrp = info->saved_regs[regnum]; 276 *realnump = -1; 277 if (bufferp != NULL) 278 get_frame_memory (next_frame, *addrp, bufferp, ALPHA_REGISTER_SIZE); 279 return; 280 } 281 282 /* The stack pointer of the previous frame is computed by popping 283 the current stack frame. */ 284 if (regnum == ALPHA_SP_REGNUM) 285 { 286 *optimizedp = 0; 287 *lvalp = not_lval; 288 *addrp = 0; 289 *realnump = -1; 290 if (bufferp != NULL) 291 store_unsigned_integer (bufferp, ALPHA_REGISTER_SIZE, info->vfp); 292 return; 293 } 294 295 /* Otherwise assume the next frame has the same register value. */ 296 frame_register (next_frame, regnum, optimizedp, lvalp, addrp, 297 realnump, bufferp); 298} 299 300static const struct frame_unwind alpha_mdebug_frame_unwind = { 301 NORMAL_FRAME, 302 alpha_mdebug_frame_this_id, 303 alpha_mdebug_frame_prev_register 304}; 305 306const struct frame_unwind * 307alpha_mdebug_frame_sniffer (struct frame_info *next_frame) 308{ 309 CORE_ADDR pc = frame_pc_unwind (next_frame); 310 alpha_extra_func_info_t proc_desc; 311 312 /* If this PC does not map to a PDR, then clearly this isn't an 313 mdebug frame. */ 314 proc_desc = find_proc_desc (pc); 315 if (proc_desc == NULL) 316 return NULL; 317 318 /* If we're in the prologue, the PDR for this frame is not yet valid. 319 Say no here and we'll fall back on the heuristic unwinder. */ 320 if (alpha_mdebug_in_prologue (pc, proc_desc)) 321 return NULL; 322 323 return &alpha_mdebug_frame_unwind; 324} 325 326static CORE_ADDR 327alpha_mdebug_frame_base_address (struct frame_info *next_frame, 328 void **this_prologue_cache) 329{ 330 struct alpha_mdebug_unwind_cache *info 331 = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache); 332 333 return info->vfp; 334} 335 336static CORE_ADDR 337alpha_mdebug_frame_locals_address (struct frame_info *next_frame, 338 void **this_prologue_cache) 339{ 340 struct alpha_mdebug_unwind_cache *info 341 = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache); 342 343 return info->vfp - PROC_LOCALOFF (info->proc_desc); 344} 345 346static CORE_ADDR 347alpha_mdebug_frame_args_address (struct frame_info *next_frame, 348 void **this_prologue_cache) 349{ 350 struct alpha_mdebug_unwind_cache *info 351 = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache); 352 353 return info->vfp - ALPHA_NUM_ARG_REGS * 8; 354} 355 356static const struct frame_base alpha_mdebug_frame_base = { 357 &alpha_mdebug_frame_unwind, 358 alpha_mdebug_frame_base_address, 359 alpha_mdebug_frame_locals_address, 360 alpha_mdebug_frame_args_address 361}; 362 363static const struct frame_base * 364alpha_mdebug_frame_base_sniffer (struct frame_info *next_frame) 365{ 366 CORE_ADDR pc = frame_pc_unwind (next_frame); 367 alpha_extra_func_info_t proc_desc; 368 369 /* If this PC does not map to a PDR, then clearly this isn't an 370 mdebug frame. */ 371 proc_desc = find_proc_desc (pc); 372 if (proc_desc == NULL) 373 return NULL; 374 375 return &alpha_mdebug_frame_base; 376} 377 378 379void 380alpha_mdebug_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 381{ 382 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 383 384 frame_unwind_append_sniffer (gdbarch, alpha_mdebug_frame_sniffer); 385 frame_base_append_sniffer (gdbarch, alpha_mdebug_frame_base_sniffer); 386} 387