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