1419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu// Copyright (C) 2012 The Android Open Source Project
2419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu// All rights reserved.
3419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu//
4419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu// Redistribution and use in source and binary forms, with or without
5419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu// modification, are permitted provided that the following conditions
6419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu// are met:
7419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu// 1. Redistributions of source code must retain the above copyright
8419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu//    notice, this list of conditions and the following disclaimer.
9419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu// 2. Redistributions in binary form must reproduce the above copyright
10419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu//    notice, this list of conditions and the following disclaimer in the
11419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu//    documentation and/or other materials provided with the distribution.
12419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu// 3. Neither the name of the project nor the names of its contributors
13419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu//    may be used to endorse or promote products derived from this software
14419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu//    without specific prior written permission.
15419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu//
16419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
17419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
20419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu// SUCH DAMAGE.
27419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu//===----------------------------------------------------------------------===//
28419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu//                     The LLVM Compiler Infrastructure
29419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu//
30419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu// This file is dual licensed under the MIT and the University of Illinois Open
31419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu// Source Licenses. See LICENSE.TXT for details.
32419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu//
33419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu//
34419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu//  This file implements the "Exception Handling APIs"
35419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu//  http://www.codesourcery.com/public/cxx-abi/abi-eh.html
36419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu//  http://www.intel.com/design/itanium/downloads/245358.htm
37419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu//
38419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu//===----------------------------------------------------------------------===//
39419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu/*
40419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu * Copyright 2010-2011 PathScale, Inc. All rights reserved.
41419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu *
42419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu * Redistribution and use in source and binary forms, with or without
43419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu * modification, are permitted provided that the following conditions are met:
44419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu *
45419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu * 1. Redistributions of source code must retain the above copyright notice,
46419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu *    this list of conditions and the following disclaimer.
47419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu *
48419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu * 2. Redistributions in binary form must reproduce the above copyright notice,
49419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu *    this list of conditions and the following disclaimer in the documentation
50419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu *    and/or other materials provided with the distribution.
51419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu *
52419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
53419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
54419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
55419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
56419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
57419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
58419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
59419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
60419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
61419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
62419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
63419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu */
64419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu
65419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu
66fdf89810ae76eac8def019716322018499531410Albert J. Wong#include <cstdlib>
67419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu#include <unwind.h>
687a9c37698a1e2cdd865b5db7b14f9781cb696da6David 'Digit' Turner
697a9c37698a1e2cdd865b5db7b14f9781cb696da6David 'Digit' Turner#include "cxxabi_defines.h"
70419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu#include "dwarf_helper.h"
71419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu#include "helper_func_internal.h"
72419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu
73419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gunamespace __cxxabiv1 {
74419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu
75419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu#ifdef __arm__
76fdf89810ae76eac8def019716322018499531410Albert J. Wongextern "C" enum type_match_result {
77fdf89810ae76eac8def019716322018499531410Albert J. Wong  ctm_failed = 0,
78fdf89810ae76eac8def019716322018499531410Albert J. Wong  ctm_succeeded = 1,
79fdf89810ae76eac8def019716322018499531410Albert J. Wong  ctm_succeeded_with_ptr_to_base = 2
80fdf89810ae76eac8def019716322018499531410Albert J. Wong};
81fdf89810ae76eac8def019716322018499531410Albert J. Wong
8286514519b937804844bd9809c6bb721fd201c0f4Andrew Hsieh
8386514519b937804844bd9809c6bb721fd201c0f4Andrew Hsiehextern "C" type_match_result __attribute__((visibility("default")))
8486514519b937804844bd9809c6bb721fd201c0f4Andrew Hsieh__cxa_type_match(_Unwind_Exception* ucbp,
8586514519b937804844bd9809c6bb721fd201c0f4Andrew Hsieh                 const __shim_type_info* rttip,
8686514519b937804844bd9809c6bb721fd201c0f4Andrew Hsieh                 bool is_reference_type,
8786514519b937804844bd9809c6bb721fd201c0f4Andrew Hsieh                 void** matched_object) {
88fdf89810ae76eac8def019716322018499531410Albert J. Wong
89fdf89810ae76eac8def019716322018499531410Albert J. Wong  __cxa_exception* header = reinterpret_cast<__cxa_exception*>(ucbp+1)-1;
90fdf89810ae76eac8def019716322018499531410Albert J. Wong  type_match_result result = ctm_succeeded;
91fdf89810ae76eac8def019716322018499531410Albert J. Wong
92fdf89810ae76eac8def019716322018499531410Albert J. Wong  void* adjustedPtr = header+1;
93fdf89810ae76eac8def019716322018499531410Albert J. Wong  if (dynamic_cast<const __pointer_type_info*>(header->exceptionType)) {
94fdf89810ae76eac8def019716322018499531410Albert J. Wong    adjustedPtr = *reinterpret_cast<void**>(adjustedPtr);
95fdf89810ae76eac8def019716322018499531410Albert J. Wong    result = ctm_succeeded_with_ptr_to_base;
96fdf89810ae76eac8def019716322018499531410Albert J. Wong  }
97419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu
98fdf89810ae76eac8def019716322018499531410Albert J. Wong  const __shim_type_info* catch_type = rttip;
99fdf89810ae76eac8def019716322018499531410Albert J. Wong  const __shim_type_info* thrown_type =
100fdf89810ae76eac8def019716322018499531410Albert J. Wong      static_cast<const __shim_type_info*>(header->exceptionType);
101fdf89810ae76eac8def019716322018499531410Albert J. Wong  if (!catch_type || !thrown_type) {
102fdf89810ae76eac8def019716322018499531410Albert J. Wong    return ctm_failed;
103fdf89810ae76eac8def019716322018499531410Albert J. Wong  }
104419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu
105fdf89810ae76eac8def019716322018499531410Albert J. Wong  if (catch_type->can_catch(thrown_type, adjustedPtr)) {
106fdf89810ae76eac8def019716322018499531410Albert J. Wong    *matched_object = adjustedPtr;
107fdf89810ae76eac8def019716322018499531410Albert J. Wong    return result;
108fdf89810ae76eac8def019716322018499531410Albert J. Wong  }
109419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu
110fdf89810ae76eac8def019716322018499531410Albert J. Wong  return ctm_failed;
111fdf89810ae76eac8def019716322018499531410Albert J. Wong}
112fdf89810ae76eac8def019716322018499531410Albert J. Wong#endif  // __arm__
113fdf89810ae76eac8def019716322018499531410Albert J. Wong
114fdf89810ae76eac8def019716322018499531410Albert J. Wongnamespace {
115fdf89810ae76eac8def019716322018499531410Albert J. Wong
116fdf89810ae76eac8def019716322018499531410Albert J. Wongvoid terminate_helper(std::terminate_handler t_handler) {
117fdf89810ae76eac8def019716322018499531410Albert J. Wong  try {
118fdf89810ae76eac8def019716322018499531410Albert J. Wong    t_handler();
119fdf89810ae76eac8def019716322018499531410Albert J. Wong    abort();
120fdf89810ae76eac8def019716322018499531410Albert J. Wong  } catch (...) {
121fdf89810ae76eac8def019716322018499531410Albert J. Wong    abort();
122419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu  }
123fdf89810ae76eac8def019716322018499531410Albert J. Wong}
124419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu
125fdf89810ae76eac8def019716322018499531410Albert J. Wongvoid unexpected_helper(std::unexpected_handler u_handler) {
126fdf89810ae76eac8def019716322018499531410Albert J. Wong  u_handler();
127fdf89810ae76eac8def019716322018499531410Albert J. Wong  std::terminate();
128fdf89810ae76eac8def019716322018499531410Albert J. Wong}
129fdf89810ae76eac8def019716322018499531410Albert J. Wong
130fdf89810ae76eac8def019716322018499531410Albert J. Wong}  // namespace
131fdf89810ae76eac8def019716322018499531410Albert J. Wong
132fdf89810ae76eac8def019716322018499531410Albert J. Wong#ifdef __arm__
13386514519b937804844bd9809c6bb721fd201c0f4Andrew Hsieh  extern "C" bool   __attribute__((visibility("default")))
13486514519b937804844bd9809c6bb721fd201c0f4Andrew Hsieh  __cxa_begin_cleanup(_Unwind_Exception* exc) {
135419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    __cxa_eh_globals *globals = __cxa_get_globals();
136419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    __cxa_exception *header = reinterpret_cast<__cxa_exception*>(exc+1)-1;
137419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    bool native = header->unwindHeader.exception_class == __gxx_exception_class;
138419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu
139419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    if (native) {
140419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      header->cleanupCount += 1;
141419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      if (header->cleanupCount == 1) {  // First time
142419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu        header->nextCleanup = globals->cleanupExceptions;
143419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu        globals->cleanupExceptions = header;
144419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      }
145419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    } else {
146419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      globals->cleanupExceptions = header;
147419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    }
148419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu
149419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    return true;
150419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu  }
151419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu
152419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu  extern "C" _Unwind_Exception * helper_end_cleanup() {
153419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    __cxa_eh_globals *globals = __cxa_get_globals();
154419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    __cxa_exception* header = globals->cleanupExceptions;
155419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu
156419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    if (!header) {
157419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      std::terminate();
158419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    }
159419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu
160419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    if (header->unwindHeader.exception_class == __gxx_exception_class) {
161419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      header->cleanupCount -= 1;
162419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      if (header->cleanupCount == 0) {  // Last one
163419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu        globals->cleanupExceptions = header->nextCleanup;
164419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu        header->nextCleanup = NULL;
165419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      }
166419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    } else {
167419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      globals->cleanupExceptions = NULL;
168419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    }
169419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu
170419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    return &header->unwindHeader;
171419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu  }
172419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu
173419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu  asm (
174419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu  ".pushsection .text.__cxa_end_cleanup    \n"
175419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu  ".global __cxa_end_cleanup               \n"
176419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu  ".type __cxa_end_cleanup, \"function\"   \n"
177419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu  "__cxa_end_cleanup:                      \n"
178419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu  " push\t{r1, r2, r3, r4}                 \n"
179419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu  " bl helper_end_cleanup                  \n"
180419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu  " pop\t{r1, r2, r3, r4}                  \n"
181419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu  " bl _Unwind_Resume                      \n"
182419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu  " bl abort                               \n"
183419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu  ".popsection                             \n"
184419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu  );
185419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu
18686514519b937804844bd9809c6bb721fd201c0f4Andrew Hsieh  extern "C" void __attribute__((visibility("default")))
18786514519b937804844bd9809c6bb721fd201c0f4Andrew Hsieh  __cxa_call_unexpected(void* arg) {
188419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    _Unwind_Exception* unwind_exception = static_cast<_Unwind_Exception*>(arg);
189419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    __cxa_exception* header = reinterpret_cast<__cxa_exception*>(unwind_exception+1)-1;
190419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    bool native_exception = unwind_exception->exception_class == __gxx_exception_class;
191419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu
192419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    if (!native_exception) {
193419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      __cxa_begin_catch(unwind_exception);    // unexpected is also a handler
194419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      try {
195419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu        std::unexpected();
196419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      } catch (...) {
197419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu        std::terminate();
198419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      }
199419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu
200419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      return;
201419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    }
202419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu
203419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    // Cache previous data first since we will change contents below.
204419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    uint32_t count = unwind_exception->barrier_cache.bitpattern[1];
205419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    uint32_t stride = unwind_exception->barrier_cache.bitpattern[3];
206419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    uint32_t* list = reinterpret_cast<uint32_t*>(
207419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu                            unwind_exception->barrier_cache.bitpattern[4]);
208419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu
209419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    __cxa_begin_catch(unwind_exception);    // unexpected is also a handler
210419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    try {
211fdf89810ae76eac8def019716322018499531410Albert J. Wong      unexpected_helper(header->unexpectedHandler);
212419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    } catch (...) {
213419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      // A new exception thrown when calling unexpected.
214419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      bool allow_bad_exception = false;
215419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu
216419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      for (uint32_t i = 0; i != count; ++i) {
217419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu        uint32_t offset = reinterpret_cast<uint32_t>(&list[i * (stride >> 2)]);
218419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu        offset = decodeRelocTarget2(offset);
219fdf89810ae76eac8def019716322018499531410Albert J. Wong        const __shim_type_info* catch_type = reinterpret_cast<const __shim_type_info*>(offset);
220419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu
221419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu        __cxa_exception* new_header = __cxa_get_globals()->caughtExceptions;
222419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu        void* adjustedPtr = new_header + 1;
223419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu        if (__cxa_type_match(&new_header->unwindHeader,
224419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu                             catch_type,
225419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu                             false/* is_ref_type */,
226419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu                             &adjustedPtr) != ctm_failed) {
227419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu          throw;
228419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu        }
229419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu
230419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu        void* null_adjustedPtr = NULL;
231fdf89810ae76eac8def019716322018499531410Albert J. Wong        const __shim_type_info* bad_excp =
232fdf89810ae76eac8def019716322018499531410Albert J. Wong            static_cast<const __shim_type_info*>(&typeid(std::bad_exception));
233fdf89810ae76eac8def019716322018499531410Albert J. Wong        if (catch_type->can_catch(bad_excp, null_adjustedPtr)) {
234419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu          allow_bad_exception = true;
235419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu        }
236419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      }
237419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu
238419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      // If no other ones match, throw bad_exception.
239419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      if (allow_bad_exception) {
240419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu        __cxa_end_catch();
241419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu        __cxa_end_catch();
242419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu        throw std::bad_exception();
243419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      }
244419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu
245fdf89810ae76eac8def019716322018499531410Albert J. Wong      terminate_helper(header->terminateHandler);
246419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    }
247419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu  }
248419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu#else // ! __arm__
24986514519b937804844bd9809c6bb721fd201c0f4Andrew Hsieh  extern "C" void __attribute__((visibility("default")))
25086514519b937804844bd9809c6bb721fd201c0f4Andrew Hsieh  __cxa_call_unexpected(void* arg) {
251419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    _Unwind_Exception* unwind_exception = static_cast<_Unwind_Exception*>(arg);
252419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    if (unwind_exception == 0) {
253419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      call_terminate(unwind_exception);
254419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    }
255419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    __cxa_begin_catch(unwind_exception);    // unexpected is also a handler
256419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu
257419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    bool native_old_exception = unwind_exception->exception_class == __gxx_exception_class;
258419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    std::unexpected_handler u_handler;
259419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    std::terminate_handler t_handler;
260419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    __cxa_exception* old_exception_header = 0;
261419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    int64_t ttypeIndex;
262419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    const uint8_t* lsda;
263419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    if (native_old_exception) {
264419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      old_exception_header = reinterpret_cast<__cxa_exception*>(unwind_exception+1)-1;
265419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      t_handler = old_exception_header->terminateHandler;
266419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      u_handler = old_exception_header->unexpectedHandler;
267fdf89810ae76eac8def019716322018499531410Albert J. Wong      // If unexpected_helper(u_handler) rethrows the same exception,
268419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      //   these values get overwritten by the rethrow.  So save them now:
269419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      ttypeIndex = old_exception_header->handlerSwitchValue;
270419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      lsda = old_exception_header->languageSpecificData;
271419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    } else {
272419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      t_handler = std::get_terminate();
273419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      u_handler = std::get_unexpected();
274419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    }
275419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu
276419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    try {
277fdf89810ae76eac8def019716322018499531410Albert J. Wong      unexpected_helper(u_handler);
278419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    } catch (...) {
279419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      // A new exception thrown when calling unexpected.
280419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu
281419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      if (!native_old_exception) {
282419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu        std::terminate();
283419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      }
284419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      uint8_t lpStartEncoding = *lsda++;
285419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      const uint8_t* lpStart = (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding);
286419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      uint8_t ttypeEncoding = *lsda++;
287419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      if (ttypeEncoding == DW_EH_PE_omit) {
288fdf89810ae76eac8def019716322018499531410Albert J. Wong        terminate_helper(t_handler);
289419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      }
290419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      uintptr_t classInfoOffset = readULEB128(&lsda);
291419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      const uint8_t* classInfo = lsda + classInfoOffset;
292419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      __cxa_eh_globals* globals = __cxa_get_globals_fast();
293419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      __cxa_exception* new_exception_header = globals->caughtExceptions;
294419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      if (new_exception_header == 0) {  // This shouldn't be able to happen!
295fdf89810ae76eac8def019716322018499531410Albert J. Wong        terminate_helper(t_handler);
296419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      }
297419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      bool native_new_exception =
298419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu        new_exception_header->unwindHeader.exception_class == __gxx_exception_class;
299419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu
300419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      if (native_new_exception && (new_exception_header != old_exception_header)) {
301419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu        const std::type_info* excpType = new_exception_header->exceptionType;
302419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu        if (!canExceptionSpecCatch(ttypeIndex, classInfo, ttypeEncoding,
303419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu                                   excpType, new_exception_header+1, unwind_exception)) {
304419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu          // We need to __cxa_end_catch, but for the old exception,
305419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu          //   not the new one.  This is a little tricky ...
306419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu          // Disguise new_exception_header as a rethrown exception, but
307419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu          //   don't actually rethrow it.  This means you can temporarily
308419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu          //   end the catch clause enclosing new_exception_header without
309419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu          //   __cxa_end_catch destroying new_exception_header.
310419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu          new_exception_header->handlerCount = -new_exception_header->handlerCount;
311419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu          globals->uncaughtExceptions += 1;
312419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu          __cxa_end_catch();
313419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu          __cxa_end_catch();
314419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu          __cxa_begin_catch(&new_exception_header->unwindHeader);
315419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu          throw;
316419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu        }
317419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      }
318419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu
319419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      const std::type_info* excpType = &typeid(std::bad_exception);
320419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      if (!canExceptionSpecCatch(ttypeIndex, classInfo, ttypeEncoding,
321419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu                                 excpType, NULL, unwind_exception)) {
322419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu        __cxa_end_catch();
323419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu        __cxa_end_catch();
324419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu        throw std::bad_exception();
325419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu      }
326419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    } // catch (...)
327419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu
328419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu    // Call terminate after unexpected normally done
329fdf89810ae76eac8def019716322018499531410Albert J. Wong    terminate_helper(t_handler);
330419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu  }
331419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu#endif // __arm__
332419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu
333419afd910dc325e65df10b53e99e49c1eded6d26WenHan Gu} // namespace __cxxabiv1
334