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