bfd/
[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"
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 {
5f6a2351 118 proc_desc = (struct mdebug_extra_func_info *) SYMBOL_VALUE (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
139/* This returns the PC of the first inst after the prologue. If we can't
140 find the prologue, then return 0. */
141
142static CORE_ADDR
5f6a2351 143alpha_mdebug_after_prologue (CORE_ADDR pc, struct mdebug_extra_func_info *proc_desc)
d2427a71
RH
144{
145 if (proc_desc)
146 {
147 /* If function is frameless, then we need to do it the hard way. I
148 strongly suspect that frameless always means prologueless... */
087779b1 149 if (PROC_FRAME_REG (proc_desc) == ALPHA_SP_REGNUM
d2427a71
RH
150 && PROC_FRAME_OFFSET (proc_desc) == 0)
151 return 0;
152 }
153
154 return alpha_after_prologue (pc);
155}
156
157/* Return non-zero if we *might* be in a function prologue. Return zero
158 if we are definitively *not* in a function prologue. */
159
160static int
5f6a2351 161alpha_mdebug_in_prologue (CORE_ADDR pc, struct mdebug_extra_func_info *proc_desc)
d2427a71
RH
162{
163 CORE_ADDR after_prologue_pc = alpha_mdebug_after_prologue (pc, proc_desc);
164 return (after_prologue_pc == 0 || pc < after_prologue_pc);
165}
166
167\f
168/* Frame unwinder that reads mdebug PDRs. */
169
170struct alpha_mdebug_unwind_cache
171{
5f6a2351 172 struct mdebug_extra_func_info *proc_desc;
d2427a71 173 CORE_ADDR vfp;
0cd9ab92 174 struct trad_frame_saved_reg *saved_regs;
d2427a71
RH
175};
176
177/* Extract all of the information about the frame from PROC_DESC
178 and store the resulting register save locations in the structure. */
179
180static struct alpha_mdebug_unwind_cache *
6834c9bb 181alpha_mdebug_frame_unwind_cache (struct frame_info *this_frame,
d2427a71
RH
182 void **this_prologue_cache)
183{
184 struct alpha_mdebug_unwind_cache *info;
5f6a2351 185 struct mdebug_extra_func_info *proc_desc;
d2427a71
RH
186 ULONGEST vfp;
187 CORE_ADDR pc, reg_position;
188 unsigned long mask;
189 int ireg, returnreg;
190
191 if (*this_prologue_cache)
192 return *this_prologue_cache;
193
194 info = FRAME_OBSTACK_ZALLOC (struct alpha_mdebug_unwind_cache);
195 *this_prologue_cache = info;
6834c9bb 196 pc = get_frame_pc (this_frame);
d2427a71
RH
197
198 /* ??? We don't seem to be able to cache the lookup of the PDR
199 from alpha_mdebug_frame_p. It'd be nice if we could change
200 the arguments to that function. Oh well. */
201 proc_desc = find_proc_desc (pc);
202 info->proc_desc = proc_desc;
203 gdb_assert (proc_desc != NULL);
204
0cd9ab92 205 info->saved_regs = trad_frame_alloc_saved_regs (this_frame);
d2427a71
RH
206
207 /* The VFP of the frame is at FRAME_REG+FRAME_OFFSET. */
6834c9bb 208 vfp = get_frame_register_unsigned (this_frame, PROC_FRAME_REG (proc_desc));
d2427a71
RH
209 vfp += PROC_FRAME_OFFSET (info->proc_desc);
210 info->vfp = vfp;
211
212 /* Fill in the offsets for the registers which gen_mask says were saved. */
213
214 reg_position = vfp + PROC_REG_OFFSET (proc_desc);
215 mask = PROC_REG_MASK (proc_desc);
216 returnreg = PROC_PC_REG (proc_desc);
217
218 /* Note that RA is always saved first, regardless of its actual
219 register number. */
220 if (mask & (1 << returnreg))
221 {
222 /* Clear bit for RA so we don't save it again later. */
223 mask &= ~(1 << returnreg);
224
0cd9ab92 225 info->saved_regs[returnreg].addr = reg_position;
d2427a71
RH
226 reg_position += 8;
227 }
228
229 for (ireg = 0; ireg <= 31; ++ireg)
230 if (mask & (1 << ireg))
231 {
0cd9ab92 232 info->saved_regs[ireg].addr = reg_position;
d2427a71
RH
233 reg_position += 8;
234 }
235
236 reg_position = vfp + PROC_FREG_OFFSET (proc_desc);
237 mask = PROC_FREG_MASK (proc_desc);
238
239 for (ireg = 0; ireg <= 31; ++ireg)
240 if (mask & (1 << ireg))
241 {
0cd9ab92 242 info->saved_regs[ALPHA_FP0_REGNUM + ireg].addr = reg_position;
d2427a71
RH
243 reg_position += 8;
244 }
245
0cd9ab92
UW
246 /* The stack pointer of the previous frame is computed by popping
247 the current stack frame. */
248 if (!trad_frame_addr_p (info->saved_regs, ALPHA_SP_REGNUM))
249 trad_frame_set_value (info->saved_regs, ALPHA_SP_REGNUM, vfp);
250
d2427a71
RH
251 return info;
252}
253
254/* Given a GDB frame, determine the address of the calling function's
255 frame. This will be used to create a new GDB frame struct. */
256
257static void
6834c9bb 258alpha_mdebug_frame_this_id (struct frame_info *this_frame,
d2427a71
RH
259 void **this_prologue_cache,
260 struct frame_id *this_id)
261{
262 struct alpha_mdebug_unwind_cache *info
6834c9bb 263 = alpha_mdebug_frame_unwind_cache (this_frame, this_prologue_cache);
d2427a71 264
6834c9bb 265 *this_id = frame_id_build (info->vfp, get_frame_func (this_frame));
d2427a71
RH
266}
267
268/* Retrieve the value of REGNUM in FRAME. Don't give up! */
269
6834c9bb
JB
270static struct value *
271alpha_mdebug_frame_prev_register (struct frame_info *this_frame,
272 void **this_prologue_cache, int regnum)
d2427a71
RH
273{
274 struct alpha_mdebug_unwind_cache *info
6834c9bb 275 = alpha_mdebug_frame_unwind_cache (this_frame, this_prologue_cache);
d2427a71 276
d2427a71
RH
277 /* The PC of the previous frame is stored in the link register of
278 the current frame. Frob regnum so that we pull the value from
279 the correct place. */
087779b1 280 if (regnum == ALPHA_PC_REGNUM)
d2427a71
RH
281 regnum = PROC_PC_REG (info->proc_desc);
282
0cd9ab92 283 return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
d2427a71
RH
284}
285
6834c9bb
JB
286static int
287alpha_mdebug_frame_sniffer (const struct frame_unwind *self,
288 struct frame_info *this_frame,
289 void **this_cache)
d2427a71 290{
6834c9bb 291 CORE_ADDR pc = get_frame_address_in_block (this_frame);
5f6a2351 292 struct mdebug_extra_func_info *proc_desc;
d2427a71
RH
293
294 /* If this PC does not map to a PDR, then clearly this isn't an
295 mdebug frame. */
296 proc_desc = find_proc_desc (pc);
297 if (proc_desc == NULL)
6834c9bb 298 return 0;
d2427a71 299
fbe586ae
RH
300 /* If we're in the prologue, the PDR for this frame is not yet valid.
301 Say no here and we'll fall back on the heuristic unwinder. */
302 if (alpha_mdebug_in_prologue (pc, proc_desc))
6834c9bb 303 return 0;
fbe586ae 304
6834c9bb 305 return 1;
d2427a71
RH
306}
307
6834c9bb
JB
308static const struct frame_unwind alpha_mdebug_frame_unwind = {
309 NORMAL_FRAME,
310 alpha_mdebug_frame_this_id,
311 alpha_mdebug_frame_prev_register,
312 NULL,
313 alpha_mdebug_frame_sniffer
314};
315
d2427a71 316static CORE_ADDR
6834c9bb 317alpha_mdebug_frame_base_address (struct frame_info *this_frame,
d2427a71
RH
318 void **this_prologue_cache)
319{
320 struct alpha_mdebug_unwind_cache *info
6834c9bb 321 = alpha_mdebug_frame_unwind_cache (this_frame, this_prologue_cache);
d2427a71 322
fbe586ae 323 return info->vfp;
d2427a71
RH
324}
325
326static CORE_ADDR
6834c9bb 327alpha_mdebug_frame_locals_address (struct frame_info *this_frame,
d2427a71
RH
328 void **this_prologue_cache)
329{
330 struct alpha_mdebug_unwind_cache *info
6834c9bb 331 = alpha_mdebug_frame_unwind_cache (this_frame, this_prologue_cache);
d2427a71 332
fbe586ae 333 return info->vfp - PROC_LOCALOFF (info->proc_desc);
d2427a71
RH
334}
335
336static CORE_ADDR
6834c9bb 337alpha_mdebug_frame_args_address (struct frame_info *this_frame,
d2427a71
RH
338 void **this_prologue_cache)
339{
340 struct alpha_mdebug_unwind_cache *info
6834c9bb 341 = alpha_mdebug_frame_unwind_cache (this_frame, this_prologue_cache);
d2427a71 342
fbe586ae 343 return info->vfp - ALPHA_NUM_ARG_REGS * 8;
d2427a71
RH
344}
345
346static const struct frame_base alpha_mdebug_frame_base = {
347 &alpha_mdebug_frame_unwind,
348 alpha_mdebug_frame_base_address,
349 alpha_mdebug_frame_locals_address,
350 alpha_mdebug_frame_args_address
351};
352
353static const struct frame_base *
6834c9bb 354alpha_mdebug_frame_base_sniffer (struct frame_info *this_frame)
d2427a71 355{
6834c9bb 356 CORE_ADDR pc = get_frame_address_in_block (this_frame);
5f6a2351 357 struct mdebug_extra_func_info *proc_desc;
d2427a71
RH
358
359 /* If this PC does not map to a PDR, then clearly this isn't an
360 mdebug frame. */
361 proc_desc = find_proc_desc (pc);
362 if (proc_desc == NULL)
363 return NULL;
364
365 return &alpha_mdebug_frame_base;
366}
367
368\f
369void
370alpha_mdebug_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
371{
372 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
373
6834c9bb 374 frame_unwind_append_unwinder (gdbarch, &alpha_mdebug_frame_unwind);
336d1bba 375 frame_base_append_sniffer (gdbarch, alpha_mdebug_frame_base_sniffer);
d2427a71 376}
This page took 0.297969 seconds and 4 git commands to generate.