Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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