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