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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [ada/] [tb-alvxw.c] - Blame information for rev 281

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 281 jeremybenn
/****************************************************************************
2
 *                                                                          *
3
 *                         GNAT COMPILER COMPONENTS                         *
4
 *                                                                          *
5
 *                T R A C E B A C K - A l p h a / V x W o r k s             *
6
 *                                                                          *
7
 *                          C Implementation File                           *
8
 *                                                                          *
9
 *                     Copyright (C) 2000-2006, AdaCore                     *
10
 *                                                                          *
11
 * GNAT is free software;  you can  redistribute it  and/or modify it under *
12
 * terms of the  GNU General Public License as published  by the Free Soft- *
13
 * ware  Foundation;  either version 2,  or (at your option) any later ver- *
14
 * sion.  GNAT is distributed in the hope that it will be useful, but WITH- *
15
 * OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY *
16
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License *
17
 * for  more details.  You should have  received  a copy of the GNU General *
18
 * Public License  distributed with GNAT;  see file COPYING.  If not, write *
19
 * to  the  Free Software Foundation,  51  Franklin  Street,  Fifth  Floor, *
20
 * Boston, MA 02110-1301, USA.                                              *
21
 *                                                                          *
22
 * As a  special  exception,  if you  link  this file  with other  files to *
23
 * produce an executable,  this file does not by itself cause the resulting *
24
 * executable to be covered by the GNU General Public License. This except- *
25
 * ion does not  however invalidate  any other reasons  why the  executable *
26
 * file might be covered by the  GNU Public License.                        *
27
 *                                                                          *
28
 * GNAT was originally developed  by the GNAT team at  New York University. *
29
 * Extensive contributions were provided by Ada Core Technologies Inc.      *
30
 *                                                                          *
31
 ****************************************************************************/
32
 
33
/* Alpha vxWorks requires a special, complex treatment that is extracted
34
   from GDB. This file is #included within tracebak.c in the appropriate
35
   case.  */
36
 
37
#include <stddef.h>
38
#include <stdlib.h>
39
#include <limits.h>
40
#include <string.h>
41
 
42
extern void kerTaskEntry(void);
43
 
44
/* We still use a number of macros similar to the ones for the generic
45
   __gnat_backtrace implementation.  */
46
#define SKIP_FRAME 1
47
#define PC_ADJUST -4
48
 
49
#define STOP_FRAME \
50
   (current == NULL \
51
    || ((CORE_ADDR) &kerTaskEntry >= PROC_LOW_ADDR (current->proc_desc) \
52
        && current->pc >= (CORE_ADDR) &kerTaskEntry))
53
 
54
/* Register numbers of various important registers.
55
   Note that most of these values are "real" register numbers,
56
   and correspond to the general registers of the machine,
57
   and FP_REGNUM is a "phony" register number which is too large
58
   to be an actual register number as far as the user is concerned
59
   but serves to get the desired value when passed to read_register.  */
60
 
61
#define T7_REGNUM 8             /* Return address register for OSF/1 __add* */
62
#define GCC_FP_REGNUM 15        /* Used by gcc as frame register */
63
#define T9_REGNUM 23            /* Return address register for OSF/1 __div* */
64
#define SP_REGNUM 30            /* Contains address of top of stack */
65
#define RA_REGNUM 26            /* Contains return address value */
66
#define FP0_REGNUM 32           /* Floating point register 0 */
67
#define PC_REGNUM 64            /* Contains program counter */
68
#define NUM_REGS 66
69
 
70
#define VM_MIN_ADDRESS (CORE_ADDR)0x120000000
71
 
72
#define SIZEOF_FRAME_SAVED_REGS (sizeof (CORE_ADDR) * (NUM_REGS))
73
#define INIT_EXTRA_FRAME_INFO(fromleaf, fci) init_extra_frame_info(fci)
74
 
75
#define FRAME_CHAIN(thisframe) (CORE_ADDR) alpha_frame_chain (thisframe)
76
 
77
#define FRAME_CHAIN_VALID(CHAIN, THISFRAME)     \
78
  ((CHAIN) != 0                                  \
79
   && !inside_entry_file (FRAME_SAVED_PC (THISFRAME)))
80
 
81
#define FRAME_SAVED_PC(FRAME)   (alpha_frame_saved_pc (FRAME))
82
 
83
#define FRAME_CHAIN_COMBINE(CHAIN, THISFRAME) (CHAIN)
84
 
85
#define INIT_FRAME_PC(FROMLEAF, PREV)
86
 
87
#define INIT_FRAME_PC_FIRST(FROMLEAF, PREV) \
88
  (PREV)->pc = ((FROMLEAF) ? SAVED_PC_AFTER_CALL ((PREV)->next) \
89
                : (PREV)->next ? FRAME_SAVED_PC ((PREV)->next) : read_pc ());
90
 
91
#define SAVED_PC_AFTER_CALL(FRAME)      alpha_saved_pc_after_call (FRAME)
92
 
93
typedef unsigned long long int bfd_vma;
94
 
95
typedef bfd_vma CORE_ADDR;
96
 
97
typedef struct pdr
98
{
99
  bfd_vma adr;          /* memory address of start of procedure */
100
  long  isym;           /* start of local symbol entries */
101
  long  iline;          /* start of line number entries*/
102
  long  regmask;        /* save register mask */
103
  long  regoffset;      /* save register offset */
104
  long  iopt;           /* start of optimization symbol entries*/
105
  long  fregmask;       /* save floating point register mask */
106
  long  fregoffset;     /* save floating point register offset */
107
  long  frameoffset;    /* frame size */
108
  short framereg;       /* frame pointer register */
109
  short pcreg;          /* offset or reg of return pc */
110
  long  lnLow;          /* lowest line in the procedure */
111
  long  lnHigh;         /* highest line in the procedure */
112
  bfd_vma cbLineOffset; /* byte offset for this procedure from the fd base */
113
  /* These fields are new for 64 bit ECOFF.  */
114
  unsigned gp_prologue : 8; /* byte size of GP prologue */
115
  unsigned gp_used : 1; /* true if the procedure uses GP */
116
  unsigned reg_frame : 1; /* true if register frame procedure */
117
  unsigned prof : 1;    /* true if compiled with -pg */
118
  unsigned reserved : 13; /* reserved: must be zero */
119
  unsigned localoff : 8; /* offset of local variables from vfp */
120
} PDR;
121
 
122
typedef struct alpha_extra_func_info
123
{
124
  long numargs;         /* number of args to procedure (was iopt) */
125
  PDR pdr;                      /* Procedure descriptor record */
126
}
127
*alpha_extra_func_info_t;
128
 
129
struct frame_info
130
{
131
  /* Nominal address of the frame described.  See comments at FRAME_FP
132
     about what this means outside the *FRAME* macros; in the *FRAME*
133
     macros, it can mean whatever makes most sense for this machine.  */
134
  CORE_ADDR frame;
135
 
136
  /* Address at which execution is occurring in this frame.  For the
137
     innermost frame, it's the current pc.  For other frames, it is a
138
     pc saved in the next frame.  */
139
  CORE_ADDR pc;
140
 
141
  /* For each register, address of where it was saved on entry to the
142
     frame, or zero if it was not saved on entry to this frame.  This
143
     includes special registers such as pc and fp saved in special
144
     ways in the stack frame.  The SP_REGNUM is even more special, the
145
     address here is the sp for the next frame, not the address where
146
     the sp was saved.  Allocated by frame_saved_regs_zalloc () which
147
     is called and initialized by FRAME_INIT_SAVED_REGS. */
148
  CORE_ADDR *saved_regs;        /*NUM_REGS */
149
 
150
  int localoff;
151
  int pc_reg;
152
  alpha_extra_func_info_t proc_desc;
153
 
154
  /* Pointers to the next and previous frame_info's in the frame cache.  */
155
  struct frame_info *next, *prev;
156
};
157
 
158
struct frame_saved_regs
159
{
160
  /* For each register R (except the SP), regs[R] is the address at
161
     which it was saved on entry to the frame, or zero if it was not
162
     saved on entry to this frame.  This includes special registers
163
     such as pc and fp saved in special ways in the stack frame.
164
 
165
     regs[SP_REGNUM] is different.  It holds the actual SP, not the
166
     address at which it was saved.  */
167
 
168
  CORE_ADDR regs[NUM_REGS];
169
};
170
 
171
static CORE_ADDR theRegisters[32];
172
 
173
/* Prototypes for local functions. */
174
 
175
static CORE_ADDR read_next_frame_reg (struct frame_info *, int);
176
static CORE_ADDR heuristic_proc_start (CORE_ADDR);
177
static int alpha_about_to_return (CORE_ADDR pc);
178
static void init_extra_frame_info (struct frame_info *);
179
static CORE_ADDR alpha_frame_chain (struct frame_info *);
180
static CORE_ADDR alpha_frame_saved_pc (struct frame_info *frame);
181
static void *trace_alloc (unsigned int);
182
static struct frame_info *create_new_frame (CORE_ADDR, CORE_ADDR);
183
 
184
static alpha_extra_func_info_t
185
heuristic_proc_desc (CORE_ADDR, CORE_ADDR, struct frame_info *,
186
                     struct frame_saved_regs *);
187
 
188
static alpha_extra_func_info_t
189
find_proc_desc (CORE_ADDR, struct frame_info *, struct frame_saved_regs *);
190
 
191
/* Heuristic_proc_start may hunt through the text section for a long
192
   time across a 2400 baud serial line.  Allows the user to limit this
193
   search.  */
194
static unsigned int heuristic_fence_post = 1<<16;
195
 
196
/* Layout of a stack frame on the alpha:
197
 
198
                |                               |
199
 pdr members:   |  7th ... nth arg,             |
200
                |  `pushed' by caller.          |
201
                |                               |
202
----------------|-------------------------------|<--  old_sp == vfp
203
   ^  ^  ^  ^   |                               |
204
   |  |  |  |   |                               |
205
   |  |localoff |  Copies of 1st .. 6th         |
206
   |  |  |  |   |  argument if necessary.       |
207
   |  |  |  v   |                               |
208
   |  |  |  --- |-------------------------------|<-- FRAME_LOCALS_ADDRESS
209
   |  |  |      |                               |
210
   |  |  |      |  Locals and temporaries.      |
211
   |  |  |      |                               |
212
   |  |  |      |-------------------------------|
213
   |  |  |      |                               |
214
   |-fregoffset |  Saved float registers.       |
215
   |  |  |      |  F9                           |
216
   |  |  |      |   .                           |
217
   |  |  |      |   .                           |
218
   |  |  |      |  F2                           |
219
   |  |  v      |                               |
220
   |  |  -------|-------------------------------|
221
   |  |         |                               |
222
   |  |         |  Saved registers.             |
223
   |  |         |  S6                           |
224
   |-regoffset  |   .                           |
225
   |  |         |   .                           |
226
   |  |         |  S0                           |
227
   |  |         |  pdr.pcreg                    |
228
   |  v         |                               |
229
   |  ----------|-------------------------------|
230
   |            |                               |
231
 frameoffset    |  Argument build area, gets    |
232
   |            |  7th ... nth arg for any      |
233
   |            |  called procedure.            |
234
   v            |                               |
235
   -------------|-------------------------------|<-- sp
236
                |                               |            */
237
 
238
#define PROC_LOW_ADDR(PROC) ((PROC)->pdr.adr)               /* least address */
239
#define PROC_HIGH_ADDR(PROC) ((PROC)->pdr.iline)      /* upper address bound */
240
#define PROC_DUMMY_FRAME(PROC) ((PROC)->pdr.cbLineOffset) /*CALL_DUMMY frame */
241
#define PROC_FRAME_OFFSET(PROC) ((PROC)->pdr.frameoffset)
242
#define PROC_FRAME_REG(PROC) ((PROC)->pdr.framereg)
243
#define PROC_REG_MASK(PROC) ((PROC)->pdr.regmask)
244
#define PROC_FREG_MASK(PROC) ((PROC)->pdr.fregmask)
245
#define PROC_REG_OFFSET(PROC) ((PROC)->pdr.regoffset)
246
#define PROC_FREG_OFFSET(PROC) ((PROC)->pdr.fregoffset)
247
#define PROC_PC_REG(PROC) ((PROC)->pdr.pcreg)
248
#define PROC_LOCALOFF(PROC) ((PROC)->pdr.localoff)
249
 
250
/* Local storage allocation/deallocation functions.  trace_alloc does
251
   a malloc, but also chains allocated blocks on trace_alloc_chain, so
252
   they may all be freed on exit from __gnat_backtrace. */
253
 
254
struct alloc_chain
255
{
256
  struct alloc_chain *next;
257
  double x[0];
258
};
259
struct alloc_chain *trace_alloc_chain;
260
 
261
static void *
262
trace_alloc (unsigned int n)
263
{
264
  struct alloc_chain * result = malloc (n + sizeof(struct alloc_chain));
265
 
266
  result->next = trace_alloc_chain;
267
  trace_alloc_chain = result;
268
  return (void*) result->x;
269
}
270
 
271
static void
272
free_trace_alloc (void)
273
{
274
  while (trace_alloc_chain != 0)
275
    {
276
      struct alloc_chain *old = trace_alloc_chain;
277
 
278
      trace_alloc_chain = trace_alloc_chain->next;
279
      free (old);
280
    }
281
}
282
 
283
/* Read value at ADDR into *DEST, returning 0 if this is valid, != 0
284
   otherwise. */
285
 
286
static int
287
read_memory_safe4 (CORE_ADDR addr, unsigned int *dest)
288
{
289
  *dest = *((unsigned int*) addr);
290
  return 0;
291
}
292
 
293
/* Read value at ADDR into *DEST, returning 0 if this is valid, != 0
294
   otherwise. */
295
 
296
static int
297
read_memory_safe8 (CORE_ADDR addr, CORE_ADDR *dest)
298
{
299
  *dest = *((CORE_ADDR*) addr);
300
  return 0;
301
}
302
 
303
static CORE_ADDR
304
read_register (int regno)
305
{
306
  if (regno >= 0 && regno < 31)
307
    return theRegisters[regno];
308
 
309
  return (CORE_ADDR) 0;
310
}
311
 
312
static void
313
frame_saved_regs_zalloc (struct frame_info *fi)
314
{
315
  fi->saved_regs = (CORE_ADDR *) trace_alloc (SIZEOF_FRAME_SAVED_REGS);
316
  memset (fi->saved_regs, 0, SIZEOF_FRAME_SAVED_REGS);
317
}
318
 
319
static void *
320
frame_obstack_alloc (unsigned long size)
321
{
322
  return (void *) trace_alloc (size);
323
}
324
 
325
static int
326
inside_entry_file (CORE_ADDR addr)
327
{
328
  if (addr == 0)
329
    return 1;
330
  else
331
    return 0;
332
}
333
 
334
static CORE_ADDR
335
alpha_saved_pc_after_call (struct frame_info *frame)
336
{
337
  CORE_ADDR pc = frame->pc;
338
  alpha_extra_func_info_t proc_desc;
339
  int pcreg;
340
 
341
  proc_desc = find_proc_desc (pc, frame->next, NULL);
342
  pcreg = proc_desc ? PROC_PC_REG (proc_desc) : RA_REGNUM;
343
 
344
  return read_register (pcreg);
345
}
346
 
347
/* Guaranteed to set frame->saved_regs to some values (it never leaves it
348
   NULL).  */
349
 
350
static void
351
alpha_find_saved_regs (struct frame_info *frame)
352
{
353
  int ireg;
354
  CORE_ADDR reg_position;
355
  unsigned long mask;
356
  alpha_extra_func_info_t proc_desc;
357
  int returnreg;
358
 
359
  frame_saved_regs_zalloc (frame);
360
 
361
  /* If it is the frame for __sigtramp, the saved registers are located in a
362
     sigcontext structure somewhere on the stack. __sigtramp passes a pointer
363
     to the sigcontext structure on the stack.  If the stack layout for
364
     __sigtramp changes, or if sigcontext offsets change, we might have to
365
     update this code.  */
366
 
367
#ifndef SIGFRAME_PC_OFF
368
#define SIGFRAME_PC_OFF         (2 * 8)
369
#define SIGFRAME_REGSAVE_OFF    (4 * 8)
370
#define SIGFRAME_FPREGSAVE_OFF  (SIGFRAME_REGSAVE_OFF + 32 * 8 + 8)
371
#endif
372
 
373
  proc_desc = frame->proc_desc;
374
  if (proc_desc == NULL)
375
    /* I'm not sure how/whether this can happen.  Normally when we can't
376
       find a proc_desc, we "synthesize" one using heuristic_proc_desc
377
       and set the saved_regs right away.  */
378
    return;
379
 
380
  /* Fill in the offsets for the registers which gen_mask says
381
     were saved.  */
382
 
383
  reg_position = frame->frame + PROC_REG_OFFSET (proc_desc);
384
  mask = PROC_REG_MASK (proc_desc);
385
 
386
  returnreg = PROC_PC_REG (proc_desc);
387
 
388
  /* Note that RA is always saved first, regardless of its actual
389
     register number.  */
390
  if (mask & (1 << returnreg))
391
    {
392
      frame->saved_regs[returnreg] = reg_position;
393
      reg_position += 8;
394
      mask &= ~(1 << returnreg);        /* Clear bit for RA so we
395
                                           don't save again later. */
396
    }
397
 
398
  for (ireg = 0; ireg <= 31; ireg++)
399
    if (mask & (1 << ireg))
400
      {
401
        frame->saved_regs[ireg] = reg_position;
402
        reg_position += 8;
403
      }
404
 
405
  /* Fill in the offsets for the registers which float_mask says
406
     were saved.  */
407
 
408
  reg_position = frame->frame + PROC_FREG_OFFSET (proc_desc);
409
  mask = PROC_FREG_MASK (proc_desc);
410
 
411
  for (ireg = 0; ireg <= 31; ireg++)
412
    if (mask & (1 << ireg))
413
      {
414
        frame->saved_regs[FP0_REGNUM + ireg] = reg_position;
415
        reg_position += 8;
416
      }
417
 
418
  frame->saved_regs[PC_REGNUM] = frame->saved_regs[returnreg];
419
}
420
 
421
static CORE_ADDR
422
read_next_frame_reg (struct frame_info *fi, int regno)
423
{
424
  CORE_ADDR result;
425
  for (; fi; fi = fi->next)
426
    {
427
      /* We have to get the saved sp from the sigcontext
428
         if it is a signal handler frame.  */
429
      if (regno == SP_REGNUM)
430
        return fi->frame;
431
      else
432
        {
433
          if (fi->saved_regs == 0)
434
            alpha_find_saved_regs (fi);
435
 
436
          if (fi->saved_regs[regno])
437
            {
438
              if (read_memory_safe8 (fi->saved_regs[regno], &result) == 0)
439
                return result;
440
              else
441
                return 0;
442
            }
443
        }
444
    }
445
 
446
  return read_register (regno);
447
}
448
 
449
static CORE_ADDR
450
alpha_frame_saved_pc (struct frame_info *frame)
451
{
452
  return read_next_frame_reg (frame, frame->pc_reg);
453
}
454
 
455
static struct alpha_extra_func_info temp_proc_desc;
456
 
457
/* Nonzero if instruction at PC is a return instruction.  "ret
458
   $zero,($ra),1" on alpha. */
459
 
460
static int
461
alpha_about_to_return (CORE_ADDR pc)
462
{
463
  int inst;
464
 
465
  read_memory_safe4 (pc, &inst);
466
  return inst == 0x6bfa8001;
467
}
468
 
469
/* A heuristically computed start address for the subprogram
470
   containing address PC.   Returns 0 if none detected. */
471
 
472
static CORE_ADDR
473
heuristic_proc_start (CORE_ADDR pc)
474
{
475
  CORE_ADDR start_pc = pc;
476
  CORE_ADDR fence = start_pc - heuristic_fence_post;
477
 
478
  if (start_pc == 0)
479
    return 0;
480
 
481
  if (heuristic_fence_post == UINT_MAX
482
      || fence < VM_MIN_ADDRESS)
483
    fence = VM_MIN_ADDRESS;
484
 
485
  /* search back for previous return */
486
  for (start_pc -= 4; ; start_pc -= 4)
487
    {
488
      if (start_pc < fence)
489
        return 0;
490
      else if (alpha_about_to_return (start_pc))
491
        break;
492
    }
493
 
494
  start_pc += 4;                /* skip return */
495
  return start_pc;
496
}
497
 
498
static alpha_extra_func_info_t
499
heuristic_proc_desc (CORE_ADDR start_pc,
500
                     CORE_ADDR limit_pc,
501
                     struct frame_info *next_frame,
502
                     struct frame_saved_regs *saved_regs_p)
503
{
504
  CORE_ADDR sp = read_next_frame_reg (next_frame, SP_REGNUM);
505
  CORE_ADDR cur_pc;
506
  int frame_size;
507
  int has_frame_reg = 0;
508
  unsigned long reg_mask = 0;
509
  int pcreg = -1;
510
 
511
  if (start_pc == 0)
512
    return 0;
513
 
514
  memset (&temp_proc_desc, '\0', sizeof (temp_proc_desc));
515
  if (saved_regs_p != 0)
516
    memset (saved_regs_p, '\0', sizeof (struct frame_saved_regs));
517
 
518
  PROC_LOW_ADDR (&temp_proc_desc) = start_pc;
519
 
520
  if (start_pc + 200 < limit_pc)
521
    limit_pc = start_pc + 200;
522
 
523
  frame_size = 0;
524
  for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += 4)
525
    {
526
      unsigned int word;
527
      int status;
528
 
529
      status = read_memory_safe4 (cur_pc, &word);
530
      if (status)
531
        return 0;
532
 
533
      if ((word & 0xffff0000) == 0x23de0000)    /* lda $sp,n($sp) */
534
        {
535
          if (word & 0x8000)
536
            frame_size += (-word) & 0xffff;
537
          else
538
            /* Exit loop if a positive stack adjustment is found, which
539
               usually means that the stack cleanup code in the function
540
               epilogue is reached.  */
541
            break;
542
        }
543
      else if ((word & 0xfc1f0000) == 0xb41e0000        /* stq reg,n($sp) */
544
               && (word & 0xffff0000) != 0xb7fe0000)    /* reg != $zero */
545
        {
546
          int reg = (word & 0x03e00000) >> 21;
547
 
548
          reg_mask |= 1 << reg;
549
          if (saved_regs_p != 0)
550
            saved_regs_p->regs[reg] = sp + (short) word;
551
 
552
          /* Starting with OSF/1-3.2C, the system libraries are shipped
553
             without local symbols, but they still contain procedure
554
             descriptors without a symbol reference. GDB is currently
555
             unable to find these procedure descriptors and uses
556
             heuristic_proc_desc instead.
557
             As some low level compiler support routines (__div*, __add*)
558
             use a non-standard return address register, we have to
559
             add some heuristics to determine the return address register,
560
             or stepping over these routines will fail.
561
             Usually the return address register is the first register
562
             saved on the stack, but assembler optimization might
563
             rearrange the register saves.
564
             So we recognize only a few registers (t7, t9, ra) within
565
             the procedure prologue as valid return address registers.
566
             If we encounter a return instruction, we extract the
567
             the return address register from it.
568
 
569
             FIXME: Rewriting GDB to access the procedure descriptors,
570
             e.g. via the minimal symbol table, might obviate this hack.  */
571
          if (pcreg == -1
572
              && cur_pc < (start_pc + 80)
573
              && (reg == T7_REGNUM || reg == T9_REGNUM || reg == RA_REGNUM))
574
            pcreg = reg;
575
        }
576
      else if ((word & 0xffe0ffff) == 0x6be08001)       /* ret zero,reg,1 */
577
        pcreg = (word >> 16) & 0x1f;
578
      else if (word == 0x47de040f)      /* bis sp,sp fp */
579
        has_frame_reg = 1;
580
    }
581
 
582
  if (pcreg == -1)
583
    {
584
      /* If we haven't found a valid return address register yet,
585
         keep searching in the procedure prologue.  */
586
      while (cur_pc < (limit_pc + 80) && cur_pc < (start_pc + 80))
587
        {
588
          unsigned int word;
589
 
590
          if (read_memory_safe4 (cur_pc, &word))
591
            break;
592
          cur_pc += 4;
593
 
594
          if ((word & 0xfc1f0000) == 0xb41e0000         /* stq reg,n($sp) */
595
              && (word & 0xffff0000) != 0xb7fe0000)     /* reg != $zero */
596
            {
597
              int reg = (word & 0x03e00000) >> 21;
598
 
599
              if (reg == T7_REGNUM || reg == T9_REGNUM || reg == RA_REGNUM)
600
                {
601
                  pcreg = reg;
602
                  break;
603
                }
604
            }
605
          else if ((word & 0xffe0ffff) == 0x6be08001)   /* ret zero,reg,1 */
606
            {
607
              pcreg = (word >> 16) & 0x1f;
608
              break;
609
            }
610
        }
611
    }
612
 
613
  if (has_frame_reg)
614
    PROC_FRAME_REG (&temp_proc_desc) = GCC_FP_REGNUM;
615
  else
616
    PROC_FRAME_REG (&temp_proc_desc) = SP_REGNUM;
617
 
618
  PROC_FRAME_OFFSET (&temp_proc_desc) = frame_size;
619
  PROC_REG_MASK (&temp_proc_desc) = reg_mask;
620
  PROC_PC_REG (&temp_proc_desc) = (pcreg == -1) ? RA_REGNUM : pcreg;
621
  PROC_LOCALOFF (&temp_proc_desc) = 0;   /* XXX - bogus */
622
 
623
  return &temp_proc_desc;
624
}
625
 
626
static alpha_extra_func_info_t
627
find_proc_desc (CORE_ADDR pc,
628
                struct frame_info *next_frame,
629
                struct frame_saved_regs *saved_regs)
630
{
631
  CORE_ADDR startaddr;
632
 
633
  /* If heuristic_fence_post is nonzero, determine the procedure
634
     start address by examining the instructions.
635
     This allows us to find the start address of static functions which
636
     have no symbolic information, as startaddr would have been set to
637
     the preceding global function start address by the
638
     find_pc_partial_function call above.  */
639
  startaddr = heuristic_proc_start (pc);
640
 
641
  return heuristic_proc_desc (startaddr, pc, next_frame, saved_regs);
642
}
643
 
644
static CORE_ADDR
645
alpha_frame_chain (struct frame_info *frame)
646
{
647
  alpha_extra_func_info_t proc_desc;
648
  CORE_ADDR saved_pc = FRAME_SAVED_PC (frame);
649
 
650
  if (saved_pc == 0 || inside_entry_file (saved_pc))
651
    return 0;
652
 
653
  proc_desc = find_proc_desc (saved_pc, frame, NULL);
654
  if (!proc_desc)
655
    return 0;
656
 
657
  /* If no frame pointer and frame size is zero, we must be at end
658
     of stack (or otherwise hosed).  If we don't check frame size,
659
     we loop forever if we see a zero size frame.  */
660
  if (PROC_FRAME_REG (proc_desc) == SP_REGNUM
661
      && PROC_FRAME_OFFSET (proc_desc) == 0)
662
    return 0;
663
  else
664
    return read_next_frame_reg (frame, PROC_FRAME_REG (proc_desc))
665
      + PROC_FRAME_OFFSET (proc_desc);
666
}
667
 
668
static void
669
init_extra_frame_info (struct frame_info *frame)
670
{
671
  struct frame_saved_regs temp_saved_regs;
672
  alpha_extra_func_info_t proc_desc =
673
    find_proc_desc (frame->pc, frame->next, &temp_saved_regs);
674
 
675
  frame->saved_regs = NULL;
676
  frame->localoff = 0;
677
  frame->pc_reg = RA_REGNUM;
678
  frame->proc_desc = proc_desc;
679
 
680
  if (proc_desc)
681
    {
682
      /* Get the locals offset and the saved pc register from the
683
         procedure descriptor, they are valid even if we are in the
684
         middle of the prologue.  */
685
      frame->localoff = PROC_LOCALOFF (proc_desc);
686
      frame->pc_reg = PROC_PC_REG (proc_desc);
687
 
688
      /* Fixup frame-pointer - only needed for top frame */
689
 
690
      /* This may not be quite right, if proc has a real frame register.
691
         Get the value of the frame relative sp, procedure might have been
692
         interrupted by a signal at it's very start.  */
693
      if (frame->pc == PROC_LOW_ADDR (proc_desc))
694
        frame->frame = read_next_frame_reg (frame->next, SP_REGNUM);
695
      else
696
        frame->frame
697
          = (read_next_frame_reg (frame->next, PROC_FRAME_REG (proc_desc))
698
             + PROC_FRAME_OFFSET (proc_desc));
699
 
700
      frame->saved_regs
701
        = (CORE_ADDR *) frame_obstack_alloc (SIZEOF_FRAME_SAVED_REGS);
702
      memcpy
703
        (frame->saved_regs, temp_saved_regs.regs, SIZEOF_FRAME_SAVED_REGS);
704
      frame->saved_regs[PC_REGNUM] = frame->saved_regs[RA_REGNUM];
705
    }
706
}
707
 
708
/* Create an arbitrary (i.e. address specified by user) or innermost frame.
709
   Always returns a non-NULL value.  */
710
 
711
static struct frame_info *
712
create_new_frame (CORE_ADDR addr, CORE_ADDR pc)
713
{
714
  struct frame_info *fi;
715
 
716
  fi = (struct frame_info *)
717
    trace_alloc (sizeof (struct frame_info));
718
 
719
  /* Arbitrary frame */
720
  fi->next = NULL;
721
  fi->prev = NULL;
722
  fi->frame = addr;
723
  fi->pc = pc;
724
 
725
#ifdef INIT_EXTRA_FRAME_INFO
726
  INIT_EXTRA_FRAME_INFO (0, fi);
727
#endif
728
 
729
  return fi;
730
}
731
 
732
static CORE_ADDR current_pc;
733
 
734
static void
735
set_current_pc (void)
736
{
737
  current_pc = (CORE_ADDR) __builtin_return_address (0);
738
}
739
 
740
static CORE_ADDR
741
read_pc (void)
742
{
743
  return current_pc;
744
}
745
 
746
static struct frame_info *
747
get_current_frame (void)
748
{
749
  return create_new_frame (0, read_pc ());
750
}
751
 
752
/* Return the frame that called FI.
753
   If FI is the original frame (it has no caller), return 0.  */
754
 
755
static struct frame_info *
756
get_prev_frame (struct frame_info *next_frame)
757
{
758
  CORE_ADDR address = 0;
759
  struct frame_info *prev;
760
  int fromleaf = 0;
761
 
762
  /* If we have the prev one, return it */
763
  if (next_frame->prev)
764
    return next_frame->prev;
765
 
766
  /* On some machines it is possible to call a function without
767
     setting up a stack frame for it.  On these machines, we
768
     define this macro to take two args; a frameinfo pointer
769
     identifying a frame and a variable to set or clear if it is
770
     or isn't leafless.  */
771
 
772
  /* Two macros defined in tm.h specify the machine-dependent
773
     actions to be performed here.
774
 
775
     First, get the frame's chain-pointer.  If that is zero, the frame
776
     is the outermost frame or a leaf called by the outermost frame.
777
     This means that if start calls main without a frame, we'll return
778
 
779
 
780
     Nope; there's a problem.  This also returns when the current
781
     routine is a leaf of main.  This is unacceptable.  We move
782
     this to after the ffi test; I'd rather have backtraces from
783
     start go curfluy than have an abort called from main not show
784
     main.  */
785
 
786
  address = FRAME_CHAIN (next_frame);
787
  if (!FRAME_CHAIN_VALID (address, next_frame))
788
    return 0;
789
  address = FRAME_CHAIN_COMBINE (address, next_frame);
790
 
791
  if (address == 0)
792
    return 0;
793
 
794
  prev = (struct frame_info *) trace_alloc (sizeof (struct frame_info));
795
 
796
  prev->saved_regs = NULL;
797
  if (next_frame)
798
    next_frame->prev = prev;
799
 
800
  prev->next = next_frame;
801
  prev->prev = (struct frame_info *) 0;
802
  prev->frame = address;
803
 
804
  /* This change should not be needed, FIXME!  We should
805
     determine whether any targets *need* INIT_FRAME_PC to happen
806
     after INIT_EXTRA_FRAME_INFO and come up with a simple way to
807
     express what goes on here.
808
 
809
     INIT_EXTRA_FRAME_INFO is called from two places: create_new_frame
810
     (where the PC is already set up) and here (where it isn't).
811
     INIT_FRAME_PC is only called from here, always after
812
     INIT_EXTRA_FRAME_INFO.
813
 
814
     The catch is the MIPS, where INIT_EXTRA_FRAME_INFO requires the PC
815
     value (which hasn't been set yet).  Some other machines appear to
816
     require INIT_EXTRA_FRAME_INFO before they can do INIT_FRAME_PC.  Phoo.
817
 
818
     We shouldn't need INIT_FRAME_PC_FIRST to add more complication to
819
     an already overcomplicated part of GDB.   gnu@cygnus.com, 15Sep92.
820
 
821
     Assuming that some machines need INIT_FRAME_PC after
822
     INIT_EXTRA_FRAME_INFO, one possible scheme:
823
 
824
     SETUP_INNERMOST_FRAME()
825
     Default version is just create_new_frame (read_fp ()),
826
     read_pc ()).  Machines with extra frame info would do that (or the
827
     local equivalent) and then set the extra fields.
828
     INIT_PREV_FRAME(fromleaf, prev)
829
     Replace INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC.  This should
830
     also return a flag saying whether to keep the new frame, or
831
     whether to discard it, because on some machines (e.g.  mips) it
832
     is really awkward to have FRAME_CHAIN_VALID called *before*
833
     INIT_EXTRA_FRAME_INFO (there is no good way to get information
834
     deduced in FRAME_CHAIN_VALID into the extra fields of the new frame).
835
     std_frame_pc(fromleaf, prev)
836
     This is the default setting for INIT_PREV_FRAME.  It just does what
837
     the default INIT_FRAME_PC does.  Some machines will call it from
838
     INIT_PREV_FRAME (either at the beginning, the end, or in the middle).
839
     Some machines won't use it.
840
     kingdon@cygnus.com, 13Apr93, 31Jan94, 14Dec94.  */
841
 
842
#ifdef INIT_FRAME_PC_FIRST
843
  INIT_FRAME_PC_FIRST (fromleaf, prev);
844
#endif
845
 
846
#ifdef INIT_EXTRA_FRAME_INFO
847
  INIT_EXTRA_FRAME_INFO (fromleaf, prev);
848
#endif
849
 
850
  /* This entry is in the frame queue now, which is good since
851
     FRAME_SAVED_PC may use that queue to figure out its value
852
     (see tm-sparc.h).  We want the pc saved in the inferior frame. */
853
  INIT_FRAME_PC (fromleaf, prev);
854
 
855
  /* If ->frame and ->pc are unchanged, we are in the process of getting
856
     ourselves into an infinite backtrace.  Some architectures check this
857
     in FRAME_CHAIN or thereabouts, but it seems like there is no reason
858
     this can't be an architecture-independent check.  */
859
  if (next_frame != NULL)
860
    {
861
      if (prev->frame == next_frame->frame
862
          && prev->pc == next_frame->pc)
863
        {
864
          next_frame->prev = NULL;
865
          free (prev);
866
          return NULL;
867
        }
868
    }
869
 
870
  return prev;
871
}
872
 
873
#define SAVE(regno,disp) \
874
    "stq $" #regno ", " #disp "(%0)\n"
875
 
876
int
877
__gnat_backtrace (void **array,
878
                  int size,
879
                  void *exclude_min,
880
                  void *exclude_max,
881
                  int skip_frames)
882
{
883
  struct frame_info* top;
884
  struct frame_info* current;
885
  int cnt;
886
 
887
  /* This function is not thread safe, protect it */
888
  (*Lock_Task) ();
889
  asm volatile (
890
      SAVE (9,72)
891
      SAVE (10,80)
892
      SAVE (11,88)
893
      SAVE (12,96)
894
      SAVE (13,104)
895
      SAVE (14,112)
896
      SAVE (15,120)
897
      SAVE (16,128)
898
      SAVE (17,136)
899
      SAVE (18,144)
900
      SAVE (19,152)
901
      SAVE (20,160)
902
      SAVE (21,168)
903
      SAVE (22,176)
904
      SAVE (23,184)
905
      SAVE (24,192)
906
      SAVE (25,200)
907
      SAVE (26,208)
908
      SAVE (27,216)
909
      SAVE (28,224)
910
      SAVE (29,232)
911
      SAVE (30,240)
912
      : : "r" (&theRegisters));
913
 
914
  trace_alloc_chain = NULL;
915
  set_current_pc ();
916
 
917
  top = current = get_current_frame ();
918
  cnt = 0;
919
 
920
  for (cnt = 0; cnt < skip_frames; cnt += 1) {
921
    current = get_prev_frame (current);
922
  }
923
 
924
  cnt = 0;
925
  while (cnt < size)
926
    {
927
      if (STOP_FRAME)
928
        break;
929
 
930
      if (current->pc < (CORE_ADDR) exclude_min
931
          || current->pc > (CORE_ADDR) exclude_max)
932
        array[cnt++] = (void*) (current->pc + PC_ADJUST);
933
 
934
      current = get_prev_frame (current);
935
    }
936
 
937
  free_trace_alloc ();
938
  (*Unlock_Task) ();
939
 
940
  return cnt;
941
}

powered by: WebSVN 2.1.0

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