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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [gcc/] [unwind-dw2.c] - Blame information for rev 38

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

Line No. Rev Author Line
1 38 julius
/* DWARF2 exception handling and frame unwind runtime interface routines.
2
   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
3
   Free Software Foundation, Inc.
4
 
5
   This file is part of GCC.
6
 
7
   GCC is free software; you can redistribute it and/or modify it
8
   under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 2, or (at your option)
10
   any later version.
11
 
12
   In addition to the permissions in the GNU General Public License, the
13
   Free Software Foundation gives you unlimited permission to link the
14
   compiled version of this file into combinations with other programs,
15
   and to distribute those combinations without any restriction coming
16
   from the use of this file.  (The General Public License restrictions
17
   do apply in other respects; for example, they cover modification of
18
   the file, and distribution when not linked into a combined
19
   executable.)
20
 
21
   GCC is distributed in the hope that it will be useful, but WITHOUT
22
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
23
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
24
   License for more details.
25
 
26
   You should have received a copy of the GNU General Public License
27
   along with GCC; see the file COPYING.  If not, write to the Free
28
   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
29
   02110-1301, USA.  */
30
 
31
#include "tconfig.h"
32
#include "tsystem.h"
33
#include "coretypes.h"
34
#include "tm.h"
35
#include "dwarf2.h"
36
#include "unwind.h"
37
#ifdef __USING_SJLJ_EXCEPTIONS__
38
# define NO_SIZE_OF_ENCODED_VALUE
39
#endif
40
#include "unwind-pe.h"
41
#include "unwind-dw2-fde.h"
42
#include "gthr.h"
43
#include "unwind-dw2.h"
44
 
45
#ifndef __USING_SJLJ_EXCEPTIONS__
46
 
47
#ifndef STACK_GROWS_DOWNWARD
48
#define STACK_GROWS_DOWNWARD 0
49
#else
50
#undef STACK_GROWS_DOWNWARD
51
#define STACK_GROWS_DOWNWARD 1
52
#endif
53
 
54
/* Dwarf frame registers used for pre gcc 3.0 compiled glibc.  */
55
#ifndef PRE_GCC3_DWARF_FRAME_REGISTERS
56
#define PRE_GCC3_DWARF_FRAME_REGISTERS DWARF_FRAME_REGISTERS
57
#endif
58
 
59
#ifndef DWARF_REG_TO_UNWIND_COLUMN
60
#define DWARF_REG_TO_UNWIND_COLUMN(REGNO) (REGNO)
61
#endif
62
 
63
/* This is the register and unwind state for a particular frame.  This
64
   provides the information necessary to unwind up past a frame and return
65
   to its caller.  */
66
struct _Unwind_Context
67
{
68
  void *reg[DWARF_FRAME_REGISTERS+1];
69
  void *cfa;
70
  void *ra;
71
  void *lsda;
72
  struct dwarf_eh_bases bases;
73
  /* Signal frame context.  */
74
#define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
75
  /* Context which has version/args_size/by_value fields.  */
76
#define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)
77
  _Unwind_Word flags;
78
  /* 0 for now, can be increased when further fields are added to
79
     struct _Unwind_Context.  */
80
  _Unwind_Word version;
81
  _Unwind_Word args_size;
82
  char by_value[DWARF_FRAME_REGISTERS+1];
83
};
84
 
85
/* Byte size of every register managed by these routines.  */
86
static unsigned char dwarf_reg_size_table[DWARF_FRAME_REGISTERS+1];
87
 
88
 
89
/* Read unaligned data from the instruction buffer.  */
90
 
91
union unaligned
92
{
93
  void *p;
94
  unsigned u2 __attribute__ ((mode (HI)));
95
  unsigned u4 __attribute__ ((mode (SI)));
96
  unsigned u8 __attribute__ ((mode (DI)));
97
  signed s2 __attribute__ ((mode (HI)));
98
  signed s4 __attribute__ ((mode (SI)));
99
  signed s8 __attribute__ ((mode (DI)));
100
} __attribute__ ((packed));
101
 
102
static void uw_update_context (struct _Unwind_Context *, _Unwind_FrameState *);
103
static _Unwind_Reason_Code uw_frame_state_for (struct _Unwind_Context *,
104
                                               _Unwind_FrameState *);
105
 
106
static inline void *
107
read_pointer (const void *p) { const union unaligned *up = p; return up->p; }
108
 
109
static inline int
110
read_1u (const void *p) { return *(const unsigned char *) p; }
111
 
112
static inline int
113
read_1s (const void *p) { return *(const signed char *) p; }
114
 
115
static inline int
116
read_2u (const void *p) { const union unaligned *up = p; return up->u2; }
117
 
118
static inline int
119
read_2s (const void *p) { const union unaligned *up = p; return up->s2; }
120
 
121
static inline unsigned int
122
read_4u (const void *p) { const union unaligned *up = p; return up->u4; }
123
 
124
static inline int
125
read_4s (const void *p) { const union unaligned *up = p; return up->s4; }
126
 
127
static inline unsigned long
128
read_8u (const void *p) { const union unaligned *up = p; return up->u8; }
129
 
130
static inline unsigned long
131
read_8s (const void *p) { const union unaligned *up = p; return up->s8; }
132
 
133
static inline _Unwind_Word
134
_Unwind_IsSignalFrame (struct _Unwind_Context *context)
135
{
136
  return (context->flags & SIGNAL_FRAME_BIT) ? 1 : 0;
137
}
138
 
139
static inline void
140
_Unwind_SetSignalFrame (struct _Unwind_Context *context, int val)
141
{
142
  if (val)
143
    context->flags |= SIGNAL_FRAME_BIT;
144
  else
145
    context->flags &= ~SIGNAL_FRAME_BIT;
146
}
147
 
148
static inline _Unwind_Word
149
_Unwind_IsExtendedContext (struct _Unwind_Context *context)
150
{
151
  return context->flags & EXTENDED_CONTEXT_BIT;
152
}
153
 
154
/* Get the value of register INDEX as saved in CONTEXT.  */
155
 
156
inline _Unwind_Word
157
_Unwind_GetGR (struct _Unwind_Context *context, int index)
158
{
159
  int size;
160
  void *ptr;
161
 
162
#ifdef DWARF_ZERO_REG
163
  if (index == DWARF_ZERO_REG)
164
    return 0;
165
#endif
166
 
167
  index = DWARF_REG_TO_UNWIND_COLUMN (index);
168
  gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
169
  size = dwarf_reg_size_table[index];
170
  ptr = context->reg[index];
171
 
172
  if (_Unwind_IsExtendedContext (context) && context->by_value[index])
173
    return (_Unwind_Word) (_Unwind_Internal_Ptr) ptr;
174
 
175
  /* This will segfault if the register hasn't been saved.  */
176
  if (size == sizeof(_Unwind_Ptr))
177
    return * (_Unwind_Ptr *) ptr;
178
  else
179
    {
180
      gcc_assert (size == sizeof(_Unwind_Word));
181
      return * (_Unwind_Word *) ptr;
182
    }
183
}
184
 
185
static inline void *
186
_Unwind_GetPtr (struct _Unwind_Context *context, int index)
187
{
188
  return (void *)(_Unwind_Ptr) _Unwind_GetGR (context, index);
189
}
190
 
191
/* Get the value of the CFA as saved in CONTEXT.  */
192
 
193
_Unwind_Word
194
_Unwind_GetCFA (struct _Unwind_Context *context)
195
{
196
  return (_Unwind_Ptr) context->cfa;
197
}
198
 
199
/* Overwrite the saved value for register INDEX in CONTEXT with VAL.  */
200
 
201
inline void
202
_Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
203
{
204
  int size;
205
  void *ptr;
206
 
207
  index = DWARF_REG_TO_UNWIND_COLUMN (index);
208
  gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
209
  size = dwarf_reg_size_table[index];
210
 
211
  if (_Unwind_IsExtendedContext (context) && context->by_value[index])
212
    {
213
      context->reg[index] = (void *) (_Unwind_Internal_Ptr) val;
214
      return;
215
    }
216
 
217
  ptr = context->reg[index];
218
 
219
  if (size == sizeof(_Unwind_Ptr))
220
    * (_Unwind_Ptr *) ptr = val;
221
  else
222
    {
223
      gcc_assert (size == sizeof(_Unwind_Word));
224
      * (_Unwind_Word *) ptr = val;
225
    }
226
}
227
 
228
/* Get the pointer to a register INDEX as saved in CONTEXT.  */
229
 
230
static inline void *
231
_Unwind_GetGRPtr (struct _Unwind_Context *context, int index)
232
{
233
  index = DWARF_REG_TO_UNWIND_COLUMN (index);
234
  if (_Unwind_IsExtendedContext (context) && context->by_value[index])
235
    return &context->reg[index];
236
  return context->reg[index];
237
}
238
 
239
/* Set the pointer to a register INDEX as saved in CONTEXT.  */
240
 
241
static inline void
242
_Unwind_SetGRPtr (struct _Unwind_Context *context, int index, void *p)
243
{
244
  index = DWARF_REG_TO_UNWIND_COLUMN (index);
245
  if (_Unwind_IsExtendedContext (context))
246
    context->by_value[index] = 0;
247
  context->reg[index] = p;
248
}
249
 
250
/* Overwrite the saved value for register INDEX in CONTEXT with VAL.  */
251
 
252
static inline void
253
_Unwind_SetGRValue (struct _Unwind_Context *context, int index,
254
                    _Unwind_Word val)
255
{
256
  index = DWARF_REG_TO_UNWIND_COLUMN (index);
257
  gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
258
  gcc_assert (dwarf_reg_size_table[index] == sizeof (_Unwind_Ptr));
259
 
260
  context->by_value[index] = 1;
261
  context->reg[index] = (void *) (_Unwind_Internal_Ptr) val;
262
}
263
 
264
/* Return nonzero if register INDEX is stored by value rather than
265
   by reference.  */
266
 
267
static inline int
268
_Unwind_GRByValue (struct _Unwind_Context *context, int index)
269
{
270
  index = DWARF_REG_TO_UNWIND_COLUMN (index);
271
  return context->by_value[index];
272
}
273
 
274
/* Retrieve the return address for CONTEXT.  */
275
 
276
inline _Unwind_Ptr
277
_Unwind_GetIP (struct _Unwind_Context *context)
278
{
279
  return (_Unwind_Ptr) context->ra;
280
}
281
 
282
/* Retrieve the return address and flag whether that IP is before
283
   or after first not yet fully executed instruction.  */
284
 
285
inline _Unwind_Ptr
286
_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
287
{
288
  *ip_before_insn = _Unwind_IsSignalFrame (context);
289
  return (_Unwind_Ptr) context->ra;
290
}
291
 
292
/* Overwrite the return address for CONTEXT with VAL.  */
293
 
294
inline void
295
_Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
296
{
297
  context->ra = (void *) val;
298
}
299
 
300
void *
301
_Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
302
{
303
  return context->lsda;
304
}
305
 
306
_Unwind_Ptr
307
_Unwind_GetRegionStart (struct _Unwind_Context *context)
308
{
309
  return (_Unwind_Ptr) context->bases.func;
310
}
311
 
312
void *
313
_Unwind_FindEnclosingFunction (void *pc)
314
{
315
  struct dwarf_eh_bases bases;
316
  const struct dwarf_fde *fde = _Unwind_Find_FDE (pc-1, &bases);
317
  if (fde)
318
    return bases.func;
319
  else
320
    return NULL;
321
}
322
 
323
#ifndef __ia64__
324
_Unwind_Ptr
325
_Unwind_GetDataRelBase (struct _Unwind_Context *context)
326
{
327
  return (_Unwind_Ptr) context->bases.dbase;
328
}
329
 
330
_Unwind_Ptr
331
_Unwind_GetTextRelBase (struct _Unwind_Context *context)
332
{
333
  return (_Unwind_Ptr) context->bases.tbase;
334
}
335
#endif
336
 
337
#ifdef MD_UNWIND_SUPPORT
338
#include MD_UNWIND_SUPPORT
339
#endif
340
 
341
/* Extract any interesting information from the CIE for the translation
342
   unit F belongs to.  Return a pointer to the byte after the augmentation,
343
   or NULL if we encountered an undecipherable augmentation.  */
344
 
345
static const unsigned char *
346
extract_cie_info (const struct dwarf_cie *cie, struct _Unwind_Context *context,
347
                  _Unwind_FrameState *fs)
348
{
349
  const unsigned char *aug = cie->augmentation;
350
  const unsigned char *p = aug + strlen ((const char *)aug) + 1;
351
  const unsigned char *ret = NULL;
352
  _Unwind_Word utmp;
353
 
354
  /* g++ v2 "eh" has pointer immediately following augmentation string,
355
     so it must be handled first.  */
356
  if (aug[0] == 'e' && aug[1] == 'h')
357
    {
358
      fs->eh_ptr = read_pointer (p);
359
      p += sizeof (void *);
360
      aug += 2;
361
    }
362
 
363
  /* Immediately following the augmentation are the code and
364
     data alignment and return address column.  */
365
  p = read_uleb128 (p, &fs->code_align);
366
  p = read_sleb128 (p, &fs->data_align);
367
  if (cie->version == 1)
368
    fs->retaddr_column = *p++;
369
  else
370
    p = read_uleb128 (p, &fs->retaddr_column);
371
  fs->lsda_encoding = DW_EH_PE_omit;
372
 
373
  /* If the augmentation starts with 'z', then a uleb128 immediately
374
     follows containing the length of the augmentation field following
375
     the size.  */
376
  if (*aug == 'z')
377
    {
378
      p = read_uleb128 (p, &utmp);
379
      ret = p + utmp;
380
 
381
      fs->saw_z = 1;
382
      ++aug;
383
    }
384
 
385
  /* Iterate over recognized augmentation subsequences.  */
386
  while (*aug != '\0')
387
    {
388
      /* "L" indicates a byte showing how the LSDA pointer is encoded.  */
389
      if (aug[0] == 'L')
390
        {
391
          fs->lsda_encoding = *p++;
392
          aug += 1;
393
        }
394
 
395
      /* "R" indicates a byte indicating how FDE addresses are encoded.  */
396
      else if (aug[0] == 'R')
397
        {
398
          fs->fde_encoding = *p++;
399
          aug += 1;
400
        }
401
 
402
      /* "P" indicates a personality routine in the CIE augmentation.  */
403
      else if (aug[0] == 'P')
404
        {
405
          _Unwind_Ptr personality;
406
 
407
          p = read_encoded_value (context, *p, p + 1, &personality);
408
          fs->personality = (_Unwind_Personality_Fn) personality;
409
          aug += 1;
410
        }
411
 
412
      /* "S" indicates a signal frame.  */
413
      else if (aug[0] == 'S')
414
        {
415
          fs->signal_frame = 1;
416
          aug += 1;
417
        }
418
 
419
      /* Otherwise we have an unknown augmentation string.
420
         Bail unless we saw a 'z' prefix.  */
421
      else
422
        return ret;
423
    }
424
 
425
  return ret ? ret : p;
426
}
427
 
428
 
429
/* Decode a DW_OP stack program.  Return the top of stack.  Push INITIAL
430
   onto the stack to start.  */
431
 
432
static _Unwind_Word
433
execute_stack_op (const unsigned char *op_ptr, const unsigned char *op_end,
434
                  struct _Unwind_Context *context, _Unwind_Word initial)
435
{
436
  _Unwind_Word stack[64];       /* ??? Assume this is enough.  */
437
  int stack_elt;
438
 
439
  stack[0] = initial;
440
  stack_elt = 1;
441
 
442
  while (op_ptr < op_end)
443
    {
444
      enum dwarf_location_atom op = *op_ptr++;
445
      _Unwind_Word result, reg, utmp;
446
      _Unwind_Sword offset, stmp;
447
 
448
      switch (op)
449
        {
450
        case DW_OP_lit0:
451
        case DW_OP_lit1:
452
        case DW_OP_lit2:
453
        case DW_OP_lit3:
454
        case DW_OP_lit4:
455
        case DW_OP_lit5:
456
        case DW_OP_lit6:
457
        case DW_OP_lit7:
458
        case DW_OP_lit8:
459
        case DW_OP_lit9:
460
        case DW_OP_lit10:
461
        case DW_OP_lit11:
462
        case DW_OP_lit12:
463
        case DW_OP_lit13:
464
        case DW_OP_lit14:
465
        case DW_OP_lit15:
466
        case DW_OP_lit16:
467
        case DW_OP_lit17:
468
        case DW_OP_lit18:
469
        case DW_OP_lit19:
470
        case DW_OP_lit20:
471
        case DW_OP_lit21:
472
        case DW_OP_lit22:
473
        case DW_OP_lit23:
474
        case DW_OP_lit24:
475
        case DW_OP_lit25:
476
        case DW_OP_lit26:
477
        case DW_OP_lit27:
478
        case DW_OP_lit28:
479
        case DW_OP_lit29:
480
        case DW_OP_lit30:
481
        case DW_OP_lit31:
482
          result = op - DW_OP_lit0;
483
          break;
484
 
485
        case DW_OP_addr:
486
          result = (_Unwind_Word) (_Unwind_Ptr) read_pointer (op_ptr);
487
          op_ptr += sizeof (void *);
488
          break;
489
 
490
        case DW_OP_const1u:
491
          result = read_1u (op_ptr);
492
          op_ptr += 1;
493
          break;
494
        case DW_OP_const1s:
495
          result = read_1s (op_ptr);
496
          op_ptr += 1;
497
          break;
498
        case DW_OP_const2u:
499
          result = read_2u (op_ptr);
500
          op_ptr += 2;
501
          break;
502
        case DW_OP_const2s:
503
          result = read_2s (op_ptr);
504
          op_ptr += 2;
505
          break;
506
        case DW_OP_const4u:
507
          result = read_4u (op_ptr);
508
          op_ptr += 4;
509
          break;
510
        case DW_OP_const4s:
511
          result = read_4s (op_ptr);
512
          op_ptr += 4;
513
          break;
514
        case DW_OP_const8u:
515
          result = read_8u (op_ptr);
516
          op_ptr += 8;
517
          break;
518
        case DW_OP_const8s:
519
          result = read_8s (op_ptr);
520
          op_ptr += 8;
521
          break;
522
        case DW_OP_constu:
523
          op_ptr = read_uleb128 (op_ptr, &result);
524
          break;
525
        case DW_OP_consts:
526
          op_ptr = read_sleb128 (op_ptr, &stmp);
527
          result = stmp;
528
          break;
529
 
530
        case DW_OP_reg0:
531
        case DW_OP_reg1:
532
        case DW_OP_reg2:
533
        case DW_OP_reg3:
534
        case DW_OP_reg4:
535
        case DW_OP_reg5:
536
        case DW_OP_reg6:
537
        case DW_OP_reg7:
538
        case DW_OP_reg8:
539
        case DW_OP_reg9:
540
        case DW_OP_reg10:
541
        case DW_OP_reg11:
542
        case DW_OP_reg12:
543
        case DW_OP_reg13:
544
        case DW_OP_reg14:
545
        case DW_OP_reg15:
546
        case DW_OP_reg16:
547
        case DW_OP_reg17:
548
        case DW_OP_reg18:
549
        case DW_OP_reg19:
550
        case DW_OP_reg20:
551
        case DW_OP_reg21:
552
        case DW_OP_reg22:
553
        case DW_OP_reg23:
554
        case DW_OP_reg24:
555
        case DW_OP_reg25:
556
        case DW_OP_reg26:
557
        case DW_OP_reg27:
558
        case DW_OP_reg28:
559
        case DW_OP_reg29:
560
        case DW_OP_reg30:
561
        case DW_OP_reg31:
562
          result = _Unwind_GetGR (context, op - DW_OP_reg0);
563
          break;
564
        case DW_OP_regx:
565
          op_ptr = read_uleb128 (op_ptr, &reg);
566
          result = _Unwind_GetGR (context, reg);
567
          break;
568
 
569
        case DW_OP_breg0:
570
        case DW_OP_breg1:
571
        case DW_OP_breg2:
572
        case DW_OP_breg3:
573
        case DW_OP_breg4:
574
        case DW_OP_breg5:
575
        case DW_OP_breg6:
576
        case DW_OP_breg7:
577
        case DW_OP_breg8:
578
        case DW_OP_breg9:
579
        case DW_OP_breg10:
580
        case DW_OP_breg11:
581
        case DW_OP_breg12:
582
        case DW_OP_breg13:
583
        case DW_OP_breg14:
584
        case DW_OP_breg15:
585
        case DW_OP_breg16:
586
        case DW_OP_breg17:
587
        case DW_OP_breg18:
588
        case DW_OP_breg19:
589
        case DW_OP_breg20:
590
        case DW_OP_breg21:
591
        case DW_OP_breg22:
592
        case DW_OP_breg23:
593
        case DW_OP_breg24:
594
        case DW_OP_breg25:
595
        case DW_OP_breg26:
596
        case DW_OP_breg27:
597
        case DW_OP_breg28:
598
        case DW_OP_breg29:
599
        case DW_OP_breg30:
600
        case DW_OP_breg31:
601
          op_ptr = read_sleb128 (op_ptr, &offset);
602
          result = _Unwind_GetGR (context, op - DW_OP_breg0) + offset;
603
          break;
604
        case DW_OP_bregx:
605
          op_ptr = read_uleb128 (op_ptr, &reg);
606
          op_ptr = read_sleb128 (op_ptr, &offset);
607
          result = _Unwind_GetGR (context, reg) + offset;
608
          break;
609
 
610
        case DW_OP_dup:
611
          gcc_assert (stack_elt);
612
          result = stack[stack_elt - 1];
613
          break;
614
 
615
        case DW_OP_drop:
616
          gcc_assert (stack_elt);
617
          stack_elt -= 1;
618
          goto no_push;
619
 
620
        case DW_OP_pick:
621
          offset = *op_ptr++;
622
          gcc_assert (offset < stack_elt - 1);
623
          result = stack[stack_elt - 1 - offset];
624
          break;
625
 
626
        case DW_OP_over:
627
          gcc_assert (stack_elt >= 2);
628
          result = stack[stack_elt - 2];
629
          break;
630
 
631
        case DW_OP_swap:
632
          {
633
            _Unwind_Word t;
634
            gcc_assert (stack_elt >= 2);
635
            t = stack[stack_elt - 1];
636
            stack[stack_elt - 1] = stack[stack_elt - 2];
637
            stack[stack_elt - 2] = t;
638
            goto no_push;
639
          }
640
 
641
        case DW_OP_rot:
642
          {
643
            _Unwind_Word t1, t2, t3;
644
 
645
            gcc_assert (stack_elt >= 3);
646
            t1 = stack[stack_elt - 1];
647
            t2 = stack[stack_elt - 2];
648
            t3 = stack[stack_elt - 3];
649
            stack[stack_elt - 1] = t2;
650
            stack[stack_elt - 2] = t3;
651
            stack[stack_elt - 3] = t1;
652
            goto no_push;
653
          }
654
 
655
        case DW_OP_deref:
656
        case DW_OP_deref_size:
657
        case DW_OP_abs:
658
        case DW_OP_neg:
659
        case DW_OP_not:
660
        case DW_OP_plus_uconst:
661
          /* Unary operations.  */
662
          gcc_assert (stack_elt);
663
          stack_elt -= 1;
664
 
665
          result = stack[stack_elt];
666
 
667
          switch (op)
668
            {
669
            case DW_OP_deref:
670
              {
671
                void *ptr = (void *) (_Unwind_Ptr) result;
672
                result = (_Unwind_Ptr) read_pointer (ptr);
673
              }
674
              break;
675
 
676
            case DW_OP_deref_size:
677
              {
678
                void *ptr = (void *) (_Unwind_Ptr) result;
679
                switch (*op_ptr++)
680
                  {
681
                  case 1:
682
                    result = read_1u (ptr);
683
                    break;
684
                  case 2:
685
                    result = read_2u (ptr);
686
                    break;
687
                  case 4:
688
                    result = read_4u (ptr);
689
                    break;
690
                  case 8:
691
                    result = read_8u (ptr);
692
                    break;
693
                  default:
694
                    gcc_unreachable ();
695
                  }
696
              }
697
              break;
698
 
699
            case DW_OP_abs:
700
              if ((_Unwind_Sword) result < 0)
701
                result = -result;
702
              break;
703
            case DW_OP_neg:
704
              result = -result;
705
              break;
706
            case DW_OP_not:
707
              result = ~result;
708
              break;
709
            case DW_OP_plus_uconst:
710
              op_ptr = read_uleb128 (op_ptr, &utmp);
711
              result += utmp;
712
              break;
713
 
714
            default:
715
              gcc_unreachable ();
716
            }
717
          break;
718
 
719
        case DW_OP_and:
720
        case DW_OP_div:
721
        case DW_OP_minus:
722
        case DW_OP_mod:
723
        case DW_OP_mul:
724
        case DW_OP_or:
725
        case DW_OP_plus:
726
        case DW_OP_shl:
727
        case DW_OP_shr:
728
        case DW_OP_shra:
729
        case DW_OP_xor:
730
        case DW_OP_le:
731
        case DW_OP_ge:
732
        case DW_OP_eq:
733
        case DW_OP_lt:
734
        case DW_OP_gt:
735
        case DW_OP_ne:
736
          {
737
            /* Binary operations.  */
738
            _Unwind_Word first, second;
739
            gcc_assert (stack_elt >= 2);
740
            stack_elt -= 2;
741
 
742
            second = stack[stack_elt];
743
            first = stack[stack_elt + 1];
744
 
745
            switch (op)
746
              {
747
              case DW_OP_and:
748
                result = second & first;
749
                break;
750
              case DW_OP_div:
751
                result = (_Unwind_Sword) second / (_Unwind_Sword) first;
752
                break;
753
              case DW_OP_minus:
754
                result = second - first;
755
                break;
756
              case DW_OP_mod:
757
                result = (_Unwind_Sword) second % (_Unwind_Sword) first;
758
                break;
759
              case DW_OP_mul:
760
                result = second * first;
761
                break;
762
              case DW_OP_or:
763
                result = second | first;
764
                break;
765
              case DW_OP_plus:
766
                result = second + first;
767
                break;
768
              case DW_OP_shl:
769
                result = second << first;
770
                break;
771
              case DW_OP_shr:
772
                result = second >> first;
773
                break;
774
              case DW_OP_shra:
775
                result = (_Unwind_Sword) second >> first;
776
                break;
777
              case DW_OP_xor:
778
                result = second ^ first;
779
                break;
780
              case DW_OP_le:
781
                result = (_Unwind_Sword) first <= (_Unwind_Sword) second;
782
                break;
783
              case DW_OP_ge:
784
                result = (_Unwind_Sword) first >= (_Unwind_Sword) second;
785
                break;
786
              case DW_OP_eq:
787
                result = (_Unwind_Sword) first == (_Unwind_Sword) second;
788
                break;
789
              case DW_OP_lt:
790
                result = (_Unwind_Sword) first < (_Unwind_Sword) second;
791
                break;
792
              case DW_OP_gt:
793
                result = (_Unwind_Sword) first > (_Unwind_Sword) second;
794
                break;
795
              case DW_OP_ne:
796
                result = (_Unwind_Sword) first != (_Unwind_Sword) second;
797
                break;
798
 
799
              default:
800
                gcc_unreachable ();
801
              }
802
          }
803
          break;
804
 
805
        case DW_OP_skip:
806
          offset = read_2s (op_ptr);
807
          op_ptr += 2;
808
          op_ptr += offset;
809
          goto no_push;
810
 
811
        case DW_OP_bra:
812
          gcc_assert (stack_elt);
813
          stack_elt -= 1;
814
 
815
          offset = read_2s (op_ptr);
816
          op_ptr += 2;
817
          if (stack[stack_elt] != 0)
818
            op_ptr += offset;
819
          goto no_push;
820
 
821
        case DW_OP_nop:
822
          goto no_push;
823
 
824
        default:
825
          gcc_unreachable ();
826
        }
827
 
828
      /* Most things push a result value.  */
829
      gcc_assert ((size_t) stack_elt < sizeof(stack)/sizeof(*stack));
830
      stack[stack_elt++] = result;
831
    no_push:;
832
    }
833
 
834
  /* We were executing this program to get a value.  It should be
835
     at top of stack.  */
836
  gcc_assert (stack_elt);
837
  stack_elt -= 1;
838
  return stack[stack_elt];
839
}
840
 
841
 
842
/* Decode DWARF 2 call frame information. Takes pointers the
843
   instruction sequence to decode, current register information and
844
   CIE info, and the PC range to evaluate.  */
845
 
846
static void
847
execute_cfa_program (const unsigned char *insn_ptr,
848
                     const unsigned char *insn_end,
849
                     struct _Unwind_Context *context,
850
                     _Unwind_FrameState *fs)
851
{
852
  struct frame_state_reg_info *unused_rs = NULL;
853
 
854
  /* Don't allow remember/restore between CIE and FDE programs.  */
855
  fs->regs.prev = NULL;
856
 
857
  /* The comparison with the return address uses < rather than <= because
858
     we are only interested in the effects of code before the call; for a
859
     noreturn function, the return address may point to unrelated code with
860
     a different stack configuration that we are not interested in.  We
861
     assume that the call itself is unwind info-neutral; if not, or if
862
     there are delay instructions that adjust the stack, these must be
863
     reflected at the point immediately before the call insn.
864
     In signal frames, return address is after last completed instruction,
865
     so we add 1 to return address to make the comparison <=.  */
866
  while (insn_ptr < insn_end
867
         && fs->pc < context->ra + _Unwind_IsSignalFrame (context))
868
    {
869
      unsigned char insn = *insn_ptr++;
870
      _Unwind_Word reg, utmp;
871
      _Unwind_Sword offset, stmp;
872
 
873
      if ((insn & 0xc0) == DW_CFA_advance_loc)
874
        fs->pc += (insn & 0x3f) * fs->code_align;
875
      else if ((insn & 0xc0) == DW_CFA_offset)
876
        {
877
          reg = insn & 0x3f;
878
          insn_ptr = read_uleb128 (insn_ptr, &utmp);
879
          offset = (_Unwind_Sword) utmp * fs->data_align;
880
          fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
881
            = REG_SAVED_OFFSET;
882
          fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
883
        }
884
      else if ((insn & 0xc0) == DW_CFA_restore)
885
        {
886
          reg = insn & 0x3f;
887
          fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_UNSAVED;
888
        }
889
      else switch (insn)
890
        {
891
        case DW_CFA_set_loc:
892
          {
893
            _Unwind_Ptr pc;
894
 
895
            insn_ptr = read_encoded_value (context, fs->fde_encoding,
896
                                           insn_ptr, &pc);
897
            fs->pc = (void *) pc;
898
          }
899
          break;
900
 
901
        case DW_CFA_advance_loc1:
902
          fs->pc += read_1u (insn_ptr) * fs->code_align;
903
          insn_ptr += 1;
904
          break;
905
        case DW_CFA_advance_loc2:
906
          fs->pc += read_2u (insn_ptr) * fs->code_align;
907
          insn_ptr += 2;
908
          break;
909
        case DW_CFA_advance_loc4:
910
          fs->pc += read_4u (insn_ptr) * fs->code_align;
911
          insn_ptr += 4;
912
          break;
913
 
914
        case DW_CFA_offset_extended:
915
          insn_ptr = read_uleb128 (insn_ptr, &reg);
916
          insn_ptr = read_uleb128 (insn_ptr, &utmp);
917
          offset = (_Unwind_Sword) utmp * fs->data_align;
918
          fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
919
            = REG_SAVED_OFFSET;
920
          fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
921
          break;
922
 
923
        case DW_CFA_restore_extended:
924
          insn_ptr = read_uleb128 (insn_ptr, &reg);
925
          /* FIXME, this is wrong; the CIE might have said that the
926
             register was saved somewhere.  */
927
          fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNSAVED;
928
          break;
929
 
930
        case DW_CFA_undefined:
931
        case DW_CFA_same_value:
932
          insn_ptr = read_uleb128 (insn_ptr, &reg);
933
          fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNSAVED;
934
          break;
935
 
936
        case DW_CFA_nop:
937
          break;
938
 
939
        case DW_CFA_register:
940
          {
941
            _Unwind_Word reg2;
942
            insn_ptr = read_uleb128 (insn_ptr, &reg);
943
            insn_ptr = read_uleb128 (insn_ptr, &reg2);
944
            fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_SAVED_REG;
945
            fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.reg = reg2;
946
          }
947
          break;
948
 
949
        case DW_CFA_remember_state:
950
          {
951
            struct frame_state_reg_info *new_rs;
952
            if (unused_rs)
953
              {
954
                new_rs = unused_rs;
955
                unused_rs = unused_rs->prev;
956
              }
957
            else
958
              new_rs = alloca (sizeof (struct frame_state_reg_info));
959
 
960
            *new_rs = fs->regs;
961
            fs->regs.prev = new_rs;
962
          }
963
          break;
964
 
965
        case DW_CFA_restore_state:
966
          {
967
            struct frame_state_reg_info *old_rs = fs->regs.prev;
968
            fs->regs = *old_rs;
969
            old_rs->prev = unused_rs;
970
            unused_rs = old_rs;
971
          }
972
          break;
973
 
974
        case DW_CFA_def_cfa:
975
          insn_ptr = read_uleb128 (insn_ptr, &fs->cfa_reg);
976
          insn_ptr = read_uleb128 (insn_ptr, &utmp);
977
          fs->cfa_offset = utmp;
978
          fs->cfa_how = CFA_REG_OFFSET;
979
          break;
980
 
981
        case DW_CFA_def_cfa_register:
982
          insn_ptr = read_uleb128 (insn_ptr, &fs->cfa_reg);
983
          fs->cfa_how = CFA_REG_OFFSET;
984
          break;
985
 
986
        case DW_CFA_def_cfa_offset:
987
          insn_ptr = read_uleb128 (insn_ptr, &utmp);
988
          fs->cfa_offset = utmp;
989
          /* cfa_how deliberately not set.  */
990
          break;
991
 
992
        case DW_CFA_def_cfa_expression:
993
          fs->cfa_exp = insn_ptr;
994
          fs->cfa_how = CFA_EXP;
995
          insn_ptr = read_uleb128 (insn_ptr, &utmp);
996
          insn_ptr += utmp;
997
          break;
998
 
999
        case DW_CFA_expression:
1000
          insn_ptr = read_uleb128 (insn_ptr, &reg);
1001
          fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_SAVED_EXP;
1002
          fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.exp = insn_ptr;
1003
          insn_ptr = read_uleb128 (insn_ptr, &utmp);
1004
          insn_ptr += utmp;
1005
          break;
1006
 
1007
          /* Dwarf3.  */
1008
        case DW_CFA_offset_extended_sf:
1009
          insn_ptr = read_uleb128 (insn_ptr, &reg);
1010
          insn_ptr = read_sleb128 (insn_ptr, &stmp);
1011
          offset = stmp * fs->data_align;
1012
          fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
1013
            = REG_SAVED_OFFSET;
1014
          fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
1015
          break;
1016
 
1017
        case DW_CFA_def_cfa_sf:
1018
          insn_ptr = read_uleb128 (insn_ptr, &fs->cfa_reg);
1019
          insn_ptr = read_sleb128 (insn_ptr, &fs->cfa_offset);
1020
          fs->cfa_how = CFA_REG_OFFSET;
1021
          fs->cfa_offset *= fs->data_align;
1022
          break;
1023
 
1024
        case DW_CFA_def_cfa_offset_sf:
1025
          insn_ptr = read_sleb128 (insn_ptr, &fs->cfa_offset);
1026
          fs->cfa_offset *= fs->data_align;
1027
          /* cfa_how deliberately not set.  */
1028
          break;
1029
 
1030
        case DW_CFA_val_offset:
1031
          insn_ptr = read_uleb128 (insn_ptr, &reg);
1032
          insn_ptr = read_uleb128 (insn_ptr, &utmp);
1033
          offset = (_Unwind_Sword) utmp * fs->data_align;
1034
          fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
1035
            = REG_SAVED_VAL_OFFSET;
1036
          fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
1037
          break;
1038
 
1039
        case DW_CFA_val_offset_sf:
1040
          insn_ptr = read_uleb128 (insn_ptr, &reg);
1041
          insn_ptr = read_sleb128 (insn_ptr, &stmp);
1042
          offset = stmp * fs->data_align;
1043
          fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
1044
            = REG_SAVED_VAL_OFFSET;
1045
          fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
1046
          break;
1047
 
1048
        case DW_CFA_val_expression:
1049
          insn_ptr = read_uleb128 (insn_ptr, &reg);
1050
          fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
1051
            = REG_SAVED_VAL_EXP;
1052
          fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.exp = insn_ptr;
1053
          insn_ptr = read_uleb128 (insn_ptr, &utmp);
1054
          insn_ptr += utmp;
1055
          break;
1056
 
1057
        case DW_CFA_GNU_window_save:
1058
          /* ??? Hardcoded for SPARC register window configuration.  */
1059
          for (reg = 16; reg < 32; ++reg)
1060
            {
1061
              fs->regs.reg[reg].how = REG_SAVED_OFFSET;
1062
              fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *);
1063
            }
1064
          break;
1065
 
1066
        case DW_CFA_GNU_args_size:
1067
          insn_ptr = read_uleb128 (insn_ptr, &context->args_size);
1068
          break;
1069
 
1070
        case DW_CFA_GNU_negative_offset_extended:
1071
          /* Obsoleted by DW_CFA_offset_extended_sf, but used by
1072
             older PowerPC code.  */
1073
          insn_ptr = read_uleb128 (insn_ptr, &reg);
1074
          insn_ptr = read_uleb128 (insn_ptr, &utmp);
1075
          offset = (_Unwind_Word) utmp * fs->data_align;
1076
          fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
1077
            = REG_SAVED_OFFSET;
1078
          fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = -offset;
1079
          break;
1080
 
1081
        default:
1082
          gcc_unreachable ();
1083
        }
1084
    }
1085
}
1086
 
1087
/* Given the _Unwind_Context CONTEXT for a stack frame, look up the FDE for
1088
   its caller and decode it into FS.  This function also sets the
1089
   args_size and lsda members of CONTEXT, as they are really information
1090
   about the caller's frame.  */
1091
 
1092
static _Unwind_Reason_Code
1093
uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
1094
{
1095
  const struct dwarf_fde *fde;
1096
  const struct dwarf_cie *cie;
1097
  const unsigned char *aug, *insn, *end;
1098
 
1099
  memset (fs, 0, sizeof (*fs));
1100
  context->args_size = 0;
1101
  context->lsda = 0;
1102
 
1103
  if (context->ra == 0)
1104
    return _URC_END_OF_STACK;
1105
 
1106
  fde = _Unwind_Find_FDE (context->ra + _Unwind_IsSignalFrame (context) - 1,
1107
                          &context->bases);
1108
  if (fde == NULL)
1109
    {
1110
#ifdef MD_FALLBACK_FRAME_STATE_FOR
1111
      /* Couldn't find frame unwind info for this function.  Try a
1112
         target-specific fallback mechanism.  This will necessarily
1113
         not provide a personality routine or LSDA.  */
1114
      return MD_FALLBACK_FRAME_STATE_FOR (context, fs);
1115
#else
1116
      return _URC_END_OF_STACK;
1117
#endif
1118
    }
1119
 
1120
  fs->pc = context->bases.func;
1121
 
1122
  cie = get_cie (fde);
1123
  insn = extract_cie_info (cie, context, fs);
1124
  if (insn == NULL)
1125
    /* CIE contained unknown augmentation.  */
1126
    return _URC_FATAL_PHASE1_ERROR;
1127
 
1128
  /* First decode all the insns in the CIE.  */
1129
  end = (unsigned char *) next_fde ((struct dwarf_fde *) cie);
1130
  execute_cfa_program (insn, end, context, fs);
1131
 
1132
  /* Locate augmentation for the fde.  */
1133
  aug = (unsigned char *) fde + sizeof (*fde);
1134
  aug += 2 * size_of_encoded_value (fs->fde_encoding);
1135
  insn = NULL;
1136
  if (fs->saw_z)
1137
    {
1138
      _Unwind_Word i;
1139
      aug = read_uleb128 (aug, &i);
1140
      insn = aug + i;
1141
    }
1142
  if (fs->lsda_encoding != DW_EH_PE_omit)
1143
    {
1144
      _Unwind_Ptr lsda;
1145
 
1146
      aug = read_encoded_value (context, fs->lsda_encoding, aug, &lsda);
1147
      context->lsda = (void *) lsda;
1148
    }
1149
 
1150
  /* Then the insns in the FDE up to our target PC.  */
1151
  if (insn == NULL)
1152
    insn = aug;
1153
  end = (unsigned char *) next_fde (fde);
1154
  execute_cfa_program (insn, end, context, fs);
1155
 
1156
  return _URC_NO_REASON;
1157
}
1158
 
1159
typedef struct frame_state
1160
{
1161
  void *cfa;
1162
  void *eh_ptr;
1163
  long cfa_offset;
1164
  long args_size;
1165
  long reg_or_offset[PRE_GCC3_DWARF_FRAME_REGISTERS+1];
1166
  unsigned short cfa_reg;
1167
  unsigned short retaddr_column;
1168
  char saved[PRE_GCC3_DWARF_FRAME_REGISTERS+1];
1169
} frame_state;
1170
 
1171
struct frame_state * __frame_state_for (void *, struct frame_state *);
1172
 
1173
/* Called from pre-G++ 3.0 __throw to find the registers to restore for
1174
   a given PC_TARGET.  The caller should allocate a local variable of
1175
   `struct frame_state' and pass its address to STATE_IN.  */
1176
 
1177
struct frame_state *
1178
__frame_state_for (void *pc_target, struct frame_state *state_in)
1179
{
1180
  struct _Unwind_Context context;
1181
  _Unwind_FrameState fs;
1182
  int reg;
1183
 
1184
  memset (&context, 0, sizeof (struct _Unwind_Context));
1185
  context.flags = EXTENDED_CONTEXT_BIT;
1186
  context.ra = pc_target + 1;
1187
 
1188
  if (uw_frame_state_for (&context, &fs) != _URC_NO_REASON)
1189
    return 0;
1190
 
1191
  /* We have no way to pass a location expression for the CFA to our
1192
     caller.  It wouldn't understand it anyway.  */
1193
  if (fs.cfa_how == CFA_EXP)
1194
    return 0;
1195
 
1196
  for (reg = 0; reg < PRE_GCC3_DWARF_FRAME_REGISTERS + 1; reg++)
1197
    {
1198
      state_in->saved[reg] = fs.regs.reg[reg].how;
1199
      switch (state_in->saved[reg])
1200
        {
1201
        case REG_SAVED_REG:
1202
          state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.reg;
1203
          break;
1204
        case REG_SAVED_OFFSET:
1205
          state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.offset;
1206
          break;
1207
        default:
1208
          state_in->reg_or_offset[reg] = 0;
1209
          break;
1210
        }
1211
    }
1212
 
1213
  state_in->cfa_offset = fs.cfa_offset;
1214
  state_in->cfa_reg = fs.cfa_reg;
1215
  state_in->retaddr_column = fs.retaddr_column;
1216
  state_in->args_size = context.args_size;
1217
  state_in->eh_ptr = fs.eh_ptr;
1218
 
1219
  return state_in;
1220
}
1221
 
1222
typedef union { _Unwind_Ptr ptr; _Unwind_Word word; } _Unwind_SpTmp;
1223
 
1224
static inline void
1225
_Unwind_SetSpColumn (struct _Unwind_Context *context, void *cfa,
1226
                     _Unwind_SpTmp *tmp_sp)
1227
{
1228
  int size = dwarf_reg_size_table[__builtin_dwarf_sp_column ()];
1229
 
1230
  if (size == sizeof(_Unwind_Ptr))
1231
    tmp_sp->ptr = (_Unwind_Ptr) cfa;
1232
  else
1233
    {
1234
      gcc_assert (size == sizeof(_Unwind_Word));
1235
      tmp_sp->word = (_Unwind_Ptr) cfa;
1236
    }
1237
  _Unwind_SetGRPtr (context, __builtin_dwarf_sp_column (), tmp_sp);
1238
}
1239
 
1240
static void
1241
uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
1242
{
1243
  struct _Unwind_Context orig_context = *context;
1244
  void *cfa;
1245
  long i;
1246
 
1247
#ifdef EH_RETURN_STACKADJ_RTX
1248
  /* Special handling here: Many machines do not use a frame pointer,
1249
     and track the CFA only through offsets from the stack pointer from
1250
     one frame to the next.  In this case, the stack pointer is never
1251
     stored, so it has no saved address in the context.  What we do
1252
     have is the CFA from the previous stack frame.
1253
 
1254
     In very special situations (such as unwind info for signal return),
1255
     there may be location expressions that use the stack pointer as well.
1256
 
1257
     Do this conditionally for one frame.  This allows the unwind info
1258
     for one frame to save a copy of the stack pointer from the previous
1259
     frame, and be able to use much easier CFA mechanisms to do it.
1260
     Always zap the saved stack pointer value for the next frame; carrying
1261
     the value over from one frame to another doesn't make sense.  */
1262
 
1263
  _Unwind_SpTmp tmp_sp;
1264
 
1265
  if (!_Unwind_GetGRPtr (&orig_context, __builtin_dwarf_sp_column ()))
1266
    _Unwind_SetSpColumn (&orig_context, context->cfa, &tmp_sp);
1267
  _Unwind_SetGRPtr (context, __builtin_dwarf_sp_column (), NULL);
1268
#endif
1269
 
1270
  /* Compute this frame's CFA.  */
1271
  switch (fs->cfa_how)
1272
    {
1273
    case CFA_REG_OFFSET:
1274
      cfa = _Unwind_GetPtr (&orig_context, fs->cfa_reg);
1275
      cfa += fs->cfa_offset;
1276
      break;
1277
 
1278
    case CFA_EXP:
1279
      {
1280
        const unsigned char *exp = fs->cfa_exp;
1281
        _Unwind_Word len;
1282
 
1283
        exp = read_uleb128 (exp, &len);
1284
        cfa = (void *) (_Unwind_Ptr)
1285
          execute_stack_op (exp, exp + len, &orig_context, 0);
1286
        break;
1287
      }
1288
 
1289
    default:
1290
      gcc_unreachable ();
1291
    }
1292
  context->cfa = cfa;
1293
 
1294
  /* Compute the addresses of all registers saved in this frame.  */
1295
  for (i = 0; i < DWARF_FRAME_REGISTERS + 1; ++i)
1296
    switch (fs->regs.reg[i].how)
1297
      {
1298
      case REG_UNSAVED:
1299
        break;
1300
 
1301
      case REG_SAVED_OFFSET:
1302
        _Unwind_SetGRPtr (context, i,
1303
                          (void *) (cfa + fs->regs.reg[i].loc.offset));
1304
        break;
1305
 
1306
      case REG_SAVED_REG:
1307
        if (_Unwind_GRByValue (&orig_context, fs->regs.reg[i].loc.reg))
1308
          _Unwind_SetGRValue (context, i,
1309
                              _Unwind_GetGR (&orig_context,
1310
                                             fs->regs.reg[i].loc.reg));
1311
        else
1312
          _Unwind_SetGRPtr (context, i,
1313
                            _Unwind_GetGRPtr (&orig_context,
1314
                                              fs->regs.reg[i].loc.reg));
1315
        break;
1316
 
1317
      case REG_SAVED_EXP:
1318
        {
1319
          const unsigned char *exp = fs->regs.reg[i].loc.exp;
1320
          _Unwind_Word len;
1321
          _Unwind_Ptr val;
1322
 
1323
          exp = read_uleb128 (exp, &len);
1324
          val = execute_stack_op (exp, exp + len, &orig_context,
1325
                                  (_Unwind_Ptr) cfa);
1326
          _Unwind_SetGRPtr (context, i, (void *) val);
1327
        }
1328
        break;
1329
 
1330
      case REG_SAVED_VAL_OFFSET:
1331
        _Unwind_SetGRValue (context, i,
1332
                            (_Unwind_Internal_Ptr)
1333
                            (cfa + fs->regs.reg[i].loc.offset));
1334
        break;
1335
 
1336
      case REG_SAVED_VAL_EXP:
1337
        {
1338
          const unsigned char *exp = fs->regs.reg[i].loc.exp;
1339
          _Unwind_Word len;
1340
          _Unwind_Ptr val;
1341
 
1342
          exp = read_uleb128 (exp, &len);
1343
          val = execute_stack_op (exp, exp + len, &orig_context,
1344
                                  (_Unwind_Ptr) cfa);
1345
          _Unwind_SetGRValue (context, i, val);
1346
        }
1347
        break;
1348
      }
1349
 
1350
  _Unwind_SetSignalFrame (context, fs->signal_frame);
1351
 
1352
#ifdef MD_FROB_UPDATE_CONTEXT
1353
  MD_FROB_UPDATE_CONTEXT (context, fs);
1354
#endif
1355
}
1356
 
1357
/* CONTEXT describes the unwind state for a frame, and FS describes the FDE
1358
   of its caller.  Update CONTEXT to refer to the caller as well.  Note
1359
   that the args_size and lsda members are not updated here, but later in
1360
   uw_frame_state_for.  */
1361
 
1362
static void
1363
uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
1364
{
1365
  uw_update_context_1 (context, fs);
1366
 
1367
  /* Compute the return address now, since the return address column
1368
     can change from frame to frame.  */
1369
  context->ra = __builtin_extract_return_addr
1370
    (_Unwind_GetPtr (context, fs->retaddr_column));
1371
}
1372
 
1373
static void
1374
uw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
1375
{
1376
  uw_update_context (context, fs);
1377
}
1378
 
1379
/* Fill in CONTEXT for top-of-stack.  The only valid registers at this
1380
   level will be the return address and the CFA.  */
1381
 
1382
#define uw_init_context(CONTEXT)                                           \
1383
  do                                                                       \
1384
    {                                                                      \
1385
      /* Do any necessary initialization to access arbitrary stack frames. \
1386
         On the SPARC, this means flushing the register windows.  */       \
1387
      __builtin_unwind_init ();                                            \
1388
      uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (),                  \
1389
                         __builtin_return_address (0));                     \
1390
    }                                                                      \
1391
  while (0)
1392
 
1393
static inline void
1394
init_dwarf_reg_size_table (void)
1395
{
1396
  __builtin_init_dwarf_reg_size_table (dwarf_reg_size_table);
1397
}
1398
 
1399
static void
1400
uw_init_context_1 (struct _Unwind_Context *context,
1401
                   void *outer_cfa, void *outer_ra)
1402
{
1403
  void *ra = __builtin_extract_return_addr (__builtin_return_address (0));
1404
  _Unwind_FrameState fs;
1405
  _Unwind_SpTmp sp_slot;
1406
  _Unwind_Reason_Code code;
1407
 
1408
  memset (context, 0, sizeof (struct _Unwind_Context));
1409
  context->ra = ra;
1410
  context->flags = EXTENDED_CONTEXT_BIT;
1411
 
1412
  code = uw_frame_state_for (context, &fs);
1413
  gcc_assert (code == _URC_NO_REASON);
1414
 
1415
#if __GTHREADS
1416
  {
1417
    static __gthread_once_t once_regsizes = __GTHREAD_ONCE_INIT;
1418
    if (__gthread_once (&once_regsizes, init_dwarf_reg_size_table) != 0
1419
        || dwarf_reg_size_table[0] == 0)
1420
      init_dwarf_reg_size_table ();
1421
  }
1422
#else
1423
  if (dwarf_reg_size_table[0] == 0)
1424
    init_dwarf_reg_size_table ();
1425
#endif
1426
 
1427
  /* Force the frame state to use the known cfa value.  */
1428
  _Unwind_SetSpColumn (context, outer_cfa, &sp_slot);
1429
  fs.cfa_how = CFA_REG_OFFSET;
1430
  fs.cfa_reg = __builtin_dwarf_sp_column ();
1431
  fs.cfa_offset = 0;
1432
 
1433
  uw_update_context_1 (context, &fs);
1434
 
1435
  /* If the return address column was saved in a register in the
1436
     initialization context, then we can't see it in the given
1437
     call frame data.  So have the initialization context tell us.  */
1438
  context->ra = __builtin_extract_return_addr (outer_ra);
1439
}
1440
 
1441
 
1442
/* Install TARGET into CURRENT so that we can return to it.  This is a
1443
   macro because __builtin_eh_return must be invoked in the context of
1444
   our caller.  */
1445
 
1446
#define uw_install_context(CURRENT, TARGET)                              \
1447
  do                                                                     \
1448
    {                                                                    \
1449
      long offset = uw_install_context_1 ((CURRENT), (TARGET));          \
1450
      void *handler = __builtin_frob_return_addr ((TARGET)->ra);         \
1451
      __builtin_eh_return (offset, handler);                             \
1452
    }                                                                    \
1453
  while (0)
1454
 
1455
static long
1456
uw_install_context_1 (struct _Unwind_Context *current,
1457
                      struct _Unwind_Context *target)
1458
{
1459
  long i;
1460
  _Unwind_SpTmp sp_slot;
1461
 
1462
  /* If the target frame does not have a saved stack pointer,
1463
     then set up the target's CFA.  */
1464
  if (!_Unwind_GetGRPtr (target, __builtin_dwarf_sp_column ()))
1465
    _Unwind_SetSpColumn (target, target->cfa, &sp_slot);
1466
 
1467
  for (i = 0; i < DWARF_FRAME_REGISTERS; ++i)
1468
    {
1469
      void *c = current->reg[i];
1470
      void *t = target->reg[i];
1471
 
1472
      gcc_assert (current->by_value[i] == 0);
1473
      if (target->by_value[i] && c)
1474
        {
1475
          _Unwind_Word w;
1476
          _Unwind_Ptr p;
1477
          if (dwarf_reg_size_table[i] == sizeof (_Unwind_Word))
1478
            {
1479
              w = (_Unwind_Internal_Ptr) t;
1480
              memcpy (c, &w, sizeof (_Unwind_Word));
1481
            }
1482
          else
1483
            {
1484
              gcc_assert (dwarf_reg_size_table[i] == sizeof (_Unwind_Ptr));
1485
              p = (_Unwind_Internal_Ptr) t;
1486
              memcpy (c, &p, sizeof (_Unwind_Ptr));
1487
            }
1488
        }
1489
      else if (t && c && t != c)
1490
        memcpy (c, t, dwarf_reg_size_table[i]);
1491
    }
1492
 
1493
  /* If the current frame doesn't have a saved stack pointer, then we
1494
     need to rely on EH_RETURN_STACKADJ_RTX to get our target stack
1495
     pointer value reloaded.  */
1496
  if (!_Unwind_GetGRPtr (current, __builtin_dwarf_sp_column ()))
1497
    {
1498
      void *target_cfa;
1499
 
1500
      target_cfa = _Unwind_GetPtr (target, __builtin_dwarf_sp_column ());
1501
 
1502
      /* We adjust SP by the difference between CURRENT and TARGET's CFA.  */
1503
      if (STACK_GROWS_DOWNWARD)
1504
        return target_cfa - current->cfa + target->args_size;
1505
      else
1506
        return current->cfa - target_cfa - target->args_size;
1507
    }
1508
  return 0;
1509
}
1510
 
1511
static inline _Unwind_Ptr
1512
uw_identify_context (struct _Unwind_Context *context)
1513
{
1514
  return _Unwind_GetIP (context);
1515
}
1516
 
1517
 
1518
#include "unwind.inc"
1519
 
1520
#if defined (USE_GAS_SYMVER) && defined (SHARED) && defined (USE_LIBUNWIND_EXCEPTIONS)
1521
alias (_Unwind_Backtrace);
1522
alias (_Unwind_DeleteException);
1523
alias (_Unwind_FindEnclosingFunction);
1524
alias (_Unwind_ForcedUnwind);
1525
alias (_Unwind_GetDataRelBase);
1526
alias (_Unwind_GetTextRelBase);
1527
alias (_Unwind_GetCFA);
1528
alias (_Unwind_GetGR);
1529
alias (_Unwind_GetIP);
1530
alias (_Unwind_GetLanguageSpecificData);
1531
alias (_Unwind_GetRegionStart);
1532
alias (_Unwind_RaiseException);
1533
alias (_Unwind_Resume);
1534
alias (_Unwind_Resume_or_Rethrow);
1535
alias (_Unwind_SetGR);
1536
alias (_Unwind_SetIP);
1537
#endif
1538
 
1539
#endif /* !USING_SJLJ_EXCEPTIONS */

powered by: WebSVN 2.1.0

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