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