* ada-lang.c (static_unwrap_type): Add forward declaration.
[deliverable/binutils-gdb.git] / gdb / alpha-mdebug-tdep.c
CommitLineData
d2427a71 1/* Target-dependent mdebug code for the ALPHA architecture.
6aba47ca 2 Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
9b254dd1 3 2003, 2007, 2008 Free Software Foundation, Inc.
d2427a71
RH
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
a9762ec7 9 the Free Software Foundation; either version 3 of the License, or
d2427a71
RH
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
a9762ec7 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
d2427a71
RH
19
20#include "defs.h"
21#include "frame.h"
22#include "frame-unwind.h"
23#include "frame-base.h"
d2427a71 24#include "symtab.h"
d2427a71 25#include "gdbcore.h"
d2427a71
RH
26#include "block.h"
27#include "gdb_assert.h"
62f6180c 28#include "gdb_string.h"
d2427a71 29
d2427a71 30#include "alpha-tdep.h"
5f6a2351 31#include "mdebugread.h"
d2427a71
RH
32
33/* FIXME: Some of this code should perhaps be merged with mips. */
34
35/* *INDENT-OFF* */
36/* Layout of a stack frame on the alpha:
37
38 | |
39 pdr members: | 7th ... nth arg, |
40 | `pushed' by caller. |
41 | |
42----------------|-------------------------------|<-- old_sp == vfp
43 ^ ^ ^ ^ | |
44 | | | | | |
45 | |localoff | Copies of 1st .. 6th |
46 | | | | | argument if necessary. |
47 | | | v | |
42efa47a 48 | | | --- |-------------------------------|<-- LOCALS_ADDRESS
d2427a71
RH
49 | | | | |
50 | | | | Locals and temporaries. |
51 | | | | |
52 | | | |-------------------------------|
53 | | | | |
54 |-fregoffset | Saved float registers. |
55 | | | | F9 |
56 | | | | . |
57 | | | | . |
58 | | | | F2 |
59 | | v | |
60 | | -------|-------------------------------|
61 | | | |
62 | | | Saved registers. |
63 | | | S6 |
64 |-regoffset | . |
65 | | | . |
66 | | | S0 |
67 | | | pdr.pcreg |
68 | v | |
69 | ----------|-------------------------------|
70 | | |
71 frameoffset | Argument build area, gets |
72 | | 7th ... nth arg for any |
73 | | called procedure. |
74 v | |
75 -------------|-------------------------------|<-- sp
76 | |
77*/
78/* *INDENT-ON* */
79
80#define PROC_LOW_ADDR(proc) ((proc)->pdr.adr)
81#define PROC_FRAME_OFFSET(proc) ((proc)->pdr.frameoffset)
82#define PROC_FRAME_REG(proc) ((proc)->pdr.framereg)
83#define PROC_REG_MASK(proc) ((proc)->pdr.regmask)
84#define PROC_FREG_MASK(proc) ((proc)->pdr.fregmask)
85#define PROC_REG_OFFSET(proc) ((proc)->pdr.regoffset)
86#define PROC_FREG_OFFSET(proc) ((proc)->pdr.fregoffset)
87#define PROC_PC_REG(proc) ((proc)->pdr.pcreg)
88#define PROC_LOCALOFF(proc) ((proc)->pdr.localoff)
89\f
90/* Locate the mdebug PDR for the given PC. Return null if one can't
91 be found; you'll have to fall back to other methods in that case. */
92
5f6a2351 93static struct mdebug_extra_func_info *
d2427a71
RH
94find_proc_desc (CORE_ADDR pc)
95{
96 struct block *b = block_for_pc (pc);
5f6a2351 97 struct mdebug_extra_func_info *proc_desc = NULL;
d2427a71 98 struct symbol *sym = NULL;
62f6180c 99 char *sh_name = NULL;
d2427a71
RH
100
101 if (b)
102 {
103 CORE_ADDR startaddr;
62f6180c 104 find_pc_partial_function (pc, &sh_name, &startaddr, NULL);
d2427a71
RH
105
106 if (startaddr > BLOCK_START (b))
107 /* This is the "pathological" case referred to in a comment in
108 print_frame_info. It might be better to move this check into
109 symbol reading. */
110 sym = NULL;
111 else
f92761ec 112 sym = lookup_symbol (MDEBUG_EFI_SYMBOL_NAME, b, LABEL_DOMAIN, 0, NULL);
d2427a71
RH
113 }
114
115 if (sym)
116 {
5f6a2351 117 proc_desc = (struct mdebug_extra_func_info *) SYMBOL_VALUE (sym);
d2427a71 118
62f6180c
UW
119 /* Correct incorrect setjmp procedure descriptor from the library
120 to make backtrace through setjmp work. */
121 if (proc_desc->pdr.pcreg == 0
122 && strcmp (sh_name, "setjmp") == 0)
123 {
124 proc_desc->pdr.pcreg = ALPHA_RA_REGNUM;
125 proc_desc->pdr.regmask = 0x80000000;
126 proc_desc->pdr.regoffset = -4;
127 }
128
d2427a71
RH
129 /* If we never found a PDR for this function in symbol reading,
130 then examine prologues to find the information. */
131 if (proc_desc->pdr.framereg == -1)
132 proc_desc = NULL;
133 }
134
135 return proc_desc;
136}
137
138/* This returns the PC of the first inst after the prologue. If we can't
139 find the prologue, then return 0. */
140
141static CORE_ADDR
5f6a2351 142alpha_mdebug_after_prologue (CORE_ADDR pc, struct mdebug_extra_func_info *proc_desc)
d2427a71
RH
143{
144 if (proc_desc)
145 {
146 /* If function is frameless, then we need to do it the hard way. I
147 strongly suspect that frameless always means prologueless... */
087779b1 148 if (PROC_FRAME_REG (proc_desc) == ALPHA_SP_REGNUM
d2427a71
RH
149 && PROC_FRAME_OFFSET (proc_desc) == 0)
150 return 0;
151 }
152
153 return alpha_after_prologue (pc);
154}
155
156/* Return non-zero if we *might* be in a function prologue. Return zero
157 if we are definitively *not* in a function prologue. */
158
159static int
5f6a2351 160alpha_mdebug_in_prologue (CORE_ADDR pc, struct mdebug_extra_func_info *proc_desc)
d2427a71
RH
161{
162 CORE_ADDR after_prologue_pc = alpha_mdebug_after_prologue (pc, proc_desc);
163 return (after_prologue_pc == 0 || pc < after_prologue_pc);
164}
165
166\f
167/* Frame unwinder that reads mdebug PDRs. */
168
169struct alpha_mdebug_unwind_cache
170{
5f6a2351 171 struct mdebug_extra_func_info *proc_desc;
d2427a71
RH
172 CORE_ADDR vfp;
173 CORE_ADDR *saved_regs;
d2427a71
RH
174};
175
176/* Extract all of the information about the frame from PROC_DESC
177 and store the resulting register save locations in the structure. */
178
179static struct alpha_mdebug_unwind_cache *
180alpha_mdebug_frame_unwind_cache (struct frame_info *next_frame,
181 void **this_prologue_cache)
182{
183 struct alpha_mdebug_unwind_cache *info;
5f6a2351 184 struct mdebug_extra_func_info *proc_desc;
d2427a71
RH
185 ULONGEST vfp;
186 CORE_ADDR pc, reg_position;
187 unsigned long mask;
188 int ireg, returnreg;
189
190 if (*this_prologue_cache)
191 return *this_prologue_cache;
192
193 info = FRAME_OBSTACK_ZALLOC (struct alpha_mdebug_unwind_cache);
194 *this_prologue_cache = info;
195 pc = frame_pc_unwind (next_frame);
196
197 /* ??? We don't seem to be able to cache the lookup of the PDR
198 from alpha_mdebug_frame_p. It'd be nice if we could change
199 the arguments to that function. Oh well. */
200 proc_desc = find_proc_desc (pc);
201 info->proc_desc = proc_desc;
202 gdb_assert (proc_desc != NULL);
203
d2427a71
RH
204 info->saved_regs = frame_obstack_zalloc (SIZEOF_FRAME_SAVED_REGS);
205
206 /* The VFP of the frame is at FRAME_REG+FRAME_OFFSET. */
11411de3 207 vfp = frame_unwind_register_unsigned (next_frame, PROC_FRAME_REG (proc_desc));
d2427a71
RH
208 vfp += PROC_FRAME_OFFSET (info->proc_desc);
209 info->vfp = vfp;
210
211 /* Fill in the offsets for the registers which gen_mask says were saved. */
212
213 reg_position = vfp + PROC_REG_OFFSET (proc_desc);
214 mask = PROC_REG_MASK (proc_desc);
215 returnreg = PROC_PC_REG (proc_desc);
216
217 /* Note that RA is always saved first, regardless of its actual
218 register number. */
219 if (mask & (1 << returnreg))
220 {
221 /* Clear bit for RA so we don't save it again later. */
222 mask &= ~(1 << returnreg);
223
224 info->saved_regs[returnreg] = reg_position;
225 reg_position += 8;
226 }
227
228 for (ireg = 0; ireg <= 31; ++ireg)
229 if (mask & (1 << ireg))
230 {
231 info->saved_regs[ireg] = reg_position;
232 reg_position += 8;
233 }
234
235 reg_position = vfp + PROC_FREG_OFFSET (proc_desc);
236 mask = PROC_FREG_MASK (proc_desc);
237
238 for (ireg = 0; ireg <= 31; ++ireg)
239 if (mask & (1 << ireg))
240 {
087779b1 241 info->saved_regs[ALPHA_FP0_REGNUM + ireg] = reg_position;
d2427a71
RH
242 reg_position += 8;
243 }
244
245 return info;
246}
247
248/* Given a GDB frame, determine the address of the calling function's
249 frame. This will be used to create a new GDB frame struct. */
250
251static void
252alpha_mdebug_frame_this_id (struct frame_info *next_frame,
253 void **this_prologue_cache,
254 struct frame_id *this_id)
255{
256 struct alpha_mdebug_unwind_cache *info
257 = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache);
258
93d42b30
DJ
259 *this_id = frame_id_build (info->vfp,
260 frame_func_unwind (next_frame, NORMAL_FRAME));
d2427a71
RH
261}
262
263/* Retrieve the value of REGNUM in FRAME. Don't give up! */
264
265static void
266alpha_mdebug_frame_prev_register (struct frame_info *next_frame,
267 void **this_prologue_cache,
268 int regnum, int *optimizedp,
269 enum lval_type *lvalp, CORE_ADDR *addrp,
5b819568 270 int *realnump, gdb_byte *bufferp)
d2427a71
RH
271{
272 struct alpha_mdebug_unwind_cache *info
273 = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache);
274
d2427a71
RH
275 /* The PC of the previous frame is stored in the link register of
276 the current frame. Frob regnum so that we pull the value from
277 the correct place. */
087779b1 278 if (regnum == ALPHA_PC_REGNUM)
d2427a71
RH
279 regnum = PROC_PC_REG (info->proc_desc);
280
281 /* For all registers known to be saved in the current frame,
282 do the obvious and pull the value out. */
283 if (info->saved_regs[regnum])
284 {
285 *optimizedp = 0;
286 *lvalp = lval_memory;
287 *addrp = info->saved_regs[regnum];
288 *realnump = -1;
289 if (bufferp != NULL)
b21fd293 290 get_frame_memory (next_frame, *addrp, bufferp, ALPHA_REGISTER_SIZE);
d2427a71
RH
291 return;
292 }
293
294 /* The stack pointer of the previous frame is computed by popping
295 the current stack frame. */
087779b1 296 if (regnum == ALPHA_SP_REGNUM)
d2427a71
RH
297 {
298 *optimizedp = 0;
299 *lvalp = not_lval;
300 *addrp = 0;
301 *realnump = -1;
302 if (bufferp != NULL)
303 store_unsigned_integer (bufferp, ALPHA_REGISTER_SIZE, info->vfp);
304 return;
305 }
306
307 /* Otherwise assume the next frame has the same register value. */
5efde112
DJ
308 *optimizedp = 0;
309 *lvalp = lval_register;
310 *addrp = 0;
311 *realnump = regnum;
312 if (bufferp)
313 frame_unwind_register (next_frame, *realnump, bufferp);
d2427a71
RH
314}
315
316static const struct frame_unwind alpha_mdebug_frame_unwind = {
317 NORMAL_FRAME,
318 alpha_mdebug_frame_this_id,
319 alpha_mdebug_frame_prev_register
320};
321
322const struct frame_unwind *
336d1bba 323alpha_mdebug_frame_sniffer (struct frame_info *next_frame)
d2427a71 324{
93d42b30 325 CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME);
5f6a2351 326 struct mdebug_extra_func_info *proc_desc;
d2427a71
RH
327
328 /* If this PC does not map to a PDR, then clearly this isn't an
329 mdebug frame. */
330 proc_desc = find_proc_desc (pc);
331 if (proc_desc == NULL)
332 return NULL;
333
fbe586ae
RH
334 /* If we're in the prologue, the PDR for this frame is not yet valid.
335 Say no here and we'll fall back on the heuristic unwinder. */
336 if (alpha_mdebug_in_prologue (pc, proc_desc))
337 return NULL;
338
d2427a71
RH
339 return &alpha_mdebug_frame_unwind;
340}
341
342static CORE_ADDR
343alpha_mdebug_frame_base_address (struct frame_info *next_frame,
344 void **this_prologue_cache)
345{
346 struct alpha_mdebug_unwind_cache *info
347 = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache);
348
fbe586ae 349 return info->vfp;
d2427a71
RH
350}
351
352static CORE_ADDR
353alpha_mdebug_frame_locals_address (struct frame_info *next_frame,
354 void **this_prologue_cache)
355{
356 struct alpha_mdebug_unwind_cache *info
357 = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache);
d2427a71 358
fbe586ae 359 return info->vfp - PROC_LOCALOFF (info->proc_desc);
d2427a71
RH
360}
361
362static CORE_ADDR
363alpha_mdebug_frame_args_address (struct frame_info *next_frame,
364 void **this_prologue_cache)
365{
366 struct alpha_mdebug_unwind_cache *info
367 = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache);
d2427a71 368
fbe586ae 369 return info->vfp - ALPHA_NUM_ARG_REGS * 8;
d2427a71
RH
370}
371
372static const struct frame_base alpha_mdebug_frame_base = {
373 &alpha_mdebug_frame_unwind,
374 alpha_mdebug_frame_base_address,
375 alpha_mdebug_frame_locals_address,
376 alpha_mdebug_frame_args_address
377};
378
379static const struct frame_base *
336d1bba 380alpha_mdebug_frame_base_sniffer (struct frame_info *next_frame)
d2427a71 381{
93d42b30 382 CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME);
5f6a2351 383 struct mdebug_extra_func_info *proc_desc;
d2427a71
RH
384
385 /* If this PC does not map to a PDR, then clearly this isn't an
386 mdebug frame. */
387 proc_desc = find_proc_desc (pc);
388 if (proc_desc == NULL)
389 return NULL;
390
391 return &alpha_mdebug_frame_base;
392}
393
394\f
395void
396alpha_mdebug_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
397{
398 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
399
336d1bba
AC
400 frame_unwind_append_sniffer (gdbarch, alpha_mdebug_frame_sniffer);
401 frame_base_append_sniffer (gdbarch, alpha_mdebug_frame_base_sniffer);
d2427a71 402}
This page took 0.291824 seconds and 4 git commands to generate.