1 /* Target-dependent mdebug code for the ALPHA architecture.
2 Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
3 Free Software Foundation, Inc.
5 This file is part of GDB.
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 2 of the License, or
10 (at your option) any later version.
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.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
24 #include "frame-unwind.h"
25 #include "frame-base.h"
34 #include "gdb_string.h"
38 #include "arch-utils.h"
41 #include "gdb_assert.h"
45 #include "alpha-tdep.h"
47 /* FIXME: Some of this code should perhaps be merged with mips. */
50 /* Layout of a stack frame on the alpha:
53 pdr members: | 7th ... nth arg, |
54 | `pushed' by caller. |
56 ----------------|-------------------------------|<-- old_sp == vfp
59 | |localoff | Copies of 1st .. 6th |
60 | | | | | argument if necessary. |
62 | | | --- |-------------------------------|<-- FRAME_LOCALS_ADDRESS
64 | | | | Locals and temporaries. |
66 | | | |-------------------------------|
68 |-fregoffset | Saved float registers. |
74 | | -------|-------------------------------|
76 | | | Saved registers. |
83 | ----------|-------------------------------|
85 frameoffset | Argument build area, gets |
86 | | 7th ... nth arg for any |
87 | | called procedure. |
89 -------------|-------------------------------|<-- sp
94 #define PROC_LOW_ADDR(proc) ((proc)->pdr.adr)
95 #define PROC_FRAME_OFFSET(proc) ((proc)->pdr.frameoffset)
96 #define PROC_FRAME_REG(proc) ((proc)->pdr.framereg)
97 #define PROC_REG_MASK(proc) ((proc)->pdr.regmask)
98 #define PROC_FREG_MASK(proc) ((proc)->pdr.fregmask)
99 #define PROC_REG_OFFSET(proc) ((proc)->pdr.regoffset)
100 #define PROC_FREG_OFFSET(proc) ((proc)->pdr.fregoffset)
101 #define PROC_PC_REG(proc) ((proc)->pdr.pcreg)
102 #define PROC_LOCALOFF(proc) ((proc)->pdr.localoff)
104 /* Locate the mdebug PDR for the given PC. Return null if one can't
105 be found; you'll have to fall back to other methods in that case. */
107 static alpha_extra_func_info_t
108 find_proc_desc (CORE_ADDR pc
)
110 struct block
*b
= block_for_pc (pc
);
111 alpha_extra_func_info_t proc_desc
= NULL
;
112 struct symbol
*sym
= NULL
;
117 find_pc_partial_function (pc
, NULL
, &startaddr
, NULL
);
119 if (startaddr
> BLOCK_START (b
))
120 /* This is the "pathological" case referred to in a comment in
121 print_frame_info. It might be better to move this check into
125 sym
= lookup_symbol (MIPS_EFI_SYMBOL_NAME
, b
, LABEL_DOMAIN
, 0, NULL
);
130 proc_desc
= (alpha_extra_func_info_t
) SYMBOL_VALUE (sym
);
132 /* If we never found a PDR for this function in symbol reading,
133 then examine prologues to find the information. */
134 if (proc_desc
->pdr
.framereg
== -1)
141 /* This returns the PC of the first inst after the prologue. If we can't
142 find the prologue, then return 0. */
145 alpha_mdebug_after_prologue (CORE_ADDR pc
, alpha_extra_func_info_t proc_desc
)
149 /* If function is frameless, then we need to do it the hard way. I
150 strongly suspect that frameless always means prologueless... */
151 if (PROC_FRAME_REG (proc_desc
) == SP_REGNUM
152 && PROC_FRAME_OFFSET (proc_desc
) == 0)
156 return alpha_after_prologue (pc
);
159 /* Return non-zero if we *might* be in a function prologue. Return zero
160 if we are definitively *not* in a function prologue. */
163 alpha_mdebug_in_prologue (CORE_ADDR pc
, alpha_extra_func_info_t proc_desc
)
165 CORE_ADDR after_prologue_pc
= alpha_mdebug_after_prologue (pc
, proc_desc
);
166 return (after_prologue_pc
== 0 || pc
< after_prologue_pc
);
170 /* Frame unwinder that reads mdebug PDRs. */
172 struct alpha_mdebug_unwind_cache
174 alpha_extra_func_info_t proc_desc
;
176 CORE_ADDR
*saved_regs
;
177 void *in_prologue_cache
;
180 /* Extract all of the information about the frame from PROC_DESC
181 and store the resulting register save locations in the structure. */
183 static struct alpha_mdebug_unwind_cache
*
184 alpha_mdebug_frame_unwind_cache (struct frame_info
*next_frame
,
185 void **this_prologue_cache
)
187 struct alpha_mdebug_unwind_cache
*info
;
188 alpha_extra_func_info_t proc_desc
;
190 CORE_ADDR pc
, reg_position
;
194 if (*this_prologue_cache
)
195 return *this_prologue_cache
;
197 info
= FRAME_OBSTACK_ZALLOC (struct alpha_mdebug_unwind_cache
);
198 *this_prologue_cache
= info
;
199 pc
= frame_pc_unwind (next_frame
);
201 /* ??? We don't seem to be able to cache the lookup of the PDR
202 from alpha_mdebug_frame_p. It'd be nice if we could change
203 the arguments to that function. Oh well. */
204 proc_desc
= find_proc_desc (pc
);
205 info
->proc_desc
= proc_desc
;
206 gdb_assert (proc_desc
!= NULL
);
208 /* If we're in the prologue, the PDR for this frame is not yet valid. */
209 /* ??? We could have said "no" in alpha_mdebug_frame_p, and we'd
210 walk down the list of unwinders and try the heuristic unwinder
211 and things would have been fine. However, since we have the PDR,
212 we know how to skip the search for the start of the procedure,
213 and all the uncertainty involved there. So instead, arrange for
214 us to defer to the heuristic unwinder directly. */
215 if (alpha_mdebug_in_prologue (pc
, proc_desc
))
217 alpha_heuristic_frame_unwind_cache (next_frame
,
218 &info
->in_prologue_cache
,
219 PROC_LOW_ADDR (proc_desc
));
223 info
->saved_regs
= frame_obstack_zalloc (SIZEOF_FRAME_SAVED_REGS
);
225 /* The VFP of the frame is at FRAME_REG+FRAME_OFFSET. */
226 frame_unwind_unsigned_register (next_frame
, PROC_FRAME_REG (proc_desc
), &vfp
);
227 vfp
+= PROC_FRAME_OFFSET (info
->proc_desc
);
230 /* Fill in the offsets for the registers which gen_mask says were saved. */
232 reg_position
= vfp
+ PROC_REG_OFFSET (proc_desc
);
233 mask
= PROC_REG_MASK (proc_desc
);
234 returnreg
= PROC_PC_REG (proc_desc
);
236 /* Note that RA is always saved first, regardless of its actual
238 if (mask
& (1 << returnreg
))
240 /* Clear bit for RA so we don't save it again later. */
241 mask
&= ~(1 << returnreg
);
243 info
->saved_regs
[returnreg
] = reg_position
;
247 for (ireg
= 0; ireg
<= 31; ++ireg
)
248 if (mask
& (1 << ireg
))
250 info
->saved_regs
[ireg
] = reg_position
;
254 reg_position
= vfp
+ PROC_FREG_OFFSET (proc_desc
);
255 mask
= PROC_FREG_MASK (proc_desc
);
257 for (ireg
= 0; ireg
<= 31; ++ireg
)
258 if (mask
& (1 << ireg
))
260 info
->saved_regs
[FP0_REGNUM
+ ireg
] = reg_position
;
267 /* Given a GDB frame, determine the address of the calling function's
268 frame. This will be used to create a new GDB frame struct. */
271 alpha_mdebug_frame_this_id (struct frame_info
*next_frame
,
272 void **this_prologue_cache
,
273 struct frame_id
*this_id
)
275 struct alpha_mdebug_unwind_cache
*info
276 = alpha_mdebug_frame_unwind_cache (next_frame
, this_prologue_cache
);
278 /* If we're in the prologue, defer to the heuristic unwinder. */
279 if (info
->in_prologue_cache
)
280 alpha_heuristic_frame_this_id (next_frame
, &info
->in_prologue_cache
,
283 *this_id
= frame_id_build (info
->vfp
, frame_func_unwind (next_frame
));
286 /* Retrieve the value of REGNUM in FRAME. Don't give up! */
289 alpha_mdebug_frame_prev_register (struct frame_info
*next_frame
,
290 void **this_prologue_cache
,
291 int regnum
, int *optimizedp
,
292 enum lval_type
*lvalp
, CORE_ADDR
*addrp
,
293 int *realnump
, void *bufferp
)
295 struct alpha_mdebug_unwind_cache
*info
296 = alpha_mdebug_frame_unwind_cache (next_frame
, this_prologue_cache
);
298 /* If we're in the prologue, defer to the heuristic unwinder. */
299 if (info
->in_prologue_cache
)
301 alpha_heuristic_frame_prev_register (next_frame
,
302 &info
->in_prologue_cache
,
303 regnum
, optimizedp
, lvalp
,
304 addrp
, realnump
, bufferp
);
308 /* The PC of the previous frame is stored in the link register of
309 the current frame. Frob regnum so that we pull the value from
310 the correct place. */
311 if (regnum
== PC_REGNUM
)
312 regnum
= PROC_PC_REG (info
->proc_desc
);
314 /* For all registers known to be saved in the current frame,
315 do the obvious and pull the value out. */
316 if (info
->saved_regs
[regnum
])
319 *lvalp
= lval_memory
;
320 *addrp
= info
->saved_regs
[regnum
];
323 read_memory (*addrp
, bufferp
, ALPHA_REGISTER_SIZE
);
327 /* The stack pointer of the previous frame is computed by popping
328 the current stack frame. */
329 if (regnum
== SP_REGNUM
)
336 store_unsigned_integer (bufferp
, ALPHA_REGISTER_SIZE
, info
->vfp
);
340 /* Otherwise assume the next frame has the same register value. */
341 frame_register (next_frame
, regnum
, optimizedp
, lvalp
, addrp
,
345 static const struct frame_unwind alpha_mdebug_frame_unwind
= {
347 alpha_mdebug_frame_this_id
,
348 alpha_mdebug_frame_prev_register
351 const struct frame_unwind
*
352 alpha_mdebug_frame_p (CORE_ADDR pc
)
354 alpha_extra_func_info_t proc_desc
;
356 /* If this PC does not map to a PDR, then clearly this isn't an
358 proc_desc
= find_proc_desc (pc
);
359 if (proc_desc
== NULL
)
362 return &alpha_mdebug_frame_unwind
;
366 alpha_mdebug_frame_base_address (struct frame_info
*next_frame
,
367 void **this_prologue_cache
)
369 struct alpha_mdebug_unwind_cache
*info
370 = alpha_mdebug_frame_unwind_cache (next_frame
, this_prologue_cache
);
372 if (info
->in_prologue_cache
)
373 return alpha_heuristic_frame_base_address (next_frame
,
374 &info
->in_prologue_cache
);
380 alpha_mdebug_frame_locals_address (struct frame_info
*next_frame
,
381 void **this_prologue_cache
)
383 struct alpha_mdebug_unwind_cache
*info
384 = alpha_mdebug_frame_unwind_cache (next_frame
, this_prologue_cache
);
387 if (info
->in_prologue_cache
)
388 vfp
= alpha_heuristic_frame_base_address (next_frame
,
389 &info
->in_prologue_cache
);
393 return vfp
- PROC_LOCALOFF (info
->proc_desc
);
397 alpha_mdebug_frame_args_address (struct frame_info
*next_frame
,
398 void **this_prologue_cache
)
400 struct alpha_mdebug_unwind_cache
*info
401 = alpha_mdebug_frame_unwind_cache (next_frame
, this_prologue_cache
);
404 if (info
->in_prologue_cache
)
405 vfp
= alpha_heuristic_frame_base_address (next_frame
,
406 &info
->in_prologue_cache
);
410 return vfp
- ALPHA_NUM_ARG_REGS
* 8;
413 static const struct frame_base alpha_mdebug_frame_base
= {
414 &alpha_mdebug_frame_unwind
,
415 alpha_mdebug_frame_base_address
,
416 alpha_mdebug_frame_locals_address
,
417 alpha_mdebug_frame_args_address
420 static const struct frame_base
*
421 alpha_mdebug_frame_base_p (CORE_ADDR pc
)
423 alpha_extra_func_info_t proc_desc
;
425 /* If this PC does not map to a PDR, then clearly this isn't an
427 proc_desc
= find_proc_desc (pc
);
428 if (proc_desc
== NULL
)
431 return &alpha_mdebug_frame_base
;
436 alpha_mdebug_init_abi (struct gdbarch_info info
, struct gdbarch
*gdbarch
)
438 struct gdbarch_tdep
*tdep
= gdbarch_tdep (gdbarch
);
440 frame_unwind_append_predicate (gdbarch
, alpha_mdebug_frame_p
);
441 frame_base_append_predicate (gdbarch
, alpha_mdebug_frame_base_p
);