stub_binding_helper.s [plain text]
/*
* Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
#ifdef __i386__
/*
* This is the interface for the stub_binding_helper for i386:
* The caller has pushed the address of the a lazy pointer to be filled in with
* the value for the defined symbol and pushed the address of the the mach
* header this pointer comes from.
*
* sp+4 address of lazy pointer
* sp+0 address of mach header
*
* Some inter-image function calls pass parameters in registers EAX, ECX, EDX, or XXM0-3,
* Therefore those registers need to be preserved during the lazy binding.
*
* After the symbol has been resolved and the pointer filled in this is to pop
* these arguments off the stack and jump to the address of the defined symbol.
*/
#define MH_PARAM_BP 4
#define LP_PARAM_BP 8
#define RESULT_BP 8 /* in order to trash no registers, the target is stored back on the stack then ret it done to it */
#define MH_PARAM_OUT 0
#define LP_PARAM_OUT 4
#define EAX_SAVE 8
#define ECX_SAVE 12
#define EDX_SAVE 16
#define XMMM0_SAVE 32 /* 16-byte align */
#define XMMM1_SAVE 48
#define XMMM2_SAVE 64
#define XMMM3_SAVE 80
#define STACK_SIZE 96 /* (XMMM3_SAVE+16) must be 16 byte aligned too */
.text
.align 4,0x90
.globl _fast_stub_binding_helper_interface
_fast_stub_binding_helper_interface:
pushl $0
.globl _stub_binding_helper_interface
_stub_binding_helper_interface:
pushl %ebp
movl %esp,%ebp
subl $STACK_SIZE,%esp # at this point stack is 16-byte aligned because two meta-parameters where pushed
movl %eax,EAX_SAVE(%esp) # save registers that might be used as parameters
movl %ecx,ECX_SAVE(%esp)
movl %edx,EDX_SAVE(%esp)
movdqa %xmm0,XMMM0_SAVE(%esp)
movdqa %xmm1,XMMM1_SAVE(%esp)
movdqa %xmm2,XMMM2_SAVE(%esp)
movdqa %xmm3,XMMM3_SAVE(%esp)
movl MH_PARAM_BP(%ebp),%eax # call dyld::bindLazySymbol(mh, lazy_ptr)
movl %eax,MH_PARAM_OUT(%esp)
movl LP_PARAM_BP(%ebp),%eax
movl %eax,LP_PARAM_OUT(%esp)
call __ZN4dyld14bindLazySymbolEPK11mach_headerPm
movl %eax,RESULT_BP(%ebp) # store target for ret
movdqa XMMM0_SAVE(%esp),%xmm0 # restore registers
movdqa XMMM1_SAVE(%esp),%xmm1
movdqa XMMM2_SAVE(%esp),%xmm2
movdqa XMMM3_SAVE(%esp),%xmm3
movl EAX_SAVE(%esp),%eax
movl ECX_SAVE(%esp),%ecx
movl EDX_SAVE(%esp),%edx
addl $STACK_SIZE,%esp
popl %ebp
addl $4,%esp # remove meta-parameter, other meta-parmaeter now holds target for ret
ret
#endif /* __i386__ */
#if __x86_64__
/*
* This is the interface for the stub_binding_helper for x86_64:
* The caller has pushed the address of the a lazy pointer to be filled in with
* the value for the defined symbol and pushed the address of the the mach
* header this pointer comes from.
*
* sp+4 address of lazy pointer
* sp+0 address of mach header
*
* All parameters registers must be preserved.
*
* After the symbol has been resolved and the pointer filled in this is to pop
* these arguments off the stack and jump to the address of the defined symbol.
*/
#define MH_PARAM_BP 8
#define LP_PARAM_BP 16
#define RDI_SAVE 0
#define RSI_SAVE 8
#define RDX_SAVE 16
#define RCX_SAVE 24
#define R8_SAVE 32
#define R9_SAVE 40
#define RAX_SAVE 48
#define XMMM0_SAVE 64 /* 16-byte align */
#define XMMM1_SAVE 80
#define XMMM2_SAVE 96
#define XMMM3_SAVE 112
#define XMMM4_SAVE 128
#define XMMM5_SAVE 144
#define XMMM6_SAVE 160
#define XMMM7_SAVE 176
#define STACK_SIZE 192 /* (XMMM7_SAVE+16) must be 16 byte aligned too */
.text
.align 2,0x90
.globl _stub_binding_helper_interface
_stub_binding_helper_interface:
pushq %rbp
movq %rsp,%rbp
subq $STACK_SIZE,%rsp # at this point stack is 16-byte aligned because two meta-parameters where pushed
movq %rdi,RDI_SAVE(%rsp) # save registers that might be used as parameters
movq %rsi,RSI_SAVE(%rsp)
movq %rdx,RDX_SAVE(%rsp)
movq %rcx,RCX_SAVE(%rsp)
movq %r8,R8_SAVE(%rsp)
movq %r9,R9_SAVE(%rsp)
movq %rax,RAX_SAVE(%rsp)
movdqa %xmm0,XMMM0_SAVE(%rsp)
movdqa %xmm1,XMMM1_SAVE(%rsp)
movdqa %xmm2,XMMM2_SAVE(%rsp)
movdqa %xmm3,XMMM3_SAVE(%rsp)
movdqa %xmm4,XMMM4_SAVE(%rsp)
movdqa %xmm5,XMMM5_SAVE(%rsp)
movdqa %xmm6,XMMM6_SAVE(%rsp)
movdqa %xmm7,XMMM7_SAVE(%rsp)
movq MH_PARAM_BP(%rbp),%rdi # call dyld::bindLazySymbol(mh, lazy_ptr)
movq LP_PARAM_BP(%rbp),%rsi
call __ZN4dyld14bindLazySymbolEPK11mach_headerPm
movq %rax,%r11 # save target
movdqa XMMM0_SAVE(%rsp),%xmm0 # restore registers
movdqa XMMM1_SAVE(%rsp),%xmm1
movdqa XMMM2_SAVE(%rsp),%xmm2
movdqa XMMM3_SAVE(%rsp),%xmm3
movdqa XMMM4_SAVE(%rsp),%xmm4
movdqa XMMM5_SAVE(%rsp),%xmm5
movdqa XMMM6_SAVE(%rsp),%xmm6
movdqa XMMM7_SAVE(%rsp),%xmm7
movq RDI_SAVE(%rsp),%rdi
movq RSI_SAVE(%rsp),%rsi
movq RDX_SAVE(%rsp),%rdx
movq RCX_SAVE(%rsp),%rcx
movq R8_SAVE(%rsp),%r8
movq R9_SAVE(%rsp),%r9
movq RAX_SAVE(%rsp),%rax
addq $STACK_SIZE,%rsp
popq %rbp
addq $16,%rsp # remove meta-parameters
jmp *%r11 # jmp to target
#endif
#if __ppc__ || __ppc64__
#include <architecture/ppc/mode_independent_asm.h>
/*
* This is the interface for the stub_binding_helper for the ppc:
* The caller has placed in r11 the address of the a lazy pointer to be filled
* in with the value for the defined symbol and placed in r12 the address of
* the the mach header this pointer comes from.
*
* r11 address of lazy pointer
* r12 address of mach header
*/
#define LRSAVE MODE_CHOICE(8,16)
#define STACK_SIZE MODE_CHOICE(144,288)
#define R3SAVE MODE_CHOICE(56,112)
#define R4SAVE MODE_CHOICE(60,120)
#define R5SAVE MODE_CHOICE(64,128)
#define R6SAVE MODE_CHOICE(68,136)
#define R7SAVE MODE_CHOICE(72,144)
#define R8SAVE MODE_CHOICE(76,152)
#define R9SAVE MODE_CHOICE(80,160)
#define R10SAVE MODE_CHOICE(84,168)
.text
.align 2
.globl _stub_binding_helper_interface
_stub_binding_helper_interface:
mflr r0 stgu r1,-STACK_SIZE(r1) stg r3,R3SAVE(r1) stg r5,R5SAVE(r1) stg r7,R7SAVE(r1)
stg r8,R8SAVE(r1)
stg r9,R9SAVE(r1)
stg r10,R10SAVE(r1)
mr r3,r12 mr r12,r3
lg r0,STACK_SIZE+LRSAVE(r1) lg r3,R3SAVE(r1) lg r5,R5SAVE(r1)
lg r6,R6SAVE(r1)
lg r7,R7SAVE(r1)
lg r8,R8SAVE(r1)
lg r9,R9SAVE(r1)
lg r10,R10SAVE(r1)
addi r1,r1,STACK_SIZE
bctr #endif /* __ppc__ */