]> git.saurik.com Git - apple/dyld.git/blob - src/dyld.cpp
dyld-97.1.tar.gz
[apple/dyld.git] / src / dyld.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 <stdint.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <sys/param.h>
31 #include <mach/mach_time.h> // mach_absolute_time()
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <mach-o/fat.h>
35 #include <mach-o/loader.h>
36 #include <mach-o/ldsyms.h>
37 #include <libkern/OSByteOrder.h>
38 #include <mach/mach.h>
39 #include <sys/sysctl.h>
40 #include <sys/mman.h>
41 #include <sys/dtrace.h>
42
43 #include <vector>
44 #include <algorithm>
45
46 #include "mach-o/dyld_gdb.h"
47
48 #include "dyld.h"
49 #include "ImageLoader.h"
50 #include "ImageLoaderMachO.h"
51 #include "dyldLibSystemInterface.h"
52 #include "dyld_cache_format.h"
53
54 // from _simple.h in libc
55 typedef struct _SIMPLE* _SIMPLE_STRING;
56 extern "C" void _simple_vdprintf(int __fd, const char *__fmt, va_list __ap);
57 extern "C" void _simple_dprintf(int __fd, const char *__fmt, ...);
58 extern "C" _SIMPLE_STRING _simple_salloc(void);
59 extern "C" int _simple_vsprintf(_SIMPLE_STRING __b, const char *__fmt, va_list __ap);
60 extern "C" void _simple_sfree(_SIMPLE_STRING __b);
61 extern "C" char * _simple_string(_SIMPLE_STRING __b);
62
63
64
65 // 32-bit ppc is only architecture that uses cpu-sub-types
66 #define CPU_SUBTYPES_SUPPORTED __ppc__
67
68
69 #define OLD_GDB_DYLD_INTERFACE __ppc__ || __i386__
70
71
72 #define CPU_TYPE_MASK 0x00FFFFFF /* complement of CPU_ARCH_MASK */
73
74
75 /* implemented in dyld_gdb.cpp */
76 extern void addImagesToAllImages(uint32_t infoCount, const dyld_image_info info[]);
77 extern void removeImageFromAllImages(const mach_header* mh);
78 #if OLD_GDB_DYLD_INTERFACE
79 extern void addImageForgdb(const mach_header* mh, uintptr_t slide, const char* physicalPath, const char* logicalPath);
80 extern void removeImageForgdb(const struct mach_header* mh);
81 #endif
82
83 // magic so CrashReporter logs message
84 extern "C" {
85 char error_string[1024];
86 }
87 // implemented in dyldStartup.s for CrashReporter
88 extern "C" void dyld_fatal_error(const char* errString) __attribute__((noreturn));
89
90
91
92 //
93 // The file contains the core of dyld used to get a process to main().
94 // The API's that dyld supports are implemented in dyldAPIs.cpp.
95 //
96 //
97 //
98 //
99 //
100
101
102 namespace dyld {
103
104
105 //
106 // state of all environment variables dyld uses
107 //
108 struct EnvironmentVariables {
109 const char* const * DYLD_FRAMEWORK_PATH;
110 const char* const * DYLD_FALLBACK_FRAMEWORK_PATH;
111 const char* const * DYLD_LIBRARY_PATH;
112 const char* const * DYLD_FALLBACK_LIBRARY_PATH;
113 const char* const * DYLD_ROOT_PATH;
114 const char* const * DYLD_INSERT_LIBRARIES;
115 const char* const * LD_LIBRARY_PATH; // for unix conformance
116 bool DYLD_PRINT_LIBRARIES;
117 bool DYLD_PRINT_LIBRARIES_POST_LAUNCH;
118 bool DYLD_BIND_AT_LAUNCH;
119 bool DYLD_PRINT_STATISTICS;
120 bool DYLD_PRINT_OPTS;
121 bool DYLD_PRINT_ENV;
122 bool DYLD_DISABLE_DOFS;
123 // DYLD_IMAGE_SUFFIX ==> gLinkContext.imageSuffix
124 // DYLD_PRINT_OPTS ==> gLinkContext.verboseOpts
125 // DYLD_PRINT_ENV ==> gLinkContext.verboseEnv
126 // DYLD_FORCE_FLAT_NAMESPACE ==> gLinkContext.bindFlat
127 // DYLD_PRINT_INITIALIZERS ==> gLinkContext.verboseInit
128 // DYLD_PRINT_SEGMENTS ==> gLinkContext.verboseMapping
129 // DYLD_PRINT_BINDINGS ==> gLinkContext.verboseBind
130 // DYLD_PRINT_REBASINGS ==> gLinkContext.verboseRebase
131 // DYLD_PRINT_DOFS ==> gLinkContext.verboseDOF
132 // DYLD_PRINT_APIS ==> gLogAPIs
133 // DYLD_IGNORE_PREBINDING ==> gLinkContext.prebindUsage
134 // DYLD_PREBIND_DEBUG ==> gLinkContext.verbosePrebinding
135 // DYLD_NEW_LOCAL_SHARED_REGIONS ==> gLinkContext.sharedRegionMode
136 // DYLD_SHARED_REGION ==> gLinkContext.sharedRegionMode
137 // DYLD_PRINT_WARNINGS ==> gLinkContext.verboseWarnings
138 };
139
140 typedef std::vector<dyld_image_state_change_handler> StateHandlers;
141 struct RegisteredDOF { const mach_header* mh; int registrationID; };
142
143 // all global state
144 static const char* sExecPath = NULL;
145 static const struct mach_header* sMainExecutableMachHeader = NULL;
146 static cpu_type_t sHostCPU;
147 static cpu_subtype_t sHostCPUsubtype;
148 static ImageLoader* sMainExecutable = NULL;
149 static bool sMainExecutableIsSetuid = false;
150 static unsigned int sInsertedDylibCount = 0;
151 static std::vector<ImageLoader*> sAllImages;
152 static std::vector<ImageLoader*> sImageRoots;
153 static std::vector<ImageLoader*> sImageFilesNeedingTermination;
154 static std::vector<RegisteredDOF> sImageFilesNeedingDOFUnregistration;
155 #if IMAGE_NOTIFY_SUPPORT
156 static std::vector<ImageLoader*> sImagesToNotifyAboutOtherImages;
157 #endif
158 static std::vector<ImageCallback> sAddImageCallbacks;
159 static std::vector<ImageCallback> sRemoveImageCallbacks;
160 static StateHandlers sSingleHandlers[7];
161 static StateHandlers sBatchHandlers[7];
162 static ImageLoader* sLastImageByAddressCache;
163 static EnvironmentVariables sEnv;
164 static const char* sFrameworkFallbackPaths[] = { "$HOME/Library/Frameworks", "/Library/Frameworks", "/Network/Library/Frameworks", "/System/Library/Frameworks", NULL };
165 static const char* sLibraryFallbackPaths[] = { "$HOME/lib", "/usr/local/lib", "/usr/lib", NULL };
166 static BundleNotificationCallBack sBundleNotifier = NULL;
167 static BundleLocatorCallBack sBundleLocation = NULL;
168 static UndefinedHandler sUndefinedHandler = NULL;
169 static ImageLoader* sBundleBeingLoaded = NULL; // hack until OFI is reworked
170 #if DYLD_SHARED_CACHE_SUPPORT
171 static const dyld_cache_header* sSharedCache = NULL;
172 bool gSharedCacheNotFound = false;
173 bool gSharedCacheNeedsUpdating = false;
174 bool gSharedCacheDontNotify = false;
175 #endif
176 ImageLoader::LinkContext gLinkContext;
177 bool gLogAPIs = false;
178 const struct LibSystemHelpers* gLibSystemHelpers = NULL;
179 #if SUPPORT_OLD_CRT_INITIALIZATION
180 bool gRunInitializersOldWay = false;
181 #endif
182 #if __i386__
183 static uint32_t sImportSegmentsStart = 0;
184 static uint32_t sImportSegmentsSize = 0;
185 #endif
186
187
188
189 const char* mkstringf(const char* format, ...)
190 {
191 va_list list;
192 va_start(list, format);
193 _SIMPLE_STRING buf = _simple_salloc();
194 _simple_vsprintf(buf, format, list);
195 va_end(list);
196 const char* t = strdup(_simple_string(buf));
197 _simple_sfree(buf);
198 return t;
199 }
200
201
202 void throwf(const char* format, ...)
203 {
204 va_list list;
205 va_start(list, format);
206 _SIMPLE_STRING buf = _simple_salloc();
207 _simple_vsprintf(buf, format, list);
208 va_end(list);
209 const char* t = strdup(_simple_string(buf));
210 _simple_sfree(buf);
211 throw t;
212 }
213
214 void log(const char* format, ...)
215 {
216 va_list list;
217 va_start(list, format);
218 _simple_vdprintf(STDERR_FILENO, format, list);
219 va_end(list);
220 }
221
222 void warn(const char* format, ...)
223 {
224 _simple_dprintf(STDERR_FILENO, "dyld: warning, ");
225 va_list list;
226 va_start(list, format);
227 _simple_vdprintf(STDERR_FILENO, format, list);
228 va_end(list);
229 }
230
231
232 // utility class to assure files are closed when an exception is thrown
233 class FileOpener {
234 public:
235 FileOpener(const char* path);
236 ~FileOpener();
237 int getFileDescriptor() { return fd; }
238 private:
239 int fd;
240 };
241
242 FileOpener::FileOpener(const char* path)
243 : fd(-1)
244 {
245 fd = open(path, O_RDONLY, 0);
246 }
247
248 FileOpener::~FileOpener()
249 {
250 if ( fd != -1 )
251 close(fd);
252 }
253
254
255 // forward declaration
256 #if __ppc__ || __i386__
257 bool isRosetta();
258 #endif
259
260
261 static void registerDOFs(const std::vector<ImageLoader::DOFInfo>& dofs)
262 {
263 #if __ppc__
264 // can't dtrace a program running emulated under rosetta rdar://problem/5179640
265 if ( isRosetta() )
266 return;
267 #endif
268 const unsigned int dofSectionCount = dofs.size();
269 if ( !sEnv.DYLD_DISABLE_DOFS && (dofSectionCount != 0) ) {
270 int fd = open("/dev/" DTRACEMNR_HELPER, O_RDWR);
271 if ( fd < 0 ) {
272 //dyld::warn("can't open /dev/" DTRACEMNR_HELPER " to register dtrace DOF sections\n");
273 }
274 else {
275 // allocate a buffer on the stack for the variable length dof_ioctl_data_t type
276 uint8_t buffer[sizeof(dof_ioctl_data_t) + dofSectionCount*sizeof(dof_helper_t)];
277 dof_ioctl_data_t* ioctlData = (dof_ioctl_data_t*)buffer;
278
279 // fill in buffer with one dof_helper_t per DOF section
280 ioctlData->dofiod_count = dofSectionCount;
281 for (unsigned int i=0; i < dofSectionCount; ++i) {
282 strlcpy(ioctlData->dofiod_helpers[i].dofhp_mod, dofs[i].imageShortName, DTRACE_MODNAMELEN);
283 ioctlData->dofiod_helpers[i].dofhp_dof = (uintptr_t)(dofs[i].dof);
284 ioctlData->dofiod_helpers[i].dofhp_addr = (uintptr_t)(dofs[i].dof);
285 }
286
287 // tell kernel about all DOF sections en mas
288 // pass pointer to ioctlData because ioctl() only copies a fixed size amount of data into kernel
289 user_addr_t val = (user_addr_t)(unsigned long)ioctlData;
290 if ( ioctl(fd, DTRACEHIOC_ADDDOF, &val) != -1 ) {
291 // kernel returns a unique identifier for each section in the dofiod_helpers[].dofhp_dof field.
292 for (unsigned int i=0; i < dofSectionCount; ++i) {
293 RegisteredDOF info;
294 info.mh = dofs[i].imageHeader;
295 info.registrationID = (int)(ioctlData->dofiod_helpers[i].dofhp_dof);
296 sImageFilesNeedingDOFUnregistration.push_back(info);
297 if ( gLinkContext.verboseDOF ) {
298 dyld::log("dyld: registering DOF section 0x%p in %s with dtrace, ID=0x%08X\n",
299 dofs[i].dof, dofs[i].imageShortName, info.registrationID);
300 }
301 }
302 }
303 else {
304 dyld::log( "dyld: ioctl to register dtrace DOF section failed\n");
305 }
306 close(fd);
307 }
308 }
309 }
310
311 static void unregisterDOF(int registrationID)
312 {
313 int fd = open("/dev/" DTRACEMNR_HELPER, O_RDWR);
314 if ( fd < 0 ) {
315 dyld::warn("can't open /dev/" DTRACEMNR_HELPER " to unregister dtrace DOF section\n");
316 }
317 else {
318 ioctl(fd, DTRACEHIOC_REMOVE, registrationID);
319 close(fd);
320 if ( gLinkContext.verboseInit )
321 dyld::warn("unregistering DOF section ID=0x%08X with dtrace\n", registrationID);
322 }
323 }
324
325
326 //
327 // _dyld_register_func_for_add_image() is implemented as part of the general image state change notification
328 //
329 static void notifyAddImageCallbacks(ImageLoader* image)
330 {
331 // use guard so that we cannot notify about the same image twice
332 if ( ! image->addFuncNotified() ) {
333 for (std::vector<ImageCallback>::iterator it=sAddImageCallbacks.begin(); it != sAddImageCallbacks.end(); it++)
334 (*it)(image->machHeader(), image->getSlide());
335 image->setAddFuncNotified();
336 }
337 }
338
339
340 // notify gdb about these new images
341 static const char* notifyGDB(enum dyld_image_states state, uint32_t infoCount, const struct dyld_image_info info[])
342 {
343 addImagesToAllImages(infoCount, info);
344 return NULL;
345 }
346
347 #if IMAGE_NOTIFY_SUPPORT
348 // notify objc about these new images
349 static void notifyAdding(const ImageLoader* const * images, unsigned int count)
350 {
351 // build array
352 if ( count != 0 ) {
353 dyld_image_info infos[count];
354 for (unsigned int i=0; i < count; ++i) {
355 dyld_image_info* p = &infos[i];
356 const ImageLoader* image = images[i];
357 p->imageLoadAddress = image->machHeader();
358 p->imageFilePath = image->getPath();
359 p->imageFileModDate = image->lastModified();
360 //dyld::log("notifying objc about %s\n", image->getPath());
361 }
362
363 // tell all interested images (after gdb, so you can debug anything the notification does)
364 for (std::vector<ImageLoader*>::iterator it=sImagesToNotifyAboutOtherImages.begin(); it != sImagesToNotifyAboutOtherImages.end(); it++) {
365 (*it)->doNotification(dyld_image_adding, count, infos);
366 }
367 }
368 }
369 #endif
370
371 static StateHandlers* stateToHandlers(dyld_image_states state, StateHandlers handlersArray[8])
372 {
373 switch ( state ) {
374 case dyld_image_state_mapped:
375 return &handlersArray[0];
376
377 case dyld_image_state_dependents_mapped:
378 return &handlersArray[1];
379
380 case dyld_image_state_rebased:
381 return &handlersArray[2];
382
383 case dyld_image_state_bound:
384 return &handlersArray[3];
385
386 case dyld_image_state_dependents_initialized:
387 return &handlersArray[4];
388
389 case dyld_image_state_initialized:
390 return &handlersArray[5];
391
392 case dyld_image_state_terminated:
393 return &handlersArray[6];
394 }
395 return NULL;
396 }
397
398 static void notifySingle(dyld_image_states state, const struct mach_header* mh, const char* path, time_t modDate)
399 {
400 std::vector<dyld_image_state_change_handler>* handlers = stateToHandlers(state, sSingleHandlers);
401 if ( handlers != NULL ) {
402 dyld_image_info info;
403 info.imageLoadAddress = mh;
404 info.imageFilePath = path;
405 info.imageFileModDate = modDate;
406 for (std::vector<dyld_image_state_change_handler>::iterator it = handlers->begin(); it != handlers->end(); ++it) {
407 const char* result = (*it)(state, 1, &info);
408 if ( (result != NULL) && (state == dyld_image_state_mapped) ) {
409 //fprintf(stderr, " image rejected by handler=%p\n", *it);
410 // make copy of thrown string so that later catch clauses can free it
411 const char* str = strdup(result);
412 throw str;
413 }
414 }
415 }
416 }
417
418
419
420 static int imageSorter(const void* l, const void* r)
421 {
422 const ImageLoader* left = *((ImageLoader**)l);
423 const ImageLoader* right= *((ImageLoader**)r);
424 return left->compare(right);
425 }
426
427 static void notifyBatchPartial(dyld_image_states state, bool orLater, dyld_image_state_change_handler onlyHandler)
428 {
429 std::vector<dyld_image_state_change_handler>* handlers = stateToHandlers(state, sBatchHandlers);
430 if ( handlers != NULL ) {
431 // don't use a vector because it will use malloc/free and we want notifcation to be low cost
432 ImageLoader* images[sAllImages.size()+1];
433 ImageLoader** end = images;
434 for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); it++) {
435 dyld_image_states imageState = (*it)->getState();
436 if ( (imageState == state) || (orLater && (imageState > state)) )
437 *end++ = *it;
438 }
439 if ( sBundleBeingLoaded != NULL ) {
440 dyld_image_states imageState = sBundleBeingLoaded->getState();
441 if ( (imageState == state) || (orLater && (imageState > state)) )
442 *end++ = sBundleBeingLoaded;
443 }
444 unsigned int count = end-images;
445 if ( end != images ) {
446 // sort bottom up
447 qsort(images, count, sizeof(ImageLoader*), &imageSorter);
448 // build info array
449 dyld_image_info infos[count];
450 for (unsigned int i=0; i < count; ++i) {
451 dyld_image_info* p = &infos[i];
452 ImageLoader* image = images[i];
453 //dyld::log(" state=%d, name=%s\n", state, image->getPath());
454 p->imageLoadAddress = image->machHeader();
455 p->imageFilePath = image->getPath();
456 p->imageFileModDate = image->lastModified();
457 // special case for add_image hook
458 if ( state == dyld_image_state_bound )
459 notifyAddImageCallbacks(image);
460 }
461
462 if ( onlyHandler != NULL ) {
463 const char* result = (*onlyHandler)(state, count, infos);
464 if ( (result != NULL) && (state == dyld_image_state_dependents_mapped) ) {
465 //fprintf(stderr, " images rejected by handler=%p\n", onlyHandler);
466 // make copy of thrown string so that later catch clauses can free it
467 const char* str = strdup(result);
468 throw str;
469 }
470 }
471 else {
472 // call each handler with whole array
473 for (std::vector<dyld_image_state_change_handler>::iterator it = handlers->begin(); it != handlers->end(); ++it) {
474 const char* result = (*it)(state, count, infos);
475 if ( (result != NULL) && (state == dyld_image_state_dependents_mapped) ) {
476 //fprintf(stderr, " images rejected by handler=%p\n", *it);
477 // make copy of thrown string so that later catch clauses can free it
478 const char* str = strdup(result);
479 throw str;
480 }
481 }
482 }
483 }
484 }
485 }
486
487 static void notifyBatch(dyld_image_states state)
488 {
489 notifyBatchPartial(state, false, NULL);
490 }
491
492 // In order for register_func_for_add_image() callbacks to to be called bottom up,
493 // we need to maintain a list of root images. The main executable is usally the
494 // first root. Any images dynamically added are also roots (unless already loaded).
495 // If DYLD_INSERT_LIBRARIES is used, those libraries are first.
496 static void addRootImage(ImageLoader* image)
497 {
498 //dyld::log("addRootImage(%p, %s)\n", image, image->getPath());
499 // add to list of roots
500 sImageRoots.push_back(image);
501 }
502
503 #if IMAGE_NOTIFY_SUPPORT
504 // Objective-C will contain a __DATA/__image_notify section which contains pointers to a function to call
505 // whenever any new image is loaded.
506 static void addImageNeedingNotification(ImageLoader* image)
507 {
508 sImagesToNotifyAboutOtherImages.push_back(image);
509 }
510 #endif
511
512 static void clearAllDepths()
513 {
514 for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); it++)
515 (*it)->clearDepth();
516 }
517
518 static unsigned int imageCount()
519 {
520 return sAllImages.size();
521 }
522
523 static void notifySharedCacheInvalid()
524 {
525 gSharedCacheNeedsUpdating = true;
526 }
527
528
529
530 #if __i386__
531 static void makeSharedCacheImportSegmentsWritable(bool writable)
532 {
533 // if cache was built with read-only __IMPORT segments
534 if ( sImportSegmentsSize != 0 ) {
535 vm_prot_t prot = VM_PROT_EXECUTE | PROT_READ;
536 if ( writable )
537 prot |= VM_PROT_WRITE;
538 vm_protect(mach_task_self(), sImportSegmentsStart, sImportSegmentsSize, false, prot);
539 if ( gLinkContext.verboseMapping ) {
540 dyld::log("%18s at %p->%p altered permissions to %c%c%c\n", "", (char*)sImportSegmentsStart, (char*)sImportSegmentsStart+sImportSegmentsSize-1,
541 (prot & PROT_READ) ? 'r' : '.', (prot & PROT_WRITE) ? 'w' : '.', (prot & PROT_EXEC) ? 'x' : '.' );
542 }
543 }
544 }
545 #endif
546
547 static void setNewProgramVars(const ProgramVars& newVars)
548 {
549 // make a copy of the pointers to program variables
550 gLinkContext.programVars = newVars;
551
552 // now set each program global to their initial value
553 *gLinkContext.programVars.NXArgcPtr = gLinkContext.argc;
554 *gLinkContext.programVars.NXArgvPtr = gLinkContext.argv;
555 *gLinkContext.programVars.environPtr = gLinkContext.envp;
556 *gLinkContext.programVars.__prognamePtr = gLinkContext.progname;
557 }
558
559 #if SUPPORT_OLD_CRT_INITIALIZATION
560 static void setRunInitialzersOldWay()
561 {
562 gRunInitializersOldWay = true;
563 }
564 #endif
565
566 static void addImage(ImageLoader* image)
567 {
568 // add to master list
569 sAllImages.push_back(image);
570
571 if ( sEnv.DYLD_PRINT_LIBRARIES || (sEnv.DYLD_PRINT_LIBRARIES_POST_LAUNCH && (sMainExecutable!=NULL) && sMainExecutable->isLinked()) ) {
572 dyld::log("dyld: loaded: %s\n", image->getPath());
573 }
574
575 #if OLD_GDB_DYLD_INTERFACE
576 // let gdb find out about this
577 addImageForgdb(image->machHeader(), image->getSlide(), image->getPath(), image->getLogicalPath());
578 #endif
579 }
580
581 void removeImage(ImageLoader* image)
582 {
583 // if in termination list, pull it out and run terminator
584 for (std::vector<ImageLoader*>::iterator it=sImageFilesNeedingTermination.begin(); it != sImageFilesNeedingTermination.end(); it++) {
585 if ( *it == image ) {
586 sImageFilesNeedingTermination.erase(it);
587 image->doTermination(gLinkContext);
588 break;
589 }
590 }
591
592 // if has dtrace DOF section, tell dtrace it is going away, then remove from sImageFilesNeedingDOFUnregistration
593 for (std::vector<RegisteredDOF>::iterator it=sImageFilesNeedingDOFUnregistration.begin(); it != sImageFilesNeedingDOFUnregistration.end(); ) {
594 if ( it->mh == image->machHeader() ) {
595 unregisterDOF(it->registrationID);
596 sImageFilesNeedingDOFUnregistration.erase(it);
597 // don't increment iterator, the erase caused next element to be copied to where this iterator points
598 }
599 else {
600 ++it;
601 }
602 }
603
604 // tell all register add image handlers about this
605 // do this before removing image from internal data structures so that the callback can query dyld about the image
606 if ( image->getState() >= dyld_image_state_bound ) {
607 for (std::vector<ImageCallback>::iterator it=sRemoveImageCallbacks.begin(); it != sRemoveImageCallbacks.end(); it++) {
608 (*it)(image->machHeader(), image->getSlide());
609 }
610 }
611
612 #if IMAGE_NOTIFY_SUPPORT
613 // tell all interested images
614 for (std::vector<ImageLoader*>::iterator it=sImagesToNotifyAboutOtherImages.begin(); it != sImagesToNotifyAboutOtherImages.end(); it++) {
615 dyld_image_info info;
616 info.imageLoadAddress = image->machHeader();
617 info.imageFilePath = image->getPath();
618 info.imageFileModDate = image->lastModified();
619 (*it)->doNotification(dyld_image_removing, 1, &info);
620 }
621 #endif
622
623 // remove from master list
624 for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); it++) {
625 if ( *it == image ) {
626 sAllImages.erase(it);
627 break;
628 }
629 }
630
631 // flush find-by-address cache (do this after removed from master list, so there is no chance it can come back)
632 if ( sLastImageByAddressCache == image )
633 sLastImageByAddressCache = NULL;
634
635 #if IMAGE_NOTIFY_SUPPORT
636 // if in announcement list, pull it out
637 for (std::vector<ImageLoader*>::iterator it=sImagesToNotifyAboutOtherImages.begin(); it != sImagesToNotifyAboutOtherImages.end(); it++) {
638 if ( *it == image ) {
639 sImagesToNotifyAboutOtherImages.erase(it);
640 break;
641 }
642 }
643 #endif
644
645 // if in root list, pull it out
646 for (std::vector<ImageLoader*>::iterator it=sImageRoots.begin(); it != sImageRoots.end(); it++) {
647 if ( *it == image ) {
648 sImageRoots.erase(it);
649 break;
650 }
651 }
652
653 // log if requested
654 if ( sEnv.DYLD_PRINT_LIBRARIES || (sEnv.DYLD_PRINT_LIBRARIES_POST_LAUNCH && (sMainExecutable!=NULL) && sMainExecutable->isLinked()) ) {
655 dyld::log("dyld: unloaded: %s\n", image->getPath());
656 }
657
658 // tell gdb, new way
659 removeImageFromAllImages(image->machHeader());
660
661 #if OLD_GDB_DYLD_INTERFACE
662 // tell gdb, old way
663 removeImageForgdb(image->machHeader());
664 gdb_dyld_state_changed();
665 #endif
666 }
667
668
669 static void terminationRecorder(ImageLoader* image)
670 {
671 sImageFilesNeedingTermination.push_back(image);
672 }
673
674 const char* getExecutablePath()
675 {
676 return sExecPath;
677 }
678
679
680 void initializeMainExecutable()
681 {
682
683 // record that we've reached this step
684 gLinkContext.startedInitializingMainExecutable = true;
685
686 #if __i386__
687 // make all __IMPORT segments in the shared cache read-only
688 // before executing any code
689 makeSharedCacheImportSegmentsWritable(false);
690 #endif
691
692 // run initialzers for any inserted dylibs
693 const int rootCount = sImageRoots.size();
694 if ( rootCount > 1 ) {
695 for(int i=1; i < rootCount; ++i)
696 sImageRoots[i]->runInitializers(gLinkContext);
697 }
698
699 // run initializers for main executable and everything it brings up
700 sMainExecutable->runInitializers(gLinkContext);
701
702 // register atexit() handler to run terminators in all loaded images when this process exits
703 if ( gLibSystemHelpers != NULL )
704 (*gLibSystemHelpers->cxa_atexit)(&runTerminators, NULL, NULL);
705
706 // dump info if requested
707 if ( sEnv.DYLD_PRINT_STATISTICS )
708 ImageLoaderMachO::printStatistics(sAllImages.size());
709 }
710
711 bool mainExecutablePrebound()
712 {
713 return sMainExecutable->usablePrebinding(gLinkContext);
714 }
715
716 ImageLoader* mainExecutable()
717 {
718 return sMainExecutable;
719 }
720
721
722 void runTerminators(void* extra)
723 {
724 const unsigned int imageCount = sImageFilesNeedingTermination.size();
725 for(unsigned int i=imageCount; i > 0; --i){
726 ImageLoader* image = sImageFilesNeedingTermination[i-1];
727 image->doTermination(gLinkContext);
728 notifySingle(dyld_image_state_terminated, image->machHeader(), image->getPath(), image->lastModified());
729 }
730 sImageFilesNeedingTermination.clear();
731 notifyBatch(dyld_image_state_terminated);
732 }
733
734
735 //
736 // Turns a colon separated list of strings
737 // into a NULL terminated array of string
738 // pointers.
739 //
740 static const char** parseColonList(const char* list)
741 {
742 if ( list[0] == '\0' )
743 return NULL;
744
745 int colonCount = 0;
746 for(const char* s=list; *s != '\0'; ++s) {
747 if (*s == ':')
748 ++colonCount;
749 }
750
751 int index = 0;
752 const char* start = list;
753 char** result = new char*[colonCount+2];
754 for(const char* s=list; *s != '\0'; ++s) {
755 if (*s == ':') {
756 int len = s-start;
757 char* str = new char[len+1];
758 strncpy(str, start, len);
759 str[len] = '\0';
760 start = &s[1];
761 result[index++] = str;
762 }
763 }
764 int len = strlen(start);
765 char* str = new char[len+1];
766 strcpy(str, start);
767 result[index++] = str;
768 result[index] = NULL;
769
770 return (const char**)result;
771 }
772
773
774 static void paths_expand_roots(const char **paths, const char *key, const char *val)
775 {
776 // assert(val != NULL);
777 // assert(paths != NULL);
778 if(NULL != key) {
779 size_t keyLen = strlen(key);
780 for(int i=0; paths[i] != NULL; ++i) {
781 if ( strncmp(paths[i], key, keyLen) == 0 ) {
782 char* newPath = new char[strlen(val) + (strlen(paths[i]) - keyLen) + 1];
783 strcpy(newPath, val);
784 strcat(newPath, &paths[i][keyLen]);
785 paths[i] = newPath;
786 }
787 }
788 }
789 return;
790 }
791
792 static void removePathWithPrefix(const char* paths[], const char* prefix)
793 {
794 size_t prefixLen = strlen(prefix);
795 int skip = 0;
796 int i;
797 for(i = 0; paths[i] != NULL; ++i) {
798 if ( strncmp(paths[i], prefix, prefixLen) == 0 )
799 ++skip;
800 else
801 paths[i-skip] = paths[i];
802 }
803 paths[i-skip] = NULL;
804 }
805
806
807 #if 0
808 static void paths_dump(const char **paths)
809 {
810 // assert(paths != NULL);
811 const char **strs = paths;
812 while(*strs != NULL)
813 {
814 dyld::log("\"%s\"\n", *strs);
815 strs++;
816 }
817 return;
818 }
819 #endif
820
821 static void printOptions(const char* argv[])
822 {
823 uint32_t i = 0;
824 while ( NULL != argv[i] ) {
825 dyld::log("opt[%i] = \"%s\"\n", i, argv[i]);
826 i++;
827 }
828 }
829
830 static void printEnvironmentVariables(const char* envp[])
831 {
832 while ( NULL != *envp ) {
833 dyld::log("%s\n", *envp);
834 envp++;
835 }
836 }
837
838 void processDyldEnvironmentVarible(const char* key, const char* value)
839 {
840 if ( strcmp(key, "DYLD_FRAMEWORK_PATH") == 0 ) {
841 sEnv.DYLD_FRAMEWORK_PATH = parseColonList(value);
842 gSharedCacheDontNotify = true;
843 }
844 else if ( strcmp(key, "DYLD_FALLBACK_FRAMEWORK_PATH") == 0 ) {
845 sEnv.DYLD_FALLBACK_FRAMEWORK_PATH = parseColonList(value);
846 gSharedCacheDontNotify = true;
847 }
848 else if ( strcmp(key, "DYLD_LIBRARY_PATH") == 0 ) {
849 sEnv.DYLD_LIBRARY_PATH = parseColonList(value);
850 gSharedCacheDontNotify = true;
851 }
852 else if ( strcmp(key, "DYLD_FALLBACK_LIBRARY_PATH") == 0 ) {
853 sEnv.DYLD_FALLBACK_LIBRARY_PATH = parseColonList(value);
854 gSharedCacheDontNotify = true;
855 }
856 else if ( (strcmp(key, "DYLD_ROOT_PATH") == 0) || (strcmp(key, "DYLD_PATHS_ROOT") == 0) ) {
857 gSharedCacheDontNotify = true;
858 if ( strcmp(value, "/") != 0 ) {
859 sEnv.DYLD_ROOT_PATH = parseColonList(value);
860 for (int i=0; sEnv.DYLD_ROOT_PATH[i] != NULL; ++i) {
861 if ( sEnv.DYLD_ROOT_PATH[i][0] != '/' ) {
862 dyld::warn("DYLD_ROOT_PATH not used because it contains a non-absolute path\n");
863 sEnv.DYLD_ROOT_PATH = NULL;
864 break;
865 }
866 }
867 }
868 }
869 else if ( strcmp(key, "DYLD_IMAGE_SUFFIX") == 0 ) {
870 gSharedCacheDontNotify = true;
871 gLinkContext.imageSuffix = value;
872 }
873 else if ( strcmp(key, "DYLD_INSERT_LIBRARIES") == 0 ) {
874 sEnv.DYLD_INSERT_LIBRARIES = parseColonList(value);
875 gSharedCacheDontNotify = true;
876 }
877 else if ( strcmp(key, "DYLD_PRINT_OPTS") == 0 ) {
878 sEnv.DYLD_PRINT_OPTS = true;
879 }
880 else if ( strcmp(key, "DYLD_PRINT_ENV") == 0 ) {
881 sEnv.DYLD_PRINT_ENV = true;
882 }
883 else if ( strcmp(key, "DYLD_DISABLE_DOFS") == 0 ) {
884 sEnv.DYLD_DISABLE_DOFS = true;
885 }
886 else if ( strcmp(key, "DYLD_DISABLE_PREFETCH") == 0 ) {
887 gLinkContext.preFetchDisabled = true;
888 }
889 else if ( strcmp(key, "DYLD_PRINT_LIBRARIES") == 0 ) {
890 sEnv.DYLD_PRINT_LIBRARIES = true;
891 }
892 else if ( strcmp(key, "DYLD_PRINT_LIBRARIES_POST_LAUNCH") == 0 ) {
893 sEnv.DYLD_PRINT_LIBRARIES_POST_LAUNCH = true;
894 }
895 else if ( strcmp(key, "DYLD_BIND_AT_LAUNCH") == 0 ) {
896 sEnv.DYLD_BIND_AT_LAUNCH = true;
897 }
898 else if ( strcmp(key, "DYLD_FORCE_FLAT_NAMESPACE") == 0 ) {
899 gLinkContext.bindFlat = true;
900 }
901 else if ( strcmp(key, "DYLD_NEW_LOCAL_SHARED_REGIONS") == 0 ) {
902 // ignore, no longer relevant but some scripts still set it
903 }
904 else if ( strcmp(key, "DYLD_NO_FIX_PREBINDING") == 0 ) {
905 gSharedCacheDontNotify = true;
906 }
907 else if ( strcmp(key, "DYLD_PREBIND_DEBUG") == 0 ) {
908 gLinkContext.verbosePrebinding = true;
909 }
910 else if ( strcmp(key, "DYLD_PRINT_INITIALIZERS") == 0 ) {
911 gLinkContext.verboseInit = true;
912 }
913 else if ( strcmp(key, "DYLD_PRINT_DOFS") == 0 ) {
914 gLinkContext.verboseDOF = true;
915 }
916 else if ( strcmp(key, "DYLD_PRINT_STATISTICS") == 0 ) {
917 sEnv.DYLD_PRINT_STATISTICS = true;
918 }
919 else if ( strcmp(key, "DYLD_PRINT_SEGMENTS") == 0 ) {
920 gLinkContext.verboseMapping = true;
921 }
922 else if ( strcmp(key, "DYLD_PRINT_BINDINGS") == 0 ) {
923 gLinkContext.verboseBind = true;
924 }
925 else if ( strcmp(key, "DYLD_PRINT_REBASINGS") == 0 ) {
926 gLinkContext.verboseRebase = true;
927 }
928 else if ( strcmp(key, "DYLD_PRINT_APIS") == 0 ) {
929 gLogAPIs = true;
930 }
931 else if ( strcmp(key, "DYLD_PRINT_WARNINGS") == 0 ) {
932 gLinkContext.verboseWarnings = true;
933 }
934 else if ( strcmp(key, "DYLD_SHARED_REGION") == 0 ) {
935 gSharedCacheDontNotify = true;
936 if ( strcmp(value, "private") == 0 ) {
937 gLinkContext.sharedRegionMode = ImageLoader::kUsePrivateSharedRegion;
938 }
939 else if ( strcmp(value, "avoid") == 0 ) {
940 gLinkContext.sharedRegionMode = ImageLoader::kDontUseSharedRegion;
941 }
942 else if ( strcmp(value, "use") == 0 ) {
943 gLinkContext.sharedRegionMode = ImageLoader::kUseSharedRegion;
944 }
945 else if ( value[0] == '\0' ) {
946 gLinkContext.sharedRegionMode = ImageLoader::kUseSharedRegion;
947 }
948 else {
949 dyld::warn("unknown option to DYLD_SHARED_REGION. Valid options are: use, private, avoid\n");
950 }
951 }
952 else if ( strcmp(key, "DYLD_IGNORE_PREBINDING") == 0 ) {
953 gSharedCacheDontNotify = true;
954 if ( strcmp(value, "all") == 0 ) {
955 gLinkContext.prebindUsage = ImageLoader::kUseNoPrebinding;
956 }
957 else if ( strcmp(value, "app") == 0 ) {
958 gLinkContext.prebindUsage = ImageLoader::kUseAllButAppPredbinding;
959 }
960 else if ( strcmp(value, "nonsplit") == 0 ) {
961 gLinkContext.prebindUsage = ImageLoader::kUseSplitSegPrebinding;
962 }
963 else if ( value[0] == '\0' ) {
964 gLinkContext.prebindUsage = ImageLoader::kUseSplitSegPrebinding;
965 }
966 else {
967 dyld::warn("unknown option to DYLD_IGNORE_PREBINDING. Valid options are: all, app, nonsplit\n");
968 }
969 }
970 else {
971 dyld::warn("unknown environment variable: %s\n", key);
972 }
973 }
974
975
976 //
977 // For security, setuid programs ignore DYLD_* environment variables.
978 // Additionally, the DYLD_* enviroment variables are removed
979 // from the environment, so that any child processes don't see them.
980 //
981 static void pruneEnvironmentVariables(const char* envp[], const char*** applep)
982 {
983 // setuit binaries don't trigger a cache rebuild
984 gSharedCacheDontNotify = true;
985
986 // delete all DYLD_* and LD_LIBRARY_PATH environment variables
987 int removedCount = 0;
988 const char** d = envp;
989 for(const char** s = envp; *s != NULL; s++) {
990 if ( (strncmp(*s, "DYLD_", 5) != 0) && (strncmp(*s, "LD_LIBRARY_PATH=", 16) != 0) ) {
991 *d++ = *s;
992 }
993 else {
994 ++removedCount;
995 }
996 }
997 *d++ = NULL;
998
999 // slide apple parameters
1000 if ( removedCount > 0 ) {
1001 *applep = d;
1002 do {
1003 *d = d[removedCount];
1004 } while ( *d++ != NULL );
1005 }
1006
1007 // disable framework and library fallback paths for setuid binaries rdar://problem/4589305
1008 sEnv.DYLD_FALLBACK_FRAMEWORK_PATH = NULL;
1009 sEnv.DYLD_FALLBACK_LIBRARY_PATH = NULL;
1010 }
1011
1012
1013 static void checkEnvironmentVariables(const char* envp[], bool ignoreEnviron)
1014 {
1015 const char* home = NULL;
1016 const char** p;
1017 for(p = envp; *p != NULL; p++) {
1018 const char* keyEqualsValue = *p;
1019 if ( strncmp(keyEqualsValue, "DYLD_", 5) == 0 ) {
1020 const char* equals = strchr(keyEqualsValue, '=');
1021 if ( (equals != NULL) && !ignoreEnviron ) {
1022 const char* value = &equals[1];
1023 const int keyLen = equals-keyEqualsValue;
1024 char key[keyLen+1];
1025 strncpy(key, keyEqualsValue, keyLen);
1026 key[keyLen] = '\0';
1027 processDyldEnvironmentVarible(key, value);
1028 }
1029 }
1030 else if ( strncmp(keyEqualsValue, "HOME=", 5) == 0 ) {
1031 home = &keyEqualsValue[5];
1032 }
1033 else if ( strncmp(keyEqualsValue, "LD_LIBRARY_PATH=", 16) == 0 ) {
1034 const char* path = &keyEqualsValue[16];
1035 sEnv.LD_LIBRARY_PATH = parseColonList(path);
1036 }
1037 }
1038
1039 // default value for DYLD_FALLBACK_FRAMEWORK_PATH, if not set in environment
1040 if ( sEnv.DYLD_FALLBACK_FRAMEWORK_PATH == NULL ) {
1041 const char** paths = sFrameworkFallbackPaths;
1042 if ( home == NULL )
1043 removePathWithPrefix(paths, "$HOME");
1044 else
1045 paths_expand_roots(paths, "$HOME", home);
1046 sEnv.DYLD_FALLBACK_FRAMEWORK_PATH = paths;
1047 }
1048
1049 // default value for DYLD_FALLBACK_LIBRARY_PATH, if not set in environment
1050 if ( sEnv.DYLD_FALLBACK_LIBRARY_PATH == NULL ) {
1051 const char** paths = sLibraryFallbackPaths;
1052 if ( home == NULL )
1053 removePathWithPrefix(paths, "$HOME");
1054 else
1055 paths_expand_roots(paths, "$HOME", home);
1056 sEnv.DYLD_FALLBACK_LIBRARY_PATH = paths;
1057 }
1058 }
1059
1060
1061 static void getHostInfo()
1062 {
1063 #if 1
1064 struct host_basic_info info;
1065 mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT;
1066 mach_port_t hostPort = mach_host_self();
1067 kern_return_t result = host_info(hostPort, HOST_BASIC_INFO, (host_info_t)&info, &count);
1068 mach_port_deallocate(mach_task_self(), hostPort);
1069 if ( result != KERN_SUCCESS )
1070 throw "host_info() failed";
1071
1072 sHostCPU = info.cpu_type;
1073 sHostCPUsubtype = info.cpu_subtype;
1074 #else
1075 size_t valSize = sizeof(sHostCPU);
1076 if (sysctlbyname ("hw.cputype", &sHostCPU, &valSize, NULL, 0) != 0)
1077 throw "sysctlbyname(hw.cputype) failed";
1078 valSize = sizeof(sHostCPUsubtype);
1079 if (sysctlbyname ("hw.cpusubtype", &sHostCPUsubtype, &valSize, NULL, 0) != 0)
1080 throw "sysctlbyname(hw.cpusubtype) failed";
1081 #endif
1082 }
1083
1084 static void checkSharedRegionDisable()
1085 {
1086 #if __ppc__ || __i386__
1087 // if main executable has segments that overlap the shared region,
1088 // then disable using the shared region
1089 if ( sMainExecutable->overlapsWithAddressRange((void*)0x90000000, (void*)0xAFFFFFFF) ) {
1090 gLinkContext.sharedRegionMode = ImageLoader::kDontUseSharedRegion;
1091 if ( gLinkContext.verboseMapping )
1092 dyld::warn("disabling shared region because main executable overlaps\n");
1093 }
1094 #endif
1095 }
1096
1097 bool validImage(const ImageLoader* possibleImage)
1098 {
1099 const unsigned int imageCount = sAllImages.size();
1100 for(unsigned int i=0; i < imageCount; ++i) {
1101 if ( possibleImage == sAllImages[i] ) {
1102 return true;
1103 }
1104 }
1105 return false;
1106 }
1107
1108 uint32_t getImageCount()
1109 {
1110 return sAllImages.size();
1111 }
1112
1113 ImageLoader* getIndexedImage(unsigned int index)
1114 {
1115 if ( index < sAllImages.size() )
1116 return sAllImages[index];
1117 return NULL;
1118 }
1119
1120 ImageLoader* findImageByMachHeader(const struct mach_header* target)
1121 {
1122 const unsigned int imageCount = sAllImages.size();
1123 for(unsigned int i=0; i < imageCount; ++i) {
1124 ImageLoader* anImage = sAllImages[i];
1125 if ( anImage->machHeader() == target )
1126 return anImage;
1127 }
1128 return NULL;
1129 }
1130
1131
1132 ImageLoader* findImageContainingAddress(const void* addr)
1133 {
1134 #if FIND_STATS
1135 static int cacheHit = 0;
1136 static int cacheMiss = 0;
1137 static int cacheNotMacho = 0;
1138 if ( ((cacheHit+cacheMiss+cacheNotMacho) % 100) == 0 )
1139 dyld::log("findImageContainingAddress(): cache hit = %d, miss = %d, unknown = %d\n", cacheHit, cacheMiss, cacheNotMacho);
1140 #endif
1141 // first look in image where last address was found rdar://problem/3685517
1142 if ( (sLastImageByAddressCache != NULL) && sLastImageByAddressCache->containsAddress(addr) ) {
1143 #if FIND_STATS
1144 ++cacheHit;
1145 #endif
1146 return sLastImageByAddressCache;
1147 }
1148 // do exhastive search
1149 // todo: consider maintaining a list sorted by address ranges and do a binary search on that
1150 const unsigned int imageCount = sAllImages.size();
1151 for(unsigned int i=0; i < imageCount; ++i) {
1152 ImageLoader* anImage = sAllImages[i];
1153 if ( anImage->containsAddress(addr) ) {
1154 sLastImageByAddressCache = anImage;
1155 #if FIND_STATS
1156 ++cacheMiss;
1157 #endif
1158 return anImage;
1159 }
1160 }
1161 #if FIND_STATS
1162 ++cacheNotMacho;
1163 #endif
1164 return NULL;
1165 }
1166
1167 ImageLoader* findImageContainingAddressThreadSafe(const void* addr)
1168 {
1169 // do exhastive search
1170 // todo: consider maintaining a list sorted by address ranges and do a binary search on that
1171 const unsigned int imageCount = sAllImages.size();
1172 for(unsigned int i=0; i < imageCount; ++i) {
1173 ImageLoader* anImage = sAllImages[i];
1174 if ( anImage->containsAddress(addr) ) {
1175 return anImage;
1176 }
1177 }
1178 return NULL;
1179 }
1180
1181
1182 void forEachImageDo( void (*callback)(ImageLoader*, void* userData), void* userData)
1183 {
1184 const unsigned int imageCount = sAllImages.size();
1185 for(unsigned int i=0; i < imageCount; ++i) {
1186 ImageLoader* anImage = sAllImages[i];
1187 (*callback)(anImage, userData);
1188 }
1189 }
1190
1191 ImageLoader* findLoadedImage(const struct stat& stat_buf)
1192 {
1193 const unsigned int imageCount = sAllImages.size();
1194 for(unsigned int i=0; i < imageCount; ++i){
1195 ImageLoader* anImage = sAllImages[i];
1196 if ( anImage->statMatch(stat_buf) )
1197 return anImage;
1198 }
1199 return NULL;
1200 }
1201
1202 // based on ANSI-C strstr()
1203 static const char* strrstr(const char* str, const char* sub)
1204 {
1205 const int sublen = strlen(sub);
1206 for(const char* p = &str[strlen(str)]; p != str; --p) {
1207 if ( strncmp(p, sub, sublen) == 0 )
1208 return p;
1209 }
1210 return NULL;
1211 }
1212
1213
1214 //
1215 // Find framework path
1216 //
1217 // /path/foo.framework/foo => foo.framework/foo
1218 // /path/foo.framework/Versions/A/foo => foo.framework/Versions/A/foo
1219 // /path/foo.framework/Frameworks/bar.framework/bar => bar.framework/bar
1220 // /path/foo.framework/Libraries/bar.dylb => NULL
1221 // /path/foo.framework/bar => NULL
1222 //
1223 // Returns NULL if not a framework path
1224 //
1225 static const char* getFrameworkPartialPath(const char* path)
1226 {
1227 const char* dirDot = strrstr(path, ".framework/");
1228 if ( dirDot != NULL ) {
1229 const char* dirStart = dirDot;
1230 for ( ; dirStart >= path; --dirStart) {
1231 if ( (*dirStart == '/') || (dirStart == path) ) {
1232 const char* frameworkStart = &dirStart[1];
1233 if ( dirStart == path )
1234 --frameworkStart;
1235 int len = dirDot - frameworkStart;
1236 char framework[len+1];
1237 strncpy(framework, frameworkStart, len);
1238 framework[len] = '\0';
1239 const char* leaf = strrchr(path, '/');
1240 if ( leaf != NULL ) {
1241 if ( strcmp(framework, &leaf[1]) == 0 ) {
1242 return frameworkStart;
1243 }
1244 if ( gLinkContext.imageSuffix != NULL ) {
1245 // some debug frameworks have install names that end in _debug
1246 if ( strncmp(framework, &leaf[1], len) == 0 ) {
1247 if ( strcmp( gLinkContext.imageSuffix, &leaf[len+1]) == 0 )
1248 return frameworkStart;
1249 }
1250 }
1251 }
1252 }
1253 }
1254 }
1255 return NULL;
1256 }
1257
1258
1259 static const char* getLibraryLeafName(const char* path)
1260 {
1261 const char* start = strrchr(path, '/');
1262 if ( start != NULL )
1263 return &start[1];
1264 else
1265 return path;
1266 }
1267
1268
1269 // only for architectures that use cpu-sub-types
1270 #if CPU_SUBTYPES_SUPPORTED
1271
1272 const cpu_subtype_t CPU_SUBTYPE_END_OF_LIST = -1;
1273
1274
1275 //
1276 // A fat file may contain multiple sub-images for the same CPU type.
1277 // In that case, dyld picks which sub-image to use by scanning a table
1278 // of preferred cpu-sub-types for the running cpu.
1279 //
1280 // There is one row in the table for each cpu-sub-type on which dyld might run.
1281 // The first entry in a row is that cpu-sub-type. It is followed by all
1282 // cpu-sub-types that can run on that cpu, if preferred order. Each row ends with
1283 // a "SUBTYPE_ALL" (to denote that images written to run on any cpu-sub-type are usable),
1284 // followed by one or more CPU_SUBTYPE_END_OF_LIST to pad out this row.
1285 //
1286
1287
1288 //
1289 // 32-bit PowerPC sub-type lists
1290 //
1291 const int kPPC_RowCount = 4;
1292 static const cpu_subtype_t kPPC32[kPPC_RowCount][6] = {
1293 // G5 can run any code
1294 { CPU_SUBTYPE_POWERPC_970, CPU_SUBTYPE_POWERPC_7450, CPU_SUBTYPE_POWERPC_7400, CPU_SUBTYPE_POWERPC_750, CPU_SUBTYPE_POWERPC_ALL, CPU_SUBTYPE_END_OF_LIST },
1295
1296 // G4 can run all but G5 code
1297 { CPU_SUBTYPE_POWERPC_7450, CPU_SUBTYPE_POWERPC_7400, CPU_SUBTYPE_POWERPC_750, CPU_SUBTYPE_POWERPC_ALL, CPU_SUBTYPE_END_OF_LIST, CPU_SUBTYPE_END_OF_LIST },
1298 { CPU_SUBTYPE_POWERPC_7400, CPU_SUBTYPE_POWERPC_7450, CPU_SUBTYPE_POWERPC_750, CPU_SUBTYPE_POWERPC_ALL, CPU_SUBTYPE_END_OF_LIST, CPU_SUBTYPE_END_OF_LIST },
1299
1300 // G3 cannot run G4 or G5 code
1301 { CPU_SUBTYPE_POWERPC_750, CPU_SUBTYPE_POWERPC_ALL, CPU_SUBTYPE_END_OF_LIST, CPU_SUBTYPE_END_OF_LIST, CPU_SUBTYPE_END_OF_LIST, CPU_SUBTYPE_END_OF_LIST }
1302 };
1303
1304
1305
1306 // scan the tables above to find the cpu-sub-type-list for this machine
1307 static const cpu_subtype_t* findCPUSubtypeList(cpu_type_t cpu, cpu_subtype_t subtype)
1308 {
1309 switch (cpu) {
1310 case CPU_TYPE_POWERPC:
1311 for (int i=0; i < kPPC_RowCount ; ++i) {
1312 if ( kPPC32[i][0] == subtype )
1313 return kPPC32[i];
1314 }
1315 break;
1316 }
1317 return NULL;
1318 }
1319
1320
1321
1322
1323 // scan fat table-of-contents for best most preferred subtype
1324 static bool fatFindBestFromOrderedList(cpu_type_t cpu, const cpu_subtype_t list[], const fat_header* fh, uint64_t* offset, uint64_t* len)
1325 {
1326 const fat_arch* const archs = (fat_arch*)(((char*)fh)+sizeof(fat_header));
1327 for (uint32_t subTypeIndex=0; list[subTypeIndex] != CPU_SUBTYPE_END_OF_LIST; ++subTypeIndex) {
1328 for(uint32_t fatIndex=0; fatIndex < OSSwapBigToHostInt32(fh->nfat_arch); ++fatIndex) {
1329 if ( ((cpu_type_t)OSSwapBigToHostInt32(archs[fatIndex].cputype) == cpu)
1330 && (list[subTypeIndex] == (cpu_subtype_t)OSSwapBigToHostInt32(archs[fatIndex].cpusubtype)) ) {
1331 *offset = OSSwapBigToHostInt32(archs[fatIndex].offset);
1332 *len = OSSwapBigToHostInt32(archs[fatIndex].size);
1333 return true;
1334 }
1335 }
1336 }
1337 return false;
1338 }
1339
1340 // scan fat table-of-contents for exact match of cpu and cpu-sub-type
1341 static bool fatFindExactMatch(cpu_type_t cpu, cpu_subtype_t subtype, const fat_header* fh, uint64_t* offset, uint64_t* len)
1342 {
1343 const fat_arch* archs = (fat_arch*)(((char*)fh)+sizeof(fat_header));
1344 for(uint32_t i=0; i < OSSwapBigToHostInt32(fh->nfat_arch); ++i) {
1345 if ( ((cpu_type_t)OSSwapBigToHostInt32(archs[i].cputype) == cpu)
1346 && ((cpu_subtype_t)OSSwapBigToHostInt32(archs[i].cpusubtype) == subtype) ) {
1347 *offset = OSSwapBigToHostInt32(archs[i].offset);
1348 *len = OSSwapBigToHostInt32(archs[i].size);
1349 return true;
1350 }
1351 }
1352 return false;
1353 }
1354
1355 // scan fat table-of-contents for image with matching cpu-type and runs-on-all-sub-types
1356 static bool fatFindRunsOnAllCPUs(cpu_type_t cpu, const fat_header* fh, uint64_t* offset, uint64_t* len)
1357 {
1358 const fat_arch* archs = (fat_arch*)(((char*)fh)+sizeof(fat_header));
1359 for(uint32_t i=0; i < OSSwapBigToHostInt32(fh->nfat_arch); ++i) {
1360 if ( (cpu_type_t)OSSwapBigToHostInt32(archs[i].cputype) == cpu) {
1361 switch (cpu) {
1362 case CPU_TYPE_POWERPC:
1363 if ( (cpu_subtype_t)OSSwapBigToHostInt32(archs[i].cpusubtype) == CPU_SUBTYPE_POWERPC_ALL ) {
1364 *offset = OSSwapBigToHostInt32(archs[i].offset);
1365 *len = OSSwapBigToHostInt32(archs[i].size);
1366 return true;
1367 }
1368 break;
1369 }
1370 }
1371 }
1372 return false;
1373 }
1374
1375 #endif // CPU_SUBTYPES_SUPPORTED
1376
1377 //
1378 // A fat file may contain multiple sub-images for the same cpu-type,
1379 // each optimized for a different cpu-sub-type (e.g G3 or G5).
1380 // This routine picks the optimal sub-image.
1381 //
1382 static bool fatFindBest(const fat_header* fh, uint64_t* offset, uint64_t* len)
1383 {
1384 #if CPU_SUBTYPES_SUPPORTED
1385 // assume all dylibs loaded must have same cpu type as main executable
1386 const cpu_type_t cpu = sMainExecutableMachHeader->cputype;
1387
1388 // We only know the subtype to use if the main executable cpu type matches the host
1389 if ( (cpu & CPU_TYPE_MASK) == sHostCPU ) {
1390 // get preference ordered list of subtypes
1391 const cpu_subtype_t* subTypePreferenceList = findCPUSubtypeList(cpu, sHostCPUsubtype);
1392
1393 // use ordered list to find best sub-image in fat file
1394 if ( subTypePreferenceList != NULL )
1395 return fatFindBestFromOrderedList(cpu, subTypePreferenceList, fh, offset, len);
1396
1397 // if running cpu is not in list, try for an exact match
1398 if ( fatFindExactMatch(cpu, sHostCPUsubtype, fh, offset, len) )
1399 return true;
1400 }
1401
1402 // running on an uknown cpu, can only load generic code
1403 return fatFindRunsOnAllCPUs(cpu, fh, offset, len);
1404 #else
1405 // just find first slice with matching architecture
1406 const fat_arch* archs = (fat_arch*)(((char*)fh)+sizeof(fat_header));
1407 for(uint32_t i=0; i < OSSwapBigToHostInt32(fh->nfat_arch); ++i) {
1408 if ( (cpu_type_t)OSSwapBigToHostInt32(archs[i].cputype) == sMainExecutableMachHeader->cputype) {
1409 *offset = OSSwapBigToHostInt32(archs[i].offset);
1410 *len = OSSwapBigToHostInt32(archs[i].size);
1411 return true;
1412 }
1413 }
1414 return false;
1415 #endif
1416 }
1417
1418
1419
1420 //
1421 // This is used to validate if a non-fat (aka thin or raw) mach-o file can be used
1422 // on the current processor. //
1423 bool isCompatibleMachO(const uint8_t* firstPage)
1424 {
1425 #if CPU_SUBTYPES_SUPPORTED
1426 // It is deemed compatible if any of the following are true:
1427 // 1) mach_header subtype is in list of compatible subtypes for running processor
1428 // 2) mach_header subtype is same as running processor subtype
1429 // 3) mach_header subtype runs on all processor variants
1430 const mach_header* mh = (mach_header*)firstPage;
1431 if ( mh->magic == sMainExecutableMachHeader->magic ) {
1432 if ( mh->cputype == sMainExecutableMachHeader->cputype ) {
1433 if ( (mh->cputype & CPU_TYPE_MASK) == sHostCPU ) {
1434 // get preference ordered list of subtypes that this machine can use
1435 const cpu_subtype_t* subTypePreferenceList = findCPUSubtypeList(mh->cputype, sHostCPUsubtype);
1436 if ( subTypePreferenceList != NULL ) {
1437 // if image's subtype is in the list, it is compatible
1438 for (const cpu_subtype_t* p = subTypePreferenceList; *p != CPU_SUBTYPE_END_OF_LIST; ++p) {
1439 if ( *p == mh->cpusubtype )
1440 return true;
1441 }
1442 // have list and not in list, so not compatible
1443 throw "incompatible cpu-subtype";
1444 }
1445 // unknown cpu sub-type, but if exact match for current subtype then ok to use
1446 if ( mh->cpusubtype == sHostCPUsubtype )
1447 return true;
1448 }
1449
1450 // cpu type has no ordered list of subtypes
1451 switch (mh->cputype) {
1452 case CPU_TYPE_POWERPC:
1453 // allow _ALL to be used by any client
1454 if ( mh->cpusubtype == CPU_SUBTYPE_POWERPC_ALL )
1455 return true;
1456 break;
1457 case CPU_TYPE_POWERPC64:
1458 case CPU_TYPE_I386:
1459 case CPU_TYPE_X86_64:
1460 // subtypes are not used or these architectures
1461 return true;
1462 }
1463 }
1464 }
1465 #else
1466 // For architectures that don't support cpu-sub-types
1467 // this just check the cpu type.
1468 const mach_header* mh = (mach_header*)firstPage;
1469 if ( mh->magic == sMainExecutableMachHeader->magic ) {
1470 if ( mh->cputype == sMainExecutableMachHeader->cputype ) {
1471 return true;
1472 }
1473 }
1474 #endif
1475 return false;
1476 }
1477
1478
1479
1480
1481 // The kernel maps in main executable before dyld gets control. We need to
1482 // make an ImageLoader* for the already mapped in main executable.
1483 static ImageLoader* instantiateFromLoadedImage(const struct mach_header* mh, uintptr_t slide, const char* path)
1484 {
1485 // try mach-o loader
1486 if ( isCompatibleMachO((const uint8_t*)mh) ) {
1487 ImageLoader* image = new ImageLoaderMachO(mh, slide, path, gLinkContext);
1488 addImage(image);
1489 return image;
1490 }
1491
1492 throw "main executable not a known format";
1493 }
1494
1495 #if DYLD_SHARED_CACHE_SUPPORT
1496 static ImageLoader* findSharedCacheImage(const struct stat& stat_buf, const char* path)
1497 {
1498 if ( sSharedCache != NULL ) {
1499 // walk shared cache to see if there is a cached image that matches the inode/mtime/path desired
1500 const dyld_cache_image_info* const start = (dyld_cache_image_info*)((uint8_t*)sSharedCache + sSharedCache->imagesOffset);
1501 const dyld_cache_image_info* const end = &start[sSharedCache->imagesCount];
1502 for( const dyld_cache_image_info* p = start; p != end; ++p) {
1503 // check mtime and inode first because it is fast
1504 if ( ((time_t)p->modTime == stat_buf.st_mtime) && ((ino_t)p->inode == stat_buf.st_ino) ) {
1505 // mod-time and inode match an image in the shared cache, now check path
1506 const char* pathInCache = (char*)sSharedCache + p->pathFileOffset;
1507 bool cacheHit = (strcmp(path, pathInCache) == 0);
1508 if ( ! cacheHit ) {
1509 // path does not match install name of dylib in cache, but inode and mtime does match
1510 // perhaps path is a symlink to the cached dylib
1511 struct stat pathInCacheStatBuf;
1512 if ( stat(pathInCache, &pathInCacheStatBuf) != -1 )
1513 cacheHit = ( (pathInCacheStatBuf.st_dev == stat_buf.st_dev) && (pathInCacheStatBuf.st_ino == stat_buf.st_ino) );
1514 }
1515 if ( cacheHit ) {
1516 // found image in cache, instantiate an ImageLoader with it
1517 return new ImageLoaderMachO((struct mach_header*)(p->address), pathInCache, stat_buf, gLinkContext);
1518 }
1519 }
1520 }
1521 }
1522 return NULL;
1523 }
1524 #endif
1525
1526 static ImageLoader* checkandAddImage(ImageLoader* image, const LoadContext& context)
1527 {
1528 // now sanity check that this loaded image does not have the same install path as any existing image
1529 const char* loadedImageInstallPath = image->getInstallPath();
1530 if ( image->isDylib() && (loadedImageInstallPath != NULL) && (loadedImageInstallPath[0] == '/') ) {
1531 for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); it++) {
1532 ImageLoader* anImage = *it;
1533 const char* installPath = anImage->getInstallPath();
1534 if ( installPath != NULL) {
1535 if ( strcmp(loadedImageInstallPath, installPath) == 0 ) {
1536 //dyld::log("duplicate(%s) => %p\n", installPath, anImage);
1537 delete image;
1538 return anImage;
1539 }
1540 }
1541 }
1542 }
1543
1544 // some API's restrict what they can load
1545 if ( context.mustBeBundle && !image->isBundle() )
1546 throw "not a bundle";
1547 if ( context.mustBeDylib && !image->isDylib() )
1548 throw "not a dylib";
1549
1550 // don't add bundles to global list, they can be loaded but not linked. When linked it will be added to list
1551 if ( ! image->isBundle() )
1552 addImage(image);
1553
1554 return image;
1555 }
1556
1557 // map in file and instantiate an ImageLoader
1558 static ImageLoader* loadPhase6(int fd, struct stat& stat_buf, const char* path, const LoadContext& context)
1559 {
1560 //dyld::log("%s(%s)\n", __func__ , path);
1561 uint64_t fileOffset = 0;
1562 uint64_t fileLength = stat_buf.st_size;
1563
1564 // validate it is a file (not directory)
1565 if ( (stat_buf.st_mode & S_IFMT) != S_IFREG )
1566 throw "not a file";
1567
1568 uint8_t firstPage[4096];
1569 bool shortPage = false;
1570
1571 // min mach-o file is 4K
1572 if ( fileLength < 4096 ) {
1573 pread(fd, firstPage, fileLength, 0);
1574 shortPage = true;
1575 }
1576 else {
1577 pread(fd, firstPage, 4096,0);
1578 }
1579
1580 // if fat wrapper, find usable sub-file
1581 const fat_header* fileStartAsFat = (fat_header*)firstPage;
1582 if ( fileStartAsFat->magic == OSSwapBigToHostInt32(FAT_MAGIC) ) {
1583 if ( fatFindBest(fileStartAsFat, &fileOffset, &fileLength) ) {
1584 pread(fd, firstPage, 4096, fileOffset);
1585 }
1586 else {
1587 throw "no matching architecture in universal wrapper";
1588 }
1589 }
1590
1591 // try mach-o loader
1592 if ( isCompatibleMachO(firstPage) ) {
1593 if ( shortPage )
1594 throw "file too short";
1595
1596 // instantiate an image
1597 ImageLoader* image = new ImageLoaderMachO(path, fd, firstPage, fileOffset, fileLength, stat_buf, gLinkContext);
1598
1599 // validate
1600 return checkandAddImage(image, context);
1601 }
1602
1603 // try other file formats here...
1604
1605
1606 // throw error about what was found
1607 switch (*(uint32_t*)firstPage) {
1608 case MH_MAGIC:
1609 case MH_CIGAM:
1610 case MH_MAGIC_64:
1611 case MH_CIGAM_64:
1612 throw "mach-o, but wrong architecture";
1613 default:
1614 throwf("unknown file type, first eight bytes: 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X",
1615 firstPage[0], firstPage[1], firstPage[2], firstPage[3], firstPage[4], firstPage[5], firstPage[6],firstPage[7]);
1616 }
1617 }
1618
1619
1620 // try to open file
1621 static ImageLoader* loadPhase5open(const char* path, const LoadContext& context, std::vector<const char*>* exceptions)
1622 {
1623 //dyld::log("%s(%s, %p)\n", __func__ , path, exceptions);
1624 ImageLoader* image = NULL;
1625
1626 // just return NULL if file not found, but record any other errors
1627 struct stat stat_buf;
1628 if ( stat(path, &stat_buf) == -1 ) {
1629 int err = errno;
1630 if ( err != ENOENT ) {
1631 exceptions->push_back(dyld::mkstringf("%s: stat() failed with errno=%d", path, err));
1632 }
1633 return NULL;
1634 }
1635
1636 // in case image was renamed or found via symlinks, check for inode match
1637 image = findLoadedImage(stat_buf);
1638 if ( image != NULL )
1639 return image;
1640
1641 // do nothing if not already loaded and if RTLD_NOLOAD or NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
1642 if ( context.dontLoad )
1643 return NULL;
1644
1645 #if DYLD_SHARED_CACHE_SUPPORT
1646 // see if this image is in shared cache
1647 image = findSharedCacheImage(stat_buf, path);
1648 if ( image != NULL ) {
1649 return checkandAddImage(image, context);
1650 }
1651 #endif
1652
1653 // open file (automagically closed when this function exits)
1654 FileOpener file(path);
1655
1656 // just return NULL if file not found
1657 if ( file.getFileDescriptor() == -1 )
1658 return NULL;
1659
1660 try {
1661 return loadPhase6(file.getFileDescriptor(), stat_buf, path, context);
1662 }
1663 catch (const char* msg) {
1664 const char* newMsg = dyld::mkstringf("%s: %s", path, msg);
1665 exceptions->push_back(newMsg);
1666 free((void*)msg);
1667 return NULL;
1668 }
1669 }
1670
1671 // look for path match with existing loaded images
1672 static ImageLoader* loadPhase5check(const char* path, const LoadContext& context)
1673 {
1674 //dyld::log("%s(%s)\n", __func__ , path);
1675 // search path against load-path and install-path of all already loaded images
1676 uint32_t hash = ImageLoader::hash(path);
1677 for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); it++) {
1678 ImageLoader* anImage = *it;
1679 // check has first to cut down on strcmp calls
1680 if ( anImage->getPathHash() == hash )
1681 if ( strcmp(path, anImage->getPath()) == 0 ) {
1682 // if we are looking for a dylib don't return something else
1683 if ( !context.mustBeDylib || anImage->isDylib() )
1684 return anImage;
1685 }
1686 if ( context.matchByInstallName || anImage->matchInstallPath() ) {
1687 const char* installPath = anImage->getInstallPath();
1688 if ( installPath != NULL) {
1689 if ( strcmp(path, installPath) == 0 ) {
1690 // if we are looking for a dylib don't return something else
1691 if ( !context.mustBeDylib || anImage->isDylib() )
1692 return anImage;
1693 }
1694 }
1695 }
1696 }
1697
1698 //dyld::log("%s(%s) => NULL\n", __func__, path);
1699 return NULL;
1700 }
1701
1702
1703 // open or check existing
1704 static ImageLoader* loadPhase5(const char* path, const LoadContext& context, std::vector<const char*>* exceptions)
1705 {
1706 //dyld::log("%s(%s, %p)\n", __func__ , path, exceptions);
1707 if ( exceptions != NULL )
1708 return loadPhase5open(path, context, exceptions);
1709 else
1710 return loadPhase5check(path, context);
1711 }
1712
1713 // try with and without image suffix
1714 static ImageLoader* loadPhase4(const char* path, const LoadContext& context, std::vector<const char*>* exceptions)
1715 {
1716 //dyld::log("%s(%s, %p)\n", __func__ , path, exceptions);
1717 ImageLoader* image = NULL;
1718 if ( gLinkContext.imageSuffix != NULL ) {
1719 char pathWithSuffix[strlen(path)+strlen( gLinkContext.imageSuffix)+2];
1720 ImageLoader::addSuffix(path, gLinkContext.imageSuffix, pathWithSuffix);
1721 image = loadPhase5(pathWithSuffix, context, exceptions);
1722 }
1723 if ( image == NULL )
1724 image = loadPhase5(path, context, exceptions);
1725 return image;
1726 }
1727
1728 static ImageLoader* loadPhase2(const char* path, const LoadContext& context,
1729 const char* const frameworkPaths[], const char* const libraryPaths[],
1730 std::vector<const char*>* exceptions); // forward reference
1731
1732
1733 // expand @ variables
1734 static ImageLoader* loadPhase3(const char* path, const LoadContext& context, std::vector<const char*>* exceptions)
1735 {
1736 //dyld::log("%s(%s, %p)\n", __func__ , path, exceptions);
1737 ImageLoader* image = NULL;
1738 if ( strncmp(path, "@executable_path/", 17) == 0 ) {
1739 // executable_path cannot be in used in any binary in a setuid process rdar://problem/4589305
1740 if ( sMainExecutableIsSetuid ) {
1741 throwf("unsafe use of @executable_path in %s with setuid binary", context.origin);
1742 }
1743 // handle @executable_path path prefix
1744 const char* executablePath = sExecPath;
1745 char newPath[strlen(executablePath) + strlen(path)];
1746 strcpy(newPath, executablePath);
1747 char* addPoint = strrchr(newPath,'/');
1748 if ( addPoint != NULL )
1749 strcpy(&addPoint[1], &path[17]);
1750 else
1751 strcpy(newPath, &path[17]);
1752 image = loadPhase4(newPath, context, exceptions);
1753 if ( image != NULL )
1754 return image;
1755
1756 // perhaps main executable path is a sym link, find realpath and retry
1757 char resolvedPath[PATH_MAX];
1758 if ( realpath(sExecPath, resolvedPath) != NULL ) {
1759 char newRealPath[strlen(resolvedPath) + strlen(path)];
1760 strcpy(newRealPath, resolvedPath);
1761 char* addPoint = strrchr(newRealPath,'/');
1762 if ( addPoint != NULL )
1763 strcpy(&addPoint[1], &path[17]);
1764 else
1765 strcpy(newRealPath, &path[17]);
1766 image = loadPhase4(newRealPath, context, exceptions);
1767 if ( image != NULL )
1768 return image;
1769 }
1770 }
1771 else if ( (strncmp(path, "@loader_path/", 13) == 0) && (context.origin != NULL) ) {
1772 // @loader_path cannot be used from the main executable of a setuid process rdar://problem/4589305
1773 if ( sMainExecutableIsSetuid && (strcmp(context.origin, sExecPath) == 0) )
1774 throwf("unsafe use of @loader_path in %s with setuid binary", context.origin);
1775
1776 // handle @loader_path path prefix
1777 char newPath[strlen(context.origin) + strlen(path)];
1778 strcpy(newPath, context.origin);
1779 char* addPoint = strrchr(newPath,'/');
1780 if ( addPoint != NULL )
1781 strcpy(&addPoint[1], &path[13]);
1782 else
1783 strcpy(newPath, &path[13]);
1784 image = loadPhase4(newPath, context, exceptions);
1785 if ( image != NULL )
1786 return image;
1787
1788 // perhaps loader path is a sym link, find realpath and retry
1789 char resolvedPath[PATH_MAX];
1790 if ( realpath(context.origin, resolvedPath) != NULL ) {
1791 char newRealPath[strlen(resolvedPath) + strlen(path)];
1792 strcpy(newRealPath, resolvedPath);
1793 char* addPoint = strrchr(newRealPath,'/');
1794 if ( addPoint != NULL )
1795 strcpy(&addPoint[1], &path[13]);
1796 else
1797 strcpy(newRealPath, &path[13]);
1798 image = loadPhase4(newRealPath, context, exceptions);
1799 if ( image != NULL )
1800 return image;
1801 }
1802 }
1803 else if ( context.implicitRPath || (strncmp(path, "@rpath/", 7) == 0) ) {
1804 const char* trailingPath = (strncmp(path, "@rpath/", 7) == 0) ? &path[7] : path;
1805 // substitute @rpath with all -rpath paths up the load chain
1806 for(const ImageLoader::RPathChain* rp=context.rpath; rp != NULL; rp=rp->next) {
1807 if (rp->paths != NULL ) {
1808 for(std::vector<const char*>::iterator it=rp->paths->begin(); it != rp->paths->end(); ++it) {
1809 const char* anRPath = *it;
1810 char newPath[strlen(anRPath) + strlen(trailingPath)+2];
1811 strcpy(newPath, anRPath);
1812 strcat(newPath, "/");
1813 strcat(newPath, trailingPath);
1814 image = loadPhase4(newPath, context, exceptions);
1815 if ( image != NULL )
1816 return image;
1817 }
1818 }
1819 }
1820
1821 // substitute @rpath with LD_LIBRARY_PATH
1822 if ( sEnv.LD_LIBRARY_PATH != NULL ) {
1823 image = loadPhase2(trailingPath, context, NULL, sEnv.LD_LIBRARY_PATH, exceptions);
1824 if ( image != NULL )
1825 return image;
1826 }
1827
1828 // if this is the "open" pass, don't try to open @rpath/... as a relative path
1829 if ( (exceptions != NULL) && (trailingPath != path) )
1830 return NULL;
1831 }
1832 else if ( sMainExecutableIsSetuid && (path[0] != '/') ) {
1833 throwf("unsafe use of relative rpath %s in %s with setuid binary", path, context.origin);
1834 }
1835
1836 return loadPhase4(path, context, exceptions);
1837 }
1838
1839
1840 // try search paths
1841 static ImageLoader* loadPhase2(const char* path, const LoadContext& context,
1842 const char* const frameworkPaths[], const char* const libraryPaths[],
1843 std::vector<const char*>* exceptions)
1844 {
1845 //dyld::log("%s(%s, %p)\n", __func__ , path, exceptions);
1846 ImageLoader* image = NULL;
1847 const char* frameworkPartialPath = getFrameworkPartialPath(path);
1848 if ( frameworkPaths != NULL ) {
1849 if ( frameworkPartialPath != NULL ) {
1850 const int frameworkPartialPathLen = strlen(frameworkPartialPath);
1851 for(const char* const* fp = frameworkPaths; *fp != NULL; ++fp) {
1852 char npath[strlen(*fp)+frameworkPartialPathLen+8];
1853 strcpy(npath, *fp);
1854 strcat(npath, "/");
1855 strcat(npath, frameworkPartialPath);
1856 //dyld::log("dyld: fallback framework path used: %s() -> loadPhase4(\"%s\", ...)\n", __func__, npath);
1857 image = loadPhase4(npath, context, exceptions);
1858 if ( image != NULL )
1859 return image;
1860 }
1861 }
1862 }
1863 if ( libraryPaths != NULL ) {
1864 const char* libraryLeafName = getLibraryLeafName(path);
1865 const int libraryLeafNameLen = strlen(libraryLeafName);
1866 for(const char* const* lp = libraryPaths; *lp != NULL; ++lp) {
1867 char libpath[strlen(*lp)+libraryLeafNameLen+8];
1868 strcpy(libpath, *lp);
1869 strcat(libpath, "/");
1870 strcat(libpath, libraryLeafName);
1871 //dyld::log("dyld: fallback library path used: %s() -> loadPhase4(\"%s\", ...)\n", __func__, libpath);
1872 image = loadPhase4(libpath, context, exceptions);
1873 if ( image != NULL )
1874 return image;
1875 }
1876 }
1877 return NULL;
1878 }
1879
1880 // try search overrides and fallbacks
1881 static ImageLoader* loadPhase1(const char* path, const LoadContext& context, std::vector<const char*>* exceptions)
1882 {
1883 //dyld::log("%s(%s, %p)\n", __func__ , path, exceptions);
1884 ImageLoader* image = NULL;
1885
1886 // handle LD_LIBRARY_PATH environment variables that force searching
1887 if ( context.useLdLibraryPath && (sEnv.LD_LIBRARY_PATH != NULL) ) {
1888 image = loadPhase2(path, context, NULL, sEnv.LD_LIBRARY_PATH, exceptions);
1889 if ( image != NULL )
1890 return image;
1891 }
1892
1893 // handle DYLD_ environment variables that force searching
1894 if ( context.useSearchPaths && ((sEnv.DYLD_FRAMEWORK_PATH != NULL) || (sEnv.DYLD_LIBRARY_PATH != NULL)) ) {
1895 image = loadPhase2(path, context, sEnv.DYLD_FRAMEWORK_PATH, sEnv.DYLD_LIBRARY_PATH, exceptions);
1896 if ( image != NULL )
1897 return image;
1898 }
1899
1900 // try raw path
1901 image = loadPhase3(path, context, exceptions);
1902 if ( image != NULL )
1903 return image;
1904
1905 // try fallback paths during second time (will open file)
1906 if ( !context.dontLoad && (exceptions != NULL) && ((sEnv.DYLD_FALLBACK_FRAMEWORK_PATH != NULL) || (sEnv.DYLD_FALLBACK_LIBRARY_PATH != NULL)) ) {
1907 image = loadPhase2(path, context, sEnv.DYLD_FALLBACK_FRAMEWORK_PATH, sEnv.DYLD_FALLBACK_LIBRARY_PATH, exceptions);
1908 if ( image != NULL )
1909 return image;
1910 }
1911
1912 return NULL;
1913 }
1914
1915 // try root substitutions
1916 static ImageLoader* loadPhase0(const char* path, const LoadContext& context, std::vector<const char*>* exceptions)
1917 {
1918 //dyld::log("%s(%s, %p)\n", __func__ , path, exceptions);
1919
1920 // handle DYLD_ROOT_PATH which forces absolute paths to use a new root
1921 if ( (sEnv.DYLD_ROOT_PATH != NULL) && (path[0] == '/') ) {
1922 for(const char* const* rootPath = sEnv.DYLD_ROOT_PATH ; *rootPath != NULL; ++rootPath) {
1923 char newPath[strlen(*rootPath) + strlen(path)+2];
1924 strcpy(newPath, *rootPath);
1925 strcat(newPath, path);
1926 ImageLoader* image = loadPhase1(newPath, context, exceptions);
1927 if ( image != NULL )
1928 return image;
1929 }
1930 }
1931
1932 // try raw path
1933 return loadPhase1(path, context, exceptions);
1934 }
1935
1936 //
1937 // Given all the DYLD_ environment variables, the general case for loading libraries
1938 // is that any given path expands into a list of possible locations to load. We
1939 // also must take care to ensure two copies of the "same" library are never loaded.
1940 //
1941 // The algorithm used here is that there is a separate function for each "phase" of the
1942 // path expansion. Each phase function calls the next phase with each possible expansion
1943 // of that phase. The result is the last phase is called with all possible paths.
1944 //
1945 // To catch duplicates the algorithm is run twice. The first time, the last phase checks
1946 // the path against all loaded images. The second time, the last phase calls open() on
1947 // the path. Either time, if an image is found, the phases all unwind without checking
1948 // for other paths.
1949 //
1950 ImageLoader* load(const char* path, const LoadContext& context)
1951 {
1952 //dyld::log("%s(%s)\n", __func__ , path);
1953 char realPath[PATH_MAX];
1954 // when DYLD_IMAGE_SUFFIX is in used, do a realpath(), otherwise a load of "Foo.framework/Foo" will not match
1955 if ( context.useSearchPaths && ( gLinkContext.imageSuffix != NULL) ) {
1956 if ( realpath(path, realPath) != NULL )
1957 path = realPath;
1958 }
1959
1960 // try all path permutations and check against existing loaded images
1961 ImageLoader* image = loadPhase0(path, context, NULL);
1962 if ( image != NULL )
1963 return image;
1964
1965 // try all path permutations and try open() until first sucesss
1966 std::vector<const char*> exceptions;
1967 image = loadPhase0(path, context, &exceptions);
1968 if ( image != NULL )
1969 return image;
1970 else if ( exceptions.size() == 0 )
1971 throw "image not found";
1972 else {
1973 const char* msgStart = "no suitable image found. Did find:";
1974 const char* delim = "\n\t";
1975 size_t allsizes = strlen(msgStart)+8;
1976 for (unsigned int i=0; i < exceptions.size(); ++i)
1977 allsizes += (strlen(exceptions[i]) + strlen(delim));
1978 char* fullMsg = new char[allsizes];
1979 strcpy(fullMsg, msgStart);
1980 for (unsigned int i=0; i < exceptions.size(); ++i) {
1981 strcat(fullMsg, delim);
1982 strcat(fullMsg, exceptions[i]);
1983 free((void*)exceptions[i]);
1984 }
1985 throw (const char*)fullMsg;
1986 }
1987 }
1988
1989
1990
1991
1992 #if DYLD_SHARED_CACHE_SUPPORT
1993
1994
1995 // hack until dyld no longer needs to run on Leopard kernels that don't have new shared region syscall
1996 static bool newSharedRegionSyscallAvailable()
1997 {
1998 int shreg_version;
1999 size_t buffer_size = sizeof(shreg_version);
2000 if ( sysctlbyname("vm.shared_region_version", &shreg_version, &buffer_size, NULL, 0) == 0 ) {
2001 if ( shreg_version == 3 )
2002 return true;
2003 }
2004 return false;
2005 }
2006
2007
2008 static int __attribute__((noinline)) _shared_region_check_np(uint64_t* start_address)
2009 {
2010 if ( (gLinkContext.sharedRegionMode == ImageLoader::kUseSharedRegion) && newSharedRegionSyscallAvailable() )
2011 return syscall(294, start_address);
2012 return -1;
2013 }
2014
2015
2016 static int __attribute__((noinline)) _shared_region_map_np(int fd, uint32_t count, const shared_file_mapping_np mappings[])
2017 {
2018 int result;
2019 if ( (gLinkContext.sharedRegionMode == ImageLoader::kUseSharedRegion) && newSharedRegionSyscallAvailable() ) {
2020 return syscall(295, fd, count, mappings);
2021 }
2022
2023 // remove the shared region sub-map
2024 #if __ppc__ || __i386__
2025 vm_address_t addr = (vm_address_t)0x90000000;
2026 vm_deallocate(mach_task_self(), addr, 0x20000000);
2027 #elif __ppc64__ || __x86_64__
2028 vm_address_t addr = (vm_address_t)0x7FFF60000000;
2029 vm_deallocate(mach_task_self(), addr, 0x80000000);
2030 #endif
2031
2032 // map cache just for this process with mmap()
2033 bool failed = false;
2034 const shared_file_mapping_np* start = mappings;
2035 const shared_file_mapping_np* end = &mappings[count];
2036 for (const shared_file_mapping_np* p = start; p < end; ++p ) {
2037 void* mmapAddress = (void*)(uintptr_t)(p->sfm_address);
2038 size_t size = p->sfm_size;
2039 int protection = 0;
2040 if ( p->sfm_init_prot & VM_PROT_EXECUTE )
2041 protection |= PROT_EXEC;
2042 if ( p->sfm_init_prot & VM_PROT_READ )
2043 protection |= PROT_READ;
2044 if ( p->sfm_init_prot & VM_PROT_WRITE )
2045 protection |= PROT_WRITE;
2046 off_t offset = p->sfm_file_offset;
2047 mmapAddress = mmap(mmapAddress, size, protection, MAP_FIXED | MAP_PRIVATE, fd, offset);
2048 if ( mmap(mmapAddress, size, protection, MAP_FIXED | MAP_PRIVATE, fd, offset) != mmapAddress )
2049 failed = true;
2050 }
2051 if ( !failed ) {
2052 result = 0;
2053 gLinkContext.sharedRegionMode = ImageLoader::kUsePrivateSharedRegion;
2054 }
2055 else {
2056 result = -1;
2057 gLinkContext.sharedRegionMode = ImageLoader::kDontUseSharedRegion;
2058 if ( gLinkContext.verboseMapping )
2059 dyld::log("dyld: shared cached cannot be mapped\n");
2060 }
2061
2062 return result;
2063 }
2064
2065
2066
2067 #if __ppc__
2068 #define ARCH_NAME "ppc"
2069 #define ARCH_NAME_ROSETTA "rosetta"
2070 #define ARCH_VALUE CPU_TYPE_POWERPC
2071 #define ARCH_CACHE_MAGIC "dyld_v1 ppc"
2072 #elif __ppc64__
2073 #define ARCH_NAME "ppc64"
2074 #define ARCH_VALUE CPU_TYPE_POWERPC64
2075 #define ARCH_CACHE_MAGIC "dyld_v1 ppc64"
2076 #elif __i386__
2077 #define ARCH_NAME "i386"
2078 #define ARCH_VALUE CPU_TYPE_I386
2079 #define ARCH_CACHE_MAGIC "dyld_v1 i386"
2080 #elif __x86_64__
2081 #define ARCH_NAME "x86_64"
2082 #define ARCH_VALUE CPU_TYPE_X86_64
2083 #define ARCH_CACHE_MAGIC "dyld_v1 x86_64"
2084 #endif
2085
2086 const void* imMemorySharedCacheHeader()
2087 {
2088 return sSharedCache;
2089 }
2090
2091 int openSharedCacheFile()
2092 {
2093 #if __ppc__
2094 // rosetta cannot handle optimized _ppc cache, so it use _rosetta cache instead, rdar://problem/5495438
2095 if ( isRosetta() )
2096 return ::open(DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME_ROSETTA, O_RDONLY);
2097 else
2098 #endif
2099 return ::open(DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME, O_RDONLY);
2100 }
2101
2102 static void mapSharedCache()
2103 {
2104 uint64_t cacheBaseAddress;
2105 // quick check if a cache is alreay mapped into shared region
2106 if ( _shared_region_check_np(&cacheBaseAddress) == 0 ) {
2107 sSharedCache = (dyld_cache_header*)cacheBaseAddress;
2108 // if we don't understand the currently mapped shared cache, then ignore
2109 if ( strcmp(sSharedCache->magic, ARCH_CACHE_MAGIC) != 0 ) {
2110 sSharedCache = NULL;
2111 if ( gLinkContext.verboseMapping )
2112 dyld::log("dyld: existing shared cached in memory is not compatible\n");
2113 }
2114 }
2115 else {
2116 // <rdar://problem/5925940> Safe Boot should disable dyld shared cache
2117 // if we are in safe-boot mode and the cache was not made during this boot cycle,
2118 // delete the cache file and let it be regenerated
2119 uint32_t safeBootValue = 0;
2120 size_t safeBootValueSize = sizeof(safeBootValue);
2121 if ( (sysctlbyname("kern.safeboot", &safeBootValue, &safeBootValueSize, NULL, 0) == 0) && (safeBootValue != 0) ) {
2122 // user booted machine in safe-boot mode
2123 struct stat dyldCacheStatInfo;
2124 if ( ::stat(DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME, &dyldCacheStatInfo) == 0 ) {
2125 struct timeval bootTimeValue;
2126 size_t bootTimeValueSize = sizeof(bootTimeValue);
2127 if ( (sysctlbyname("kern.boottime", &bootTimeValue, &bootTimeValueSize, NULL, 0) == 0) && (bootTimeValue.tv_sec != 0) ) {
2128 // if the cache file was created before this boot, then throw it away and let it rebuild itself
2129 if ( dyldCacheStatInfo.st_mtime < bootTimeValue.tv_sec ) {
2130 ::unlink(DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME);
2131 gLinkContext.sharedRegionMode = ImageLoader::kDontUseSharedRegion;
2132 gSharedCacheNotFound = true;
2133 return;
2134 }
2135 }
2136 }
2137 }
2138 // map in shared cache to shared region
2139 int fd = openSharedCacheFile();
2140 if ( fd != -1 ) {
2141 uint8_t firstPage[4096];
2142 if ( ::read(fd, firstPage, 4096) == 4096 ) {
2143 dyld_cache_header* header = (dyld_cache_header*)firstPage;
2144 if ( strcmp(header->magic, ARCH_CACHE_MAGIC) == 0 ) {
2145 const shared_file_mapping_np* mappings = (shared_file_mapping_np*)&firstPage[header->mappingOffset];
2146 const shared_file_mapping_np* const end = &mappings[header->mappingCount];
2147 // validate that the cache file has not been truncated
2148 bool goodCache = false;
2149 struct stat stat_buf;
2150 if ( fstat(fd, &stat_buf) == 0 ) {
2151 goodCache = true;
2152 for (const shared_file_mapping_np* p = mappings; p < end; ++p) {
2153 // rdar://problem/5694507 old update_dyld_shared_cache tool could make a cache file
2154 // that is not page aligned, but otherwise ok.
2155 if ( p->sfm_file_offset+p->sfm_size > (uint64_t)(stat_buf.st_size+4095 & (-4096)) )
2156 goodCache = false;
2157 }
2158 }
2159 if ( goodCache ) {
2160 const shared_file_mapping_np* mappings = (shared_file_mapping_np*)&firstPage[header->mappingOffset];
2161 if (_shared_region_map_np(fd, header->mappingCount, mappings) == 0) {
2162 // sucessfully mapped cache into shared region
2163 sSharedCache = (dyld_cache_header*)mappings[0].sfm_address;
2164 }
2165 }
2166 else {
2167 gSharedCacheNeedsUpdating = true;
2168 dyld::log("dyld: shared cached file is corrupt: " DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME "\n");
2169 }
2170 }
2171 else {
2172 gSharedCacheNeedsUpdating = true;
2173 if ( gLinkContext.verboseMapping )
2174 dyld::log("dyld: shared cached file is invalid\n");
2175 }
2176 }
2177 else {
2178 gSharedCacheNeedsUpdating = true;
2179 if ( gLinkContext.verboseMapping )
2180 dyld::log("dyld: shared cached file cannot be read\n");
2181 }
2182 close(fd);
2183 }
2184 else {
2185 gSharedCacheNotFound = true;
2186 if ( gLinkContext.verboseMapping )
2187 dyld::log("dyld: shared cached file cannot be opened\n");
2188 }
2189 }
2190
2191 // remember if dyld loaded at same address as when cache built
2192 if ( sSharedCache != NULL ) {
2193 gLinkContext.dyldLoadedAtSameAddressNeededBySharedCache = ((uintptr_t)(sSharedCache->dyldBaseAddress) == (uintptr_t)&_mh_dylinker_header);
2194 }
2195
2196 // tell gdb where the shared cache is
2197 if ( sSharedCache != NULL ) {
2198 const shared_file_mapping_np* const start = (shared_file_mapping_np*)((uint8_t*)sSharedCache + sSharedCache->mappingOffset);
2199 dyld_shared_cache_ranges.sharedRegionsCount = sSharedCache->mappingCount;
2200 // only room to tell gdb about first four regions
2201 if ( dyld_shared_cache_ranges.sharedRegionsCount > 4 )
2202 dyld_shared_cache_ranges.sharedRegionsCount = 4;
2203 if ( gLinkContext.verboseMapping ) {
2204 if ( gLinkContext.sharedRegionMode == ImageLoader::kUseSharedRegion )
2205 dyld::log("dyld: Mapping shared cache\n");
2206 else if ( gLinkContext.sharedRegionMode == ImageLoader::kUsePrivateSharedRegion )
2207 dyld::log("dyld: Mapping private shared cache\n");
2208 }
2209 const shared_file_mapping_np* const end = &start[dyld_shared_cache_ranges.sharedRegionsCount];
2210 int index = 0;
2211 for (const shared_file_mapping_np* p = start; p < end; ++p, ++index ) {
2212 dyld_shared_cache_ranges.ranges[index].start = p->sfm_address;
2213 dyld_shared_cache_ranges.ranges[index].length = p->sfm_size;
2214 if ( gLinkContext.verboseMapping ) {
2215 dyld::log(" 0x%08llX->0x%08llX %s%s%s init=%x, max=%x\n", p->sfm_address, p->sfm_address+p->sfm_size-1,
2216 ((p->sfm_init_prot & VM_PROT_READ) ? "read " : ""),
2217 ((p->sfm_init_prot & VM_PROT_WRITE) ? "write " : ""),
2218 ((p->sfm_init_prot & VM_PROT_EXECUTE) ? "execute " : ""), p->sfm_init_prot, p->sfm_max_prot);
2219 }
2220 #if __i386__
2221 // record if a non-writable and executable region is found in the R/W shared region
2222 // this is the __IMPORT segments. dyld will turn write protection on and off as needed
2223 if ( (p->sfm_init_prot == (VM_PROT_READ|VM_PROT_EXECUTE)) && ((p->sfm_address & 0xF0000000) == 0xA0000000) ) {
2224 sImportSegmentsStart = p->sfm_address;
2225 sImportSegmentsSize = p->sfm_size;
2226 makeSharedCacheImportSegmentsWritable(true);
2227 }
2228 #endif
2229 }
2230
2231 }
2232 }
2233 #endif // #if DYLD_SHARED_CACHE_SUPPORT
2234
2235
2236
2237 // create when NSLinkModule is called for a second time on a bundle
2238 ImageLoader* cloneImage(ImageLoader* image)
2239 {
2240 const uint64_t offsetInFat = image->getOffsetInFatFile();
2241
2242 // open file (automagically closed when this function exits)
2243 FileOpener file(image->getPath());
2244
2245 struct stat stat_buf;
2246 if ( fstat(file.getFileDescriptor(), &stat_buf) == -1)
2247 throw "stat error";
2248
2249 // read first page of file
2250 uint8_t firstPage[4096];
2251 pread(file.getFileDescriptor(), firstPage, 4096, offsetInFat);
2252
2253 // fat length is only used for sanity checking, since this image was already loaded once, just use upper bound
2254 uint64_t lenInFat = stat_buf.st_size - offsetInFat;
2255
2256 // try mach-o loader
2257 if ( isCompatibleMachO(firstPage) ) {
2258 ImageLoader* clone = new ImageLoaderMachO(image->getPath(), file.getFileDescriptor(), firstPage, offsetInFat, lenInFat, stat_buf, gLinkContext);
2259 // don't add bundles to global list, they can be loaded but not linked. When linked it will be added to list
2260 if ( ! image->isBundle() )
2261 addImage(clone);
2262 return clone;
2263 }
2264
2265 // try other file formats...
2266 throw "can't clone image";
2267 }
2268
2269
2270 ImageLoader* loadFromMemory(const uint8_t* mem, uint64_t len, const char* moduleName)
2271 {
2272 // if fat wrapper, find usable sub-file
2273 const fat_header* memStartAsFat = (fat_header*)mem;
2274 uint64_t fileOffset = 0;
2275 uint64_t fileLength = len;
2276 if ( memStartAsFat->magic == OSSwapBigToHostInt32(FAT_MAGIC) ) {
2277 if ( fatFindBest(memStartAsFat, &fileOffset, &fileLength) ) {
2278 mem = &mem[fileOffset];
2279 len = fileLength;
2280 }
2281 else {
2282 throw "no matching architecture in universal wrapper";
2283 }
2284 }
2285
2286 // try each loader
2287 if ( isCompatibleMachO(mem) ) {
2288 ImageLoader* image = new ImageLoaderMachO(moduleName, (mach_header*)mem, len, gLinkContext);
2289 // don't add bundles to global list, they can be loaded but not linked. When linked it will be added to list
2290 if ( ! image->isBundle() )
2291 addImage(image);
2292 return image;
2293 }
2294
2295 // try other file formats here...
2296
2297 // throw error about what was found
2298 switch (*(uint32_t*)mem) {
2299 case MH_MAGIC:
2300 case MH_CIGAM:
2301 case MH_MAGIC_64:
2302 case MH_CIGAM_64:
2303 throw "mach-o, but wrong architecture";
2304 default:
2305 throwf("unknown file type, first eight bytes: 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X",
2306 mem[0], mem[1], mem[2], mem[3], mem[4], mem[5], mem[6],mem[7]);
2307 }
2308 }
2309
2310
2311 void registerAddCallback(ImageCallback func)
2312 {
2313 // now add to list to get notified when any more images are added
2314 sAddImageCallbacks.push_back(func);
2315
2316 // call callback with all existing images
2317 for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); it++) {
2318 ImageLoader* image = *it;
2319 if ( image->getState() >= dyld_image_state_bound && image->getState() < dyld_image_state_terminated )
2320 (*func)(image->machHeader(), image->getSlide());
2321 }
2322 }
2323
2324 void registerRemoveCallback(ImageCallback func)
2325 {
2326 sRemoveImageCallbacks.push_back(func);
2327 }
2328
2329 void clearErrorMessage()
2330 {
2331 error_string[0] = '\0';
2332 }
2333
2334 void setErrorMessage(const char* message)
2335 {
2336 // save off error message in global buffer for CrashReporter to find
2337 strncpy(error_string, message, sizeof(error_string)-1);
2338 error_string[sizeof(error_string)-1] = '\0';
2339 }
2340
2341 const char* getErrorMessage()
2342 {
2343 return error_string;
2344 }
2345
2346
2347 void halt(const char* message)
2348 {
2349 dyld::log("dyld: %s\n", message);
2350 setErrorMessage(message);
2351 strncpy(error_string, message, sizeof(error_string)-1);
2352 error_string[sizeof(error_string)-1] = '\0';
2353 dyld_fatal_error(error_string);
2354 }
2355
2356
2357 uintptr_t bindLazySymbol(const mach_header* mh, uintptr_t* lazyPointer)
2358 {
2359 uintptr_t result = 0;
2360 // acquire read-lock on dyld's data structures
2361 #if 0 // rdar://problem/3811777 turn off locking until deadlock is resolved
2362 if ( gLibSystemHelpers != NULL )
2363 (*gLibSystemHelpers->lockForReading)();
2364 #endif
2365 // lookup and bind lazy pointer and get target address
2366 try {
2367 ImageLoader* target;
2368 #if __i386__
2369 // fast stubs pass NULL for mh and image is instead found via the location of stub (aka lazyPointer)
2370 if ( mh == NULL )
2371 target = dyld::findImageContainingAddressThreadSafe(lazyPointer);
2372 else
2373 target = dyld::findImageByMachHeader(mh);
2374 #else
2375 // note, target should always be mach-o, because only mach-o lazy handler wired up to this
2376 target = dyld::findImageByMachHeader(mh);
2377 #endif
2378 if ( target == NULL )
2379 throwf("image not found for lazy pointer at %p", lazyPointer);
2380 result = target->doBindLazySymbol(lazyPointer, gLinkContext);
2381 }
2382 catch (const char* message) {
2383 dyld::log("dyld: lazy symbol binding failed: %s\n", message);
2384 halt(message);
2385 }
2386 // release read-lock on dyld's data structures
2387 #if 0
2388 if ( gLibSystemHelpers != NULL )
2389 (*gLibSystemHelpers->unlockForReading)();
2390 #endif
2391 // return target address to glue which jumps to it with real parameters restored
2392 return result;
2393 }
2394
2395
2396 // SPI used by ZeroLink to lazy load bundles
2397 void registerZeroLinkHandlers(BundleNotificationCallBack notify, BundleLocatorCallBack locate)
2398 {
2399 sBundleNotifier = notify;
2400 sBundleLocation = locate;
2401 }
2402
2403 void registerUndefinedHandler(UndefinedHandler handler)
2404 {
2405 sUndefinedHandler = handler;
2406 }
2407
2408 static void undefinedHandler(const char* symboName)
2409 {
2410 if ( sUndefinedHandler != NULL ) {
2411 (*sUndefinedHandler)(symboName);
2412 }
2413 }
2414
2415 static bool findExportedSymbol(const char* name, bool onlyInCoalesced, const ImageLoader::Symbol** sym, const ImageLoader** image)
2416 {
2417 // try ZeroLink short cut to finding bundle which exports this symbol
2418 if ( sBundleLocation != NULL ) {
2419 ImageLoader* zlImage = (*sBundleLocation)(name);
2420 if ( zlImage == ((ImageLoader*)(-1)) ) {
2421 // -1 is magic value that request symbol is in a bundle not yet linked into process
2422 // try calling handler to link in that symbol
2423 undefinedHandler(name);
2424 // call locator again
2425 zlImage = (*sBundleLocation)(name);
2426 }
2427 // if still not found, then ZeroLink has no idea where to find it
2428 if ( zlImage == ((ImageLoader*)(-1)) )
2429 return false;
2430 if ( zlImage != NULL ) {
2431 // ZeroLink cache knows where the symbol is
2432 if ( onlyInCoalesced ) {
2433 // but ZeroLink does not know about coalescing weak symbols, so ignore ZeroLink's hint when onlyInCoalesced==true
2434 }
2435 else {
2436 *sym = zlImage->findExportedSymbol(name, NULL, false, image);
2437 if ( *sym != NULL ) {
2438 *image = zlImage;
2439 return true;
2440 }
2441 }
2442 }
2443 else {
2444 // ZeroLink says it is in some bundle already loaded, but not linked, walk them all
2445 const unsigned int imageCount = sAllImages.size();
2446 for(unsigned int i=0; i < imageCount; ++i){
2447 ImageLoader* anImage = sAllImages[i];
2448 if ( anImage->isBundle() && !anImage->hasHiddenExports() ) {
2449 //dyld::log("dyld: search for %s in %s\n", name, anImage->getPath());
2450 *sym = anImage->findExportedSymbol(name, NULL, false, image);
2451 if ( *sym != NULL ) {
2452 return true;
2453 }
2454 }
2455 }
2456 }
2457 }
2458
2459 // search all images in order
2460 const ImageLoader* firstWeakImage = NULL;
2461 const ImageLoader::Symbol* firstWeakSym = NULL;
2462 const unsigned int imageCount = sAllImages.size();
2463 for(unsigned int i=0; i < imageCount; ++i) {
2464 ImageLoader* anImage = sAllImages[i];
2465 // the use of inserted libraries alters search order
2466 // so that inserted libraries are found before the main executable
2467 if ( sInsertedDylibCount > 0 ) {
2468 if ( i < sInsertedDylibCount )
2469 anImage = sAllImages[i+1];
2470 else if ( i == sInsertedDylibCount )
2471 anImage = sAllImages[0];
2472 }
2473 if ( ! anImage->hasHiddenExports() && (!onlyInCoalesced || anImage->hasCoalescedExports()) ) {
2474 *sym = anImage->findExportedSymbol(name, NULL, false, image);
2475 if ( *sym != NULL ) {
2476 // if weak definition found, record first one found
2477 if ( ((*image)->getExportedSymbolInfo(*sym) & ImageLoader::kWeakDefinition) != 0 ) {
2478 if ( firstWeakImage == NULL ) {
2479 firstWeakImage = *image;
2480 firstWeakSym = *sym;
2481 }
2482 }
2483 else {
2484 // found non-weak, so immediately return with it
2485 return true;
2486 }
2487 }
2488 }
2489 }
2490 if ( firstWeakSym != NULL ) {
2491 // found a weak definition, but no non-weak, so return first weak found
2492 *sym = firstWeakSym;
2493 *image = firstWeakImage;
2494 return true;
2495 }
2496
2497 return false;
2498 }
2499
2500 bool flatFindExportedSymbol(const char* name, const ImageLoader::Symbol** sym, const ImageLoader** image)
2501 {
2502 return findExportedSymbol(name, false, sym, image);
2503 }
2504
2505 bool findCoalescedExportedSymbol(const char* name, const ImageLoader::Symbol** sym, const ImageLoader** image)
2506 {
2507 return findExportedSymbol(name, true, sym, image);
2508 }
2509
2510
2511 bool flatFindExportedSymbolWithHint(const char* name, const char* librarySubstring, const ImageLoader::Symbol** sym, const ImageLoader** image)
2512 {
2513 // search all images in order
2514 const unsigned int imageCount = sAllImages.size();
2515 for(unsigned int i=0; i < imageCount; ++i){
2516 ImageLoader* anImage = sAllImages[i];
2517 // only look at images whose paths contain the hint string (NULL hint string is wildcard)
2518 if ( ! anImage->isBundle() && ((librarySubstring==NULL) || (strstr(anImage->getPath(), librarySubstring) != NULL)) ) {
2519 *sym = anImage->findExportedSymbol(name, NULL, false, image);
2520 if ( *sym != NULL ) {
2521 return true;
2522 }
2523 }
2524 }
2525 return false;
2526 }
2527
2528 static ImageLoader::MappedRegion* getMappedRegions(ImageLoader::MappedRegion* regions)
2529 {
2530 ImageLoader::MappedRegion* end = regions;
2531 for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); it++) {
2532 (*it)->getMappedRegions(end);
2533 }
2534 return end;
2535 }
2536
2537 void registerImageStateSingleChangeHandler(dyld_image_states state, dyld_image_state_change_handler handler)
2538 {
2539 // mark the image that the handler is in as never-unload because dyld has a reference into it
2540 ImageLoader* handlerImage = findImageContainingAddress((void*)handler);
2541 if ( handlerImage != NULL )
2542 handlerImage->setNeverUnload();
2543
2544 // add to list of handlers
2545 std::vector<dyld_image_state_change_handler>* handlers = stateToHandlers(state, sSingleHandlers);
2546 if ( handlers != NULL ) {
2547 handlers->push_back(handler);
2548
2549 // call callback with all existing images
2550 for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); it++) {
2551 ImageLoader* image = *it;
2552 dyld_image_info info;
2553 info.imageLoadAddress = image->machHeader();
2554 info.imageFilePath = image->getPath();
2555 info.imageFileModDate = image->lastModified();
2556 // should only call handler if state == image->state
2557 if ( image->getState() == state )
2558 (*handler)(state, 1, &info);
2559 // ignore returned string, too late to do anything
2560 }
2561 }
2562 }
2563
2564 void registerImageStateBatchChangeHandler(dyld_image_states state, dyld_image_state_change_handler handler)
2565 {
2566 // mark the image that the handler is in as never-unload because dyld has a reference into it
2567 ImageLoader* handlerImage = findImageContainingAddress((void*)handler);
2568 if ( handlerImage != NULL )
2569 handlerImage->setNeverUnload();
2570
2571 // add to list of handlers
2572 std::vector<dyld_image_state_change_handler>* handlers = stateToHandlers(state, sBatchHandlers);
2573 if ( handlers != NULL ) {
2574 // insert at front, so that gdb handler is always last
2575 handlers->insert(handlers->begin(), handler);
2576
2577 // call callback with all existing images
2578 try {
2579 notifyBatchPartial(state, true, handler);
2580 }
2581 catch (const char* msg) {
2582 // ignore request to abort during registration
2583 }
2584 }
2585 }
2586
2587 static ImageLoader* libraryLocator(const char* libraryName, bool search, bool findDLL, const char* origin, const ImageLoader::RPathChain* rpaths)
2588 {
2589 dyld::LoadContext context;
2590 context.useSearchPaths = search;
2591 context.useLdLibraryPath = false;
2592 context.implicitRPath = false;
2593 context.matchByInstallName = false;
2594 context.dontLoad = false;
2595 context.mustBeBundle = false;
2596 context.mustBeDylib = true;
2597 context.findDLL = findDLL;
2598 context.origin = origin;
2599 context.rpath = rpaths;
2600 return load(libraryName, context);
2601 }
2602
2603 static const char* basename(const char* path)
2604 {
2605 const char* last = path;
2606 for (const char* s = path; *s != '\0'; s++) {
2607 if (*s == '/')
2608 last = s+1;
2609 }
2610 return last;
2611 }
2612
2613 static void setContext(const struct mach_header* mainExecutableMH, int argc, const char* argv[], const char* envp[], const char* apple[])
2614 {
2615 gLinkContext.loadLibrary = &libraryLocator;
2616 gLinkContext.terminationRecorder = &terminationRecorder;
2617 gLinkContext.flatExportFinder = &flatFindExportedSymbol;
2618 gLinkContext.coalescedExportFinder = &findCoalescedExportedSymbol;
2619 gLinkContext.undefinedHandler = &undefinedHandler;
2620 #if IMAGE_NOTIFY_SUPPORT
2621 gLinkContext.addImageNeedingNotification = &addImageNeedingNotification;
2622 gLinkContext.notifyAdding = &notifyAdding;
2623 #endif
2624 gLinkContext.getAllMappedRegions = &getMappedRegions;
2625 gLinkContext.bindingHandler = NULL;
2626 gLinkContext.notifySingle = &notifySingle;
2627 gLinkContext.notifyBatch = &notifyBatch;
2628 gLinkContext.removeImage = &removeImage;
2629 gLinkContext.registerDOFs = &registerDOFs;
2630 gLinkContext.clearAllDepths = &clearAllDepths;
2631 gLinkContext.imageCount = &imageCount;
2632 gLinkContext.notifySharedCacheInvalid= &notifySharedCacheInvalid;
2633 #if __i386__
2634 gLinkContext.makeSharedCacheImportSegmentsWritable = &makeSharedCacheImportSegmentsWritable;
2635 #endif
2636 gLinkContext.setNewProgramVars = &setNewProgramVars;
2637 #if SUPPORT_OLD_CRT_INITIALIZATION
2638 gLinkContext.setRunInitialzersOldWay= &setRunInitialzersOldWay;
2639 #endif
2640 gLinkContext.bindingOptions = ImageLoader::kBindingNone;
2641 gLinkContext.argc = argc;
2642 gLinkContext.argv = argv;
2643 gLinkContext.envp = envp;
2644 gLinkContext.apple = apple;
2645 gLinkContext.progname = (argv[0] != NULL) ? basename(argv[0]) : "";
2646 gLinkContext.programVars.mh = mainExecutableMH;
2647 gLinkContext.programVars.NXArgcPtr = &gLinkContext.argc;
2648 gLinkContext.programVars.NXArgvPtr = &gLinkContext.argv;
2649 gLinkContext.programVars.environPtr = &gLinkContext.envp;
2650 gLinkContext.programVars.__prognamePtr=&gLinkContext.progname;
2651 gLinkContext.mainExecutable = NULL;
2652 gLinkContext.imageSuffix = NULL;
2653 gLinkContext.prebindUsage = ImageLoader::kUseAllPrebinding;
2654 gLinkContext.sharedRegionMode = ImageLoader::kUseSharedRegion;
2655 }
2656
2657 #if __ppc__ || __i386__
2658 bool isRosetta()
2659 {
2660 int mib[] = { CTL_KERN, KERN_CLASSIC, getpid() };
2661 int is_classic = 0;
2662 size_t len = sizeof(int);
2663 int ret = sysctl(mib, 3, &is_classic, &len, NULL, 0);
2664 if ((ret != -1) && is_classic) {
2665 // we're running under Rosetta
2666 return true;
2667 }
2668 return false;
2669 }
2670 #endif
2671
2672 #if 0
2673 static void printAllImages()
2674 {
2675 dyld::log("printAllImages()\n");
2676 for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); it++) {
2677 ImageLoader* image = *it;
2678 dyld_image_states imageState = image->getState();
2679 dyld::log(" state=%d, refcount=%d, name=%s\n", imageState, image->referenceCount(), image->getShortName());
2680 image->printReferenceCounts();
2681 }
2682 }
2683 #endif
2684
2685
2686 void link(ImageLoader* image, bool forceLazysBound, const ImageLoader::RPathChain& loaderRPaths)
2687 {
2688 // add to list of known images. This did not happen at creation time for bundles
2689 if ( image->isBundle() && !image->isLinked() )
2690 addImage(image);
2691
2692 // we detect root images as those not linked in yet
2693 if ( !image->isLinked() )
2694 addRootImage(image);
2695
2696 // notify ZeroLink of new image with concat of logical and physical name
2697 if ( sBundleNotifier != NULL && image->isBundle() ) {
2698 const int logicalLen = strlen(image->getLogicalPath());
2699 char logAndPhys[strlen(image->getPath())+logicalLen+2];
2700 strcpy(logAndPhys, image->getLogicalPath());
2701 strcpy(&logAndPhys[logicalLen+1], image->getPath());
2702 (*sBundleNotifier)(logAndPhys, image);
2703 }
2704
2705 // process images
2706 try {
2707 image->link(gLinkContext, forceLazysBound, false, loaderRPaths);
2708 }
2709 catch (const char* msg) {
2710 garbageCollectImages();
2711 throw;
2712 }
2713
2714 #if OLD_GDB_DYLD_INTERFACE
2715 // notify gdb that loaded libraries have changed
2716 gdb_dyld_state_changed();
2717 #endif
2718 }
2719
2720
2721 void runInitializers(ImageLoader* image)
2722 {
2723 // do bottom up initialization
2724 image->runInitializers(gLinkContext);
2725 }
2726
2727 void garbageCollectImages()
2728 {
2729 // keep scanning list of images until entire list is scanned with no unreferenced images
2730 bool mightBeUnreferencedImages = true;
2731 while ( mightBeUnreferencedImages ) {
2732 mightBeUnreferencedImages = false;
2733 for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); it++) {
2734 ImageLoader* image = *it;
2735 if ( (image->referenceCount() == 0) && !image->neverUnload() && !image->isBeingRemoved() ) {
2736 try {
2737 //dyld::log("garbageCollectImages: deleting %s\n", image->getPath());
2738 image->setBeingRemoved();
2739 removeImage(image);
2740 delete image;
2741 }
2742 catch (const char* msg) {
2743 dyld::warn("problem deleting image: %s\n", msg);
2744 }
2745 mightBeUnreferencedImages = true;
2746 break;
2747 }
2748 }
2749 }
2750 //printAllImages();
2751 }
2752
2753
2754 static void preflight_finally(ImageLoader* image)
2755 {
2756 if ( image->isBundle() ) {
2757 removeImageFromAllImages(image->machHeader());
2758 delete image;
2759 }
2760 sBundleBeingLoaded = NULL;
2761 dyld::garbageCollectImages();
2762 }
2763
2764
2765 void preflight(ImageLoader* image, const ImageLoader::RPathChain& loaderRPaths)
2766 {
2767 try {
2768 if ( image->isBundle() )
2769 sBundleBeingLoaded = image; // hack
2770 image->link(gLinkContext, false, true, loaderRPaths);
2771 }
2772 catch (const char* msg) {
2773 preflight_finally(image);
2774 throw;
2775 }
2776 preflight_finally(image);
2777 }
2778
2779 static void loadInsertedDylib(const char* path)
2780 {
2781 ImageLoader* image = NULL;
2782 try {
2783 LoadContext context;
2784 context.useSearchPaths = false;
2785 context.useLdLibraryPath = false;
2786 context.implicitRPath = false;
2787 context.matchByInstallName = false;
2788 context.dontLoad = false;
2789 context.mustBeBundle = false;
2790 context.mustBeDylib = true;
2791 context.findDLL = false;
2792 context.origin = NULL; // can't use @loader_path with DYLD_INSERT_LIBRARIES
2793 context.rpath = NULL;
2794 image = load(path, context);
2795 image->setNeverUnload();
2796 }
2797 catch (...) {
2798 halt(dyld::mkstringf("could not load inserted library: %s\n", path));
2799 }
2800 }
2801
2802 //
2803 // Entry point for dyld. The kernel loads dyld and jumps to __dyld_start which
2804 // sets up some registers and call this function.
2805 //
2806 // Returns address of main() in target program which __dyld_start jumps to
2807 //
2808 uintptr_t
2809 _main(const struct mach_header* mainExecutableMH, uintptr_t mainExecutableSlide, int argc, const char* argv[], const char* envp[], const char* apple[])
2810 {
2811 setContext(mainExecutableMH, argc, argv, envp, apple);
2812
2813 // Pickup the pointer to the exec path.
2814 sExecPath = apple[0];
2815 bool ignoreEnvironmentVariables = false;
2816 #if __i386__
2817 if ( isRosetta() ) {
2818 // under Rosetta (x86 side)
2819 // When a 32-bit ppc program is run under emulation on an Intel processor,
2820 // we want any i386 dylibs (e.g. any used by Rosetta) to not load in the shared region
2821 // because the shared region is being used by ppc dylibs
2822 gLinkContext.sharedRegionMode = ImageLoader::kDontUseSharedRegion;
2823 ignoreEnvironmentVariables = true;
2824 }
2825 #endif
2826 if ( sExecPath[0] != '/' ) {
2827 // have relative path, use cwd to make absolute
2828 char cwdbuff[MAXPATHLEN];
2829 if ( getcwd(cwdbuff, MAXPATHLEN) != NULL ) {
2830 // maybe use static buffer to avoid calling malloc so early...
2831 char* s = new char[strlen(cwdbuff) + strlen(sExecPath) + 2];
2832 strcpy(s, cwdbuff);
2833 strcat(s, "/");
2834 strcat(s, sExecPath);
2835 sExecPath = s;
2836 }
2837 }
2838 uintptr_t result = 0;
2839 sMainExecutableMachHeader = mainExecutableMH;
2840 sMainExecutableIsSetuid = issetugid();
2841 if ( sMainExecutableIsSetuid )
2842 pruneEnvironmentVariables(envp, &apple);
2843 else
2844 checkEnvironmentVariables(envp, ignoreEnvironmentVariables);
2845 if ( sEnv.DYLD_PRINT_OPTS )
2846 printOptions(argv);
2847 if ( sEnv.DYLD_PRINT_ENV )
2848 printEnvironmentVariables(envp);
2849 getHostInfo();
2850 // install gdb notifier
2851 stateToHandlers(dyld_image_state_dependents_mapped, sBatchHandlers)->push_back(notifyGDB);
2852 // make initial allocations large enough that it is unlikely to need to be re-alloced
2853 sAllImages.reserve(200);
2854 sImageRoots.reserve(16);
2855 sAddImageCallbacks.reserve(4);
2856 sRemoveImageCallbacks.reserve(4);
2857 sImageFilesNeedingTermination.reserve(16);
2858 sImageFilesNeedingDOFUnregistration.reserve(8);
2859
2860 try {
2861 // instantiate ImageLoader for main executable
2862 sMainExecutable = instantiateFromLoadedImage(mainExecutableMH, mainExecutableSlide, sExecPath);
2863 sMainExecutable->setNeverUnload();
2864 gLinkContext.mainExecutable = sMainExecutable;
2865 // load shared cache
2866 checkSharedRegionDisable();
2867 #if DYLD_SHARED_CACHE_SUPPORT
2868 if ( gLinkContext.sharedRegionMode != ImageLoader::kDontUseSharedRegion )
2869 mapSharedCache();
2870 #endif
2871 // load any inserted libraries
2872 if ( sEnv.DYLD_INSERT_LIBRARIES != NULL ) {
2873 for (const char* const* lib = sEnv.DYLD_INSERT_LIBRARIES; *lib != NULL; ++lib)
2874 loadInsertedDylib(*lib);
2875 }
2876 // record count of inserted libraries so that a flat search will look at
2877 // inserted libraries, then main, then others.
2878 sInsertedDylibCount = sAllImages.size()-1;
2879
2880 // link main executable
2881 gLinkContext.linkingMainExecutable = true;
2882 link(sMainExecutable, sEnv.DYLD_BIND_AT_LAUNCH, ImageLoader::RPathChain(NULL, NULL));
2883 gLinkContext.linkingMainExecutable = false;
2884 if ( sMainExecutable->forceFlat() ) {
2885 gLinkContext.bindFlat = true;
2886 gLinkContext.prebindUsage = ImageLoader::kUseNoPrebinding;
2887 }
2888 result = (uintptr_t)sMainExecutable->getMain();
2889
2890 // link any inserted libraries
2891 // do this after linking main executable so that any dylibs pulled in by inserted
2892 // dylibs (e.g. libSystem) will not be in front of dylibs the program uses
2893 if ( sInsertedDylibCount > 0 ) {
2894 for(unsigned int i=0; i < sInsertedDylibCount; ++i) {
2895 ImageLoader* image = sAllImages[i+1];
2896 link(image, sEnv.DYLD_BIND_AT_LAUNCH, ImageLoader::RPathChain(NULL, NULL));
2897 }
2898 }
2899
2900 #if SUPPORT_OLD_CRT_INITIALIZATION
2901 // Old way is to run initializers via a callback from crt1.o
2902 if ( ! gRunInitializersOldWay )
2903 #endif
2904 initializeMainExecutable(); // run all initializers
2905 }
2906 catch(const char* message) {
2907 halt(message);
2908 }
2909 catch(...) {
2910 dyld::log("dyld: launch failed\n");
2911 }
2912
2913 return result;
2914 }
2915
2916
2917
2918
2919 }; // namespace
2920
2921
2922