1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
base / apple / call_with_eh_frame_asm.S [blame]
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#if defined(__x86_64__) || defined(__aarch64__)
// base::apple::CallWithEHFrame(void () block_pointer)
#define CALL_WITH_EH_FRAME __ZN4base5apple15CallWithEHFrameEU13block_pointerFvvE
.section __TEXT,__text,regular,pure_instructions
#if !defined(COMPONENT_BUILD)
.private_extern CALL_WITH_EH_FRAME
#endif
.globl CALL_WITH_EH_FRAME
.p2align 2
CALL_WITH_EH_FRAME:
.cfi_startproc
// Configure the C++ exception handler personality routine. Normally the
// compiler would emit ___gxx_personality_v0 here. The purpose of this
// function is to use a custom personality routine.
.cfi_personality 155, __ZN4base5apple21CxxPersonalityRoutineEi14_Unwind_ActionyP17_Unwind_ExceptionP15_Unwind_Context
.cfi_lsda 16, CallWithEHFrame_exception_table
#if defined(__x86_64__)
Lfunction_start:
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
// Load the function pointer from the block descriptor.
movq 16(%rdi), %rax
// Execute the block in the context of a C++ try{}.
Ltry_start:
callq *%rax
Ltry_end:
popq %rbp
ret
// Landing pad for the exception handler. This should never be called, since
// the personality routine will stop the search for an exception handler,
// which will cause the runtime to invoke the default terminate handler.
Lcatch:
movq %rax, %rdi
callq ___cxa_begin_catch // The ABI requires a call to the catch handler.
ud2 // In the event this is called, make it fatal.
#elif defined(__aarch64__)
Lfunction_start:
stp x29, x30, [sp, #-16]!
mov x29, sp
.cfi_def_cfa w29, 16
.cfi_offset w30, -8
.cfi_offset w29, -16
// Load the function pointer from the block descriptor.
ldr x8, [x0, #16]
// Execute the block in the context of a C++ try{}.
Ltry_start:
blr x8
Ltry_end:
ldp x29, x30, [sp], #16
ret
// Landing pad for the exception handler. This should never be called, since
// the personality routine will stop the search for an exception handler,
// which will cause the runtime to invoke the default terminate handler.
Lcatch:
bl ___cxa_begin_catch // The ABI requires a call to the catch handler.
brk #0x1 // In the event this is called, make it fatal.
#endif
Lfunction_end:
.cfi_endproc
// The C++ exception table that is used to identify this frame as an
// exception handler. See https://llvm.org/docs/ExceptionHandling.html,
// https://itanium-cxx-abi.github.io/cxx-abi/exceptions.pdf and
// https://www.airs.com/blog/archives/464.
.section __TEXT,__gcc_except_tab
.p2align 2
CallWithEHFrame_exception_table:
.byte 255 // DW_EH_PE_omit
.byte 155 // DW_EH_PE_indirect | DW_EH_PE_pcrel | DW_EH_PE_sdata4
// The number of bytes in this table
.uleb128 Ltypes_table_base - Ltypes_table_ref_base
Ltypes_table_ref_base:
.byte 1 // DW_EH_PE_uleb128
// Callsite table length.
.uleb128 Lcall_site_table_end - Lcall_site_table_start
Lcall_site_table_start:
// First callsite.
CS1_begin = Ltry_start - Lfunction_start
.uleb128 CS1_begin
CS1_end = Ltry_end - Ltry_start
.uleb128 CS1_end
// First landing pad.
LP1 = Lcatch - Lfunction_start
.uleb128 LP1
.uleb128 1 // Action record.
// Second callsite.
CS2_begin = Ltry_end - Lfunction_start
.uleb128 CS2_begin
CS2_end = Lfunction_end - Ltry_end
.uleb128 CS2_end
// Second landing pad (none).
.uleb128 0
.uleb128 0 // No action.
Lcall_site_table_end:
// Action table.
// Action record 1.
.uleb128 1 // Type filter -1.
.uleb128 0 // No further action to take.
// Types table.
.p2align 2
.long 0 // Type filter -1: no type filter for this catch(){} clause.
Ltypes_table_base:
.p2align 2
#endif // defined(__x86_64__) || defined(__aarch64__)