/* * Copyright 2018-2025 Yury Gribov * * The MIT License (MIT) * * Use of this source code is governed by MIT license that can be * found in the LICENSE.txt file. */ .section .note.GNU-stack,"",%progbits .data .globl _${lib_suffix}_tramp_table .hidden _${lib_suffix}_tramp_table .align 4 _${lib_suffix}_tramp_table: .zero $table_size .text .globl _${lib_suffix}_tramp_resolve .hidden _${lib_suffix}_tramp_resolve .globl _${lib_suffix}_save_regs_and_resolve .hidden _${lib_suffix}_save_regs_and_resolve .type _${lib_suffix}_save_regs_and_resolve, %function _${lib_suffix}_save_regs_and_resolve: .cfi_startproc #define PUSH_REG(reg) push {reg}; .cfi_adjust_cfa_offset 4; .cfi_rel_offset reg, 0 #define POP_REG(reg) pop {reg} ; .cfi_adjust_cfa_offset -4; .cfi_restore reg // Binutils 2.30 does not like q0 in .cfi_rel_offset #define PUSH_DREG_PAIR(reg1, reg2) vpush {reg1, reg2}; .cfi_adjust_cfa_offset 16; .cfi_rel_offset reg1, 0; .cfi_rel_offset reg2, 8 #define POP_DREG_PAIR(reg1, reg2) vpop {reg1, reg2}; .cfi_adjust_cfa_offset -16; .cfi_restore reg1; .cfi_restore reg2 // Slow path which calls dlsym, taken only on first call. // Registers are saved acc. to "Procedure Call Standard for the ARM Architecture". // For DWARF directives, read https://www.imperialviolet.org/2017/01/18/cfi.html. // Stack is aligned at 16 bytes at this point // Save only arguments (and lr) PUSH_REG(r0) ldr r0, [sp, #8] PUSH_REG(r1) PUSH_REG(r2) PUSH_REG(r3) PUSH_REG(lr) PUSH_REG(lr) // Align to 8 bytes // Arguments can be passed in VFP registers only when hard-float ABI is used // for arm-gnueabihf target // (http://android-doc.github.io/ndk/guides/abis.html#v7a). // Use compiler macro to detect this case. #ifdef __ARM_PCS_VFP PUSH_DREG_PAIR(d0, d1) PUSH_DREG_PAIR(d2, d3) PUSH_DREG_PAIR(d4, d5) PUSH_DREG_PAIR(d6, d7) PUSH_DREG_PAIR(d8, d9) PUSH_DREG_PAIR(d10, d11) PUSH_DREG_PAIR(d12, d13) PUSH_DREG_PAIR(d14, d15) // FIXME: NEON actually supports 32 D-registers but it's unclear how to detect this #endif bl _${lib_suffix}_tramp_resolve(PLT) mov ip, r0 #ifdef __ARM_PCS_VFP POP_DREG_PAIR(d14, d15) POP_DREG_PAIR(d12, d13) POP_DREG_PAIR(d10, d11) POP_DREG_PAIR(d8, d9) POP_DREG_PAIR(d6, d7) POP_DREG_PAIR(d4, d5) POP_DREG_PAIR(d2, d3) POP_DREG_PAIR(d0, d1) #endif POP_REG(lr) // TODO: pop pc? POP_REG(lr) POP_REG(r3) POP_REG(r2) POP_REG(r1) POP_REG(r0) bx lr .cfi_endproc