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