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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [ada/] [tb-alvxw.c] - Blame information for rev 715

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

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

powered by: WebSVN 2.1.0

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