]> git.saurik.com Git - apple/dyld.git/blob - src/dyldAPIsInLibSystem.cpp
0417585d684bfd9da642327b3246ac3b6e6f5eaf
[apple/dyld.git] / src / dyldAPIsInLibSystem.cpp
1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
2 *
3 * Copyright (c) 2004-2009 Apple Inc. All rights reserved.
4 *
5 * @APPLE_LICENSE_HEADER_START@
6 *
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
12 * file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25 #include <stddef.h>
26 #include <string.h>
27 #include <malloc/malloc.h>
28
29 #include <crt_externs.h>
30 #include <Availability.h>
31
32 #include "mach-o/dyld.h"
33 #include "mach-o/dyld_priv.h"
34
35 #include "dyldLock.h"
36
37 extern "C" int __cxa_atexit(void (*func)(void *), void *arg, void *dso);
38 extern "C" void __cxa_finalize(const void *dso);
39
40
41 #ifndef LC_VERSION_MIN_MACOSX
42 #define LC_VERSION_MIN_MACOSX 0x24
43 struct version_min_command {
44 uint32_t cmd; /* LC_VERSION_MIN_MACOSX or
45 LC_VERSION_MIN_IPHONEOS */
46 uint32_t cmdsize; /* sizeof(struct min_version_command) */
47 uint32_t version; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
48 uint32_t sdk; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
49 };
50 #endif
51
52 #ifndef LC_VERSION_MIN_IPHONEOS
53 #define LC_VERSION_MIN_IPHONEOS 0x25
54 #endif
55
56
57 #ifndef LC_LOAD_UPWARD_DYLIB
58 #define LC_LOAD_UPWARD_DYLIB (0x23|LC_REQ_DYLD) /* load of dylib whose initializers run later */
59 #endif
60
61 #define DYLD_SHARED_CACHE_SUPPORT (__i386__ || __x86_64__ || __arm__)
62
63 // deprecated APIs are still availble on Mac OS X, but not on iPhone OS
64 #if __IPHONE_OS_VERSION_MIN_REQUIRED
65 #define DEPRECATED_APIS_SUPPORTED 0
66 #else
67 #define DEPRECATED_APIS_SUPPORTED 1
68 #endif
69
70 /*
71 * names_match() takes an install_name from an LC_LOAD_DYLIB command and a
72 * libraryName (which is -lx or -framework Foo argument passed to the static
73 * link editor for the same library) and determines if they match. This depends
74 * on conventional use of names including major versioning.
75 */
76 static
77 bool
78 names_match(
79 char *install_name,
80 const char* libraryName)
81 {
82 char *basename;
83 unsigned long n;
84
85 /*
86 * Conventional install names have these forms:
87 * /System/Library/Frameworks/AppKit.framework/Versions/A/Appkit
88 * /Local/Library/Frameworks/AppKit.framework/Appkit
89 * /lib/libsys_s.A.dylib
90 * /usr/lib/libsys_s.dylib
91 */
92 basename = strrchr(install_name, '/');
93 if(basename == NULL)
94 basename = install_name;
95 else
96 basename++;
97
98 /*
99 * By checking the base name matching the library name we take care
100 * of the -framework cases.
101 */
102 if(strcmp(basename, libraryName) == 0)
103 return(TRUE);
104
105 /*
106 * Now check the base name for "lib" if so proceed to check for the
107 * -lx case dealing with a possible .X.dylib and a .dylib extension.
108 */
109 if(strncmp(basename, "lib", 3) ==0){
110 n = strlen(libraryName);
111 if(strncmp(basename+3, libraryName, n) == 0){
112 if(strncmp(basename+3+n, ".dylib", 6) == 0)
113 return(TRUE);
114 if(basename[3+n] == '.' &&
115 basename[3+n+1] != '\0' &&
116 strncmp(basename+3+n+2, ".dylib", 6) == 0)
117 return(TRUE);
118 }
119 }
120 return(FALSE);
121 }
122
123 #if DEPRECATED_APIS_SUPPORTED
124
125 void NSInstallLinkEditErrorHandlers(
126 const NSLinkEditErrorHandlers* handlers)
127 {
128 DYLD_LOCK_THIS_BLOCK;
129 typedef void (*ucallback_t)(const char* symbol_name);
130 typedef NSModule (*mcallback_t)(NSSymbol s, NSModule old, NSModule newhandler);
131 typedef void (*lcallback_t)(NSLinkEditErrors c, int errorNumber,
132 const char* fileName, const char* errorString);
133 static void (*p)(ucallback_t undefined, mcallback_t multiple, lcallback_t linkEdit) = NULL;
134
135 if(p == NULL)
136 _dyld_func_lookup("__dyld_install_handlers", (void**)&p);
137 mcallback_t m = handlers->multiple;
138 p(handlers->undefined, m, handlers->linkEdit);
139 }
140
141 const char*
142 NSNameOfModule(
143 NSModule module)
144 {
145 DYLD_LOCK_THIS_BLOCK;
146 static const char* (*p)(NSModule module) = NULL;
147
148 if(p == NULL)
149 _dyld_func_lookup("__dyld_NSNameOfModule", (void**)&p);
150 return(p(module));
151 }
152
153 const char*
154 NSLibraryNameForModule(
155 NSModule module)
156 {
157 DYLD_LOCK_THIS_BLOCK;
158 static const char* (*p)(NSModule module) = NULL;
159
160 if(p == NULL)
161 _dyld_func_lookup("__dyld_NSLibraryNameForModule", (void**)&p);
162 return(p(module));
163 }
164
165 bool
166 NSIsSymbolNameDefined(
167 const char* symbolName)
168 {
169 DYLD_LOCK_THIS_BLOCK;
170 static bool (*p)(const char* symbolName) = NULL;
171
172 if(p == NULL)
173 _dyld_func_lookup("__dyld_NSIsSymbolNameDefined", (void**)&p);
174 return(p(symbolName));
175 }
176
177 bool
178 NSIsSymbolNameDefinedWithHint(
179 const char* symbolName,
180 const char* libraryNameHint)
181 {
182 DYLD_LOCK_THIS_BLOCK;
183 static bool (*p)(const char* symbolName,
184 const char* libraryNameHint) = NULL;
185
186 if(p == NULL)
187 _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedWithHint", (void**)&p);
188 return(p(symbolName, libraryNameHint));
189 }
190
191 bool
192 NSIsSymbolNameDefinedInImage(
193 const struct mach_header *image,
194 const char* symbolName)
195 {
196 DYLD_LOCK_THIS_BLOCK;
197 static bool (*p)(const struct mach_header *image,
198 const char* symbolName) = NULL;
199
200 if(p == NULL)
201 _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage", (void**)&p);
202 return(p(image, symbolName));
203 }
204
205 NSSymbol
206 NSLookupAndBindSymbol(
207 const char* symbolName)
208 {
209 DYLD_LOCK_THIS_BLOCK;
210 static NSSymbol (*p)(const char* symbolName) = NULL;
211
212 if(p == NULL)
213 _dyld_func_lookup("__dyld_NSLookupAndBindSymbol", (void**)&p);
214 return(p(symbolName));
215 }
216
217 NSSymbol
218 NSLookupAndBindSymbolWithHint(
219 const char* symbolName,
220 const char* libraryNameHint)
221 {
222 DYLD_LOCK_THIS_BLOCK;
223 static NSSymbol (*p)(const char* symbolName,
224 const char* libraryNameHint) = NULL;
225
226 if(p == NULL)
227 _dyld_func_lookup("__dyld_NSLookupAndBindSymbolWithHint", (void**)&p);
228 return(p(symbolName, libraryNameHint));
229 }
230
231 NSSymbol
232 NSLookupSymbolInModule(
233 NSModule module,
234 const char* symbolName)
235 {
236 DYLD_LOCK_THIS_BLOCK;
237 static NSSymbol (*p)(NSModule module, const char* symbolName) = NULL;
238
239 if(p == NULL)
240 _dyld_func_lookup("__dyld_NSLookupSymbolInModule", (void**)&p);
241 return(p(module, symbolName));
242 }
243
244 NSSymbol
245 NSLookupSymbolInImage(
246 const struct mach_header *image,
247 const char* symbolName,
248 uint32_t options)
249 {
250 DYLD_LOCK_THIS_BLOCK;
251 static NSSymbol (*p)(const struct mach_header *image,
252 const char* symbolName,
253 uint32_t options) = NULL;
254
255 if(p == NULL)
256 _dyld_func_lookup("__dyld_NSLookupSymbolInImage", (void**)&p);
257 return(p(image, symbolName, options));
258 }
259
260 const char*
261 NSNameOfSymbol(
262 NSSymbol symbol)
263 {
264 DYLD_LOCK_THIS_BLOCK;
265 static char * (*p)(NSSymbol symbol) = NULL;
266
267 if(p == NULL)
268 _dyld_func_lookup("__dyld_NSNameOfSymbol",(void**)&p);
269 return(p(symbol));
270 }
271
272 void *
273 NSAddressOfSymbol(
274 NSSymbol symbol)
275 {
276 DYLD_LOCK_THIS_BLOCK;
277 static void * (*p)(NSSymbol symbol) = NULL;
278
279 if(p == NULL)
280 _dyld_func_lookup("__dyld_NSAddressOfSymbol", (void**)&p);
281 return(p(symbol));
282 }
283
284 NSModule
285 NSModuleForSymbol(
286 NSSymbol symbol)
287 {
288 DYLD_LOCK_THIS_BLOCK;
289 static NSModule (*p)(NSSymbol symbol) = NULL;
290
291 if(p == NULL)
292 _dyld_func_lookup("__dyld_NSModuleForSymbol", (void**)&p);
293 return(p(symbol));
294 }
295
296 bool
297 NSAddLibrary(
298 const char* pathName)
299 {
300 DYLD_LOCK_THIS_BLOCK;
301 static bool (*p)(const char* pathName) = NULL;
302
303 if(p == NULL)
304 _dyld_func_lookup("__dyld_NSAddLibrary", (void**)&p);
305 return(p(pathName));
306 }
307
308 bool
309 NSAddLibraryWithSearching(
310 const char* pathName)
311 {
312 DYLD_LOCK_THIS_BLOCK;
313 static bool (*p)(const char* pathName) = NULL;
314
315 if(p == NULL)
316 _dyld_func_lookup("__dyld_NSAddLibraryWithSearching", (void**)&p);
317 return(p(pathName));
318 }
319
320 const struct mach_header *
321 NSAddImage(
322 const char* image_name,
323 uint32_t options)
324 {
325 DYLD_LOCK_THIS_BLOCK;
326 static const struct mach_header * (*p)(const char* image_name,
327 uint32_t options) = NULL;
328
329 if(p == NULL)
330 _dyld_func_lookup("__dyld_NSAddImage", (void**)&p);
331 return(p(image_name, options));
332 }
333 #endif // DEPRECATED_APIS_SUPPORTED
334
335 /*
336 * This routine returns the current version of the named shared library the
337 * executable it was built with. The libraryName parameter is the same as the
338 * -lx or -framework Foo argument passed to the static link editor when building
339 * the executable (with -lx it would be "x" and with -framework Foo it would be
340 * "Foo"). If this the executable was not built against the specified library
341 * it returns -1. It should be noted that if this only returns the value the
342 * current version of the named shared library the executable was built with
343 * and not a list of current versions that dependent libraries and bundles the
344 * program is using were built with.
345 */
346 int32_t
347 NSVersionOfLinkTimeLibrary(
348 const char* libraryName)
349 {
350 unsigned long i;
351 struct load_command *load_commands, *lc;
352 struct dylib_command *dl;
353 char *install_name;
354 #if __LP64__
355 static struct mach_header_64 *mh = NULL;
356 #else
357 static struct mach_header *mh = NULL;
358 #endif
359 if(mh == NULL)
360 mh = _NSGetMachExecuteHeader();
361 load_commands = (struct load_command *)
362 #if __LP64__
363 ((char *)mh + sizeof(struct mach_header_64));
364 #else
365 ((char *)mh + sizeof(struct mach_header));
366 #endif
367 lc = load_commands;
368 for(i = 0; i < mh->ncmds; i++){
369 switch ( lc->cmd ) {
370 case LC_LOAD_DYLIB:
371 case LC_LOAD_WEAK_DYLIB:
372 case LC_LOAD_UPWARD_DYLIB:
373 dl = (struct dylib_command *)lc;
374 install_name = (char *)dl + dl->dylib.name.offset;
375 if(names_match(install_name, libraryName) == TRUE)
376 return(dl->dylib.current_version);
377 break;
378 }
379 lc = (struct load_command *)((char *)lc + lc->cmdsize);
380 }
381 return(-1);
382 }
383
384 /*
385 * This routine returns the current version of the named shared library the
386 * program it is running against. The libraryName parameter is the same as
387 * would be static link editor using the -lx or -framework Foo flags (with -lx
388 * it would be "x" and with -framework Foo it would be "Foo"). If the program
389 * is not using the specified library it returns -1.
390 */
391 int32_t
392 NSVersionOfRunTimeLibrary(
393 const char* libraryName)
394 {
395 unsigned long i, j, n;
396 char *install_name;
397 struct load_command *load_commands, *lc;
398 struct dylib_command *dl;
399 const struct mach_header *mh;
400
401 n = _dyld_image_count();
402 for(i = 0; i < n; i++){
403 mh = _dyld_get_image_header(i);
404 if(mh->filetype != MH_DYLIB)
405 continue;
406 load_commands = (struct load_command *)
407 #if __LP64__
408 ((char *)mh + sizeof(struct mach_header_64));
409 #else
410 ((char *)mh + sizeof(struct mach_header));
411 #endif
412 lc = load_commands;
413 for(j = 0; j < mh->ncmds; j++){
414 if(lc->cmd == LC_ID_DYLIB){
415 dl = (struct dylib_command *)lc;
416 install_name = (char *)dl + dl->dylib.name.offset;
417 if(names_match(install_name, libraryName) == TRUE)
418 return(dl->dylib.current_version);
419 }
420 lc = (struct load_command *)((char *)lc + lc->cmdsize);
421 }
422 }
423 return(-1);
424 }
425
426
427 /*
428 * Returns the sdk version (encode as nibble XXXX.YY.ZZ) the
429 * specified binary was built against.
430 *
431 * First looks for LC_VERSION_MIN_MACOSX/LC_VERSION_MIN_IPHONEOS
432 * in binary and if sdk field is not zero, return that value.
433 * Otherwise, looks for the libSystem.B.dylib the binary linked
434 * against and uses a table to convert that to an sdk version.
435 */
436 uint32_t dyld_get_sdk_version(const mach_header* mh)
437 {
438 #if __LP64__
439 const load_command* cmds = (load_command*)((char *)mh + sizeof(mach_header_64));
440 #else
441 const load_command* cmds = (load_command*)((char *)mh + sizeof(mach_header));
442 #endif
443 const version_min_command* versCmd;
444 const dylib_command* dylibCmd;
445 const load_command* cmd = cmds;
446 uint32_t libSystemVers = 0;
447 for(uint32_t i = 0; i < mh->ncmds; ++i) {
448 switch ( cmd->cmd ) {
449 case LC_VERSION_MIN_MACOSX:
450 case LC_VERSION_MIN_IPHONEOS:
451 versCmd = (version_min_command*)cmd;
452 if ( versCmd->sdk != 0 )
453 return versCmd->sdk; // found explicit SDK version
454 break;
455 case LC_LOAD_DYLIB:
456 case LC_LOAD_WEAK_DYLIB:
457 case LC_LOAD_UPWARD_DYLIB:
458 dylibCmd = (dylib_command*)cmd;
459 if ( strcmp((char*)dylibCmd + dylibCmd->dylib.name.offset, "/usr/lib/libSystem.B.dylib") == 0 )
460 libSystemVers = dylibCmd->dylib.current_version;
461 else if ( strcmp((char*)dylibCmd + dylibCmd->dylib.name.offset, "/usr/lib/libSystem.dylib") == 0 )
462 return 0x00040000; // all iOS simulator have same libSystem.dylib version
463 break;
464 }
465 cmd = (load_command*)((char *)cmd + cmd->cmdsize);
466 }
467
468 if ( libSystemVers != 0 ) {
469 // found linked libSystem.B.dylib version linked against
470 #if __IPHONE_OS_VERSION_MIN_REQUIRED
471 // convert libSystem.B.dylib version to iOS sdk version
472 if ( libSystemVers < 0x006F0010 ) // libSystem 111.0.16 in 3.0
473 return 0x00020000; // 2.0
474 else if ( libSystemVers < 0x006F0201 ) // libSystem 111.2.1 in 3.1
475 return 0x00030000; // 3.0
476 else if ( libSystemVers < 0x007D020B ) // libSystem 125.2.11 in 4.0
477 return 0x00030100; // 3.1
478 else if ( libSystemVers < 0x007D0400 ) // libSystem 125.4 in 4.1 and in 4.2
479 return 0x00040000; // 4.0
480 else if ( libSystemVers < 0x009F0000 ) // libSystem 159 in 4.3
481 return 0x00040100; // 4.1
482 else if ( libSystemVers < 0x00A10000 ) // libSystem 161 in 5.0
483 return 0x00040300; // 4.3
484 else
485 return 0x00050000;
486 #else
487 // convert libSystem.B.dylib version to MacOSX sdk version
488 if ( libSystemVers < 0x006F0000 ) // libSystem 111 in 10.5
489 return 0x000A0400; // 10.4
490 else if ( libSystemVers < 0x007B0000 ) // libSystem 123 in 10.6
491 return 0x000A0500; // 10.5
492 else if ( libSystemVers < 0x009F0000 ) // libSystem 159 in 10.7
493 return 0x000A0600; // 10.6
494 else if ( libSystemVers < 0x00A10000 ) // libSystem 161 in 10.8
495 return 0x000A0700; // 10.7
496 else
497 return 0x000A0800; // 10.8
498 #endif
499 }
500
501 return 0;
502 }
503
504 uint32_t dyld_get_program_sdk_version()
505 {
506 return dyld_get_sdk_version((mach_header*)_NSGetMachExecuteHeader());
507 }
508
509
510 uint32_t dyld_get_min_os_version(const struct mach_header* mh)
511 {
512 #if __LP64__
513 const load_command* cmds = (load_command*)((char *)mh + sizeof(mach_header_64));
514 #else
515 const load_command* cmds = (load_command*)((char *)mh + sizeof(mach_header));
516 #endif
517 const version_min_command* versCmd;
518 const load_command* cmd = cmds;
519 for(uint32_t i = 0; i < mh->ncmds; ++i) {
520 switch ( cmd->cmd ) {
521 case LC_VERSION_MIN_MACOSX:
522 case LC_VERSION_MIN_IPHONEOS:
523 versCmd = (version_min_command*)cmd;
524 return versCmd->version; // found explicit min OS version
525 break;
526 }
527 cmd = (load_command*)((char *)cmd + cmd->cmdsize);
528 }
529 return 0;
530 }
531
532
533 uint32_t dyld_get_program_min_os_version()
534 {
535 return dyld_get_min_os_version((mach_header*)_NSGetMachExecuteHeader());
536 }
537
538
539 #if DEPRECATED_APIS_SUPPORTED
540 /*
541 * NSCreateObjectFileImageFromFile() creates an NSObjectFileImage for the
542 * specified file name if the file is a correct Mach-O file that can be loaded
543 * with NSloadModule(). For return codes of NSObjectFileImageFailure and
544 * NSObjectFileImageFormat an error message is printed to stderr. All
545 * other codes cause no printing.
546 */
547 NSObjectFileImageReturnCode
548 NSCreateObjectFileImageFromFile(
549 const char* pathName,
550 NSObjectFileImage *objectFileImage)
551 {
552 DYLD_LOCK_THIS_BLOCK;
553 static NSObjectFileImageReturnCode (*p)(const char*, NSObjectFileImage*) = NULL;
554
555 if(p == NULL)
556 _dyld_func_lookup("__dyld_NSCreateObjectFileImageFromFile", (void**)&p);
557 return p(pathName, objectFileImage);
558 }
559
560
561 /*
562 * NSCreateObjectFileImageFromMemory() creates an NSObjectFileImage for the
563 * object file mapped into memory at address of size length if the object file
564 * is a correct Mach-O file that can be loaded with NSloadModule(). For return
565 * codes of NSObjectFileImageFailure and NSObjectFileImageFormat an error
566 * message is printed to stderr. All other codes cause no printing.
567 */
568 NSObjectFileImageReturnCode
569 NSCreateObjectFileImageFromMemory(
570 const void* address,
571 size_t size,
572 NSObjectFileImage *objectFileImage)
573 {
574 DYLD_LOCK_THIS_BLOCK;
575 static NSObjectFileImageReturnCode (*p)(const void*, size_t, NSObjectFileImage*) = NULL;
576
577 if(p == NULL)
578 _dyld_func_lookup("__dyld_NSCreateObjectFileImageFromMemory", (void**)&p);
579 return p(address, size, objectFileImage);
580 }
581
582 #if OBSOLETE_DYLD_API
583 /*
584 * NSCreateCoreFileImageFromFile() creates an NSObjectFileImage for the
585 * specified core file name if the file is a correct Mach-O core file.
586 * For return codes of NSObjectFileImageFailure and NSObjectFileImageFormat
587 * an error message is printed to stderr. All other codes cause no printing.
588 */
589 NSObjectFileImageReturnCode
590 NSCreateCoreFileImageFromFile(
591 const char* pathName,
592 NSObjectFileImage *objectFileImage)
593 {
594 DYLD_LOCK_THIS_BLOCK;
595 static NSObjectFileImageReturnCode (*p)(const char*, NSObjectFileImage*) = NULL;
596
597 if(p == NULL)
598 _dyld_func_lookup("__dyld_NSCreateCoreFileImageFromFile", (void**)&p);
599 return p(pathName, objectFileImage);
600 }
601 #endif
602
603 bool
604 NSDestroyObjectFileImage(
605 NSObjectFileImage objectFileImage)
606 {
607 DYLD_LOCK_THIS_BLOCK;
608 static bool (*p)(NSObjectFileImage) = NULL;
609
610 if(p == NULL)
611 _dyld_func_lookup("__dyld_NSDestroyObjectFileImage", (void**)&p);
612 return p(objectFileImage);
613 }
614
615
616 NSModule
617 NSLinkModule(
618 NSObjectFileImage objectFileImage,
619 const char* moduleName,
620 uint32_t options)
621 {
622 DYLD_LOCK_THIS_BLOCK;
623 static NSModule (*p)(NSObjectFileImage, const char*, unsigned long) = NULL;
624
625 if(p == NULL)
626 _dyld_func_lookup("__dyld_NSLinkModule", (void**)&p);
627
628 return p(objectFileImage, moduleName, options);
629 }
630
631
632
633
634 /*
635 * NSSymbolDefinitionCountInObjectFileImage() returns the number of symbol
636 * definitions in the NSObjectFileImage.
637 */
638 uint32_t
639 NSSymbolDefinitionCountInObjectFileImage(
640 NSObjectFileImage objectFileImage)
641 {
642 DYLD_LOCK_THIS_BLOCK;
643 static unsigned long (*p)(NSObjectFileImage) = NULL;
644
645 if(p == NULL)
646 _dyld_func_lookup("__dyld_NSSymbolDefinitionCountInObjectFileImage", (void**)&p);
647
648 return p(objectFileImage);
649 }
650
651 /*
652 * NSSymbolDefinitionNameInObjectFileImage() returns the name of the i'th
653 * symbol definitions in the NSObjectFileImage. If the ordinal specified is
654 * outside the range [0..NSSymbolDefinitionCountInObjectFileImage], NULL will
655 * be returned.
656 */
657 const char*
658 NSSymbolDefinitionNameInObjectFileImage(
659 NSObjectFileImage objectFileImage,
660 uint32_t ordinal)
661 {
662 DYLD_LOCK_THIS_BLOCK;
663 static const char* (*p)(NSObjectFileImage, uint32_t) = NULL;
664
665 if(p == NULL)
666 _dyld_func_lookup("__dyld_NSSymbolDefinitionNameInObjectFileImage", (void**)&p);
667
668 return p(objectFileImage, ordinal);
669 }
670
671 /*
672 * NSSymbolReferenceCountInObjectFileImage() returns the number of references
673 * to undefined symbols the NSObjectFileImage.
674 */
675 uint32_t
676 NSSymbolReferenceCountInObjectFileImage(
677 NSObjectFileImage objectFileImage)
678 {
679 DYLD_LOCK_THIS_BLOCK;
680 static unsigned long (*p)(NSObjectFileImage) = NULL;
681
682 if(p == NULL)
683 _dyld_func_lookup("__dyld_NSSymbolReferenceCountInObjectFileImage", (void**)&p);
684
685 return p(objectFileImage);
686 }
687
688 /*
689 * NSSymbolReferenceNameInObjectFileImage() returns the name of the i'th
690 * undefined symbol in the NSObjectFileImage. If the ordinal specified is
691 * outside the range [0..NSSymbolReferenceCountInObjectFileImage], NULL will be
692 * returned.
693 */
694 const char*
695 NSSymbolReferenceNameInObjectFileImage(
696 NSObjectFileImage objectFileImage,
697 uint32_t ordinal,
698 bool *tentative_definition) /* can be NULL */
699 {
700 DYLD_LOCK_THIS_BLOCK;
701 static const char* (*p)(NSObjectFileImage, uint32_t, bool*) = NULL;
702
703 if(p == NULL)
704 _dyld_func_lookup("__dyld_NSSymbolReferenceNameInObjectFileImage", (void**)&p);
705
706 return p(objectFileImage, ordinal, tentative_definition);
707 }
708
709 /*
710 * NSIsSymbolDefinedInObjectFileImage() returns TRUE if the specified symbol
711 * name has a definition in the NSObjectFileImage and FALSE otherwise.
712 */
713 bool
714 NSIsSymbolDefinedInObjectFileImage(
715 NSObjectFileImage objectFileImage,
716 const char* symbolName)
717 {
718 DYLD_LOCK_THIS_BLOCK;
719 static bool (*p)(NSObjectFileImage, const char*) = NULL;
720
721 if(p == NULL)
722 _dyld_func_lookup("__dyld_NSIsSymbolDefinedInObjectFileImage", (void**)&p);
723
724 return p(objectFileImage, symbolName);
725 }
726
727 /*
728 * NSGetSectionDataInObjectFileImage() returns a pointer to the section contents
729 * in the NSObjectFileImage for the specified segmentName and sectionName if
730 * it exists and it is not a zerofill section. If not it returns NULL. If
731 * the parameter size is not NULL the size of the section is also returned
732 * indirectly through that pointer.
733 */
734 void *
735 NSGetSectionDataInObjectFileImage(
736 NSObjectFileImage objectFileImage,
737 const char* segmentName,
738 const char* sectionName,
739 unsigned long *size) /* can be NULL */
740 {
741 DYLD_LOCK_THIS_BLOCK;
742 static void* (*p)(NSObjectFileImage, const char*, const char*, unsigned long*) = NULL;
743
744 if(p == NULL)
745 _dyld_func_lookup("__dyld_NSGetSectionDataInObjectFileImage", (void**)&p);
746
747 return p(objectFileImage, segmentName, sectionName, size);
748 }
749
750
751 void
752 NSLinkEditError(
753 NSLinkEditErrors *c,
754 int *errorNumber,
755 const char* *fileName,
756 const char* *errorString)
757 {
758 DYLD_LOCK_THIS_BLOCK;
759 static void (*p)(NSLinkEditErrors *c,
760 int *errorNumber,
761 const char* *fileName,
762 const char* *errorString) = NULL;
763
764 if(p == NULL)
765 _dyld_func_lookup("__dyld_link_edit_error", (void**)&p);
766 if(p != NULL)
767 p(c, errorNumber, fileName, errorString);
768 }
769
770 bool
771 NSUnLinkModule(
772 NSModule module,
773 uint32_t options)
774 {
775 DYLD_LOCK_THIS_BLOCK;
776 static bool (*p)(NSModule module, uint32_t options) = NULL;
777
778 if(p == NULL)
779 _dyld_func_lookup("__dyld_unlink_module", (void**)&p);
780
781 return p(module, options);
782 }
783
784 #if OBSOLETE_DYLD_API
785 NSModule
786 NSReplaceModule(
787 NSModule moduleToReplace,
788 NSObjectFileImage newObjectFileImage,
789 uint32_t options)
790 {
791 return(NULL);
792 }
793 #endif
794
795
796 #endif // DEPRECATED_APIS_SUPPORTED
797
798 /*
799 *_NSGetExecutablePath copies the path of the executable into the buffer and
800 * returns 0 if the path was successfully copied in the provided buffer. If the
801 * buffer is not large enough, -1 is returned and the expected buffer size is
802 * copied in *bufsize. Note that _NSGetExecutablePath will return "a path" to
803 * the executable not a "real path" to the executable. That is the path may be
804 * a symbolic link and not the real file. And with deep directories the total
805 * bufsize needed could be more than MAXPATHLEN.
806 */
807 int
808 _NSGetExecutablePath(
809 char *buf,
810 uint32_t *bufsize)
811 {
812 DYLD_LOCK_THIS_BLOCK;
813 static int (*p)(char *buf, uint32_t *bufsize) = NULL;
814
815 if(p == NULL)
816 _dyld_func_lookup("__dyld__NSGetExecutablePath", (void**)&p);
817 return(p(buf, bufsize));
818 }
819
820 #if DEPRECATED_APIS_SUPPORTED
821 void
822 _dyld_lookup_and_bind(
823 const char* symbol_name,
824 void** address,
825 NSModule* module)
826 {
827 DYLD_LOCK_THIS_BLOCK;
828 static void (*p)(const char*, void** , NSModule*) = NULL;
829
830 if(p == NULL)
831 _dyld_func_lookup("__dyld_lookup_and_bind", (void**)&p);
832 p(symbol_name, address, module);
833 }
834
835 void
836 _dyld_lookup_and_bind_with_hint(
837 const char* symbol_name,
838 const char* library_name_hint,
839 void** address,
840 NSModule* module)
841 {
842 DYLD_LOCK_THIS_BLOCK;
843 static void (*p)(const char*, const char*, void**, NSModule*) = NULL;
844
845 if(p == NULL)
846 _dyld_func_lookup("__dyld_lookup_and_bind_with_hint", (void**)&p);
847 p(symbol_name, library_name_hint, address, module);
848 }
849
850 #if OBSOLETE_DYLD_API
851 void
852 _dyld_lookup_and_bind_objc(
853 const char* symbol_name,
854 void** address,
855 NSModule* module)
856 {
857 DYLD_LOCK_THIS_BLOCK;
858 static void (*p)(const char* , void**, NSModule*) = NULL;
859
860 if(p == NULL)
861 _dyld_func_lookup("__dyld_lookup_and_bind_objc", (void**)&p);
862 p(symbol_name, address, module);
863 }
864 #endif
865
866 void
867 _dyld_lookup_and_bind_fully(
868 const char* symbol_name,
869 void** address,
870 NSModule* module)
871 {
872 DYLD_LOCK_THIS_BLOCK;
873 static void (*p)(const char*, void**, NSModule*) = NULL;
874
875 if(p == NULL)
876 _dyld_func_lookup("__dyld_lookup_and_bind_fully", (void**)&p);
877 p(symbol_name, address, module);
878 }
879
880 bool
881 _dyld_bind_fully_image_containing_address(
882 const void* address)
883 {
884 DYLD_LOCK_THIS_BLOCK;
885 static bool (*p)(const void*) = NULL;
886
887 if(p == NULL)
888 _dyld_func_lookup("__dyld_bind_fully_image_containing_address", (void**)&p);
889 return p(address);
890 }
891 #endif // DEPRECATED_APIS_SUPPORTED
892
893
894 /*
895 * _dyld_register_func_for_add_image registers the specified function to be
896 * called when a new image is added (a bundle or a dynamic shared library) to
897 * the program. When this function is first registered it is called for once
898 * for each image that is currently part of the program.
899 */
900 void
901 _dyld_register_func_for_add_image(
902 void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide))
903 {
904 DYLD_LOCK_THIS_BLOCK;
905 typedef void (*callback_t)(const struct mach_header *mh, intptr_t vmaddr_slide);
906 static void (*p)(callback_t func) = NULL;
907
908 if(p == NULL)
909 _dyld_func_lookup("__dyld_register_func_for_add_image", (void**)&p);
910 p(func);
911 }
912
913 /*
914 * _dyld_register_func_for_remove_image registers the specified function to be
915 * called when an image is removed (a bundle or a dynamic shared library) from
916 * the program.
917 */
918 void
919 _dyld_register_func_for_remove_image(
920 void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide))
921 {
922 DYLD_LOCK_THIS_BLOCK;
923 typedef void (*callback_t)(const struct mach_header *mh, intptr_t vmaddr_slide);
924 static void (*p)(callback_t func) = NULL;
925
926 if(p == NULL)
927 _dyld_func_lookup("__dyld_register_func_for_remove_image", (void**)&p);
928 p(func);
929 }
930
931 #if OBSOLETE_DYLD_API
932 /*
933 * _dyld_register_func_for_link_module registers the specified function to be
934 * called when a module is bound into the program. When this function is first
935 * registered it is called for once for each module that is currently bound into
936 * the program.
937 */
938 void
939 _dyld_register_func_for_link_module(
940 void (*func)(NSModule module))
941 {
942 DYLD_LOCK_THIS_BLOCK;
943 static void (*p)(void (*func)(NSModule module)) = NULL;
944
945 if(p == NULL)
946 _dyld_func_lookup("__dyld_register_func_for_link_module", (void**)&p);
947 p(func);
948 }
949
950 /*
951 * _dyld_register_func_for_unlink_module registers the specified function to be
952 * called when a module is unbound from the program.
953 */
954 void
955 _dyld_register_func_for_unlink_module(
956 void (*func)(NSModule module))
957 {
958 DYLD_LOCK_THIS_BLOCK;
959 static void (*p)(void (*func)(NSModule module)) = NULL;
960
961 if(p == NULL)
962 _dyld_func_lookup("__dyld_register_func_for_unlink_module", (void**)&p);
963 p(func);
964 }
965
966 /*
967 * _dyld_register_func_for_replace_module registers the specified function to be
968 * called when a module is to be replace with another module in the program.
969 */
970 void
971 _dyld_register_func_for_replace_module(
972 void (*func)(NSModule oldmodule, NSModule newmodule))
973 {
974 DYLD_LOCK_THIS_BLOCK;
975 static void (*p)(void (*func)(NSModule oldmodule,
976 NSModule newmodule)) = NULL;
977
978 if(p == NULL)
979 _dyld_func_lookup("__dyld_register_func_for_replace_module", (void**)&p);
980 p(func);
981 }
982
983
984 /*
985 * _dyld_get_objc_module_sect_for_module is passed a module and sets a
986 * pointer to the (__OBJC,__module) section and its size for the specified
987 * module.
988 */
989 void
990 _dyld_get_objc_module_sect_for_module(
991 NSModule module,
992 void **objc_module,
993 unsigned long *size)
994 {
995 DYLD_LOCK_THIS_BLOCK;
996 static void (*p)(NSModule module,
997 void **objc_module,
998 unsigned long *size) = NULL;
999
1000 if(p == NULL)
1001 _dyld_func_lookup("__dyld_get_objc_module_sect_for_module", (void**)&p);
1002 p(module, objc_module, size);
1003 }
1004
1005 /*
1006 * _dyld_bind_objc_module() is passed a pointer to something in an (__OBJC,
1007 * __module) section and causes the module that is associated with that address
1008 * to be bound.
1009 */
1010 void
1011 _dyld_bind_objc_module(const void* objc_module)
1012 {
1013 DYLD_LOCK_THIS_BLOCK;
1014 static void (*p)(const void *objc_module) = NULL;
1015
1016 if(p == NULL)
1017 _dyld_func_lookup("__dyld_bind_objc_module", (void**)&p);
1018 p(objc_module);
1019 }
1020 #endif
1021
1022 #if DEPRECATED_APIS_SUPPORTED
1023 bool
1024 _dyld_present(void)
1025 {
1026 // this function exists for compatiblity only
1027 return true;
1028 }
1029 #endif
1030
1031 uint32_t
1032 _dyld_image_count(void)
1033 {
1034 DYLD_NO_LOCK_THIS_BLOCK;
1035 static unsigned long (*p)(void) = NULL;
1036
1037 if(p == NULL)
1038 _dyld_func_lookup("__dyld_image_count", (void**)&p);
1039 return(p());
1040 }
1041
1042 const struct mach_header *
1043 _dyld_get_image_header(uint32_t image_index)
1044 {
1045 DYLD_NO_LOCK_THIS_BLOCK;
1046 static struct mach_header * (*p)(uint32_t image_index) = NULL;
1047
1048 if(p == NULL)
1049 _dyld_func_lookup("__dyld_get_image_header", (void**)&p);
1050 return(p(image_index));
1051 }
1052
1053 intptr_t
1054 _dyld_get_image_vmaddr_slide(uint32_t image_index)
1055 {
1056 DYLD_NO_LOCK_THIS_BLOCK;
1057 static unsigned long (*p)(uint32_t image_index) = NULL;
1058
1059 if(p == NULL)
1060 _dyld_func_lookup("__dyld_get_image_vmaddr_slide", (void**)&p);
1061 return(p(image_index));
1062 }
1063
1064 const char*
1065 _dyld_get_image_name(uint32_t image_index)
1066 {
1067 DYLD_NO_LOCK_THIS_BLOCK;
1068 static const char* (*p)(uint32_t image_index) = NULL;
1069
1070 if(p == NULL)
1071 _dyld_func_lookup("__dyld_get_image_name", (void**)&p);
1072 return(p(image_index));
1073 }
1074
1075 // SPI in Mac OS X 10.6
1076 intptr_t _dyld_get_image_slide(const struct mach_header* mh)
1077 {
1078 DYLD_NO_LOCK_THIS_BLOCK;
1079 static intptr_t (*p)(const struct mach_header*) = NULL;
1080
1081 if(p == NULL)
1082 _dyld_func_lookup("__dyld_get_image_slide", (void**)&p);
1083 return(p(mh));
1084 }
1085
1086
1087 bool
1088 _dyld_image_containing_address(const void* address)
1089 {
1090 DYLD_LOCK_THIS_BLOCK;
1091 static bool (*p)(const void*) = NULL;
1092
1093 if(p == NULL)
1094 _dyld_func_lookup("__dyld_image_containing_address", (void**)&p);
1095 return(p(address));
1096 }
1097
1098 const struct mach_header *
1099 _dyld_get_image_header_containing_address(
1100 const void* address)
1101 {
1102 DYLD_LOCK_THIS_BLOCK;
1103 static const struct mach_header * (*p)(const void*) = NULL;
1104
1105 if(p == NULL)
1106 _dyld_func_lookup("__dyld_get_image_header_containing_address", (void**)&p);
1107 return p(address);
1108 }
1109
1110 void _dyld_moninit(
1111 void (*monaddition)(char *lowpc, char *highpc))
1112 {
1113 DYLD_LOCK_THIS_BLOCK;
1114 typedef void (*monproc)(char *lowpc, char *highpc);
1115 static void (*p)(monproc monaddition) = NULL;
1116
1117 if(p == NULL)
1118 _dyld_func_lookup("__dyld_moninit", (void**)&p);
1119 p(monaddition);
1120 }
1121
1122 #if DEPRECATED_APIS_SUPPORTED
1123 bool _dyld_launched_prebound(void)
1124 {
1125 DYLD_LOCK_THIS_BLOCK;
1126 static bool (*p)(void) = NULL;
1127
1128 if(p == NULL)
1129 _dyld_func_lookup("__dyld_launched_prebound", (void**)&p);
1130 return(p());
1131 }
1132
1133 bool _dyld_all_twolevel_modules_prebound(void)
1134 {
1135 DYLD_LOCK_THIS_BLOCK;
1136 static bool (*p)(void) = NULL;
1137
1138 if(p == NULL)
1139 _dyld_func_lookup("__dyld_all_twolevel_modules_prebound", (void**)&p);
1140 return(p());
1141 }
1142 #endif // DEPRECATED_APIS_SUPPORTED
1143
1144
1145 #include <dlfcn.h>
1146 #include <stddef.h>
1147 #include <pthread.h>
1148 #include <stdlib.h>
1149 #include <mach-o/dyld.h>
1150 #include <servers/bootstrap.h>
1151 #include "dyldLibSystemInterface.h"
1152
1153
1154 // pthread key used to access per-thread dlerror message
1155 static pthread_key_t dlerrorPerThreadKey;
1156 static bool dlerrorPerThreadKeyInitialized = false;
1157
1158 // data kept per-thread
1159 struct dlerrorPerThreadData
1160 {
1161 uint32_t sizeAllocated;
1162 char message[1];
1163 };
1164
1165 // function called by dyld to get buffer to store dlerror message
1166 static char* getPerThreadBufferFor_dlerror(uint32_t sizeRequired)
1167 {
1168 // ok to create key lazily because this function is called within dyld lock, so there is no race condition
1169 if (!dlerrorPerThreadKeyInitialized ) {
1170 // create key and tell pthread package to call free() on any data associated with key if thread dies
1171 pthread_key_create(&dlerrorPerThreadKey, &free);
1172 dlerrorPerThreadKeyInitialized = true;
1173 }
1174
1175 const int size = (sizeRequired < 256) ? 256 : sizeRequired;
1176 dlerrorPerThreadData* data = (dlerrorPerThreadData*)pthread_getspecific(dlerrorPerThreadKey);
1177 if ( data == NULL ) {
1178 //int mallocSize = offsetof(dlerrorPerThreadData, message[size]);
1179 const int mallocSize = sizeof(dlerrorPerThreadData)+size;
1180 data = (dlerrorPerThreadData*)malloc(mallocSize);
1181 data->sizeAllocated = size;
1182 pthread_setspecific(dlerrorPerThreadKey, data);
1183 }
1184 else if ( data->sizeAllocated < sizeRequired ) {
1185 free(data);
1186 //int mallocSize = offsetof(dlerrorPerThreadData, message[size]);
1187 const int mallocSize = sizeof(dlerrorPerThreadData)+size;
1188 data = (dlerrorPerThreadData*)malloc(mallocSize);
1189 data->sizeAllocated = size;
1190 pthread_setspecific(dlerrorPerThreadKey, data);
1191 }
1192 return data->message;
1193 }
1194
1195
1196 #if DYLD_SHARED_CACHE_SUPPORT
1197 static void shared_cache_missing()
1198 {
1199 // leave until dyld's that might call this are rare
1200 }
1201
1202 static void shared_cache_out_of_date()
1203 {
1204 // leave until dyld's that might call this are rare
1205 }
1206 #endif // DYLD_SHARED_CACHE_SUPPORT
1207
1208 extern void* start;
1209
1210 // the table passed to dyld containing thread helpers
1211 static dyld::LibSystemHelpers sHelpers = { 9, &dyldGlobalLockAcquire, &dyldGlobalLockRelease,
1212 &getPerThreadBufferFor_dlerror, &malloc, &free, &__cxa_atexit,
1213 #if DYLD_SHARED_CACHE_SUPPORT
1214 &shared_cache_missing, &shared_cache_out_of_date,
1215 #else
1216 NULL, NULL,
1217 #endif
1218 NULL, NULL,
1219 &pthread_key_create, &pthread_setspecific,
1220 &malloc_size,
1221 &pthread_getspecific,
1222 &__cxa_finalize,
1223 &start};
1224
1225
1226 //
1227 // during initialization of libSystem this routine will run
1228 // and call dyld, registering the helper functions.
1229 //
1230 extern "C" void tlv_initializer();
1231 extern "C" void _dyld_initializer();
1232 void _dyld_initializer()
1233 {
1234 DYLD_LOCK_INITIALIZER;
1235
1236 void (*p)(dyld::LibSystemHelpers*);
1237
1238 _dyld_func_lookup("__dyld_register_thread_helpers", (void**)&p);
1239 if(p != NULL)
1240 p(&sHelpers);
1241
1242 tlv_initializer();
1243 }
1244
1245
1246 char* dlerror()
1247 {
1248 DYLD_LOCK_THIS_BLOCK;
1249 static char* (*p)() = NULL;
1250
1251 if(p == NULL)
1252 _dyld_func_lookup("__dyld_dlerror", (void**)&p);
1253 return(p());
1254 }
1255
1256 int dladdr(const void* addr, Dl_info* info)
1257 {
1258 DYLD_LOCK_THIS_BLOCK;
1259 static int (*p)(const void* , Dl_info*) = NULL;
1260
1261 if(p == NULL)
1262 _dyld_func_lookup("__dyld_dladdr", (void**)&p);
1263 return(p(addr, info));
1264 }
1265
1266 int dlclose(void* handle)
1267 {
1268 DYLD_LOCK_THIS_BLOCK;
1269 static int (*p)(void* handle) = NULL;
1270
1271 if(p == NULL)
1272 _dyld_func_lookup("__dyld_dlclose", (void**)&p);
1273 return(p(handle));
1274 }
1275
1276 void* dlopen(const char* path, int mode)
1277 {
1278 // dlopen is special. locking is done inside dyld to allow initializer to run without lock
1279 DYLD_NO_LOCK_THIS_BLOCK;
1280
1281 static void* (*p)(const char* path, int) = NULL;
1282
1283 if(p == NULL)
1284 _dyld_func_lookup("__dyld_dlopen", (void**)&p);
1285 void* result = p(path, mode);
1286 // use asm block to prevent tail call optimization
1287 // this is needed because dlopen uses __builtin_return_address() and depends on this glue being in the frame chain
1288 // <rdar://problem/5313172 dlopen() looks too far up stack, can cause crash>
1289 __asm__ volatile("");
1290
1291 return result;
1292 }
1293
1294 bool dlopen_preflight(const char* path)
1295 {
1296 DYLD_LOCK_THIS_BLOCK;
1297 static bool (*p)(const char* path) = NULL;
1298
1299 if(p == NULL)
1300 _dyld_func_lookup("__dyld_dlopen_preflight", (void**)&p);
1301 return(p(path));
1302 }
1303
1304 void* dlsym(void* handle, const char* symbol)
1305 {
1306 DYLD_LOCK_THIS_BLOCK;
1307 static void* (*p)(void* handle, const char* symbol) = NULL;
1308
1309 if(p == NULL)
1310 _dyld_func_lookup("__dyld_dlsym", (void**)&p);
1311 return(p(handle, symbol));
1312 }
1313
1314 void dyld_register_image_state_change_handler(dyld_image_states state,
1315 bool batch, dyld_image_state_change_handler handler)
1316 {
1317 DYLD_LOCK_THIS_BLOCK;
1318 static void* (*p)(dyld_image_states, bool, dyld_image_state_change_handler) = NULL;
1319
1320 if(p == NULL)
1321 _dyld_func_lookup("__dyld_dyld_register_image_state_change_handler", (void**)&p);
1322 p(state, batch, handler);
1323 }
1324
1325
1326 const struct dyld_all_image_infos* _dyld_get_all_image_infos()
1327 {
1328 DYLD_NO_LOCK_THIS_BLOCK;
1329 static struct dyld_all_image_infos* (*p)() = NULL;
1330
1331 if(p == NULL)
1332 _dyld_func_lookup("__dyld_get_all_image_infos", (void**)&p);
1333 return p();
1334 }
1335
1336 #if !__arm__
1337 bool _dyld_find_unwind_sections(void* addr, dyld_unwind_sections* info)
1338 {
1339 DYLD_NO_LOCK_THIS_BLOCK;
1340 static void* (*p)(void*, dyld_unwind_sections*) = NULL;
1341
1342 if(p == NULL)
1343 _dyld_func_lookup("__dyld_find_unwind_sections", (void**)&p);
1344 return p(addr, info);
1345 }
1346 #endif
1347
1348
1349 #if __i386__ || __x86_64__ || __arm__
1350 __attribute__((visibility("hidden")))
1351 void* _dyld_fast_stub_entry(void* loadercache, long lazyinfo)
1352 {
1353 DYLD_NO_LOCK_THIS_BLOCK;
1354 static void* (*p)(void*, long) = NULL;
1355
1356 if(p == NULL)
1357 _dyld_func_lookup("__dyld_fast_stub_entry", (void**)&p);
1358 return p(loadercache, lazyinfo);
1359 }
1360 #endif
1361
1362
1363 const char* dyld_image_path_containing_address(const void* addr)
1364 {
1365 DYLD_NO_LOCK_THIS_BLOCK;
1366 static const char* (*p)(const void*) = NULL;
1367
1368 if(p == NULL)
1369 _dyld_func_lookup("__dyld_image_path_containing_address", (void**)&p);
1370 return p(addr);
1371 }
1372
1373 #if __IPHONE_OS_VERSION_MIN_REQUIRED
1374 bool dyld_shared_cache_some_image_overridden()
1375 {
1376 DYLD_NO_LOCK_THIS_BLOCK;
1377 static bool (*p)() = NULL;
1378
1379 if(p == NULL)
1380 _dyld_func_lookup("__dyld_shared_cache_some_image_overridden", (void**)&p);
1381 return p();
1382 }
1383 #endif
1384
1385
1386 // SPI called __fork
1387 void _dyld_fork_child()
1388 {
1389 DYLD_NO_LOCK_THIS_BLOCK;
1390 static void (*p)() = NULL;
1391
1392 if(p == NULL)
1393 _dyld_func_lookup("__dyld_fork_child", (void**)&p);
1394 return p();
1395 }
1396
1397
1398
1399