1/* 2 * Copyright (c) 1999-2008 Apple 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#if __i386__ 27/* 28 * This is the implementation of dyld_lazy_dylib_stub_binding_helper for i386 29 * on versions before Macs OS X 10.6. On entry the address of the lazy pointer 30 * has been pushed on the stack. 31 * 32 * After the symbol has been resolved and the lazy pointer filled in, this jumps 33 * to the target address. 34 */ 35#define LP_PARAM_OUT 0 36#define XMMM0_SAVE 16 /* 16-byte align */ 37#define XMMM1_SAVE 32 38#define XMMM2_SAVE 48 39#define XMMM3_SAVE 64 40#define EAX_SAVE 84 41#define ECX_SAVE 88 42#define EDX_SAVE 92 43#define LP_LOCAL 96 44#define STACK_SIZE 104 /* must be 8 mod 16 so that stack winds up 16-byte aliged */ 45#define LP_OLD_BP_SAVE 104 46 47 .text 48 .align 4,0x90 49 .globl dyld_lazy_dylib_stub_binding_helper 50 .private_extern dyld_lazy_dylib_stub_binding_helper 51dyld_lazy_dylib_stub_binding_helper: 52 subl $STACK_SIZE,%esp # makes stack 16-byte aligned 53 movl %eax,EAX_SAVE(%esp) 54 movl LP_OLD_BP_SAVE(%esp),%eax # get lazy-pointer meta-parameter 55 movl %eax,LP_LOCAL(%esp) 56 movl %ebp,LP_OLD_BP_SAVE(%esp) # store epb back chain 57 movl %esp,%ebp # set epb to be this frame 58 add $LP_OLD_BP_SAVE,%ebp 59 movl %ecx,ECX_SAVE(%esp) 60 movl %edx,EDX_SAVE(%esp) 61 movdqu %xmm0,XMMM0_SAVE(%esp) 62 movdqu %xmm1,XMMM1_SAVE(%esp) 63 movdqu %xmm2,XMMM2_SAVE(%esp) 64 movdqu %xmm3,XMMM3_SAVE(%esp) 65 movl LP_LOCAL(%esp),%eax 66 movl %eax,LP_PARAM_OUT(%esp) # call lazy_load_dylib(lazy_ptr) 67 call _lazy_load_dylib 68 movdqu XMMM0_SAVE(%esp),%xmm0 # restore registers 69 movdqu XMMM1_SAVE(%esp),%xmm1 70 movdqu XMMM2_SAVE(%esp),%xmm2 71 movdqu XMMM3_SAVE(%esp),%xmm3 72 movl ECX_SAVE(%esp),%ecx 73 movl EDX_SAVE(%esp),%edx 74 movl %eax,%ebp # move target address to epb 75 movl EAX_SAVE(%esp),%eax # restore eax 76 addl $STACK_SIZE,%esp # cut back stack 77 xchg %ebp, (%esp) # restore ebp and set target to top of stack 78 ret # jump to target 79 80#endif /* __i386__ */ 81 82 83#if __x86_64__ 84/* 85 * This is the implementation of dyld_lazy_dylib_stub_binding_helper for x86_64 86 * on versions before Macs OS X 10.6. On entry r11 contains address of the 87 * lazy pointer. 88 * 89 * All parameters registers must be preserved. 90 * 91 * After the symbol has been resolved and the pointer filled in this is to pop 92 * these arguments off the stack and jump to the address of the defined symbol. 93 */ 94#define RDI_SAVE 0 95#define RSI_SAVE 8 96#define RDX_SAVE 16 97#define RCX_SAVE 24 98#define R8_SAVE 32 99#define R9_SAVE 40 100#define RAX_SAVE 48 101#define XMMM0_SAVE 64 /* 16-byte align */ 102#define XMMM1_SAVE 80 103#define XMMM2_SAVE 96 104#define XMMM3_SAVE 112 105#define XMMM4_SAVE 128 106#define XMMM5_SAVE 144 107#define XMMM6_SAVE 160 108#define XMMM7_SAVE 176 109#define STACK_SIZE 192 /* (XMMM7_SAVE+16) must be 16 byte aligned too */ 110 111 .text 112 .align 2,0x90 113 .globl dyld_lazy_dylib_stub_binding_helper 114 .private_extern dyld_lazy_dylib_stub_binding_helper 115dyld_lazy_dylib_stub_binding_helper: 116 pushq %rbp 117 movq %rsp,%rbp 118 subq $STACK_SIZE,%rsp 119 movq %rdi,RDI_SAVE(%rsp) # save registers that might be used as parameters 120 movq %rsi,RSI_SAVE(%rsp) 121 movq %rdx,RDX_SAVE(%rsp) 122 movq %rcx,RCX_SAVE(%rsp) 123 movq %r8,R8_SAVE(%rsp) 124 movq %r9,R9_SAVE(%rsp) 125 movq %rax,RAX_SAVE(%rsp) 126 movdqa %xmm0,XMMM0_SAVE(%rsp) 127 movdqa %xmm1,XMMM1_SAVE(%rsp) 128 movdqa %xmm2,XMMM2_SAVE(%rsp) 129 movdqa %xmm3,XMMM3_SAVE(%rsp) 130 movdqa %xmm4,XMMM4_SAVE(%rsp) 131 movdqa %xmm5,XMMM5_SAVE(%rsp) 132 movdqa %xmm6,XMMM6_SAVE(%rsp) 133 movdqa %xmm7,XMMM7_SAVE(%rsp) 134 movq %r11,%rdi # call lazy_load_dylib(lazy_ptr) 135 call _lazy_load_dylib 136 movq %rax,%r11 # save target 137 movdqa XMMM0_SAVE(%rsp),%xmm0 # restore registers 138 movdqa XMMM1_SAVE(%rsp),%xmm1 139 movdqa XMMM2_SAVE(%rsp),%xmm2 140 movdqa XMMM3_SAVE(%rsp),%xmm3 141 movdqa XMMM4_SAVE(%rsp),%xmm4 142 movdqa XMMM5_SAVE(%rsp),%xmm5 143 movdqa XMMM6_SAVE(%rsp),%xmm6 144 movdqa XMMM7_SAVE(%rsp),%xmm7 145 movq RDI_SAVE(%rsp),%rdi 146 movq RSI_SAVE(%rsp),%rsi 147 movq RDX_SAVE(%rsp),%rdx 148 movq RCX_SAVE(%rsp),%rcx 149 movq R8_SAVE(%rsp),%r8 150 movq R9_SAVE(%rsp),%r9 151 movq RAX_SAVE(%rsp),%rax 152 addq $STACK_SIZE,%rsp 153 popq %rbp 154 jmp *%r11 # jmp to target 155 156#endif 157 158 159#if __ppc__ || __ppc64__ 160#include <architecture/ppc/mode_independent_asm.h> 161/* 162 * This is the implementation of dyld_lazy_dylib_stub_binding_helper for ppc 163 * on versions before Macs OS X 10.6. On entry r11 contains address of the 164 * lazy pointer to be filled 165 * 166 * r11 address of lazy pointer 167 */ 168#define LRSAVE MODE_CHOICE(8,16) 169#define STACK_SIZE MODE_CHOICE(144,288) 170#define R3SAVE MODE_CHOICE(56,112) 171#define R4SAVE MODE_CHOICE(60,120) 172#define R5SAVE MODE_CHOICE(64,128) 173#define R6SAVE MODE_CHOICE(68,136) 174#define R7SAVE MODE_CHOICE(72,144) 175#define R8SAVE MODE_CHOICE(76,152) 176#define R9SAVE MODE_CHOICE(80,160) 177#define R10SAVE MODE_CHOICE(84,168) 178 179 180 .text 181 .align 2 182 .globl dyld_lazy_dylib_stub_binding_helper 183 .private_extern dyld_lazy_dylib_stub_binding_helper 184dyld_lazy_dylib_stub_binding_helper: 185 mflr r0 ; get link register value 186 stg r0,LRSAVE(r1) ; save link register value in the linkage area 187 stgu r1,-STACK_SIZE(r1) ; save stack pointer and update it 188 189 stg r3,R3SAVE(r1) ; save all registers that could contain 190 stg r4,R4SAVE(r1) ; parameters to the routine that is being 191 stg r5,R5SAVE(r1) ; bound. 192 stg r6,R6SAVE(r1) 193 stg r7,R7SAVE(r1) 194 stg r8,R8SAVE(r1) 195 stg r9,R9SAVE(r1) 196 stg r10,R10SAVE(r1) 197 198 mr r3,r11 ; move address of lazy pointer to 1st parameter 199 ; call lazy_load_dylib(lazy_ptr) 200 bl _lazy_load_dylib 201 mr r12,r3 ; move the symbol`s address into r12 202 mtctr r12 ; move the symbol`s address into count register 203 204 lg r0,STACK_SIZE+LRSAVE(r1) ; get old link register value 205 206 lg r3,R3SAVE(r1) ; restore all registers that could contain 207 lg r4,R4SAVE(r1) ; parameters to the routine that was bound. 208 lg r5,R5SAVE(r1) 209 lg r6,R6SAVE(r1) 210 lg r7,R7SAVE(r1) 211 lg r8,R8SAVE(r1) 212 lg r9,R9SAVE(r1) 213 lg r10,R10SAVE(r1) 214 215 addi r1,r1,STACK_SIZE; restore old stack pointer 216 mtlr r0 ; restore link register 217 218 bctr ; jump to the symbol`s address that was bound 219 220#endif /* __ppc__ */ 221 222#if __arm__ 223/* 224 * This is the implementation of dyld_lazy_dylib_stub_binding_helper for ARM 225 * The caller has pushed the address of the a lazy pointer to be filled in with 226 * the value for the defined symbol 227 * 228 * ip address of lazy pointer 229 * 230 * After the symbol has been resolved and the pointer filled in this is to pop 231 * these arguments off the stack and jump to the address of the defined symbol. 232 */ 233 .text 234 .align 2 235 .globl dyld_lazy_dylib_stub_binding_helper 236 .private_extern dyld_lazy_dylib_stub_binding_helper 237dyld_lazy_dylib_stub_binding_helper: 238 stmfd sp!, {r0,r1,r2,r3,r7,lr} // save registers 239 add r7, sp, #16 // point FP to previous FP 240 241 mov r0, ip // move address of lazy pointer to 1st parameter 242 // call lazy_load_dylib(lazy_ptr) 243 bl _lazy_load_dylib 244 mov ip, r0 // move the symbol`s address into ip 245 246 ldmfd sp!, {r0,r1,r2,r3,r7,lr} // restore registers 247 248 bx ip // jump to the symbol`s address that was bound 249 250#endif /* __arm__ */ 251 252 253 254 255// This code has be written to allow dead code stripping 256 .subsections_via_symbols 257 258 259 260 261 262