// 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__)