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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gcc-4.5.1/] [libstdc++-v3/] [libsupc++/] [eh_personality.cc] - Blame information for rev 859

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

Line No. Rev Author Line
1 424 jeremybenn
// -*- C++ -*- The GNU C++ exception personality routine.
2
// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
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
8
// it under the terms of the GNU General Public License as published by
9
// the Free Software Foundation; either version 3, or (at your option)
10
// any later version.
11
//
12
// GCC is distributed in the hope that it will be useful,
13
// but WITHOUT ANY WARRANTY; without even the implied warranty of
14
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
// GNU General Public License for more details.
16
//
17
// Under Section 7 of GPL version 3, you are granted additional
18
// permissions described in the GCC Runtime Library Exception, version
19
// 3.1, as published by the Free Software Foundation.
20
 
21
// You should have received a copy of the GNU General Public License and
22
// a copy of the GCC Runtime Library Exception along with this program;
23
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24
// <http://www.gnu.org/licenses/>.
25
 
26
#include <bits/c++config.h>
27
#include <cstdlib>
28
#include <exception_defines.h>
29
#include <cxxabi.h>
30
#include "unwind-cxx.h"
31
 
32
using namespace __cxxabiv1;
33
 
34
#ifdef __ARM_EABI_UNWINDER__
35
#define NO_SIZE_OF_ENCODED_VALUE
36
#endif
37
 
38
#include "unwind-pe.h"
39
 
40
 
41
struct lsda_header_info
42
{
43
  _Unwind_Ptr Start;
44
  _Unwind_Ptr LPStart;
45
  _Unwind_Ptr ttype_base;
46
  const unsigned char *TType;
47
  const unsigned char *action_table;
48
  unsigned char ttype_encoding;
49
  unsigned char call_site_encoding;
50
};
51
 
52
static const unsigned char *
53
parse_lsda_header (_Unwind_Context *context, const unsigned char *p,
54
                   lsda_header_info *info)
55
{
56
  _uleb128_t tmp;
57
  unsigned char lpstart_encoding;
58
 
59
  info->Start = (context ? _Unwind_GetRegionStart (context) : 0);
60
 
61
  // Find @LPStart, the base to which landing pad offsets are relative.
62
  lpstart_encoding = *p++;
63
  if (lpstart_encoding != DW_EH_PE_omit)
64
    p = read_encoded_value (context, lpstart_encoding, p, &info->LPStart);
65
  else
66
    info->LPStart = info->Start;
67
 
68
  // Find @TType, the base of the handler and exception spec type data.
69
  info->ttype_encoding = *p++;
70
  if (info->ttype_encoding != DW_EH_PE_omit)
71
    {
72
      p = read_uleb128 (p, &tmp);
73
      info->TType = p + tmp;
74
    }
75
  else
76
    info->TType = 0;
77
 
78
  // The encoding and length of the call-site table; the action table
79
  // immediately follows.
80
  info->call_site_encoding = *p++;
81
  p = read_uleb128 (p, &tmp);
82
  info->action_table = p + tmp;
83
 
84
  return p;
85
}
86
 
87
#ifdef __ARM_EABI_UNWINDER__
88
 
89
// Return an element from a type table.
90
 
91
static const std::type_info*
92
get_ttype_entry(lsda_header_info* info, _uleb128_t i)
93
{
94
  _Unwind_Ptr ptr;
95
 
96
  ptr = (_Unwind_Ptr) (info->TType - (i * 4));
97
  ptr = _Unwind_decode_target2(ptr);
98
 
99
  return reinterpret_cast<const std::type_info *>(ptr);
100
}
101
 
102
// The ABI provides a routine for matching exception object types.
103
typedef _Unwind_Control_Block _throw_typet;
104
#define get_adjusted_ptr(catch_type, throw_type, thrown_ptr_p) \
105
  (__cxa_type_match (throw_type, catch_type, false, thrown_ptr_p) \
106
   != ctm_failed)
107
 
108
// Return true if THROW_TYPE matches one if the filter types.
109
 
110
static bool
111
check_exception_spec(lsda_header_info* info, _throw_typet* throw_type,
112
                     void* thrown_ptr, _sleb128_t filter_value)
113
{
114
  const _uleb128_t* e = ((const _uleb128_t*) info->TType)
115
                          - filter_value - 1;
116
 
117
  while (1)
118
    {
119
      const std::type_info* catch_type;
120
      _uleb128_t tmp;
121
 
122
      tmp = *e;
123
 
124
      // Zero signals the end of the list.  If we've not found
125
      // a match by now, then we've failed the specification.
126
      if (tmp == 0)
127
        return false;
128
 
129
      tmp = _Unwind_decode_target2((_Unwind_Word) e);
130
 
131
      // Match a ttype entry.
132
      catch_type = reinterpret_cast<const std::type_info*>(tmp);
133
 
134
      // ??? There is currently no way to ask the RTTI code about the
135
      // relationship between two types without reference to a specific
136
      // object.  There should be; then we wouldn't need to mess with
137
      // thrown_ptr here.
138
      if (get_adjusted_ptr(catch_type, throw_type, &thrown_ptr))
139
        return true;
140
 
141
      // Advance to the next entry.
142
      e++;
143
    }
144
}
145
 
146
 
147
// Save stage1 handler information in the exception object
148
 
149
static inline void
150
save_caught_exception(struct _Unwind_Exception* ue_header,
151
                      struct _Unwind_Context* context,
152
                      void* thrown_ptr,
153
                      int handler_switch_value,
154
                      const unsigned char* language_specific_data,
155
                      _Unwind_Ptr landing_pad,
156
                      const unsigned char* action_record
157
                        __attribute__((__unused__)))
158
{
159
    ue_header->barrier_cache.sp = _Unwind_GetGR(context, 13);
160
    ue_header->barrier_cache.bitpattern[0] = (_uw) thrown_ptr;
161
    ue_header->barrier_cache.bitpattern[1]
162
      = (_uw) handler_switch_value;
163
    ue_header->barrier_cache.bitpattern[2]
164
      = (_uw) language_specific_data;
165
    ue_header->barrier_cache.bitpattern[3] = (_uw) landing_pad;
166
}
167
 
168
 
169
// Restore the catch handler data saved during phase1.
170
 
171
static inline void
172
restore_caught_exception(struct _Unwind_Exception* ue_header,
173
                         int& handler_switch_value,
174
                         const unsigned char*& language_specific_data,
175
                         _Unwind_Ptr& landing_pad)
176
{
177
  handler_switch_value = (int) ue_header->barrier_cache.bitpattern[1];
178
  language_specific_data =
179
    (const unsigned char*) ue_header->barrier_cache.bitpattern[2];
180
  landing_pad = (_Unwind_Ptr) ue_header->barrier_cache.bitpattern[3];
181
}
182
 
183
#define CONTINUE_UNWINDING \
184
  do                                                            \
185
    {                                                           \
186
      if (__gnu_unwind_frame(ue_header, context) != _URC_OK)    \
187
        return _URC_FAILURE;                                    \
188
      return _URC_CONTINUE_UNWIND;                              \
189
    }                                                           \
190
  while (0)
191
 
192
// Return true if the filter spec is empty, ie throw().
193
 
194
static bool
195
empty_exception_spec (lsda_header_info *info, _Unwind_Sword filter_value)
196
{
197
  const _Unwind_Word* e = ((const _Unwind_Word*) info->TType)
198
                          - filter_value - 1;
199
 
200
  return *e == 0;
201
}
202
 
203
#else
204
typedef const std::type_info _throw_typet;
205
 
206
 
207
// Return an element from a type table.
208
 
209
static const std::type_info *
210
get_ttype_entry (lsda_header_info *info, _uleb128_t i)
211
{
212
  _Unwind_Ptr ptr;
213
 
214
  i *= size_of_encoded_value (info->ttype_encoding);
215
  read_encoded_value_with_base (info->ttype_encoding, info->ttype_base,
216
                                info->TType - i, &ptr);
217
 
218
  return reinterpret_cast<const std::type_info *>(ptr);
219
}
220
 
221
// Given the thrown type THROW_TYPE, pointer to a variable containing a
222
// pointer to the exception object THROWN_PTR_P and a type CATCH_TYPE to
223
// compare against, return whether or not there is a match and if so,
224
// update *THROWN_PTR_P.
225
 
226
static bool
227
get_adjusted_ptr (const std::type_info *catch_type,
228
                  const std::type_info *throw_type,
229
                  void **thrown_ptr_p)
230
{
231
  void *thrown_ptr = *thrown_ptr_p;
232
 
233
  // Pointer types need to adjust the actual pointer, not
234
  // the pointer to pointer that is the exception object.
235
  // This also has the effect of passing pointer types
236
  // "by value" through the __cxa_begin_catch return value.
237
  if (throw_type->__is_pointer_p ())
238
    thrown_ptr = *(void **) thrown_ptr;
239
 
240
  if (catch_type->__do_catch (throw_type, &thrown_ptr, 1))
241
    {
242
      *thrown_ptr_p = thrown_ptr;
243
      return true;
244
    }
245
 
246
  return false;
247
}
248
 
249
// Return true if THROW_TYPE matches one if the filter types.
250
 
251
static bool
252
check_exception_spec(lsda_header_info* info, _throw_typet* throw_type,
253
                      void* thrown_ptr, _sleb128_t filter_value)
254
{
255
  const unsigned char *e = info->TType - filter_value - 1;
256
 
257
  while (1)
258
    {
259
      const std::type_info *catch_type;
260
      _uleb128_t tmp;
261
 
262
      e = read_uleb128 (e, &tmp);
263
 
264
      // Zero signals the end of the list.  If we've not found
265
      // a match by now, then we've failed the specification.
266
      if (tmp == 0)
267
        return false;
268
 
269
      // Match a ttype entry.
270
      catch_type = get_ttype_entry (info, tmp);
271
 
272
      // ??? There is currently no way to ask the RTTI code about the
273
      // relationship between two types without reference to a specific
274
      // object.  There should be; then we wouldn't need to mess with
275
      // thrown_ptr here.
276
      if (get_adjusted_ptr (catch_type, throw_type, &thrown_ptr))
277
        return true;
278
    }
279
}
280
 
281
 
282
// Save stage1 handler information in the exception object
283
 
284
static inline void
285
save_caught_exception(struct _Unwind_Exception* ue_header,
286
                      struct _Unwind_Context* context
287
                        __attribute__((__unused__)),
288
                      void* thrown_ptr,
289
                      int handler_switch_value,
290
                      const unsigned char* language_specific_data,
291
                      _Unwind_Ptr landing_pad __attribute__((__unused__)),
292
                      const unsigned char* action_record)
293
{
294
  __cxa_exception* xh = __get_exception_header_from_ue(ue_header);
295
 
296
  xh->handlerSwitchValue = handler_switch_value;
297
  xh->actionRecord = action_record;
298
  xh->languageSpecificData = language_specific_data;
299
  xh->adjustedPtr = thrown_ptr;
300
 
301
  // ??? Completely unknown what this field is supposed to be for.
302
  // ??? Need to cache TType encoding base for call_unexpected.
303
  xh->catchTemp = landing_pad;
304
}
305
 
306
 
307
// Restore the catch handler information saved during phase1.
308
 
309
static inline void
310
restore_caught_exception(struct _Unwind_Exception* ue_header,
311
                         int& handler_switch_value,
312
                         const unsigned char*& language_specific_data,
313
                         _Unwind_Ptr& landing_pad)
314
{
315
  __cxa_exception* xh = __get_exception_header_from_ue(ue_header);
316
  handler_switch_value = xh->handlerSwitchValue;
317
  language_specific_data = xh->languageSpecificData;
318
  landing_pad = (_Unwind_Ptr) xh->catchTemp;
319
}
320
 
321
#define CONTINUE_UNWINDING return _URC_CONTINUE_UNWIND
322
 
323
// Return true if the filter spec is empty, ie throw().
324
 
325
static bool
326
empty_exception_spec (lsda_header_info *info, _Unwind_Sword filter_value)
327
{
328
  const unsigned char *e = info->TType - filter_value - 1;
329
  _uleb128_t tmp;
330
 
331
  e = read_uleb128 (e, &tmp);
332
  return tmp == 0;
333
}
334
 
335
#endif // !__ARM_EABI_UNWINDER__
336
 
337
namespace __cxxabiv1
338
{
339
 
340
// Using a different personality function name causes link failures
341
// when trying to mix code using different exception handling models.
342
#ifdef _GLIBCXX_SJLJ_EXCEPTIONS
343
#define PERSONALITY_FUNCTION    __gxx_personality_sj0
344
#define __builtin_eh_return_data_regno(x) x
345
#else
346
#define PERSONALITY_FUNCTION    __gxx_personality_v0
347
#endif
348
 
349
extern "C" _Unwind_Reason_Code
350
#ifdef __ARM_EABI_UNWINDER__
351
PERSONALITY_FUNCTION (_Unwind_State state,
352
                      struct _Unwind_Exception* ue_header,
353
                      struct _Unwind_Context* context)
354
#else
355
PERSONALITY_FUNCTION (int version,
356
                      _Unwind_Action actions,
357
                      _Unwind_Exception_Class exception_class,
358
                      struct _Unwind_Exception *ue_header,
359
                      struct _Unwind_Context *context)
360
#endif
361
{
362
  enum found_handler_type
363
  {
364
    found_nothing,
365
    found_terminate,
366
    found_cleanup,
367
    found_handler
368
  } found_type;
369
 
370
  lsda_header_info info;
371
  const unsigned char *language_specific_data;
372
  const unsigned char *action_record;
373
  const unsigned char *p;
374
  _Unwind_Ptr landing_pad, ip;
375
  int handler_switch_value;
376
  void* thrown_ptr = 0;
377
  bool foreign_exception;
378
  int ip_before_insn = 0;
379
 
380
#ifdef __ARM_EABI_UNWINDER__
381
  _Unwind_Action actions;
382
 
383
  switch (state & _US_ACTION_MASK)
384
    {
385
    case _US_VIRTUAL_UNWIND_FRAME:
386
      actions = _UA_SEARCH_PHASE;
387
      break;
388
 
389
    case _US_UNWIND_FRAME_STARTING:
390
      actions = _UA_CLEANUP_PHASE;
391
      if (!(state & _US_FORCE_UNWIND)
392
          && ue_header->barrier_cache.sp == _Unwind_GetGR(context, 13))
393
        actions |= _UA_HANDLER_FRAME;
394
      break;
395
 
396
    case _US_UNWIND_FRAME_RESUME:
397
      CONTINUE_UNWINDING;
398
      break;
399
 
400
    default:
401
      std::abort();
402
    }
403
  actions |= state & _US_FORCE_UNWIND;
404
 
405
  // We don't know which runtime we're working with, so can't check this.
406
  // However the ABI routines hide this from us, and we don't actually need
407
  // to know.
408
  foreign_exception = false;
409
 
410
  // The dwarf unwinder assumes the context structure holds things like the
411
  // function and LSDA pointers.  The ARM implementation caches these in
412
  // the exception header (UCB).  To avoid rewriting everything we make the
413
  // virtual IP register point at the UCB.
414
  ip = (_Unwind_Ptr) ue_header;
415
  _Unwind_SetGR(context, 12, ip);
416
#else
417
  __cxa_exception* xh = __get_exception_header_from_ue(ue_header);
418
 
419
  // Interface version check.
420
  if (version != 1)
421
    return _URC_FATAL_PHASE1_ERROR;
422
  foreign_exception = !__is_gxx_exception_class(exception_class);
423
#endif
424
 
425
  // Shortcut for phase 2 found handler for domestic exception.
426
  if (actions == (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME)
427
      && !foreign_exception)
428
    {
429
      restore_caught_exception(ue_header, handler_switch_value,
430
                               language_specific_data, landing_pad);
431
      found_type = (landing_pad == 0 ? found_terminate : found_handler);
432
      goto install_context;
433
    }
434
 
435
  language_specific_data = (const unsigned char *)
436
    _Unwind_GetLanguageSpecificData (context);
437
 
438
  // If no LSDA, then there are no handlers or cleanups.
439
  if (! language_specific_data)
440
    CONTINUE_UNWINDING;
441
 
442
  // Parse the LSDA header.
443
  p = parse_lsda_header (context, language_specific_data, &info);
444
  info.ttype_base = base_of_encoded_value (info.ttype_encoding, context);
445
#ifdef _GLIBCXX_HAVE_GETIPINFO
446
  ip = _Unwind_GetIPInfo (context, &ip_before_insn);
447
#else
448
  ip = _Unwind_GetIP (context);
449
#endif
450
  if (! ip_before_insn)
451
    --ip;
452
  landing_pad = 0;
453
  action_record = 0;
454
  handler_switch_value = 0;
455
 
456
#ifdef _GLIBCXX_SJLJ_EXCEPTIONS
457
  // The given "IP" is an index into the call-site table, with two
458
  // exceptions -- -1 means no-action, and 0 means terminate.  But
459
  // since we're using uleb128 values, we've not got random access
460
  // to the array.
461
  if ((int) ip < 0)
462
    return _URC_CONTINUE_UNWIND;
463
  else if (ip == 0)
464
    {
465
      // Fall through to set found_terminate.
466
    }
467
  else
468
    {
469
      _uleb128_t cs_lp, cs_action;
470
      do
471
        {
472
          p = read_uleb128 (p, &cs_lp);
473
          p = read_uleb128 (p, &cs_action);
474
        }
475
      while (--ip);
476
 
477
      // Can never have null landing pad for sjlj -- that would have
478
      // been indicated by a -1 call site index.
479
      landing_pad = cs_lp + 1;
480
      if (cs_action)
481
        action_record = info.action_table + cs_action - 1;
482
      goto found_something;
483
    }
484
#else
485
  // Search the call-site table for the action associated with this IP.
486
  while (p < info.action_table)
487
    {
488
      _Unwind_Ptr cs_start, cs_len, cs_lp;
489
      _uleb128_t cs_action;
490
 
491
      // Note that all call-site encodings are "absolute" displacements.
492
      p = read_encoded_value (0, info.call_site_encoding, p, &cs_start);
493
      p = read_encoded_value (0, info.call_site_encoding, p, &cs_len);
494
      p = read_encoded_value (0, info.call_site_encoding, p, &cs_lp);
495
      p = read_uleb128 (p, &cs_action);
496
 
497
      // The table is sorted, so if we've passed the ip, stop.
498
      if (ip < info.Start + cs_start)
499
        p = info.action_table;
500
      else if (ip < info.Start + cs_start + cs_len)
501
        {
502
          if (cs_lp)
503
            landing_pad = info.LPStart + cs_lp;
504
          if (cs_action)
505
            action_record = info.action_table + cs_action - 1;
506
          goto found_something;
507
        }
508
    }
509
#endif // _GLIBCXX_SJLJ_EXCEPTIONS
510
 
511
  // If ip is not present in the table, call terminate.  This is for
512
  // a destructor inside a cleanup, or a library routine the compiler
513
  // was not expecting to throw.
514
  found_type = found_terminate;
515
  goto do_something;
516
 
517
 found_something:
518
  if (landing_pad == 0)
519
    {
520
      // If ip is present, and has a null landing pad, there are
521
      // no cleanups or handlers to be run.
522
      found_type = found_nothing;
523
    }
524
  else if (action_record == 0)
525
    {
526
      // If ip is present, has a non-null landing pad, and a null
527
      // action table offset, then there are only cleanups present.
528
      // Cleanups use a zero switch value, as set above.
529
      found_type = found_cleanup;
530
    }
531
  else
532
    {
533
      // Otherwise we have a catch handler or exception specification.
534
 
535
      _sleb128_t ar_filter, ar_disp;
536
      const std::type_info* catch_type;
537
      _throw_typet* throw_type;
538
      bool saw_cleanup = false;
539
      bool saw_handler = false;
540
 
541
#ifdef __ARM_EABI_UNWINDER__
542
      // ??? How does this work - more importantly, how does it interact with
543
      // dependent exceptions?
544
      throw_type = ue_header;
545
      if (actions & _UA_FORCE_UNWIND)
546
        {
547
          __GXX_INIT_FORCED_UNWIND_CLASS(ue_header->exception_class);
548
        }
549
      else if (!foreign_exception)
550
        thrown_ptr = __get_object_from_ue (ue_header);
551
#else
552
#ifdef __GXX_RTTI
553
      // During forced unwinding, match a magic exception type.
554
      if (actions & _UA_FORCE_UNWIND)
555
        {
556
          throw_type = &typeid(abi::__forced_unwind);
557
        }
558
      // With a foreign exception class, there's no exception type.
559
      // ??? What to do about GNU Java and GNU Ada exceptions?
560
      else if (foreign_exception)
561
        {
562
          throw_type = &typeid(abi::__foreign_exception);
563
        }
564
      else
565
#endif
566
        {
567
          thrown_ptr = __get_object_from_ue (ue_header);
568
          throw_type = __get_exception_header_from_obj
569
            (thrown_ptr)->exceptionType;
570
        }
571
#endif
572
 
573
      while (1)
574
        {
575
          p = action_record;
576
          p = read_sleb128 (p, &ar_filter);
577
          read_sleb128 (p, &ar_disp);
578
 
579
          if (ar_filter == 0)
580
            {
581
              // Zero filter values are cleanups.
582
              saw_cleanup = true;
583
            }
584
          else if (ar_filter > 0)
585
            {
586
              // Positive filter values are handlers.
587
              catch_type = get_ttype_entry (&info, ar_filter);
588
 
589
              // Null catch type is a catch-all handler; we can catch foreign
590
              // exceptions with this.  Otherwise we must match types.
591
              if (! catch_type
592
                  || (throw_type
593
                      && get_adjusted_ptr (catch_type, throw_type,
594
                                           &thrown_ptr)))
595
                {
596
                  saw_handler = true;
597
                  break;
598
                }
599
            }
600
          else
601
            {
602
              // Negative filter values are exception specifications.
603
              // ??? How do foreign exceptions fit in?  As far as I can
604
              // see we can't match because there's no __cxa_exception
605
              // object to stuff bits in for __cxa_call_unexpected to use.
606
              // Allow them iff the exception spec is non-empty.  I.e.
607
              // a throw() specification results in __unexpected.
608
              if ((throw_type
609
                   && !(actions & _UA_FORCE_UNWIND)
610
                   && !foreign_exception)
611
                  ? ! check_exception_spec (&info, throw_type, thrown_ptr,
612
                                            ar_filter)
613
                  : empty_exception_spec (&info, ar_filter))
614
                {
615
                  saw_handler = true;
616
                  break;
617
                }
618
            }
619
 
620
          if (ar_disp == 0)
621
            break;
622
          action_record = p + ar_disp;
623
        }
624
 
625
      if (saw_handler)
626
        {
627
          handler_switch_value = ar_filter;
628
          found_type = found_handler;
629
        }
630
      else
631
        found_type = (saw_cleanup ? found_cleanup : found_nothing);
632
    }
633
 
634
 do_something:
635
   if (found_type == found_nothing)
636
     CONTINUE_UNWINDING;
637
 
638
  if (actions & _UA_SEARCH_PHASE)
639
    {
640
      if (found_type == found_cleanup)
641
        CONTINUE_UNWINDING;
642
 
643
      // For domestic exceptions, we cache data from phase 1 for phase 2.
644
      if (!foreign_exception)
645
        {
646
          save_caught_exception(ue_header, context, thrown_ptr,
647
                                handler_switch_value, language_specific_data,
648
                                landing_pad, action_record);
649
        }
650
      return _URC_HANDLER_FOUND;
651
    }
652
 
653
 install_context:
654
 
655
  // We can't use any of the cxa routines with foreign exceptions,
656
  // because they all expect ue_header to be a struct __cxa_exception.
657
  // So in that case, call terminate or unexpected directly.
658
  if ((actions & _UA_FORCE_UNWIND)
659
      || foreign_exception)
660
    {
661
      if (found_type == found_terminate)
662
        std::terminate ();
663
      else if (handler_switch_value < 0)
664
        {
665
          __try
666
            { std::unexpected (); }
667
          __catch(...)
668
            { std::terminate (); }
669
        }
670
    }
671
  else
672
    {
673
      if (found_type == found_terminate)
674
        __cxa_call_terminate(ue_header);
675
 
676
      // Cache the TType base value for __cxa_call_unexpected, as we won't
677
      // have an _Unwind_Context then.
678
      if (handler_switch_value < 0)
679
        {
680
          parse_lsda_header (context, language_specific_data, &info);
681
 
682
#ifdef __ARM_EABI_UNWINDER__
683
          const _Unwind_Word* e;
684
          _Unwind_Word n;
685
 
686
          e = ((const _Unwind_Word*) info.TType) - handler_switch_value - 1;
687
          // Count the number of rtti objects.
688
          n = 0;
689
          while (e[n] != 0)
690
            n++;
691
 
692
          // Count.
693
          ue_header->barrier_cache.bitpattern[1] = n;
694
          // Base (obsolete)
695
          ue_header->barrier_cache.bitpattern[2] = 0;
696
          // Stride.
697
          ue_header->barrier_cache.bitpattern[3] = 4;
698
          // List head.
699
          ue_header->barrier_cache.bitpattern[4] = (_Unwind_Word) e;
700
#else
701
          xh->catchTemp = base_of_encoded_value (info.ttype_encoding, context);
702
#endif
703
        }
704
    }
705
 
706
  /* For targets with pointers smaller than the word size, we must extend the
707
     pointer, and this extension is target dependent.  */
708
  _Unwind_SetGR (context, __builtin_eh_return_data_regno (0),
709
                 __builtin_extend_pointer (ue_header));
710
  _Unwind_SetGR (context, __builtin_eh_return_data_regno (1),
711
                 handler_switch_value);
712
  _Unwind_SetIP (context, landing_pad);
713
#ifdef __ARM_EABI_UNWINDER__
714
  if (found_type == found_cleanup)
715
    __cxa_begin_cleanup(ue_header);
716
#endif
717
  return _URC_INSTALL_CONTEXT;
718
}
719
 
720
/* The ARM EABI implementation of __cxa_call_unexpected is in a
721
   different file so that the personality routine (PR) can be used
722
   standalone.  The generic routine shared datastructures with the PR
723
   so it is most convenient to implement it here.  */
724
#ifndef __ARM_EABI_UNWINDER__
725
extern "C" void
726
__cxa_call_unexpected (void *exc_obj_in)
727
{
728
  _Unwind_Exception *exc_obj
729
    = reinterpret_cast <_Unwind_Exception *>(exc_obj_in);
730
 
731
  __cxa_begin_catch (exc_obj);
732
 
733
  // This function is a handler for our exception argument.  If we exit
734
  // by throwing a different exception, we'll need the original cleaned up.
735
  struct end_catch_protect
736
  {
737
    end_catch_protect() { }
738
    ~end_catch_protect() { __cxa_end_catch(); }
739
  } end_catch_protect_obj;
740
 
741
  lsda_header_info info;
742
  __cxa_exception *xh = __get_exception_header_from_ue (exc_obj);
743
  const unsigned char *xh_lsda;
744
  _Unwind_Sword xh_switch_value;
745
  std::terminate_handler xh_terminate_handler;
746
 
747
  // If the unexpectedHandler rethrows the exception (e.g. to categorize it),
748
  // it will clobber data about the current handler.  So copy the data out now.
749
  xh_lsda = xh->languageSpecificData;
750
  xh_switch_value = xh->handlerSwitchValue;
751
  xh_terminate_handler = xh->terminateHandler;
752
  info.ttype_base = (_Unwind_Ptr) xh->catchTemp;
753
 
754
  __try
755
    { __unexpected (xh->unexpectedHandler); }
756
  __catch(...)
757
    {
758
      // Get the exception thrown from unexpected.
759
 
760
      __cxa_eh_globals *globals = __cxa_get_globals_fast ();
761
      __cxa_exception *new_xh = globals->caughtExceptions;
762
      void *new_ptr = __get_object_from_ambiguous_exception (new_xh);
763
 
764
      // We don't quite have enough stuff cached; re-parse the LSDA.
765
      parse_lsda_header (0, xh_lsda, &info);
766
 
767
      // If this new exception meets the exception spec, allow it.
768
      if (check_exception_spec (&info, __get_exception_header_from_obj
769
                                  (new_ptr)->exceptionType,
770
                                new_ptr, xh_switch_value))
771
        __throw_exception_again;
772
 
773
      // If the exception spec allows std::bad_exception, throw that.
774
      // We don't have a thrown object to compare against, but since
775
      // bad_exception doesn't have virtual bases, that's OK; just pass 0.
776
#if defined(__EXCEPTIONS) && defined(__GXX_RTTI)
777
      const std::type_info &bad_exc = typeid (std::bad_exception);
778
      if (check_exception_spec (&info, &bad_exc, 0, xh_switch_value))
779
        throw std::bad_exception();
780
#endif   
781
 
782
      // Otherwise, die.
783
      __terminate (xh_terminate_handler);
784
    }
785
}
786
#endif
787
 
788
} // namespace __cxxabiv1

powered by: WebSVN 2.1.0

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