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