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