]> git.saurik.com Git - apple/dyld.git/blob - src/dyldAPIsInLibSystem.cpp
dyld-239.4.tar.gz
[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* startCmds = NULL;
444 if ( mh->magic == MH_MAGIC_64 )
445 startCmds = (load_command*)((char *)mh + sizeof(mach_header_64));
446 else if ( mh->magic == MH_MAGIC )
447 startCmds = (load_command*)((char *)mh + sizeof(mach_header));
448 else
449 return 0; // not a mach-o file, or wrong endianness
450
451 const load_command* const cmdsEnd = (load_command*)((char*)startCmds + mh->sizeofcmds);
452 const version_min_command* versCmd;
453 const dylib_command* dylibCmd;
454 const load_command* cmd = startCmds;
455 const char* dylibName;
456 #if __IPHONE_OS_VERSION_MIN_REQUIRED
457 uint32_t foundationVers = 0;
458 #else
459 uint32_t libSystemVers = 0;
460 #endif
461 for(uint32_t i = 0; i < mh->ncmds; ++i) {
462 switch ( cmd->cmd ) {
463 #if __IPHONE_OS_VERSION_MIN_REQUIRED
464 case LC_VERSION_MIN_IPHONEOS:
465 #else
466 case LC_VERSION_MIN_MACOSX:
467 #endif
468 versCmd = (version_min_command*)cmd;
469 #ifdef DICE_KIND_DATA
470 if ( versCmd->sdk != 0 )
471 return versCmd->sdk; // found explicit SDK version
472 #else
473 if ( versCmd->reserved != 0 )
474 return versCmd->reserved; // found explicit SDK version
475 #endif
476 break;
477 case LC_LOAD_DYLIB:
478 case LC_LOAD_WEAK_DYLIB:
479 case LC_LOAD_UPWARD_DYLIB:
480 dylibCmd = (dylib_command*)cmd;
481 dylibName = (char*)dylibCmd + dylibCmd->dylib.name.offset;
482 #if __IPHONE_OS_VERSION_MIN_REQUIRED
483 if ( strcmp(dylibName, "/System/Library/Frameworks/Foundation.framework/Foundation") == 0 )
484 foundationVers = dylibCmd->dylib.current_version;
485 #else
486 if ( strcmp(dylibName, "/usr/lib/libSystem.B.dylib") == 0 )
487 libSystemVers = dylibCmd->dylib.current_version;
488 #endif
489 break;
490 }
491 // <rdar://problem/14381579> sanity check size of command
492 if ( (cmd->cmdsize < 8) || (cmd->cmdsize > mh->sizeofcmds) )
493 return 0;
494 cmd = (load_command*)((char *)cmd + cmd->cmdsize);
495 // <rdar://problem/14381579> bounds check
496 if ( (cmd > cmdsEnd) || (cmd < startCmds) )
497 return 0;
498 }
499
500 struct DylibToOSMapping {
501 uint32_t dylibVersion;
502 uint32_t osVersion;
503 };
504
505 #if __IPHONE_OS_VERSION_MIN_REQUIRED
506 static const DylibToOSMapping foundationMapping[] = {
507 { PACKED_VERSION(678,24,0), DYLD_IOS_VERSION_2_0 },
508 { PACKED_VERSION(678,26,0), DYLD_IOS_VERSION_2_1 },
509 { PACKED_VERSION(678,29,0), DYLD_IOS_VERSION_2_2 },
510 { PACKED_VERSION(678,47,0), DYLD_IOS_VERSION_3_0 },
511 { PACKED_VERSION(678,51,0), DYLD_IOS_VERSION_3_1 },
512 { PACKED_VERSION(678,60,0), DYLD_IOS_VERSION_3_2 },
513 { PACKED_VERSION(751,32,0), DYLD_IOS_VERSION_4_0 },
514 { PACKED_VERSION(751,37,0), DYLD_IOS_VERSION_4_1 },
515 { PACKED_VERSION(751,49,0), DYLD_IOS_VERSION_4_2 },
516 { PACKED_VERSION(751,58,0), DYLD_IOS_VERSION_4_3 },
517 { PACKED_VERSION(881,0,0), DYLD_IOS_VERSION_5_0 },
518 { PACKED_VERSION(890,1,0), DYLD_IOS_VERSION_5_1 },
519 { PACKED_VERSION(992,0,0), DYLD_IOS_VERSION_6_0 },
520 { PACKED_VERSION(993,0,0), DYLD_IOS_VERSION_6_1 },
521 { PACKED_VERSION(1038,14,0),DYLD_IOS_VERSION_7_0 }, // check final
522 { PACKED_VERSION(0,0,0), DYLD_IOS_VERSION_7_0 }
523 };
524
525 if ( foundationVers != 0 ) {
526 uint32_t lastOsVersion = 0;
527 for (const DylibToOSMapping* p=foundationMapping; ; ++p) {
528 if ( p->dylibVersion == 0 )
529 return p->osVersion;
530 if ( foundationVers < p->dylibVersion )
531 return lastOsVersion;
532 lastOsVersion = p->osVersion;
533 }
534 }
535
536 #else
537 // Note: versions are for the GM release. The last entry should
538 // always be zero. At the start of the next major version,
539 // a new last entry needs to be added and the previous zero
540 // updated to the GM dylib version.
541 static const DylibToOSMapping libSystemMapping[] = {
542 { PACKED_VERSION(88,1,3), DYLD_MACOSX_VERSION_10_4 },
543 { PACKED_VERSION(111,0,0), DYLD_MACOSX_VERSION_10_5 },
544 { PACKED_VERSION(123,0,0), DYLD_MACOSX_VERSION_10_6 },
545 { PACKED_VERSION(159,0,0), DYLD_MACOSX_VERSION_10_7 },
546 { PACKED_VERSION(169,3,0), DYLD_MACOSX_VERSION_10_8 },
547 { PACKED_VERSION(1197,0,0), DYLD_MACOSX_VERSION_10_9 },
548 { PACKED_VERSION(0,0,0), DYLD_MACOSX_VERSION_10_9 }
549 };
550
551 if ( libSystemVers != 0 ) {
552 uint32_t lastOsVersion = 0;
553 for (const DylibToOSMapping* p=libSystemMapping; ; ++p) {
554 if ( p->dylibVersion == 0 )
555 return p->osVersion;
556 if ( libSystemVers < p->dylibVersion )
557 return lastOsVersion;
558 lastOsVersion = p->osVersion;
559 }
560 }
561 #endif
562
563 return 0;
564 }
565
566 uint32_t dyld_get_program_sdk_version()
567 {
568 return dyld_get_sdk_version((mach_header*)_NSGetMachExecuteHeader());
569 }
570
571 uint32_t dyld_get_min_os_version(const struct mach_header* mh)
572 {
573 const load_command* startCmds = NULL;
574 if ( mh->magic == MH_MAGIC_64 )
575 startCmds = (load_command*)((char *)mh + sizeof(mach_header_64));
576 else if ( mh->magic == MH_MAGIC )
577 startCmds = (load_command*)((char *)mh + sizeof(mach_header));
578 else
579 return 0; // not a mach-o file, or wrong endianness
580
581 const load_command* const cmdsEnd = (load_command*)((char*)startCmds + mh->sizeofcmds);
582 const version_min_command* versCmd;
583 const load_command* cmd = startCmds;
584 for(uint32_t i = 0; i < mh->ncmds; ++i) {
585 switch ( cmd->cmd ) {
586 #if __IPHONE_OS_VERSION_MIN_REQUIRED
587 case LC_VERSION_MIN_IPHONEOS:
588 #else
589 case LC_VERSION_MIN_MACOSX:
590 #endif
591 versCmd = (version_min_command*)cmd;
592 return versCmd->version; // found explicit min OS version
593 break;
594 }
595 // <rdar://problem/14381579> sanity check size of command
596 if ( (cmd->cmdsize < 8) || (cmd->cmdsize > mh->sizeofcmds) )
597 return 0;
598 cmd = (load_command*)((char *)cmd + cmd->cmdsize);
599 // <rdar://problem/14381579> bounds check
600 if ( (cmd > cmdsEnd) || (cmd < startCmds) )
601 return 0;
602 }
603 return 0;
604 }
605
606
607 uint32_t dyld_get_program_min_os_version()
608 {
609 return dyld_get_min_os_version((mach_header*)_NSGetMachExecuteHeader());
610 }
611
612
613 #if DEPRECATED_APIS_SUPPORTED
614 /*
615 * NSCreateObjectFileImageFromFile() creates an NSObjectFileImage for the
616 * specified file name if the file is a correct Mach-O file that can be loaded
617 * with NSloadModule(). For return codes of NSObjectFileImageFailure and
618 * NSObjectFileImageFormat an error message is printed to stderr. All
619 * other codes cause no printing.
620 */
621 NSObjectFileImageReturnCode
622 NSCreateObjectFileImageFromFile(
623 const char* pathName,
624 NSObjectFileImage *objectFileImage)
625 {
626 DYLD_LOCK_THIS_BLOCK;
627 static NSObjectFileImageReturnCode (*p)(const char*, NSObjectFileImage*) = NULL;
628
629 if(p == NULL)
630 _dyld_func_lookup("__dyld_NSCreateObjectFileImageFromFile", (void**)&p);
631 return p(pathName, objectFileImage);
632 }
633
634
635 /*
636 * NSCreateObjectFileImageFromMemory() creates an NSObjectFileImage for the
637 * object file mapped into memory at address of size length if the object file
638 * is a correct Mach-O file that can be loaded with NSloadModule(). For return
639 * codes of NSObjectFileImageFailure and NSObjectFileImageFormat an error
640 * message is printed to stderr. All other codes cause no printing.
641 */
642 NSObjectFileImageReturnCode
643 NSCreateObjectFileImageFromMemory(
644 const void* address,
645 size_t size,
646 NSObjectFileImage *objectFileImage)
647 {
648 DYLD_LOCK_THIS_BLOCK;
649 static NSObjectFileImageReturnCode (*p)(const void*, size_t, NSObjectFileImage*) = NULL;
650
651 if(p == NULL)
652 _dyld_func_lookup("__dyld_NSCreateObjectFileImageFromMemory", (void**)&p);
653 return p(address, size, objectFileImage);
654 }
655
656 #if OBSOLETE_DYLD_API
657 /*
658 * NSCreateCoreFileImageFromFile() creates an NSObjectFileImage for the
659 * specified core file name if the file is a correct Mach-O core file.
660 * For return codes of NSObjectFileImageFailure and NSObjectFileImageFormat
661 * an error message is printed to stderr. All other codes cause no printing.
662 */
663 NSObjectFileImageReturnCode
664 NSCreateCoreFileImageFromFile(
665 const char* pathName,
666 NSObjectFileImage *objectFileImage)
667 {
668 DYLD_LOCK_THIS_BLOCK;
669 static NSObjectFileImageReturnCode (*p)(const char*, NSObjectFileImage*) = NULL;
670
671 if(p == NULL)
672 _dyld_func_lookup("__dyld_NSCreateCoreFileImageFromFile", (void**)&p);
673 return p(pathName, objectFileImage);
674 }
675 #endif
676
677 bool
678 NSDestroyObjectFileImage(
679 NSObjectFileImage objectFileImage)
680 {
681 DYLD_LOCK_THIS_BLOCK;
682 static bool (*p)(NSObjectFileImage) = NULL;
683
684 if(p == NULL)
685 _dyld_func_lookup("__dyld_NSDestroyObjectFileImage", (void**)&p);
686 return p(objectFileImage);
687 }
688
689
690 NSModule
691 NSLinkModule(
692 NSObjectFileImage objectFileImage,
693 const char* moduleName,
694 uint32_t options)
695 {
696 DYLD_LOCK_THIS_BLOCK;
697 static NSModule (*p)(NSObjectFileImage, const char*, unsigned long) = NULL;
698
699 if(p == NULL)
700 _dyld_func_lookup("__dyld_NSLinkModule", (void**)&p);
701
702 return p(objectFileImage, moduleName, options);
703 }
704
705
706
707
708 /*
709 * NSSymbolDefinitionCountInObjectFileImage() returns the number of symbol
710 * definitions in the NSObjectFileImage.
711 */
712 uint32_t
713 NSSymbolDefinitionCountInObjectFileImage(
714 NSObjectFileImage objectFileImage)
715 {
716 DYLD_LOCK_THIS_BLOCK;
717 static unsigned long (*p)(NSObjectFileImage) = NULL;
718
719 if(p == NULL)
720 _dyld_func_lookup("__dyld_NSSymbolDefinitionCountInObjectFileImage", (void**)&p);
721
722 return p(objectFileImage);
723 }
724
725 /*
726 * NSSymbolDefinitionNameInObjectFileImage() returns the name of the i'th
727 * symbol definitions in the NSObjectFileImage. If the ordinal specified is
728 * outside the range [0..NSSymbolDefinitionCountInObjectFileImage], NULL will
729 * be returned.
730 */
731 const char*
732 NSSymbolDefinitionNameInObjectFileImage(
733 NSObjectFileImage objectFileImage,
734 uint32_t ordinal)
735 {
736 DYLD_LOCK_THIS_BLOCK;
737 static const char* (*p)(NSObjectFileImage, uint32_t) = NULL;
738
739 if(p == NULL)
740 _dyld_func_lookup("__dyld_NSSymbolDefinitionNameInObjectFileImage", (void**)&p);
741
742 return p(objectFileImage, ordinal);
743 }
744
745 /*
746 * NSSymbolReferenceCountInObjectFileImage() returns the number of references
747 * to undefined symbols the NSObjectFileImage.
748 */
749 uint32_t
750 NSSymbolReferenceCountInObjectFileImage(
751 NSObjectFileImage objectFileImage)
752 {
753 DYLD_LOCK_THIS_BLOCK;
754 static unsigned long (*p)(NSObjectFileImage) = NULL;
755
756 if(p == NULL)
757 _dyld_func_lookup("__dyld_NSSymbolReferenceCountInObjectFileImage", (void**)&p);
758
759 return p(objectFileImage);
760 }
761
762 /*
763 * NSSymbolReferenceNameInObjectFileImage() returns the name of the i'th
764 * undefined symbol in the NSObjectFileImage. If the ordinal specified is
765 * outside the range [0..NSSymbolReferenceCountInObjectFileImage], NULL will be
766 * returned.
767 */
768 const char*
769 NSSymbolReferenceNameInObjectFileImage(
770 NSObjectFileImage objectFileImage,
771 uint32_t ordinal,
772 bool *tentative_definition) /* can be NULL */
773 {
774 DYLD_LOCK_THIS_BLOCK;
775 static const char* (*p)(NSObjectFileImage, uint32_t, bool*) = NULL;
776
777 if(p == NULL)
778 _dyld_func_lookup("__dyld_NSSymbolReferenceNameInObjectFileImage", (void**)&p);
779
780 return p(objectFileImage, ordinal, tentative_definition);
781 }
782
783 /*
784 * NSIsSymbolDefinedInObjectFileImage() returns TRUE if the specified symbol
785 * name has a definition in the NSObjectFileImage and FALSE otherwise.
786 */
787 bool
788 NSIsSymbolDefinedInObjectFileImage(
789 NSObjectFileImage objectFileImage,
790 const char* symbolName)
791 {
792 DYLD_LOCK_THIS_BLOCK;
793 static bool (*p)(NSObjectFileImage, const char*) = NULL;
794
795 if(p == NULL)
796 _dyld_func_lookup("__dyld_NSIsSymbolDefinedInObjectFileImage", (void**)&p);
797
798 return p(objectFileImage, symbolName);
799 }
800
801 /*
802 * NSGetSectionDataInObjectFileImage() returns a pointer to the section contents
803 * in the NSObjectFileImage for the specified segmentName and sectionName if
804 * it exists and it is not a zerofill section. If not it returns NULL. If
805 * the parameter size is not NULL the size of the section is also returned
806 * indirectly through that pointer.
807 */
808 void *
809 NSGetSectionDataInObjectFileImage(
810 NSObjectFileImage objectFileImage,
811 const char* segmentName,
812 const char* sectionName,
813 unsigned long *size) /* can be NULL */
814 {
815 DYLD_LOCK_THIS_BLOCK;
816 static void* (*p)(NSObjectFileImage, const char*, const char*, unsigned long*) = NULL;
817
818 if(p == NULL)
819 _dyld_func_lookup("__dyld_NSGetSectionDataInObjectFileImage", (void**)&p);
820
821 return p(objectFileImage, segmentName, sectionName, size);
822 }
823
824
825 void
826 NSLinkEditError(
827 NSLinkEditErrors *c,
828 int *errorNumber,
829 const char* *fileName,
830 const char* *errorString)
831 {
832 DYLD_LOCK_THIS_BLOCK;
833 static void (*p)(NSLinkEditErrors *c,
834 int *errorNumber,
835 const char* *fileName,
836 const char* *errorString) = NULL;
837
838 if(p == NULL)
839 _dyld_func_lookup("__dyld_link_edit_error", (void**)&p);
840 if(p != NULL)
841 p(c, errorNumber, fileName, errorString);
842 }
843
844 bool
845 NSUnLinkModule(
846 NSModule module,
847 uint32_t options)
848 {
849 DYLD_LOCK_THIS_BLOCK;
850 static bool (*p)(NSModule module, uint32_t options) = NULL;
851
852 if(p == NULL)
853 _dyld_func_lookup("__dyld_unlink_module", (void**)&p);
854
855 return p(module, options);
856 }
857
858 #if OBSOLETE_DYLD_API
859 NSModule
860 NSReplaceModule(
861 NSModule moduleToReplace,
862 NSObjectFileImage newObjectFileImage,
863 uint32_t options)
864 {
865 return(NULL);
866 }
867 #endif
868
869
870 #endif // DEPRECATED_APIS_SUPPORTED
871
872 /*
873 *_NSGetExecutablePath copies the path of the executable into the buffer and
874 * returns 0 if the path was successfully copied in the provided buffer. If the
875 * buffer is not large enough, -1 is returned and the expected buffer size is
876 * copied in *bufsize. Note that _NSGetExecutablePath will return "a path" to
877 * the executable not a "real path" to the executable. That is the path may be
878 * a symbolic link and not the real file. And with deep directories the total
879 * bufsize needed could be more than MAXPATHLEN.
880 */
881 int
882 _NSGetExecutablePath(
883 char *buf,
884 uint32_t *bufsize)
885 {
886 DYLD_LOCK_THIS_BLOCK;
887 static int (*p)(char *buf, uint32_t *bufsize) = NULL;
888
889 if(p == NULL)
890 _dyld_func_lookup("__dyld__NSGetExecutablePath", (void**)&p);
891 return(p(buf, bufsize));
892 }
893
894 #if DEPRECATED_APIS_SUPPORTED
895 void
896 _dyld_lookup_and_bind(
897 const char* symbol_name,
898 void** address,
899 NSModule* module)
900 {
901 DYLD_LOCK_THIS_BLOCK;
902 static void (*p)(const char*, void** , NSModule*) = NULL;
903
904 if(p == NULL)
905 _dyld_func_lookup("__dyld_lookup_and_bind", (void**)&p);
906 p(symbol_name, address, module);
907 }
908
909 void
910 _dyld_lookup_and_bind_with_hint(
911 const char* symbol_name,
912 const char* library_name_hint,
913 void** address,
914 NSModule* module)
915 {
916 DYLD_LOCK_THIS_BLOCK;
917 static void (*p)(const char*, const char*, void**, NSModule*) = NULL;
918
919 if(p == NULL)
920 _dyld_func_lookup("__dyld_lookup_and_bind_with_hint", (void**)&p);
921 p(symbol_name, library_name_hint, address, module);
922 }
923
924 #if OBSOLETE_DYLD_API
925 void
926 _dyld_lookup_and_bind_objc(
927 const char* symbol_name,
928 void** address,
929 NSModule* module)
930 {
931 DYLD_LOCK_THIS_BLOCK;
932 static void (*p)(const char* , void**, NSModule*) = NULL;
933
934 if(p == NULL)
935 _dyld_func_lookup("__dyld_lookup_and_bind_objc", (void**)&p);
936 p(symbol_name, address, module);
937 }
938 #endif
939
940 void
941 _dyld_lookup_and_bind_fully(
942 const char* symbol_name,
943 void** address,
944 NSModule* module)
945 {
946 DYLD_LOCK_THIS_BLOCK;
947 static void (*p)(const char*, void**, NSModule*) = NULL;
948
949 if(p == NULL)
950 _dyld_func_lookup("__dyld_lookup_and_bind_fully", (void**)&p);
951 p(symbol_name, address, module);
952 }
953
954 bool
955 _dyld_bind_fully_image_containing_address(
956 const void* address)
957 {
958 DYLD_LOCK_THIS_BLOCK;
959 static bool (*p)(const void*) = NULL;
960
961 if(p == NULL)
962 _dyld_func_lookup("__dyld_bind_fully_image_containing_address", (void**)&p);
963 return p(address);
964 }
965 #endif // DEPRECATED_APIS_SUPPORTED
966
967
968 /*
969 * _dyld_register_func_for_add_image registers the specified function to be
970 * called when a new image is added (a bundle or a dynamic shared library) to
971 * the program. When this function is first registered it is called for once
972 * for each image that is currently part of the program.
973 */
974 void
975 _dyld_register_func_for_add_image(
976 void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide))
977 {
978 DYLD_LOCK_THIS_BLOCK;
979 typedef void (*callback_t)(const struct mach_header *mh, intptr_t vmaddr_slide);
980 static void (*p)(callback_t func) = NULL;
981
982 if(p == NULL)
983 _dyld_func_lookup("__dyld_register_func_for_add_image", (void**)&p);
984 p(func);
985 }
986
987 /*
988 * _dyld_register_func_for_remove_image registers the specified function to be
989 * called when an image is removed (a bundle or a dynamic shared library) from
990 * the program.
991 */
992 void
993 _dyld_register_func_for_remove_image(
994 void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide))
995 {
996 DYLD_LOCK_THIS_BLOCK;
997 typedef void (*callback_t)(const struct mach_header *mh, intptr_t vmaddr_slide);
998 static void (*p)(callback_t func) = NULL;
999
1000 if(p == NULL)
1001 _dyld_func_lookup("__dyld_register_func_for_remove_image", (void**)&p);
1002 p(func);
1003 }
1004
1005 #if OBSOLETE_DYLD_API
1006 /*
1007 * _dyld_register_func_for_link_module registers the specified function to be
1008 * called when a module is bound into the program. When this function is first
1009 * registered it is called for once for each module that is currently bound into
1010 * the program.
1011 */
1012 void
1013 _dyld_register_func_for_link_module(
1014 void (*func)(NSModule module))
1015 {
1016 DYLD_LOCK_THIS_BLOCK;
1017 static void (*p)(void (*func)(NSModule module)) = NULL;
1018
1019 if(p == NULL)
1020 _dyld_func_lookup("__dyld_register_func_for_link_module", (void**)&p);
1021 p(func);
1022 }
1023
1024 /*
1025 * _dyld_register_func_for_unlink_module registers the specified function to be
1026 * called when a module is unbound from the program.
1027 */
1028 void
1029 _dyld_register_func_for_unlink_module(
1030 void (*func)(NSModule module))
1031 {
1032 DYLD_LOCK_THIS_BLOCK;
1033 static void (*p)(void (*func)(NSModule module)) = NULL;
1034
1035 if(p == NULL)
1036 _dyld_func_lookup("__dyld_register_func_for_unlink_module", (void**)&p);
1037 p(func);
1038 }
1039
1040 /*
1041 * _dyld_register_func_for_replace_module registers the specified function to be
1042 * called when a module is to be replace with another module in the program.
1043 */
1044 void
1045 _dyld_register_func_for_replace_module(
1046 void (*func)(NSModule oldmodule, NSModule newmodule))
1047 {
1048 DYLD_LOCK_THIS_BLOCK;
1049 static void (*p)(void (*func)(NSModule oldmodule,
1050 NSModule newmodule)) = NULL;
1051
1052 if(p == NULL)
1053 _dyld_func_lookup("__dyld_register_func_for_replace_module", (void**)&p);
1054 p(func);
1055 }
1056
1057
1058 /*
1059 * _dyld_get_objc_module_sect_for_module is passed a module and sets a
1060 * pointer to the (__OBJC,__module) section and its size for the specified
1061 * module.
1062 */
1063 void
1064 _dyld_get_objc_module_sect_for_module(
1065 NSModule module,
1066 void **objc_module,
1067 unsigned long *size)
1068 {
1069 DYLD_LOCK_THIS_BLOCK;
1070 static void (*p)(NSModule module,
1071 void **objc_module,
1072 unsigned long *size) = NULL;
1073
1074 if(p == NULL)
1075 _dyld_func_lookup("__dyld_get_objc_module_sect_for_module", (void**)&p);
1076 p(module, objc_module, size);
1077 }
1078
1079 /*
1080 * _dyld_bind_objc_module() is passed a pointer to something in an (__OBJC,
1081 * __module) section and causes the module that is associated with that address
1082 * to be bound.
1083 */
1084 void
1085 _dyld_bind_objc_module(const void* objc_module)
1086 {
1087 DYLD_LOCK_THIS_BLOCK;
1088 static void (*p)(const void *objc_module) = NULL;
1089
1090 if(p == NULL)
1091 _dyld_func_lookup("__dyld_bind_objc_module", (void**)&p);
1092 p(objc_module);
1093 }
1094 #endif
1095
1096 #if DEPRECATED_APIS_SUPPORTED
1097 bool
1098 _dyld_present(void)
1099 {
1100 // this function exists for compatiblity only
1101 return true;
1102 }
1103 #endif
1104
1105 uint32_t
1106 _dyld_image_count(void)
1107 {
1108 DYLD_NO_LOCK_THIS_BLOCK;
1109 static unsigned long (*p)(void) = NULL;
1110
1111 if(p == NULL)
1112 _dyld_func_lookup("__dyld_image_count", (void**)&p);
1113 return(p());
1114 }
1115
1116 const struct mach_header *
1117 _dyld_get_image_header(uint32_t image_index)
1118 {
1119 DYLD_NO_LOCK_THIS_BLOCK;
1120 static struct mach_header * (*p)(uint32_t image_index) = NULL;
1121
1122 if(p == NULL)
1123 _dyld_func_lookup("__dyld_get_image_header", (void**)&p);
1124 return(p(image_index));
1125 }
1126
1127 intptr_t
1128 _dyld_get_image_vmaddr_slide(uint32_t image_index)
1129 {
1130 DYLD_NO_LOCK_THIS_BLOCK;
1131 static unsigned long (*p)(uint32_t image_index) = NULL;
1132
1133 if(p == NULL)
1134 _dyld_func_lookup("__dyld_get_image_vmaddr_slide", (void**)&p);
1135 return(p(image_index));
1136 }
1137
1138 const char*
1139 _dyld_get_image_name(uint32_t image_index)
1140 {
1141 DYLD_NO_LOCK_THIS_BLOCK;
1142 static const char* (*p)(uint32_t image_index) = NULL;
1143
1144 if(p == NULL)
1145 _dyld_func_lookup("__dyld_get_image_name", (void**)&p);
1146 return(p(image_index));
1147 }
1148
1149 // SPI in Mac OS X 10.6
1150 intptr_t _dyld_get_image_slide(const struct mach_header* mh)
1151 {
1152 DYLD_NO_LOCK_THIS_BLOCK;
1153 static intptr_t (*p)(const struct mach_header*) = NULL;
1154
1155 if(p == NULL)
1156 _dyld_func_lookup("__dyld_get_image_slide", (void**)&p);
1157 return(p(mh));
1158 }
1159
1160
1161 bool
1162 _dyld_image_containing_address(const void* address)
1163 {
1164 DYLD_LOCK_THIS_BLOCK;
1165 static bool (*p)(const void*) = NULL;
1166
1167 if(p == NULL)
1168 _dyld_func_lookup("__dyld_image_containing_address", (void**)&p);
1169 return(p(address));
1170 }
1171
1172 const struct mach_header *
1173 _dyld_get_image_header_containing_address(
1174 const void* address)
1175 {
1176 DYLD_LOCK_THIS_BLOCK;
1177 static const struct mach_header * (*p)(const void*) = NULL;
1178
1179 if(p == NULL)
1180 _dyld_func_lookup("__dyld_get_image_header_containing_address", (void**)&p);
1181 return p(address);
1182 }
1183
1184 void _dyld_moninit(
1185 void (*monaddition)(char *lowpc, char *highpc))
1186 {
1187 DYLD_LOCK_THIS_BLOCK;
1188 typedef void (*monproc)(char *lowpc, char *highpc);
1189 static void (*p)(monproc monaddition) = NULL;
1190
1191 if(p == NULL)
1192 _dyld_func_lookup("__dyld_moninit", (void**)&p);
1193 p(monaddition);
1194 }
1195
1196 #if DEPRECATED_APIS_SUPPORTED
1197 bool _dyld_launched_prebound(void)
1198 {
1199 DYLD_LOCK_THIS_BLOCK;
1200 static bool (*p)(void) = NULL;
1201
1202 if(p == NULL)
1203 _dyld_func_lookup("__dyld_launched_prebound", (void**)&p);
1204 return(p());
1205 }
1206
1207 bool _dyld_all_twolevel_modules_prebound(void)
1208 {
1209 DYLD_LOCK_THIS_BLOCK;
1210 static bool (*p)(void) = NULL;
1211
1212 if(p == NULL)
1213 _dyld_func_lookup("__dyld_all_twolevel_modules_prebound", (void**)&p);
1214 return(p());
1215 }
1216 #endif // DEPRECATED_APIS_SUPPORTED
1217
1218
1219 #include <dlfcn.h>
1220 #include <stddef.h>
1221 #include <pthread.h>
1222 #include <stdlib.h>
1223 #include <mach-o/dyld.h>
1224 #include <servers/bootstrap.h>
1225 #include "dyldLibSystemInterface.h"
1226
1227
1228 // pthread key used to access per-thread dlerror message
1229 static pthread_key_t dlerrorPerThreadKey;
1230 static bool dlerrorPerThreadKeyInitialized = false;
1231
1232 // data kept per-thread
1233 struct dlerrorPerThreadData
1234 {
1235 uint32_t sizeAllocated;
1236 char message[1];
1237 };
1238
1239 // function called by dyld to get buffer to store dlerror message
1240 static char* getPerThreadBufferFor_dlerror(uint32_t sizeRequired)
1241 {
1242 // ok to create key lazily because this function is called within dyld lock, so there is no race condition
1243 if (!dlerrorPerThreadKeyInitialized ) {
1244 // create key and tell pthread package to call free() on any data associated with key if thread dies
1245 pthread_key_create(&dlerrorPerThreadKey, &free);
1246 dlerrorPerThreadKeyInitialized = true;
1247 }
1248
1249 const int size = (sizeRequired < 256) ? 256 : sizeRequired;
1250 dlerrorPerThreadData* data = (dlerrorPerThreadData*)pthread_getspecific(dlerrorPerThreadKey);
1251 if ( data == NULL ) {
1252 //int mallocSize = offsetof(dlerrorPerThreadData, message[size]);
1253 const int mallocSize = sizeof(dlerrorPerThreadData)+size;
1254 data = (dlerrorPerThreadData*)malloc(mallocSize);
1255 data->sizeAllocated = size;
1256 pthread_setspecific(dlerrorPerThreadKey, data);
1257 }
1258 else if ( data->sizeAllocated < sizeRequired ) {
1259 free(data);
1260 //int mallocSize = offsetof(dlerrorPerThreadData, message[size]);
1261 const int mallocSize = sizeof(dlerrorPerThreadData)+size;
1262 data = (dlerrorPerThreadData*)malloc(mallocSize);
1263 data->sizeAllocated = size;
1264 pthread_setspecific(dlerrorPerThreadKey, data);
1265 }
1266 return data->message;
1267 }
1268
1269 // <rdar://problem/10595338> dlerror buffer leak
1270 // Only allocate buffer if an actual error message needs to be set
1271 static bool hasPerThreadBufferFor_dlerror()
1272 {
1273 if (!dlerrorPerThreadKeyInitialized )
1274 return false;
1275
1276 return (pthread_getspecific(dlerrorPerThreadKey) != NULL);
1277 }
1278
1279 // use non-lazy pointer to vproc_swap_integer so that lazy binding does not recurse
1280 typedef vproc_err_t (*vswapproc)(vproc_t vp, vproc_gsk_t key,int64_t *inval, int64_t *outval);
1281 static vswapproc swapProc = &vproc_swap_integer;
1282
1283 static bool isLaunchdOwned() {
1284 static bool first = true;
1285 static bool result;
1286 if ( first ) {
1287 int64_t val = 0;
1288 (*swapProc)(NULL, VPROC_GSK_IS_MANAGED, NULL, &val);
1289 result = ( val != 0 );
1290 first = false;
1291 }
1292 return result;
1293 }
1294
1295
1296 #if DYLD_SHARED_CACHE_SUPPORT
1297 static void shared_cache_missing()
1298 {
1299 // leave until dyld's that might call this are rare
1300 }
1301
1302 static void shared_cache_out_of_date()
1303 {
1304 // leave until dyld's that might call this are rare
1305 }
1306 #endif // DYLD_SHARED_CACHE_SUPPORT
1307
1308
1309 // the table passed to dyld containing thread helpers
1310 static dyld::LibSystemHelpers sHelpers = { 12, &dyldGlobalLockAcquire, &dyldGlobalLockRelease,
1311 &getPerThreadBufferFor_dlerror, &malloc, &free, &__cxa_atexit,
1312 #if DYLD_SHARED_CACHE_SUPPORT
1313 &shared_cache_missing, &shared_cache_out_of_date,
1314 #else
1315 NULL, NULL,
1316 #endif
1317 NULL, NULL,
1318 &pthread_key_create, &pthread_setspecific,
1319 &malloc_size,
1320 &pthread_getspecific,
1321 &__cxa_finalize,
1322 address_of_start,
1323 &hasPerThreadBufferFor_dlerror,
1324 &isLaunchdOwned,
1325 &vm_allocate,
1326 &mmap};
1327
1328
1329 //
1330 // during initialization of libSystem this routine will run
1331 // and call dyld, registering the helper functions.
1332 //
1333 extern "C" void tlv_initializer();
1334 extern "C" void _dyld_initializer();
1335 void _dyld_initializer()
1336 {
1337 void (*p)(dyld::LibSystemHelpers*);
1338
1339 _dyld_func_lookup("__dyld_register_thread_helpers", (void**)&p);
1340 if(p != NULL)
1341 p(&sHelpers);
1342
1343 tlv_initializer();
1344 }
1345
1346
1347 char* dlerror()
1348 {
1349 DYLD_LOCK_THIS_BLOCK;
1350 static char* (*p)() = NULL;
1351
1352 if(p == NULL)
1353 _dyld_func_lookup("__dyld_dlerror", (void**)&p);
1354 return(p());
1355 }
1356
1357 int dladdr(const void* addr, Dl_info* info)
1358 {
1359 DYLD_LOCK_THIS_BLOCK;
1360 static int (*p)(const void* , Dl_info*) = NULL;
1361
1362 if(p == NULL)
1363 _dyld_func_lookup("__dyld_dladdr", (void**)&p);
1364 return(p(addr, info));
1365 }
1366
1367 int dlclose(void* handle)
1368 {
1369 DYLD_LOCK_THIS_BLOCK;
1370 static int (*p)(void* handle) = NULL;
1371
1372 if(p == NULL)
1373 _dyld_func_lookup("__dyld_dlclose", (void**)&p);
1374 return(p(handle));
1375 }
1376
1377 void* dlopen(const char* path, int mode)
1378 {
1379 // dlopen is special. locking is done inside dyld to allow initializer to run without lock
1380 DYLD_NO_LOCK_THIS_BLOCK;
1381
1382 static void* (*p)(const char* path, int) = NULL;
1383
1384 if(p == NULL)
1385 _dyld_func_lookup("__dyld_dlopen", (void**)&p);
1386 void* result = p(path, mode);
1387 // use asm block to prevent tail call optimization
1388 // this is needed because dlopen uses __builtin_return_address() and depends on this glue being in the frame chain
1389 // <rdar://problem/5313172 dlopen() looks too far up stack, can cause crash>
1390 __asm__ volatile("");
1391
1392 return result;
1393 }
1394
1395 bool dlopen_preflight(const char* path)
1396 {
1397 DYLD_LOCK_THIS_BLOCK;
1398 static bool (*p)(const char* path) = NULL;
1399
1400 if(p == NULL)
1401 _dyld_func_lookup("__dyld_dlopen_preflight", (void**)&p);
1402 return(p(path));
1403 }
1404
1405 void* dlsym(void* handle, const char* symbol)
1406 {
1407 DYLD_LOCK_THIS_BLOCK;
1408 static void* (*p)(void* handle, const char* symbol) = NULL;
1409
1410 if(p == NULL)
1411 _dyld_func_lookup("__dyld_dlsym", (void**)&p);
1412 return(p(handle, symbol));
1413 }
1414
1415 void dyld_register_image_state_change_handler(dyld_image_states state,
1416 bool batch, dyld_image_state_change_handler handler)
1417 {
1418 DYLD_LOCK_THIS_BLOCK;
1419 static void* (*p)(dyld_image_states, bool, dyld_image_state_change_handler) = NULL;
1420
1421 if(p == NULL)
1422 _dyld_func_lookup("__dyld_dyld_register_image_state_change_handler", (void**)&p);
1423 p(state, batch, handler);
1424 }
1425
1426
1427 const struct dyld_all_image_infos* _dyld_get_all_image_infos()
1428 {
1429 DYLD_NO_LOCK_THIS_BLOCK;
1430 static struct dyld_all_image_infos* (*p)() = NULL;
1431
1432 if(p == NULL)
1433 _dyld_func_lookup("__dyld_get_all_image_infos", (void**)&p);
1434 return p();
1435 }
1436
1437 #if !__arm__
1438 bool _dyld_find_unwind_sections(void* addr, dyld_unwind_sections* info)
1439 {
1440 DYLD_NO_LOCK_THIS_BLOCK;
1441 static void* (*p)(void*, dyld_unwind_sections*) = NULL;
1442
1443 if(p == NULL)
1444 _dyld_func_lookup("__dyld_find_unwind_sections", (void**)&p);
1445 return p(addr, info);
1446 }
1447 #endif
1448
1449
1450 #if __i386__ || __x86_64__ || __arm__
1451 __attribute__((visibility("hidden")))
1452 void* _dyld_fast_stub_entry(void* loadercache, long lazyinfo)
1453 {
1454 DYLD_NO_LOCK_THIS_BLOCK;
1455 static void* (*p)(void*, long) = NULL;
1456
1457 if(p == NULL)
1458 _dyld_func_lookup("__dyld_fast_stub_entry", (void**)&p);
1459 return p(loadercache, lazyinfo);
1460 }
1461 #endif
1462
1463
1464 const char* dyld_image_path_containing_address(const void* addr)
1465 {
1466 DYLD_NO_LOCK_THIS_BLOCK;
1467 static const char* (*p)(const void*) = NULL;
1468
1469 if(p == NULL)
1470 _dyld_func_lookup("__dyld_image_path_containing_address", (void**)&p);
1471 return p(addr);
1472 }
1473
1474 #if __IPHONE_OS_VERSION_MIN_REQUIRED
1475 bool dyld_shared_cache_some_image_overridden()
1476 {
1477 DYLD_NO_LOCK_THIS_BLOCK;
1478 static bool (*p)() = NULL;
1479
1480 if(p == NULL)
1481 _dyld_func_lookup("__dyld_shared_cache_some_image_overridden", (void**)&p);
1482 return p();
1483 }
1484 #endif
1485
1486
1487 bool dyld_process_is_restricted()
1488 {
1489 DYLD_NO_LOCK_THIS_BLOCK;
1490 static bool (*p)() = NULL;
1491
1492 if(p == NULL)
1493 _dyld_func_lookup("__dyld_process_is_restricted", (void**)&p);
1494 return p();
1495 }
1496
1497
1498
1499
1500 // SPI called __fork
1501 void _dyld_fork_child()
1502 {
1503 DYLD_NO_LOCK_THIS_BLOCK;
1504 static void (*p)() = NULL;
1505
1506 if(p == NULL)
1507 _dyld_func_lookup("__dyld_fork_child", (void**)&p);
1508 return p();
1509 }
1510
1511
1512
1513