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