1/* 2 * Copyright (c) 2006-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#if __ppc__ && __PIC__ 26// 27// Force stub section next to __text section to minimize chance that 28// a bl to a stub will be out of range. 29// 30 .text 31 .section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 32#endif 33 34//////////////////////////////////////////////////////////////////// 35// 36// The dyld_stub_binding_helper adds the mach_header parameter 37// and then jumps into dyld via a pointer in __dyld section 38// 39//////////////////////////////////////////////////////////////////// 40 .text 41 .private_extern dyld_stub_binding_helper 42 .align 2 43dyld_stub_binding_helper: 44 45#if __ppc__ 46 // for ppc the mach_header parameter is place in r12 47 // and the lazy_pointer is already in r11 48 #if __PIC__ 49 mflr r0 50 bcl 20,31,L1 51L1: mflr r12 52 mtlr r0 53 mr r0,r12 54 addis r12,r12,ha16(Ldyld_content_lazy_binder-L1) 55 lwz r12,lo16(Ldyld_content_lazy_binder-L1)(r12) 56 mtctr r12 57 mr r12,r0 58 addis r12,r12,ha16(dyld__mach_header-L1) 59 lwz r12,lo16(dyld__mach_header-L1)(r12) 60 bctr 61 #else 62 lis r12,ha16(Ldyld_content_lazy_binder) 63 lwz r12,lo16(Ldyld_content_lazy_binder)(r12) 64 mtctr r12 65 lis r12,ha16(___dso_handle) 66 la r12,lo16(___dso_handle)(r12) 67 bctr 68 #endif 69 70#elif __ppc64__ 71 // for ppc the mach_header parameter is place in r12 72 // and the lazy_pointer is already in r11 73 // always use PIC code so we can have 4GB zero page 74 mflr r0 75 bcl 20,31,L1 76L1: mflr r12 77 mtlr r0 78 mr r0,r12 79 addis r12,r12,ha16(Ldyld_content_lazy_binder-L1) 80 ld r12,lo16(Ldyld_content_lazy_binder-L1)(r12) 81 mtctr r12 82 mr r12,r0 83 addis r12,r12,ha16(dyld__mach_header-L1) 84 ld r12,lo16(dyld__mach_header-L1)(r12) 85 bctr 86 87#elif __i386__ 88 // for i386 the mach_header parameter is pushed on the stack 89 // and the lazy_pointer is already on the stack 90 #if __PIC__ 91 subl $8,%esp 92 pushl %eax 93 pushl %ecx 94 call L1 95L1: popl %eax 96 movl dyld__mach_header-L1(%eax),%ecx 97 movl %ecx,12(%esp) 98 movl Ldyld_content_lazy_binder-L1(%eax),%ecx 99 movl %ecx,8(%esp) 100 popl %ecx 101 popl %eax 102 ret // jumps into dyld with lp and mh on the stack 103 #else 104 pushl $___dso_handle 105 jmpl *Ldyld_content_lazy_binder 106 #endif 107 108#elif __x86_64__ 109 // for x86_64 the mach_header parameter is pushed on the stack 110 // and the lazy_pointer was in r11 and is pushed on the stack 111 pushq %r11 112 leaq ___dso_handle(%rip), %r11 113 pushq %r11 114 jmp *Ldyld_content_lazy_binder(%rip) 115 116#elif __arm__ 117 str ip, [sp, #-4]! // push address of lazy pointer 118 ldr ip, Ldyld__mach_header_pointer 119#if __PIC__ 120Ldyld__mach_header_pointer_base: 121 ldr ip, [pc, ip] 122#endif 123 str ip, [sp, #-4]! // push address of mach header 124 ldr ip, Ldyld_lazy_symbol_binding_entry_point 125#if __PIC__ 126Ldyld_lazy_symbol_binding_entry_point_base: 127 ldr pc, [pc, ip] // jump to dyld_lazy_symbol_binding_entry_point 128#else 129 ldr pc, [ip] 130#endif 131 132Ldyld__mach_header_pointer: 133#if __PIC__ 134 .long dyld__mach_header - (Ldyld__mach_header_pointer_base + 8) 135#else 136 .long ___dso_handle 137#endif 138Ldyld_lazy_symbol_binding_entry_point: 139#if __PIC__ 140 .long Ldyld_content_lazy_binder - (Ldyld_lazy_symbol_binding_entry_point_base + 8) 141#else 142 .long Ldyld_content_lazy_binder 143#endif 144#endif 145 146 147 148//////////////////////////////////////////////////////////////////// 149// 150// cfm_stub_binding_helper 151// 152// only needed by ppc dylibs which support CFM clients 153// 154//////////////////////////////////////////////////////////////////// 155#if __ppc__ && CFM_GLUE 156 .text 157 .align 2 158 .private_extern cfm_stub_binding_helper 159cfm_stub_binding_helper: 160 mr r11, r12 ; The TVector address is the binding pointer address. 161 b dyld_stub_binding_helper ; Let the normal code handle the rest. 162#endif 163 164 165 166//////////////////////////////////////////////////////////////////// 167// 168// __dyld_func_lookup(const char*, void**) 169// 170// jumps into dyld via a pointer in __dyld section 171// 172//////////////////////////////////////////////////////////////////// 173 .text 174 .private_extern __dyld_func_lookup 175 .align 2 176__dyld_func_lookup: 177 178#if __ppc__ 179 #if __PIC__ 180 mflr r0 181 bcl 20,31,L2 182L2: mflr r11 183 mtlr r0 184 addis r11,r11,ha16(Ldyld_content_func_lookup-L2) 185 lwz r11,lo16(Ldyld_content_func_lookup-L2)(r11) 186 mtctr r11 187 bctr 188 #else 189 lis r11,ha16(Ldyld_content_func_lookup) 190 lwz r11,lo16(Ldyld_content_func_lookup)(r11) 191 mtctr r11 192 bctr 193 #endif 194 195#elif __ppc64__ 196 mflr r0 197 bcl 20,31,L2 198L2: mflr r11 199 mtlr r0 200 addis r11,r11,ha16(Ldyld_content_func_lookup-L2) 201 ld r11,lo16(Ldyld_content_func_lookup-L2)(r11) 202 mtctr r11 203 bctr 204 205#elif __i386__ 206 #if __PIC__ 207 call L2 208L2: popl %eax 209 movl Ldyld_content_func_lookup-L2(%eax),%eax 210 jmpl *%eax 211 #else 212 jmpl *Ldyld_content_func_lookup 213 #endif 214 215#elif __x86_64__ 216 jmp *Ldyld_content_func_lookup(%rip) 217 218#elif __arm__ 219 ldr ip, L__dyld_func_lookup_pointer 220#if __PIC__ 221L__dyld_func_lookup_pointer_base: 222 ldr pc, [pc, ip] 223#else 224 ldr pc, [ip] 225#endif 226L__dyld_func_lookup_pointer: 227#if __PIC__ 228 .long Ldyld_content_func_lookup - (L__dyld_func_lookup_pointer_base + 8) 229#else 230 .long Ldyld_content_func_lookup 231#endif 232#endif 233 234 235 236#if __LP64__ 237 #define align_pointer align 3 238 #define pointer quad 239#else 240 #define align_pointer align 2 241 #define pointer long 242#endif 243 244 245 246#if __ppc64__ || ((__i386__ || __ppc__ || __arm__) && __PIC__) 247//////////////////////////////////////////////////////////////////// 248// 249// dyld__mach_header 250// contains a pointer to the mach_header for this linkage unit 251// only needed for some code models 252// 253//////////////////////////////////////////////////////////////////// 254 .data 255 .align_pointer 256dyld__mach_header: 257 .pointer ___dso_handle 258#endif // __x86_64__ 259 260 261//////////////////////////////////////////////////////////////////// 262// 263// __dyld section content 264// 265// 0: pointer to lazy symbol binder in dyld 266// 1: pointer to dyld_func_lookup implementation in dyld 267// 268//////////////////////////////////////////////////////////////////// 269#if __ppc__ 270 Ldyld_base_addr = 0x8fe00000 271#elif __ppc64__ 272 Ldyld_base_addr = 0x00007fff5fc00000 273#elif __i386__ 274 Ldyld_base_addr = 0x8fe00000 275#elif __x86_64__ 276 Ldyld_base_addr = 0x00007fff5fc00000 277#elif __arm__ 278 Ldyld_base_addr = 0x2fe00000 279#elif __arm64__ 280#else 281#error unknown architecture 282#endif 283 284#if !__arm64__ 285 .dyld 286 .align_pointer 287Ldyld_content_lazy_binder: 288 .pointer Ldyld_base_addr + 0x1000 289Ldyld_content_func_lookup: 290 .pointer Ldyld_base_addr + 0x1008 291#if CRT && !OLD_LIBSYSTEM_SUPPORT 292 .pointer ___dso_handle 293 .pointer _NXArgc 294 .pointer _NXArgv 295 .pointer _environ 296 .pointer ___progname 297#endif 298#endif 299 300// This code has be written to allow dead code stripping 301 .subsections_via_symbols 302 303