1/* Target-dependent mdebug code for the ALPHA architecture. 2 Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 3 2003, 2007 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20#include "defs.h" 21#include "frame.h" 22#include "frame-unwind.h" 23#include "frame-base.h" 24#include "symtab.h" 25#include "gdbcore.h" 26#include "block.h" 27#include "gdb_assert.h" 28 29#include "alpha-tdep.h" 30#include "mdebugread.h" 31 32/* FIXME: Some of this code should perhaps be merged with mips. */ 33 34/* *INDENT-OFF* */ 35/* Layout of a stack frame on the alpha: 36 37 | | 38 pdr members: | 7th ... nth arg, | 39 | `pushed' by caller. | 40 | | 41----------------|-------------------------------|<-- old_sp == vfp 42 ^ ^ ^ ^ | | 43 | | | | | | 44 | |localoff | Copies of 1st .. 6th | 45 | | | | | argument if necessary. | 46 | | | v | | 47 | | | --- |-------------------------------|<-- LOCALS_ADDRESS 48 | | | | | 49 | | | | Locals and temporaries. | 50 | | | | | 51 | | | |-------------------------------| 52 | | | | | 53 |-fregoffset | Saved float registers. | 54 | | | | F9 | 55 | | | | . | 56 | | | | . | 57 | | | | F2 | 58 | | v | | 59 | | -------|-------------------------------| 60 | | | | 61 | | | Saved registers. | 62 | | | S6 | 63 |-regoffset | . | 64 | | | . | 65 | | | S0 | 66 | | | pdr.pcreg | 67 | v | | 68 | ----------|-------------------------------| 69 | | | 70 frameoffset | Argument build area, gets | 71 | | 7th ... nth arg for any | 72 | | called procedure. | 73 v | | 74 -------------|-------------------------------|<-- sp 75 | | 76*/ 77/* *INDENT-ON* */ 78 79#define PROC_LOW_ADDR(proc) ((proc)->pdr.adr) 80#define PROC_FRAME_OFFSET(proc) ((proc)->pdr.frameoffset) 81#define PROC_FRAME_REG(proc) ((proc)->pdr.framereg) 82#define PROC_REG_MASK(proc) ((proc)->pdr.regmask) 83#define PROC_FREG_MASK(proc) ((proc)->pdr.fregmask) 84#define PROC_REG_OFFSET(proc) ((proc)->pdr.regoffset) 85#define PROC_FREG_OFFSET(proc) ((proc)->pdr.fregoffset) 86#define PROC_PC_REG(proc) ((proc)->pdr.pcreg) 87#define PROC_LOCALOFF(proc) ((proc)->pdr.localoff) 88 89/* Locate the mdebug PDR for the given PC. Return null if one can't 90 be found; you'll have to fall back to other methods in that case. */ 91 92static struct mdebug_extra_func_info * 93find_proc_desc (CORE_ADDR pc) 94{ 95 struct block *b = block_for_pc (pc); 96 struct mdebug_extra_func_info *proc_desc = NULL; 97 struct symbol *sym = NULL; 98 99 if (b) 100 { 101 CORE_ADDR startaddr; 102 find_pc_partial_function (pc, NULL, &startaddr, NULL); 103 104 if (startaddr > BLOCK_START (b)) 105 /* This is the "pathological" case referred to in a comment in 106 print_frame_info. It might be better to move this check into 107 symbol reading. */ 108 sym = NULL; 109 else 110 sym = lookup_symbol (MDEBUG_EFI_SYMBOL_NAME, b, LABEL_DOMAIN, 0, NULL); 111 } 112 113 if (sym) 114 { 115 proc_desc = (struct mdebug_extra_func_info *) SYMBOL_VALUE (sym); 116 117 /* If we never found a PDR for this function in symbol reading, 118 then examine prologues to find the information. */ 119 if (proc_desc->pdr.framereg == -1) 120 proc_desc = NULL; 121 } 122 123 return proc_desc; 124} 125 126/* This returns the PC of the first inst after the prologue. If we can't 127 find the prologue, then return 0. */ 128 129static CORE_ADDR 130alpha_mdebug_after_prologue (CORE_ADDR pc, struct mdebug_extra_func_info *proc_desc) 131{ 132 if (proc_desc) 133 { 134 /* If function is frameless, then we need to do it the hard way. I 135 strongly suspect that frameless always means prologueless... */ 136 if (PROC_FRAME_REG (proc_desc) == ALPHA_SP_REGNUM 137 && PROC_FRAME_OFFSET (proc_desc) == 0) 138 return 0; 139 } 140 141 return alpha_after_prologue (pc); 142} 143 144/* Return non-zero if we *might* be in a function prologue. Return zero 145 if we are definitively *not* in a function prologue. */ 146 147static int 148alpha_mdebug_in_prologue (CORE_ADDR pc, struct mdebug_extra_func_info *proc_desc) 149{ 150 CORE_ADDR after_prologue_pc = alpha_mdebug_after_prologue (pc, proc_desc); 151 return (after_prologue_pc == 0 || pc < after_prologue_pc); 152} 153 154 155/* Frame unwinder that reads mdebug PDRs. */ 156 157struct alpha_mdebug_unwind_cache 158{ 159 struct mdebug_extra_func_info *proc_desc; 160 CORE_ADDR vfp; 161 CORE_ADDR *saved_regs; 162}; 163 164/* Extract all of the information about the frame from PROC_DESC 165 and store the resulting register save locations in the structure. */ 166 167static struct alpha_mdebug_unwind_cache * 168alpha_mdebug_frame_unwind_cache (struct frame_info *next_frame, 169 void **this_prologue_cache) 170{ 171 struct alpha_mdebug_unwind_cache *info; 172 struct mdebug_extra_func_info *proc_desc; 173 ULONGEST vfp; 174 CORE_ADDR pc, reg_position; 175 unsigned long mask; 176 int ireg, returnreg; 177 178 if (*this_prologue_cache) 179 return *this_prologue_cache; 180 181 info = FRAME_OBSTACK_ZALLOC (struct alpha_mdebug_unwind_cache); 182 *this_prologue_cache = info; 183 pc = frame_pc_unwind (next_frame); 184 185 /* ??? We don't seem to be able to cache the lookup of the PDR 186 from alpha_mdebug_frame_p. It'd be nice if we could change 187 the arguments to that function. Oh well. */ 188 proc_desc = find_proc_desc (pc); 189 info->proc_desc = proc_desc; 190 gdb_assert (proc_desc != NULL); 191 192 info->saved_regs = frame_obstack_zalloc (SIZEOF_FRAME_SAVED_REGS); 193 194 /* The VFP of the frame is at FRAME_REG+FRAME_OFFSET. */ 195 frame_unwind_unsigned_register (next_frame, PROC_FRAME_REG (proc_desc), &vfp); 196 vfp += PROC_FRAME_OFFSET (info->proc_desc); 197 info->vfp = vfp; 198 199 /* Fill in the offsets for the registers which gen_mask says were saved. */ 200 201 reg_position = vfp + PROC_REG_OFFSET (proc_desc); 202 mask = PROC_REG_MASK (proc_desc); 203 returnreg = PROC_PC_REG (proc_desc); 204 205 /* Note that RA is always saved first, regardless of its actual 206 register number. */ 207 if (mask & (1 << returnreg)) 208 { 209 /* Clear bit for RA so we don't save it again later. */ 210 mask &= ~(1 << returnreg); 211 212 info->saved_regs[returnreg] = reg_position; 213 reg_position += 8; 214 } 215 216 for (ireg = 0; ireg <= 31; ++ireg) 217 if (mask & (1 << ireg)) 218 { 219 info->saved_regs[ireg] = reg_position; 220 reg_position += 8; 221 } 222 223 reg_position = vfp + PROC_FREG_OFFSET (proc_desc); 224 mask = PROC_FREG_MASK (proc_desc); 225 226 for (ireg = 0; ireg <= 31; ++ireg) 227 if (mask & (1 << ireg)) 228 { 229 info->saved_regs[ALPHA_FP0_REGNUM + ireg] = reg_position; 230 reg_position += 8; 231 } 232 233 return info; 234} 235 236/* Given a GDB frame, determine the address of the calling function's 237 frame. This will be used to create a new GDB frame struct. */ 238 239static void 240alpha_mdebug_frame_this_id (struct frame_info *next_frame, 241 void **this_prologue_cache, 242 struct frame_id *this_id) 243{ 244 struct alpha_mdebug_unwind_cache *info 245 = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache); 246 247 *this_id = frame_id_build (info->vfp, 248 frame_func_unwind (next_frame, NORMAL_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, gdb_byte *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 *optimizedp = 0; 297 *lvalp = lval_register; 298 *addrp = 0; 299 *realnump = regnum; 300 if (bufferp) 301 frame_unwind_register (next_frame, *realnump, bufferp); 302} 303 304static const struct frame_unwind alpha_mdebug_frame_unwind = { 305 NORMAL_FRAME, 306 alpha_mdebug_frame_this_id, 307 alpha_mdebug_frame_prev_register 308}; 309 310const struct frame_unwind * 311alpha_mdebug_frame_sniffer (struct frame_info *next_frame) 312{ 313 CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); 314 struct mdebug_extra_func_info *proc_desc; 315 316 /* If this PC does not map to a PDR, then clearly this isn't an 317 mdebug frame. */ 318 proc_desc = find_proc_desc (pc); 319 if (proc_desc == NULL) 320 return NULL; 321 322 /* If we're in the prologue, the PDR for this frame is not yet valid. 323 Say no here and we'll fall back on the heuristic unwinder. */ 324 if (alpha_mdebug_in_prologue (pc, proc_desc)) 325 return NULL; 326 327 return &alpha_mdebug_frame_unwind; 328} 329 330static CORE_ADDR 331alpha_mdebug_frame_base_address (struct frame_info *next_frame, 332 void **this_prologue_cache) 333{ 334 struct alpha_mdebug_unwind_cache *info 335 = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache); 336 337 return info->vfp; 338} 339 340static CORE_ADDR 341alpha_mdebug_frame_locals_address (struct frame_info *next_frame, 342 void **this_prologue_cache) 343{ 344 struct alpha_mdebug_unwind_cache *info 345 = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache); 346 347 return info->vfp - PROC_LOCALOFF (info->proc_desc); 348} 349 350static CORE_ADDR 351alpha_mdebug_frame_args_address (struct frame_info *next_frame, 352 void **this_prologue_cache) 353{ 354 struct alpha_mdebug_unwind_cache *info 355 = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache); 356 357 return info->vfp - ALPHA_NUM_ARG_REGS * 8; 358} 359 360static const struct frame_base alpha_mdebug_frame_base = { 361 &alpha_mdebug_frame_unwind, 362 alpha_mdebug_frame_base_address, 363 alpha_mdebug_frame_locals_address, 364 alpha_mdebug_frame_args_address 365}; 366 367static const struct frame_base * 368alpha_mdebug_frame_base_sniffer (struct frame_info *next_frame) 369{ 370 CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); 371 struct mdebug_extra_func_info *proc_desc; 372 373 /* If this PC does not map to a PDR, then clearly this isn't an 374 mdebug frame. */ 375 proc_desc = find_proc_desc (pc); 376 if (proc_desc == NULL) 377 return NULL; 378 379 return &alpha_mdebug_frame_base; 380} 381 382 383void 384alpha_mdebug_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 385{ 386 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 387 388 frame_unwind_append_sniffer (gdbarch, alpha_mdebug_frame_sniffer); 389 frame_base_append_sniffer (gdbarch, alpha_mdebug_frame_base_sniffer); 390} 391