OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-6.8/] [gdb/] [alpha-mdebug-tdep.c] - Blame information for rev 866

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 24 jeremybenn
/* Target-dependent mdebug code for the ALPHA architecture.
2
   Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
3
   2003, 2007, 2008 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 3 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, see <http://www.gnu.org/licenses/>.  */
19
 
20
#include "defs.h"
21
#include "frame.h"
22
#include "frame-unwind.h"
23
#include "frame-base.h"
24
#include "symtab.h"
25
#include "gdbcore.h"
26
#include "block.h"
27
#include "gdb_assert.h"
28
#include "gdb_string.h"
29
 
30
#include "alpha-tdep.h"
31
#include "mdebugread.h"
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   |                               |
48
   |  |  |  --- |-------------------------------|<-- LOCALS_ADDRESS
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
 
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
 
93
static struct mdebug_extra_func_info *
94
find_proc_desc (CORE_ADDR pc)
95
{
96
  struct block *b = block_for_pc (pc);
97
  struct mdebug_extra_func_info *proc_desc = NULL;
98
  struct symbol *sym = NULL;
99
  char *sh_name = NULL;
100
 
101
  if (b)
102
    {
103
      CORE_ADDR startaddr;
104
      find_pc_partial_function (pc, &sh_name, &startaddr, NULL);
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
112
        sym = lookup_symbol (MDEBUG_EFI_SYMBOL_NAME, b, LABEL_DOMAIN, 0, NULL);
113
    }
114
 
115
  if (sym)
116
    {
117
      proc_desc = (struct mdebug_extra_func_info *) SYMBOL_VALUE (sym);
118
 
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
 
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
 
141
static CORE_ADDR
142
alpha_mdebug_after_prologue (CORE_ADDR pc, struct mdebug_extra_func_info *proc_desc)
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... */
148
      if (PROC_FRAME_REG (proc_desc) == ALPHA_SP_REGNUM
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
 
159
static int
160
alpha_mdebug_in_prologue (CORE_ADDR pc, struct mdebug_extra_func_info *proc_desc)
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
 
167
/* Frame unwinder that reads mdebug PDRs.  */
168
 
169
struct alpha_mdebug_unwind_cache
170
{
171
  struct mdebug_extra_func_info *proc_desc;
172
  CORE_ADDR vfp;
173
  CORE_ADDR *saved_regs;
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
 
179
static struct alpha_mdebug_unwind_cache *
180
alpha_mdebug_frame_unwind_cache (struct frame_info *next_frame,
181
                                 void **this_prologue_cache)
182
{
183
  struct alpha_mdebug_unwind_cache *info;
184
  struct mdebug_extra_func_info *proc_desc;
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;
195
  pc = frame_pc_unwind (next_frame);
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
 
204
  info->saved_regs = frame_obstack_zalloc (SIZEOF_FRAME_SAVED_REGS);
205
 
206
  /* The VFP of the frame is at FRAME_REG+FRAME_OFFSET.  */
207
  vfp = frame_unwind_register_unsigned (next_frame, PROC_FRAME_REG (proc_desc));
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
      {
241
        info->saved_regs[ALPHA_FP0_REGNUM + ireg] = reg_position;
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
 
251
static void
252
alpha_mdebug_frame_this_id (struct frame_info *next_frame,
253
                            void **this_prologue_cache,
254
                            struct frame_id *this_id)
255
{
256
  struct alpha_mdebug_unwind_cache *info
257
    = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache);
258
 
259
  *this_id = frame_id_build (info->vfp,
260
                             frame_func_unwind (next_frame, NORMAL_FRAME));
261
}
262
 
263
/* Retrieve the value of REGNUM in FRAME.  Don't give up!  */
264
 
265
static void
266
alpha_mdebug_frame_prev_register (struct frame_info *next_frame,
267
                                  void **this_prologue_cache,
268
                                  int regnum, int *optimizedp,
269
                                  enum lval_type *lvalp, CORE_ADDR *addrp,
270
                                  int *realnump, gdb_byte *bufferp)
271
{
272
  struct alpha_mdebug_unwind_cache *info
273
    = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache);
274
 
275
  /* The PC of the previous frame is stored in the link register of
276
     the current frame.  Frob regnum so that we pull the value from
277
     the correct place.  */
278
  if (regnum == ALPHA_PC_REGNUM)
279
    regnum = PROC_PC_REG (info->proc_desc);
280
 
281
  /* For all registers known to be saved in the current frame,
282
     do the obvious and pull the value out.  */
283
  if (info->saved_regs[regnum])
284
    {
285
      *optimizedp = 0;
286
      *lvalp = lval_memory;
287
      *addrp = info->saved_regs[regnum];
288
      *realnump = -1;
289
      if (bufferp != NULL)
290
        get_frame_memory (next_frame, *addrp, bufferp, ALPHA_REGISTER_SIZE);
291
      return;
292
    }
293
 
294
  /* The stack pointer of the previous frame is computed by popping
295
     the current stack frame.  */
296
  if (regnum == ALPHA_SP_REGNUM)
297
    {
298
      *optimizedp = 0;
299
      *lvalp = not_lval;
300
      *addrp = 0;
301
      *realnump = -1;
302
      if (bufferp != NULL)
303
        store_unsigned_integer (bufferp, ALPHA_REGISTER_SIZE, info->vfp);
304
      return;
305
    }
306
 
307
  /* Otherwise assume the next frame has the same register value.  */
308
  *optimizedp = 0;
309
  *lvalp = lval_register;
310
  *addrp = 0;
311
  *realnump = regnum;
312
  if (bufferp)
313
    frame_unwind_register (next_frame, *realnump, bufferp);
314
}
315
 
316
static const struct frame_unwind alpha_mdebug_frame_unwind = {
317
  NORMAL_FRAME,
318
  alpha_mdebug_frame_this_id,
319
  alpha_mdebug_frame_prev_register
320
};
321
 
322
const struct frame_unwind *
323
alpha_mdebug_frame_sniffer (struct frame_info *next_frame)
324
{
325
  CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME);
326
  struct mdebug_extra_func_info *proc_desc;
327
 
328
  /* If this PC does not map to a PDR, then clearly this isn't an
329
     mdebug frame.  */
330
  proc_desc = find_proc_desc (pc);
331
  if (proc_desc == NULL)
332
    return NULL;
333
 
334
  /* If we're in the prologue, the PDR for this frame is not yet valid.
335
     Say no here and we'll fall back on the heuristic unwinder.  */
336
  if (alpha_mdebug_in_prologue (pc, proc_desc))
337
    return NULL;
338
 
339
  return &alpha_mdebug_frame_unwind;
340
}
341
 
342
static CORE_ADDR
343
alpha_mdebug_frame_base_address (struct frame_info *next_frame,
344
                                 void **this_prologue_cache)
345
{
346
  struct alpha_mdebug_unwind_cache *info
347
    = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache);
348
 
349
  return info->vfp;
350
}
351
 
352
static CORE_ADDR
353
alpha_mdebug_frame_locals_address (struct frame_info *next_frame,
354
                                   void **this_prologue_cache)
355
{
356
  struct alpha_mdebug_unwind_cache *info
357
    = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache);
358
 
359
  return info->vfp - PROC_LOCALOFF (info->proc_desc);
360
}
361
 
362
static CORE_ADDR
363
alpha_mdebug_frame_args_address (struct frame_info *next_frame,
364
                                 void **this_prologue_cache)
365
{
366
  struct alpha_mdebug_unwind_cache *info
367
    = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache);
368
 
369
  return info->vfp - ALPHA_NUM_ARG_REGS * 8;
370
}
371
 
372
static const struct frame_base alpha_mdebug_frame_base = {
373
  &alpha_mdebug_frame_unwind,
374
  alpha_mdebug_frame_base_address,
375
  alpha_mdebug_frame_locals_address,
376
  alpha_mdebug_frame_args_address
377
};
378
 
379
static const struct frame_base *
380
alpha_mdebug_frame_base_sniffer (struct frame_info *next_frame)
381
{
382
  CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME);
383
  struct mdebug_extra_func_info *proc_desc;
384
 
385
  /* If this PC does not map to a PDR, then clearly this isn't an
386
     mdebug frame.  */
387
  proc_desc = find_proc_desc (pc);
388
  if (proc_desc == NULL)
389
    return NULL;
390
 
391
  return &alpha_mdebug_frame_base;
392
}
393
 
394
 
395
void
396
alpha_mdebug_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
397
{
398
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
399
 
400
  frame_unwind_append_sniffer (gdbarch, alpha_mdebug_frame_sniffer);
401
  frame_base_append_sniffer (gdbarch, alpha_mdebug_frame_base_sniffer);
402
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.