PR ld/6519
[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
2570f2b7 112 sym = lookup_symbol (MDEBUG_EFI_SYMBOL_NAME, b, LABEL_DOMAIN, 0);
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 *
6834c9bb 180alpha_mdebug_frame_unwind_cache (struct frame_info *this_frame,
d2427a71
RH
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;
6834c9bb 195 pc = get_frame_pc (this_frame);
d2427a71
RH
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. */
6834c9bb 207 vfp = get_frame_register_unsigned (this_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
6834c9bb 252alpha_mdebug_frame_this_id (struct frame_info *this_frame,
d2427a71
RH
253 void **this_prologue_cache,
254 struct frame_id *this_id)
255{
256 struct alpha_mdebug_unwind_cache *info
6834c9bb 257 = alpha_mdebug_frame_unwind_cache (this_frame, this_prologue_cache);
d2427a71 258
6834c9bb 259 *this_id = frame_id_build (info->vfp, get_frame_func (this_frame));
d2427a71
RH
260}
261
262/* Retrieve the value of REGNUM in FRAME. Don't give up! */
263
6834c9bb
JB
264static struct value *
265alpha_mdebug_frame_prev_register (struct frame_info *this_frame,
266 void **this_prologue_cache, int regnum)
d2427a71
RH
267{
268 struct alpha_mdebug_unwind_cache *info
6834c9bb 269 = alpha_mdebug_frame_unwind_cache (this_frame, this_prologue_cache);
d2427a71 270
d2427a71
RH
271 /* The PC of the previous frame is stored in the link register of
272 the current frame. Frob regnum so that we pull the value from
273 the correct place. */
087779b1 274 if (regnum == ALPHA_PC_REGNUM)
d2427a71
RH
275 regnum = PROC_PC_REG (info->proc_desc);
276
277 /* For all registers known to be saved in the current frame,
278 do the obvious and pull the value out. */
279 if (info->saved_regs[regnum])
6834c9bb
JB
280 return frame_unwind_got_memory (this_frame, regnum,
281 info->saved_regs[regnum]);
d2427a71
RH
282
283 /* The stack pointer of the previous frame is computed by popping
284 the current stack frame. */
087779b1 285 if (regnum == ALPHA_SP_REGNUM)
6834c9bb 286 return frame_unwind_got_constant (this_frame, regnum, info->vfp);
d2427a71
RH
287
288 /* Otherwise assume the next frame has the same register value. */
6834c9bb 289 return frame_unwind_got_register (this_frame, regnum, regnum);
d2427a71
RH
290}
291
6834c9bb
JB
292static int
293alpha_mdebug_frame_sniffer (const struct frame_unwind *self,
294 struct frame_info *this_frame,
295 void **this_cache)
d2427a71 296{
6834c9bb 297 CORE_ADDR pc = get_frame_address_in_block (this_frame);
5f6a2351 298 struct mdebug_extra_func_info *proc_desc;
d2427a71
RH
299
300 /* If this PC does not map to a PDR, then clearly this isn't an
301 mdebug frame. */
302 proc_desc = find_proc_desc (pc);
303 if (proc_desc == NULL)
6834c9bb 304 return 0;
d2427a71 305
fbe586ae
RH
306 /* If we're in the prologue, the PDR for this frame is not yet valid.
307 Say no here and we'll fall back on the heuristic unwinder. */
308 if (alpha_mdebug_in_prologue (pc, proc_desc))
6834c9bb 309 return 0;
fbe586ae 310
6834c9bb 311 return 1;
d2427a71
RH
312}
313
6834c9bb
JB
314static const struct frame_unwind alpha_mdebug_frame_unwind = {
315 NORMAL_FRAME,
316 alpha_mdebug_frame_this_id,
317 alpha_mdebug_frame_prev_register,
318 NULL,
319 alpha_mdebug_frame_sniffer
320};
321
d2427a71 322static CORE_ADDR
6834c9bb 323alpha_mdebug_frame_base_address (struct frame_info *this_frame,
d2427a71
RH
324 void **this_prologue_cache)
325{
326 struct alpha_mdebug_unwind_cache *info
6834c9bb 327 = alpha_mdebug_frame_unwind_cache (this_frame, this_prologue_cache);
d2427a71 328
fbe586ae 329 return info->vfp;
d2427a71
RH
330}
331
332static CORE_ADDR
6834c9bb 333alpha_mdebug_frame_locals_address (struct frame_info *this_frame,
d2427a71
RH
334 void **this_prologue_cache)
335{
336 struct alpha_mdebug_unwind_cache *info
6834c9bb 337 = alpha_mdebug_frame_unwind_cache (this_frame, this_prologue_cache);
d2427a71 338
fbe586ae 339 return info->vfp - PROC_LOCALOFF (info->proc_desc);
d2427a71
RH
340}
341
342static CORE_ADDR
6834c9bb 343alpha_mdebug_frame_args_address (struct frame_info *this_frame,
d2427a71
RH
344 void **this_prologue_cache)
345{
346 struct alpha_mdebug_unwind_cache *info
6834c9bb 347 = alpha_mdebug_frame_unwind_cache (this_frame, this_prologue_cache);
d2427a71 348
fbe586ae 349 return info->vfp - ALPHA_NUM_ARG_REGS * 8;
d2427a71
RH
350}
351
352static const struct frame_base alpha_mdebug_frame_base = {
353 &alpha_mdebug_frame_unwind,
354 alpha_mdebug_frame_base_address,
355 alpha_mdebug_frame_locals_address,
356 alpha_mdebug_frame_args_address
357};
358
359static const struct frame_base *
6834c9bb 360alpha_mdebug_frame_base_sniffer (struct frame_info *this_frame)
d2427a71 361{
6834c9bb 362 CORE_ADDR pc = get_frame_address_in_block (this_frame);
5f6a2351 363 struct mdebug_extra_func_info *proc_desc;
d2427a71
RH
364
365 /* If this PC does not map to a PDR, then clearly this isn't an
366 mdebug frame. */
367 proc_desc = find_proc_desc (pc);
368 if (proc_desc == NULL)
369 return NULL;
370
371 return &alpha_mdebug_frame_base;
372}
373
374\f
375void
376alpha_mdebug_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
377{
378 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
379
6834c9bb 380 frame_unwind_append_unwinder (gdbarch, &alpha_mdebug_frame_unwind);
336d1bba 381 frame_base_append_sniffer (gdbarch, alpha_mdebug_frame_base_sniffer);
d2427a71 382}
This page took 0.308478 seconds and 4 git commands to generate.