1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/apple/call_with_eh_frame.h"
6
7 #include <stdint.h>
8 #include <unwind.h>
9
10 namespace base::apple {
11
12 #if defined(__x86_64__) || defined(__aarch64__)
13 extern "C" _Unwind_Reason_Code __gxx_personality_v0(int,
14 _Unwind_Action,
15 uint64_t,
16 struct _Unwind_Exception*,
17 struct _Unwind_Context*);
18
CxxPersonalityRoutine(int version,_Unwind_Action actions,uint64_t exception_class,struct _Unwind_Exception * exception_object,struct _Unwind_Context * context)19 _Unwind_Reason_Code CxxPersonalityRoutine(
20 int version,
21 _Unwind_Action actions,
22 uint64_t exception_class,
23 struct _Unwind_Exception* exception_object,
24 struct _Unwind_Context* context) {
25 // Unwinding is a two-phase process: phase one searches for an exception
26 // handler, and phase two performs cleanup. For phase one, this custom
27 // personality will terminate the search. For phase two, this should delegate
28 // back to the standard personality routine.
29
30 if ((actions & _UA_SEARCH_PHASE) != 0) {
31 // Tell libunwind that this is the end of the stack. When it encounters the
32 // CallWithEHFrame, it will stop searching for an exception handler. The
33 // result is that no exception handler has been found higher on the stack,
34 // and any that are lower on the stack (e.g. in CFRunLoopRunSpecific), will
35 // now be skipped. Since this is reporting the end of the stack, and no
36 // exception handler will have been found, std::terminate() will be called.
37 return _URC_END_OF_STACK;
38 }
39
40 return __gxx_personality_v0(version, actions, exception_class,
41 exception_object, context);
42 }
43 #else // !defined(__x86_64__) && !defined(__aarch64__)
44 // No implementation exists, so just call the block directly.
45 void CallWithEHFrame(void (^block)(void)) {
46 block();
47 }
48 #endif // defined(__x86_64__) || defined(__aarch64__)
49 } // namespace base::apple
50