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