1/* 2 * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 25 26#ifdef __i386__ 27/* 28 * This is the interface for the stub_binding_helper for i386: 29 * The caller has pushed the address of the a lazy pointer to be filled in 30 * and pushed the address of the the mach header this pointer comes from. 31 * 32 * sp+4 address of lazy pointer 33 * sp+0 address of mach header 34 * 35 * Some inter-image function calls pass parameters in registers EAX, ECX, EDX, or XXM0-3, 36 * Therefore those registers need to be preserved during the lazy binding. 37 * 38 * After the symbol has been resolved and the lazy pointer filled in, this jumps 39 * to the target address. 40 */ 41#define MH_PARAM_OUT 0 42#define LP_PARAM_OUT 4 43#define XMMM0_SAVE 16 /* 16-byte align */ 44#define XMMM1_SAVE 32 45#define XMMM2_SAVE 48 46#define XMMM3_SAVE 64 47#define EAX_SAVE 84 48#define ECX_SAVE 88 49#define EDX_SAVE 92 50#define LP_LOCAL 96 51#define MH_LOCAL 100 52#define STACK_SIZE 100 /* must be 4 mod 16 so that stack winds up 16-byte aliged */ 53#define LP_OLD_BP_SAVE 104 54 55 .text 56 .align 4,0x90 57 .globl _stub_binding_helper_i386_old 58_stub_binding_helper_i386_old: 59 pushl $0 60 .globl _stub_binding_helper 61 .globl _misaligned_stack_error 62_stub_binding_helper: 63 subl $STACK_SIZE,%esp # makes stack 16-byte aligned 64 movl %eax,EAX_SAVE(%esp) 65 movl LP_OLD_BP_SAVE(%esp),%eax # get lazy-pointer meta-parameter 66 movl %eax,LP_LOCAL(%esp) 67 movl %ebp,LP_OLD_BP_SAVE(%esp) # store epb back chain 68 movl %esp,%ebp # set epb to be this frame 69 add $LP_OLD_BP_SAVE,%ebp 70 movl %ecx,ECX_SAVE(%esp) 71 movl %edx,EDX_SAVE(%esp) 72 .align 0,0x90 73_misaligned_stack_error: 74 movdqa %xmm0,XMMM0_SAVE(%esp) 75 movdqa %xmm1,XMMM1_SAVE(%esp) 76 movdqa %xmm2,XMMM2_SAVE(%esp) 77 movdqa %xmm3,XMMM3_SAVE(%esp) 78_stub_binding_helper_interface2: 79 movl MH_LOCAL(%esp),%eax # call dyld::bindLazySymbol(mh, lazy_ptr) 80 movl %eax,MH_PARAM_OUT(%esp) 81 movl LP_LOCAL(%esp),%eax 82 movl %eax,LP_PARAM_OUT(%esp) 83 call __ZN4dyld14bindLazySymbolEPK11mach_headerPm 84 movdqa XMMM0_SAVE(%esp),%xmm0 # restore registers 85 movdqa XMMM1_SAVE(%esp),%xmm1 86 movdqa XMMM2_SAVE(%esp),%xmm2 87 movdqa XMMM3_SAVE(%esp),%xmm3 88 movl ECX_SAVE(%esp),%ecx 89 movl EDX_SAVE(%esp),%edx 90 movl %eax,%ebp # move target address to epb 91 movl EAX_SAVE(%esp),%eax # restore eaz 92 addl $STACK_SIZE+4,%esp # cut back stack 93 xchg %ebp, (%esp) # restore ebp and set target to top of stack 94 ret # jump to target 95 96#endif /* __i386__ */ 97 98 99#if __x86_64__ 100/* 101 * This is the interface for the stub_binding_helper for x86_64: 102 * The caller has pushed the address of the a lazy pointer to be filled in with 103 * the value for the defined symbol and pushed the address of the the mach 104 * header this pointer comes from. 105 * 106 * sp+8 address of lazy pointer 107 * sp+0 address of mach header 108 * 109 * All parameters registers must be preserved. 110 * 111 * After the symbol has been resolved and the pointer filled in this is to pop 112 * these arguments off the stack and jump to the address of the defined symbol. 113 */ 114#define MH_PARAM_BP 8 115#define LP_PARAM_BP 16 116 117#define RDI_SAVE 0 118#define RSI_SAVE 8 119#define RDX_SAVE 16 120#define RCX_SAVE 24 121#define R8_SAVE 32 122#define R9_SAVE 40 123#define RAX_SAVE 48 124#define XMMM0_SAVE 64 /* 16-byte align */ 125#define XMMM1_SAVE 80 126#define XMMM2_SAVE 96 127#define XMMM3_SAVE 112 128#define XMMM4_SAVE 128 129#define XMMM5_SAVE 144 130#define XMMM6_SAVE 160 131#define XMMM7_SAVE 176 132#define STACK_SIZE 192 /* (XMMM7_SAVE+16) must be 16 byte aligned too */ 133 134 .text 135 .align 2,0x90 136 .globl _stub_binding_helper 137_stub_binding_helper: 138 pushq %rbp 139 movq %rsp,%rbp 140 subq $STACK_SIZE,%rsp # at this point stack is 16-byte aligned because two meta-parameters where pushed 141 movq %rdi,RDI_SAVE(%rsp) # save registers that might be used as parameters 142 movq %rsi,RSI_SAVE(%rsp) 143 movq %rdx,RDX_SAVE(%rsp) 144 movq %rcx,RCX_SAVE(%rsp) 145 movq %r8,R8_SAVE(%rsp) 146 movq %r9,R9_SAVE(%rsp) 147 movq %rax,RAX_SAVE(%rsp) 148 movdqa %xmm0,XMMM0_SAVE(%rsp) 149 movdqa %xmm1,XMMM1_SAVE(%rsp) 150 movdqa %xmm2,XMMM2_SAVE(%rsp) 151 movdqa %xmm3,XMMM3_SAVE(%rsp) 152 movdqa %xmm4,XMMM4_SAVE(%rsp) 153 movdqa %xmm5,XMMM5_SAVE(%rsp) 154 movdqa %xmm6,XMMM6_SAVE(%rsp) 155 movdqa %xmm7,XMMM7_SAVE(%rsp) 156 movq MH_PARAM_BP(%rbp),%rdi # call dyld::bindLazySymbol(mh, lazy_ptr) 157 movq LP_PARAM_BP(%rbp),%rsi 158 call __ZN4dyld14bindLazySymbolEPK11mach_headerPm 159 movq %rax,%r11 # save target 160 movdqa XMMM0_SAVE(%rsp),%xmm0 # restore registers 161 movdqa XMMM1_SAVE(%rsp),%xmm1 162 movdqa XMMM2_SAVE(%rsp),%xmm2 163 movdqa XMMM3_SAVE(%rsp),%xmm3 164 movdqa XMMM4_SAVE(%rsp),%xmm4 165 movdqa XMMM5_SAVE(%rsp),%xmm5 166 movdqa XMMM6_SAVE(%rsp),%xmm6 167 movdqa XMMM7_SAVE(%rsp),%xmm7 168 movq RDI_SAVE(%rsp),%rdi 169 movq RSI_SAVE(%rsp),%rsi 170 movq RDX_SAVE(%rsp),%rdx 171 movq RCX_SAVE(%rsp),%rcx 172 movq R8_SAVE(%rsp),%r8 173 movq R9_SAVE(%rsp),%r9 174 movq RAX_SAVE(%rsp),%rax 175 addq $STACK_SIZE,%rsp 176 popq %rbp 177 addq $16,%rsp # remove meta-parameters 178 jmp *%r11 # jmp to target 179 180#endif 181 182 183#if __arm__ 184/* 185 * This is the interface for the stub_binding_helper for ARM: 186 * The caller has pushed the address of the a lazy pointer to be filled in with 187 * the value for the defined symbol and pushed the address of the the mach 188 * header this pointer comes from. 189 * 190 * sp+4 address of lazy pointer 191 * sp+0 address of mach header 192 * 193 * After the symbol has been resolved and the pointer filled in this is to pop 194 * these arguments off the stack and jump to the address of the defined symbol. 195 */ 196 197 .text 198 .align 2 199 .globl _stub_binding_helper 200_stub_binding_helper: 201 stmfd sp!, {r0,r1,r2,r3,r7,lr} // save registers 202 add r7, sp, #16 // point FP to previous FP 203 204 ldr r0, [sp, #24] // move address of mach header to 1st parameter 205 ldr r1, [sp, #28] // move address of lazy pointer to 2nd parameter 206 207 // call dyld::bindLazySymbol(mh, lazy_symbol_pointer_address) 208 bl __ZN4dyld14bindLazySymbolEPK11mach_headerPm 209 mov ip, r0 // move the symbol`s address into ip 210 211 ldmfd sp!, {r0,r1,r2,r3,r7,lr} // restore registers 212 add sp, sp, #8 // remove meta-parameters 213 214 bx ip // jump to the symbol`s address that was bound 215 216#endif /* __arm__ */ 217 218 219 220 221 222 223 224 225 226 227