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