1/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
2 *
3 * Copyright (c) 2004-2010 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#define __STDC_LIMIT_MACROS
26#include <stdint.h>
27#include <stdlib.h>
28#include <errno.h>
29#include <fcntl.h>
30#include <mach/mach.h>
31#include <mach-o/fat.h>
32#include <sys/types.h>
33#include <sys/stat.h>
34#include <sys/mman.h>
35#include <sys/param.h>
36#include <sys/mount.h>
37#include <libkern/OSAtomic.h>
38
39#include "ImageLoader.h"
40
41
42uint32_t								ImageLoader::fgImagesUsedFromSharedCache = 0;
43uint32_t								ImageLoader::fgImagesWithUsedPrebinding = 0;
44uint32_t								ImageLoader::fgImagesRequiringCoalescing = 0;
45uint32_t								ImageLoader::fgImagesHasWeakDefinitions = 0;
46uint32_t								ImageLoader::fgTotalRebaseFixups = 0;
47uint32_t								ImageLoader::fgTotalBindFixups = 0;
48uint32_t								ImageLoader::fgTotalBindSymbolsResolved = 0;
49uint32_t								ImageLoader::fgTotalBindImageSearches = 0;
50uint32_t								ImageLoader::fgTotalLazyBindFixups = 0;
51uint32_t								ImageLoader::fgTotalPossibleLazyBindFixups = 0;
52uint32_t								ImageLoader::fgTotalSegmentsMapped = 0;
53uint64_t								ImageLoader::fgTotalBytesMapped = 0;
54uint64_t								ImageLoader::fgTotalBytesPreFetched = 0;
55uint64_t								ImageLoader::fgTotalLoadLibrariesTime;
56uint64_t								ImageLoader::fgTotalRebaseTime;
57uint64_t								ImageLoader::fgTotalBindTime;
58uint64_t								ImageLoader::fgTotalWeakBindTime;
59uint64_t								ImageLoader::fgTotalDOF;
60uint64_t								ImageLoader::fgTotalInitTime;
61uint16_t								ImageLoader::fgLoadOrdinal = 0;
62std::vector<ImageLoader::InterposeTuple>ImageLoader::fgInterposingTuples;
63uintptr_t								ImageLoader::fgNextPIEDylibAddress = 0;
64
65
66
67ImageLoader::ImageLoader(const char* path, unsigned int libCount)
68	: fPath(path), fRealPath(NULL), fDevice(0), fInode(0), fLastModified(0),
69	fPathHash(0), fDlopenReferenceCount(0), fInitializerRecursiveLock(NULL),
70	fDepth(0), fLoadOrder(fgLoadOrdinal++), fState(0), fLibraryCount(libCount),
71	fAllLibraryChecksumsAndLoadAddressesMatch(false), fLeaveMapped(false), fNeverUnload(false),
72	fHideSymbols(false), fMatchByInstallName(false),
73	fInterposed(false), fRegisteredDOF(false), fAllLazyPointersBound(false),
74    fBeingRemoved(false), fAddFuncNotified(false),
75	fPathOwnedByImage(false), fIsReferencedDownward(false),
76	fWeakSymbolsBound(false)
77{
78	if ( fPath != NULL )
79		fPathHash = hash(fPath);
80	if ( libCount > 512 )
81		dyld::throwf("too many dependent dylibs in %s", path);
82}
83
84
85void ImageLoader::deleteImage(ImageLoader* image)
86{
87	delete image;
88}
89
90
91ImageLoader::~ImageLoader()
92{
93	if ( fRealPath != NULL )
94		delete [] fRealPath;
95	if ( fPathOwnedByImage && (fPath != NULL) )
96		delete [] fPath;
97}
98
99void ImageLoader::setFileInfo(dev_t device, ino_t inode, time_t modDate)
100{
101	fDevice = device;
102	fInode = inode;
103	fLastModified = modDate;
104}
105
106void ImageLoader::setMapped(const LinkContext& context)
107{
108	fState = dyld_image_state_mapped;
109	context.notifySingle(dyld_image_state_mapped, this);  // note: can throw exception
110}
111
112int ImageLoader::compare(const ImageLoader* right) const
113{
114	if ( this->fDepth == right->fDepth ) {
115		if ( this->fLoadOrder == right->fLoadOrder )
116			return 0;
117		else if ( this->fLoadOrder < right->fLoadOrder )
118			return -1;
119		else
120			return 1;
121	}
122	else {
123		if ( this->fDepth < right->fDepth )
124			return -1;
125		else
126			return 1;
127	}
128}
129
130void ImageLoader::setPath(const char* path)
131{
132	if ( fPathOwnedByImage && (fPath != NULL) )
133		delete [] fPath;
134	fPath = new char[strlen(path)+1];
135	strcpy((char*)fPath, path);
136	fPathOwnedByImage = true;  // delete fPath when this image is destructed
137	fPathHash = hash(fPath);
138	fRealPath = NULL;
139}
140
141void ImageLoader::setPathUnowned(const char* path)
142{
143	if ( fPathOwnedByImage && (fPath != NULL) ) {
144		delete [] fPath;
145	}
146	fPath = path;
147	fPathOwnedByImage = false;
148	fPathHash = hash(fPath);
149}
150
151void ImageLoader::setPaths(const char* path, const char* realPath)
152{
153	this->setPath(path);
154	fRealPath = new char[strlen(realPath)+1];
155	strcpy((char*)fRealPath, realPath);
156}
157
158const char* ImageLoader::getRealPath() const
159{
160	if ( fRealPath != NULL )
161		return fRealPath;
162	else
163		return fPath;
164}
165
166
167uint32_t ImageLoader::hash(const char* path)
168{
169	// this does not need to be a great hash
170	// it is just used to reduce the number of strcmp() calls
171	// of existing images when loading a new image
172	uint32_t h = 0;
173	for (const char* s=path; *s != '\0'; ++s)
174		h = h*5 + *s;
175	return h;
176}
177
178bool ImageLoader::matchInstallPath() const
179{
180	return fMatchByInstallName;
181}
182
183void ImageLoader::setMatchInstallPath(bool match)
184{
185	fMatchByInstallName = match;
186}
187
188bool ImageLoader::statMatch(const struct stat& stat_buf) const
189{
190	return ( (this->fDevice == stat_buf.st_dev) && (this->fInode == stat_buf.st_ino) );
191}
192
193const char* ImageLoader::getShortName() const
194{
195	// try to return leaf name
196	if ( fPath != NULL ) {
197		const char* s = strrchr(fPath, '/');
198		if ( s != NULL )
199			return &s[1];
200	}
201	return fPath;
202}
203
204void ImageLoader::setLeaveMapped()
205{
206	fLeaveMapped = true;
207}
208
209void ImageLoader::setHideExports(bool hide)
210{
211	fHideSymbols = hide;
212}
213
214bool ImageLoader::hasHiddenExports() const
215{
216	return fHideSymbols;
217}
218
219bool ImageLoader::isLinked() const
220{
221	return (fState >= dyld_image_state_bound);
222}
223
224time_t ImageLoader::lastModified() const
225{
226	return fLastModified;
227}
228
229bool ImageLoader::containsAddress(const void* addr) const
230{
231	for(unsigned int i=0, e=segmentCount(); i < e; ++i) {
232		const uint8_t* start = (const uint8_t*)segActualLoadAddress(i);
233		const uint8_t* end = (const uint8_t*)segActualEndAddress(i);
234		if ( (start <= addr) && (addr < end) && !segUnaccessible(i) )
235			return true;
236	}
237	return false;
238}
239
240bool ImageLoader::overlapsWithAddressRange(const void* start, const void* end) const
241{
242	for(unsigned int i=0, e=segmentCount(); i < e; ++i) {
243		const uint8_t* segStart = (const uint8_t*)segActualLoadAddress(i);
244		const uint8_t* segEnd = (const uint8_t*)segActualEndAddress(i);
245		if ( strcmp(segName(i), "__UNIXSTACK") == 0 ) {
246			// __UNIXSTACK never slides.  This is the only place that cares
247			// and checking for that segment name in segActualLoadAddress()
248			// is too expensive.
249			segStart -= getSlide();
250			segEnd -= getSlide();
251		}
252		if ( (start <= segStart) && (segStart < end) )
253			return true;
254		if ( (start <= segEnd) && (segEnd < end) )
255			return true;
256		if ( (segStart < start) && (end < segEnd) )
257			return true;
258	}
259	return false;
260}
261
262void ImageLoader::getMappedRegions(MappedRegion*& regions) const
263{
264	for(unsigned int i=0, e=segmentCount(); i < e; ++i) {
265		MappedRegion region;
266		region.address = segActualLoadAddress(i);
267		region.size = segSize(i);
268		*regions++ = region;
269	}
270}
271
272
273
274bool ImageLoader::dependsOn(ImageLoader* image) {
275	for(unsigned int i=0; i < libraryCount(); ++i) {
276		if ( libImage(i) == image )
277			return true;
278	}
279	return false;
280}
281
282
283static bool notInImgageList(const ImageLoader* image, const ImageLoader** dsiStart, const ImageLoader** dsiCur)
284{
285	for (const ImageLoader** p = dsiStart; p < dsiCur; ++p)
286		if ( *p == image )
287			return false;
288	return true;
289}
290
291
292// private method that handles circular dependencies by only search any image once
293const ImageLoader::Symbol* ImageLoader::findExportedSymbolInDependentImagesExcept(const char* name,
294			const ImageLoader** dsiStart, const ImageLoader**& dsiCur, const ImageLoader** dsiEnd, const ImageLoader** foundIn) const
295{
296	const ImageLoader::Symbol* sym;
297	// search self
298	if ( notInImgageList(this, dsiStart, dsiCur) ) {
299		sym = this->findExportedSymbol(name, false, foundIn);
300		if ( sym != NULL )
301			return sym;
302		*dsiCur++ = this;
303	}
304
305	// search directly dependent libraries
306	for(unsigned int i=0; i < libraryCount(); ++i) {
307		ImageLoader* dependentImage = libImage(i);
308		if ( (dependentImage != NULL) && notInImgageList(dependentImage, dsiStart, dsiCur) ) {
309			const ImageLoader::Symbol* sym = dependentImage->findExportedSymbol(name, false, foundIn);
310			if ( sym != NULL )
311				return sym;
312		}
313	}
314
315	// search indirectly dependent libraries
316	for(unsigned int i=0; i < libraryCount(); ++i) {
317		ImageLoader* dependentImage = libImage(i);
318		if ( (dependentImage != NULL) && notInImgageList(dependentImage, dsiStart, dsiCur) ) {
319			*dsiCur++ = dependentImage;
320			const ImageLoader::Symbol* sym = dependentImage->findExportedSymbolInDependentImagesExcept(name, dsiStart, dsiCur, dsiEnd, foundIn);
321			if ( sym != NULL )
322				return sym;
323		}
324	}
325
326	return NULL;
327}
328
329
330const ImageLoader::Symbol* ImageLoader::findExportedSymbolInDependentImages(const char* name, const LinkContext& context, const ImageLoader** foundIn) const
331{
332	unsigned int imageCount = context.imageCount();
333	const ImageLoader* dontSearchImages[imageCount];
334	dontSearchImages[0] = this; // don't search this image
335	const ImageLoader** cur = &dontSearchImages[1];
336	return this->findExportedSymbolInDependentImagesExcept(name, &dontSearchImages[0], cur, &dontSearchImages[imageCount], foundIn);
337}
338
339const ImageLoader::Symbol* ImageLoader::findExportedSymbolInImageOrDependentImages(const char* name, const LinkContext& context, const ImageLoader** foundIn) const
340{
341	unsigned int imageCount = context.imageCount();
342	const ImageLoader* dontSearchImages[imageCount];
343	const ImageLoader** cur = &dontSearchImages[0];
344	return this->findExportedSymbolInDependentImagesExcept(name, &dontSearchImages[0], cur, &dontSearchImages[imageCount], foundIn);
345}
346
347// this is called by initializeMainExecutable() to interpose on the initial set of images
348void ImageLoader::applyInterposing(const LinkContext& context)
349{
350	if ( fgInterposingTuples.size() != 0 )
351		this->recursiveApplyInterposing(context);
352}
353
354void ImageLoader::link(const LinkContext& context, bool forceLazysBound, bool preflightOnly, bool neverUnload, const RPathChain& loaderRPaths)
355{
356	//dyld::log("ImageLoader::link(%s) refCount=%d, neverUnload=%d\n", this->getPath(), fDlopenReferenceCount, fNeverUnload);
357
358	// clear error strings
359	(*context.setErrorStrings)(dyld_error_kind_none, NULL, NULL, NULL);
360
361	uint64_t t0 = mach_absolute_time();
362	this->recursiveLoadLibraries(context, preflightOnly, loaderRPaths);
363	context.notifyBatch(dyld_image_state_dependents_mapped);
364
365	// we only do the loading step for preflights
366	if ( preflightOnly )
367		return;
368
369	uint64_t t1 = mach_absolute_time();
370	context.clearAllDepths();
371	this->recursiveUpdateDepth(context.imageCount());
372
373	uint64_t t2 = mach_absolute_time();
374 	this->recursiveRebase(context);
375	context.notifyBatch(dyld_image_state_rebased);
376
377	uint64_t t3 = mach_absolute_time();
378 	this->recursiveBind(context, forceLazysBound, neverUnload);
379
380	uint64_t t4 = mach_absolute_time();
381	if ( !context.linkingMainExecutable )
382		this->weakBind(context);
383	uint64_t t5 = mach_absolute_time();
384
385	context.notifyBatch(dyld_image_state_bound);
386	uint64_t t6 = mach_absolute_time();
387
388	std::vector<DOFInfo> dofs;
389	this->recursiveGetDOFSections(context, dofs);
390	context.registerDOFs(dofs);
391	uint64_t t7 = mach_absolute_time();
392
393	// interpose any dynamically loaded images
394	if ( !context.linkingMainExecutable && (fgInterposingTuples.size() != 0) ) {
395		this->recursiveApplyInterposing(context);
396	}
397
398	// clear error strings
399	(*context.setErrorStrings)(dyld_error_kind_none, NULL, NULL, NULL);
400
401	fgTotalLoadLibrariesTime += t1 - t0;
402	fgTotalRebaseTime += t3 - t2;
403	fgTotalBindTime += t4 - t3;
404	fgTotalWeakBindTime += t5 - t4;
405	fgTotalDOF += t7 - t6;
406
407	// done with initial dylib loads
408	fgNextPIEDylibAddress = 0;
409}
410
411
412void ImageLoader::printReferenceCounts()
413{
414	dyld::log("      dlopen=%d for %s\n", fDlopenReferenceCount, getPath() );
415}
416
417
418bool ImageLoader::decrementDlopenReferenceCount()
419{
420	if ( fDlopenReferenceCount == 0 )
421		return true;
422	--fDlopenReferenceCount;
423	return false;
424}
425
426void ImageLoader::runInitializers(const LinkContext& context, InitializerTimingList& timingInfo)
427{
428	uint64_t t1 = mach_absolute_time();
429	mach_port_t this_thread = mach_thread_self();
430	this->recursiveInitialization(context, this_thread, timingInfo);
431	context.notifyBatch(dyld_image_state_initialized);
432	mach_port_deallocate(mach_task_self(), this_thread);
433	uint64_t t2 = mach_absolute_time();
434	fgTotalInitTime += (t2 - t1);
435}
436
437
438void ImageLoader::bindAllLazyPointers(const LinkContext& context, bool recursive)
439{
440	if ( ! fAllLazyPointersBound ) {
441		fAllLazyPointersBound = true;
442
443		if ( recursive ) {
444			// bind lower level libraries first
445			for(unsigned int i=0; i < libraryCount(); ++i) {
446				ImageLoader* dependentImage = libImage(i);
447				if ( dependentImage != NULL )
448					dependentImage->bindAllLazyPointers(context, recursive);
449			}
450		}
451		// bind lazies in this image
452		this->doBindJustLazies(context);
453	}
454}
455
456
457bool ImageLoader::allDependentLibrariesAsWhenPreBound() const
458{
459	return fAllLibraryChecksumsAndLoadAddressesMatch;
460}
461
462
463void ImageLoader::markedUsedRecursive(const std::vector<DynamicReference>& dynamicReferences)
464{
465	// already visited here
466	if ( fMarkedInUse )
467		return;
468	fMarkedInUse = true;
469
470	// clear mark on all statically dependent dylibs
471	for(unsigned int i=0; i < libraryCount(); ++i) {
472		ImageLoader* dependentImage = libImage(i);
473		if ( dependentImage != NULL ) {
474			dependentImage->markedUsedRecursive(dynamicReferences);
475		}
476	}
477
478	// clear mark on all dynamically dependent dylibs
479	for (std::vector<ImageLoader::DynamicReference>::const_iterator it=dynamicReferences.begin(); it != dynamicReferences.end(); ++it) {
480		if ( it->from == this )
481			it->to->markedUsedRecursive(dynamicReferences);
482	}
483
484}
485
486unsigned int ImageLoader::recursiveUpdateDepth(unsigned int maxDepth)
487{
488	// the purpose of this phase is to make the images sortable such that
489	// in a sort list of images, every image that an image depends on
490	// occurs in the list before it.
491	if ( fDepth == 0 ) {
492		// break cycles
493		fDepth = maxDepth;
494
495		// get depth of dependents
496		unsigned int minDependentDepth = maxDepth;
497		for(unsigned int i=0; i < libraryCount(); ++i) {
498			ImageLoader* dependentImage = libImage(i);
499			if ( (dependentImage != NULL) && !libIsUpward(i) ) {
500				unsigned int d = dependentImage->recursiveUpdateDepth(maxDepth);
501				if ( d < minDependentDepth )
502					minDependentDepth = d;
503			}
504		}
505
506		// make me less deep then all my dependents
507		fDepth = minDependentDepth - 1;
508	}
509
510	return fDepth;
511}
512
513
514void ImageLoader::recursiveLoadLibraries(const LinkContext& context, bool preflightOnly, const RPathChain& loaderRPaths)
515{
516	if ( fState < dyld_image_state_dependents_mapped ) {
517		// break cycles
518		fState = dyld_image_state_dependents_mapped;
519
520		// get list of libraries this image needs
521		//dyld::log("ImageLoader::recursiveLoadLibraries() %ld = %d*%ld\n", fLibrariesCount*sizeof(DependentLibrary), fLibrariesCount, sizeof(DependentLibrary));
522		DependentLibraryInfo libraryInfos[fLibraryCount];
523		this->doGetDependentLibraries(libraryInfos);
524
525		// get list of rpaths that this image adds
526		std::vector<const char*> rpathsFromThisImage;
527		this->getRPaths(context, rpathsFromThisImage);
528		const RPathChain thisRPaths(&loaderRPaths, &rpathsFromThisImage);
529
530		// try to load each
531		bool canUsePrelinkingInfo = true;
532		for(unsigned int i=0; i < fLibraryCount; ++i){
533			ImageLoader* dependentLib;
534			bool depLibReExported = false;
535			bool depLibReRequired = false;
536			bool depLibCheckSumsMatch = false;
537			DependentLibraryInfo& requiredLibInfo = libraryInfos[i];
538#if DYLD_SHARED_CACHE_SUPPORT
539			if ( preflightOnly && context.inSharedCache(requiredLibInfo.name) ) {
540				// <rdar://problem/5910137> dlopen_preflight() on image in shared cache leaves it loaded but not objc initialized
541				// in preflight mode, don't even load dylib that are in the shared cache because they will never be unloaded
542				setLibImage(i, NULL, false, false);
543				continue;
544			}
545#endif
546			try {
547				dependentLib = context.loadLibrary(requiredLibInfo.name, true, this->getPath(), &thisRPaths);
548				if ( dependentLib == this ) {
549					// found circular reference, perhaps DYLD_LIBARY_PATH is causing this rdar://problem/3684168
550					dependentLib = context.loadLibrary(requiredLibInfo.name, false, NULL, NULL);
551					if ( dependentLib != this )
552						dyld::warn("DYLD_ setting caused circular dependency in %s\n", this->getPath());
553				}
554				if ( fNeverUnload )
555					dependentLib->setNeverUnload();
556				if ( requiredLibInfo.upward ) {
557				}
558				else {
559					dependentLib->fIsReferencedDownward = true;
560				}
561				LibraryInfo actualInfo = dependentLib->doGetLibraryInfo();
562				depLibReRequired = requiredLibInfo.required;
563				depLibCheckSumsMatch = ( actualInfo.checksum == requiredLibInfo.info.checksum );
564				depLibReExported = requiredLibInfo.reExported;
565				if ( ! depLibReExported ) {
566					// for pre-10.5 binaries that did not use LC_REEXPORT_DYLIB
567					depLibReExported = dependentLib->isSubframeworkOf(context, this) || this->hasSubLibrary(context, dependentLib);
568				}
569				// check found library version is compatible
570				// <rdar://problem/89200806> 0xFFFFFFFF is wildcard that matches any version
571				if ( (requiredLibInfo.info.minVersion != 0xFFFFFFFF) && (actualInfo.minVersion < requiredLibInfo.info.minVersion) ) {
572					// record values for possible use by CrashReporter or Finder
573					dyld::throwf("Incompatible library version: %s requires version %d.%d.%d or later, but %s provides version %d.%d.%d",
574							this->getShortName(), requiredLibInfo.info.minVersion >> 16, (requiredLibInfo.info.minVersion >> 8) & 0xff, requiredLibInfo.info.minVersion & 0xff,
575							dependentLib->getShortName(), actualInfo.minVersion >> 16, (actualInfo.minVersion >> 8) & 0xff, actualInfo.minVersion & 0xff);
576				}
577				// prebinding for this image disabled if any dependent library changed
578				if ( !depLibCheckSumsMatch )
579					canUsePrelinkingInfo = false;
580				// prebinding for this image disabled unless both this and dependent are in the shared cache
581				if ( !dependentLib->inSharedCache() || !this->inSharedCache() )
582					canUsePrelinkingInfo = false;
583
584				//if ( context.verbosePrebinding ) {
585				//	if ( !requiredLib.checksumMatches )
586				//		fprintf(stderr, "dyld: checksum mismatch, (%u v %u) for %s referencing %s\n",
587				//			requiredLibInfo.info.checksum, actualInfo.checksum, this->getPath(), 	dependentLib->getPath());
588				//	if ( dependentLib->getSlide() != 0 )
589				//		fprintf(stderr, "dyld: dependent library slid for %s referencing %s\n", this->getPath(), dependentLib->getPath());
590				//}
591			}
592			catch (const char* msg) {
593				//if ( context.verbosePrebinding )
594				//	fprintf(stderr, "dyld: exception during processing for %s referencing %s\n", this->getPath(), dependentLib->getPath());
595				if ( requiredLibInfo.required ) {
596					fState = dyld_image_state_mapped;
597					// record values for possible use by CrashReporter or Finder
598					if ( strstr(msg, "Incompatible") != NULL )
599						(*context.setErrorStrings)(dyld_error_kind_dylib_version, this->getPath(), requiredLibInfo.name, NULL);
600					else if ( strstr(msg, "architecture") != NULL )
601						(*context.setErrorStrings)(dyld_error_kind_dylib_wrong_arch, this->getPath(), requiredLibInfo.name, NULL);
602					else
603						(*context.setErrorStrings)(dyld_error_kind_dylib_missing, this->getPath(), requiredLibInfo.name, NULL);
604					dyld::throwf("Library not loaded: %s\n  Referenced from: %s\n  Reason: %s", requiredLibInfo.name, this->getRealPath(), msg);
605				}
606				// ok if weak library not found
607				dependentLib = NULL;
608				canUsePrelinkingInfo = false;  // this disables all prebinding, we may want to just slam import vectors for this lib to zero
609			}
610			setLibImage(i, dependentLib, depLibReExported, requiredLibInfo.upward);
611		}
612		fAllLibraryChecksumsAndLoadAddressesMatch = canUsePrelinkingInfo;
613
614		// tell each to load its dependents
615		for(unsigned int i=0; i < libraryCount(); ++i) {
616			ImageLoader* dependentImage = libImage(i);
617			if ( dependentImage != NULL ) {
618				dependentImage->recursiveLoadLibraries(context, preflightOnly, thisRPaths);
619			}
620		}
621
622		// do deep prebind check
623		if ( fAllLibraryChecksumsAndLoadAddressesMatch ) {
624			for(unsigned int i=0; i < libraryCount(); ++i){
625				ImageLoader* dependentImage = libImage(i);
626				if ( dependentImage != NULL ) {
627					if ( !dependentImage->allDependentLibrariesAsWhenPreBound() )
628						fAllLibraryChecksumsAndLoadAddressesMatch = false;
629				}
630			}
631		}
632
633		// free rpaths (getRPaths() malloc'ed each string)
634		for(std::vector<const char*>::iterator it=rpathsFromThisImage.begin(); it != rpathsFromThisImage.end(); ++it) {
635			const char* str = *it;
636			free((void*)str);
637		}
638
639	}
640}
641
642void ImageLoader::recursiveRebase(const LinkContext& context)
643{
644	if ( fState < dyld_image_state_rebased ) {
645		// break cycles
646		fState = dyld_image_state_rebased;
647
648		try {
649			// rebase lower level libraries first
650			for(unsigned int i=0; i < libraryCount(); ++i) {
651				ImageLoader* dependentImage = libImage(i);
652				if ( dependentImage != NULL )
653					dependentImage->recursiveRebase(context);
654			}
655
656			// rebase this image
657			doRebase(context);
658
659			// notify
660			context.notifySingle(dyld_image_state_rebased, this);
661		}
662		catch (const char* msg) {
663			// this image is not rebased
664			fState = dyld_image_state_dependents_mapped;
665            CRSetCrashLogMessage2(NULL);
666			throw;
667		}
668	}
669}
670
671void ImageLoader::recursiveApplyInterposing(const LinkContext& context)
672{
673	if ( ! fInterposed ) {
674		// break cycles
675		fInterposed = true;
676
677		try {
678			// interpose lower level libraries first
679			for(unsigned int i=0; i < libraryCount(); ++i) {
680				ImageLoader* dependentImage = libImage(i);
681				if ( dependentImage != NULL )
682					dependentImage->recursiveApplyInterposing(context);
683			}
684
685			// interpose this image
686			doInterpose(context);
687		}
688		catch (const char* msg) {
689			// this image is not interposed
690			fInterposed = false;
691			throw;
692		}
693	}
694}
695
696
697
698void ImageLoader::recursiveBind(const LinkContext& context, bool forceLazysBound, bool neverUnload)
699{
700	// Normally just non-lazy pointers are bound immediately.
701	// The exceptions are:
702	//   1) DYLD_BIND_AT_LAUNCH will cause lazy pointers to be bound immediately
703	//   2) some API's (e.g. RTLD_NOW) can cause lazy pointers to be bound immediately
704	if ( fState < dyld_image_state_bound ) {
705		// break cycles
706		fState = dyld_image_state_bound;
707
708		try {
709			// bind lower level libraries first
710			for(unsigned int i=0; i < libraryCount(); ++i) {
711				ImageLoader* dependentImage = libImage(i);
712				if ( dependentImage != NULL )
713					dependentImage->recursiveBind(context, forceLazysBound, neverUnload);
714			}
715			// bind this image
716			this->doBind(context, forceLazysBound);
717			// mark if lazys are also bound
718			if ( forceLazysBound || this->usablePrebinding(context) )
719				fAllLazyPointersBound = true;
720			// mark as never-unload if requested
721			if ( neverUnload )
722				this->setNeverUnload();
723
724			context.notifySingle(dyld_image_state_bound, this);
725		}
726		catch (const char* msg) {
727			// restore state
728			fState = dyld_image_state_rebased;
729            CRSetCrashLogMessage2(NULL);
730			throw;
731		}
732	}
733}
734
735void ImageLoader::weakBind(const LinkContext& context)
736{
737	if ( context.verboseWeakBind )
738		dyld::log("dyld: weak bind start:\n");
739	uint64_t t1 = mach_absolute_time();
740	// get set of ImageLoaders that participate in coalecsing
741	ImageLoader* imagesNeedingCoalescing[fgImagesRequiringCoalescing];
742	int count = context.getCoalescedImages(imagesNeedingCoalescing);
743
744	// count how many have not already had weakbinding done
745	int countNotYetWeakBound = 0;
746	int countOfImagesWithWeakDefinitions = 0;
747	int countOfImagesWithWeakDefinitionsNotInSharedCache = 0;
748	for(int i=0; i < count; ++i) {
749		if ( ! imagesNeedingCoalescing[i]->fWeakSymbolsBound )
750			++countNotYetWeakBound;
751		if ( imagesNeedingCoalescing[i]->hasCoalescedExports() ) {
752			++countOfImagesWithWeakDefinitions;
753			if ( ! imagesNeedingCoalescing[i]->inSharedCache() )
754				++countOfImagesWithWeakDefinitionsNotInSharedCache;
755		}
756	}
757
758	// don't need to do any coalescing if only one image has overrides, or all have already been done
759	if ( (countOfImagesWithWeakDefinitionsNotInSharedCache > 0) && (countNotYetWeakBound > 0) ) {
760		// make symbol iterators for each
761		ImageLoader::CoalIterator iterators[count];
762		ImageLoader::CoalIterator* sortedIts[count];
763		for(int i=0; i < count; ++i) {
764			imagesNeedingCoalescing[i]->initializeCoalIterator(iterators[i], i);
765			sortedIts[i] = &iterators[i];
766			if ( context.verboseWeakBind )
767				dyld::log("dyld: weak bind load order %d/%d for %s\n", i, count, imagesNeedingCoalescing[i]->getPath());
768		}
769
770		// walk all symbols keeping iterators in sync by
771		// only ever incrementing the iterator with the lowest symbol
772		int doneCount = 0;
773		while ( doneCount != count ) {
774			//for(int i=0; i < count; ++i)
775			//	dyld::log("sym[%d]=%s ", sortedIts[i]->loadOrder, sortedIts[i]->symbolName);
776			//dyld::log("\n");
777			// increment iterator with lowest symbol
778			if ( sortedIts[0]->image->incrementCoalIterator(*sortedIts[0]) )
779				++doneCount;
780			// re-sort iterators
781			for(int i=1; i < count; ++i) {
782				int result = strcmp(sortedIts[i-1]->symbolName, sortedIts[i]->symbolName);
783				if ( result == 0 )
784					sortedIts[i-1]->symbolMatches = true;
785				if ( result > 0 ) {
786					// new one is bigger then next, so swap
787					ImageLoader::CoalIterator* temp = sortedIts[i-1];
788					sortedIts[i-1] = sortedIts[i];
789					sortedIts[i] = temp;
790				}
791				if ( result < 0 )
792					break;
793			}
794			// process all matching symbols just before incrementing the lowest one that matches
795			if ( sortedIts[0]->symbolMatches && !sortedIts[0]->done ) {
796				const char* nameToCoalesce = sortedIts[0]->symbolName;
797				// pick first symbol in load order (and non-weak overrides weak)
798				uintptr_t targetAddr = 0;
799				ImageLoader* targetImage = NULL;
800				for(int i=0; i < count; ++i) {
801					if ( strcmp(iterators[i].symbolName, nameToCoalesce) == 0 ) {
802						if ( context.verboseWeakBind )
803							dyld::log("dyld: weak bind, found %s weak=%d in %s \n", nameToCoalesce, iterators[i].weakSymbol, iterators[i].image->getPath());
804						if ( iterators[i].weakSymbol ) {
805							if ( targetAddr == 0 ) {
806								targetAddr = iterators[i].image->getAddressCoalIterator(iterators[i], context);
807								if ( targetAddr != 0 )
808									targetImage = iterators[i].image;
809							}
810						}
811						else {
812							targetAddr = iterators[i].image->getAddressCoalIterator(iterators[i], context);
813							if ( targetAddr != 0 ) {
814								targetImage = iterators[i].image;
815								// strong implementation found, stop searching
816								break;
817							}
818						}
819					}
820				}
821				if ( context.verboseWeakBind )
822					dyld::log("dyld: weak binding all uses of %s to copy from %s\n", nameToCoalesce, targetImage->getShortName());
823
824				// tell each to bind to this symbol (unless already bound)
825				if ( targetAddr != 0 ) {
826					for(int i=0; i < count; ++i) {
827						if ( strcmp(iterators[i].symbolName, nameToCoalesce) == 0 ) {
828							if ( context.verboseWeakBind )
829								dyld::log("dyld: weak bind, setting all uses of %s in %s to 0x%lX from %s\n", nameToCoalesce, iterators[i].image->getShortName(), targetAddr, targetImage->getShortName());
830							if ( ! iterators[i].image->fWeakSymbolsBound )
831								iterators[i].image->updateUsesCoalIterator(iterators[i], targetAddr, targetImage, context);
832							iterators[i].symbolMatches = false;
833						}
834					}
835				}
836
837			}
838		}
839
840		// mark all as having all weak symbols bound
841		for(int i=0; i < count; ++i) {
842			imagesNeedingCoalescing[i]->fWeakSymbolsBound = true;
843		}
844	}
845	uint64_t t2 = mach_absolute_time();
846	fgTotalWeakBindTime += t2  - t1;
847
848	if ( context.verboseWeakBind )
849		dyld::log("dyld: weak bind end\n");
850}
851
852
853
854void ImageLoader::recursiveGetDOFSections(const LinkContext& context, std::vector<DOFInfo>& dofs)
855{
856	if ( ! fRegisteredDOF ) {
857		// break cycles
858		fRegisteredDOF = true;
859
860		// gather lower level libraries first
861		for(unsigned int i=0; i < libraryCount(); ++i) {
862			ImageLoader* dependentImage = libImage(i);
863			if ( dependentImage != NULL )
864				dependentImage->recursiveGetDOFSections(context, dofs);
865		}
866		this->doGetDOFSections(context, dofs);
867	}
868}
869
870void ImageLoader::setNeverUnloadRecursive() {
871	if ( ! fNeverUnload ) {
872		// break cycles
873		fNeverUnload = true;
874
875		// gather lower level libraries first
876		for(unsigned int i=0; i < libraryCount(); ++i) {
877			ImageLoader* dependentImage = libImage(i);
878			if ( dependentImage != NULL )
879				dependentImage->setNeverUnloadRecursive();
880		}
881	}
882}
883
884void ImageLoader::recursiveSpinLock(recursive_lock& rlock)
885{
886	// try to set image's ivar fInitializerRecursiveLock to point to this lock_info
887	// keep trying until success (spin)
888	while ( ! OSAtomicCompareAndSwapPtrBarrier(NULL, &rlock, (void**)&fInitializerRecursiveLock) ) {
889		// if fInitializerRecursiveLock already points to a different lock_info, if it is for
890		// the same thread we are on, the increment the lock count, otherwise continue to spin
891		if ( (fInitializerRecursiveLock != NULL) && (fInitializerRecursiveLock->thread == rlock.thread) )
892			break;
893	}
894	++(fInitializerRecursiveLock->count);
895}
896
897void ImageLoader::recursiveSpinUnLock()
898{
899	if ( --(fInitializerRecursiveLock->count) == 0 )
900		fInitializerRecursiveLock = NULL;
901}
902
903
904void ImageLoader::recursiveInitialization(const LinkContext& context, mach_port_t this_thread, InitializerTimingList& timingInfo)
905{
906	recursive_lock lock_info(this_thread);
907	recursiveSpinLock(lock_info);
908
909	if ( fState < dyld_image_state_dependents_initialized-1 ) {
910		uint8_t oldState = fState;
911		// break cycles
912		fState = dyld_image_state_dependents_initialized-1;
913		try {
914			bool hasUpwards = false;
915			// initialize lower level libraries first
916			for(unsigned int i=0; i < libraryCount(); ++i) {
917				ImageLoader* dependentImage = libImage(i);
918				if ( dependentImage != NULL ) {
919					// don't try to initialize stuff "above" me
920					bool isUpward = libIsUpward(i);
921					if ( (dependentImage->fDepth >= fDepth) && !isUpward ) {
922						dependentImage->recursiveInitialization(context, this_thread, timingInfo);
923					}
924					hasUpwards |= isUpward;
925                }
926			}
927
928			// record termination order
929			if ( this->needsTermination() )
930				context.terminationRecorder(this);
931
932			// let objc know we are about to initialize this image
933			uint64_t t1 = mach_absolute_time();
934			fState = dyld_image_state_dependents_initialized;
935			oldState = fState;
936			context.notifySingle(dyld_image_state_dependents_initialized, this);
937
938			// initialize this image
939			bool hasInitializers = this->doInitialization(context);
940
941			// <rdar://problem/10491874> initialize any upward depedencies
942			if ( hasUpwards ) {
943				for(unsigned int i=0; i < libraryCount(); ++i) {
944					ImageLoader* dependentImage = libImage(i);
945					// <rdar://problem/10643239> ObjC CG hang
946					// only init upward lib here if lib is not downwardly referenced somewhere
947					if ( (dependentImage != NULL) && libIsUpward(i) && !dependentImage->isReferencedDownward() ) {
948						dependentImage->recursiveInitialization(context, this_thread, timingInfo);
949					}
950				}
951			}
952
953			// let anyone know we finished initializing this image
954			fState = dyld_image_state_initialized;
955			oldState = fState;
956			context.notifySingle(dyld_image_state_initialized, this);
957
958			if ( hasInitializers ) {
959				uint64_t t2 = mach_absolute_time();
960				timingInfo.images[timingInfo.count].image = this;
961				timingInfo.images[timingInfo.count].initTime = (t2-t1);
962				timingInfo.count++;
963			}
964		}
965		catch (const char* msg) {
966			// this image is not initialized
967			fState = oldState;
968			recursiveSpinUnLock();
969			throw;
970		}
971	}
972
973	recursiveSpinUnLock();
974}
975
976
977static void printTime(const char* msg, uint64_t partTime, uint64_t totalTime)
978{
979	static uint64_t sUnitsPerSecond = 0;
980	if ( sUnitsPerSecond == 0 ) {
981		struct mach_timebase_info timeBaseInfo;
982		if ( mach_timebase_info(&timeBaseInfo) == KERN_SUCCESS ) {
983			sUnitsPerSecond = 1000000000ULL * timeBaseInfo.denom / timeBaseInfo.numer;
984		}
985	}
986	if ( partTime < sUnitsPerSecond ) {
987		uint32_t milliSecondsTimesHundred = (partTime*100000)/sUnitsPerSecond;
988		uint32_t milliSeconds = milliSecondsTimesHundred/100;
989		uint32_t percentTimesTen = (partTime*1000)/totalTime;
990		uint32_t percent = percentTimesTen/10;
991		dyld::log("%s: %u.%02u milliseconds (%u.%u%%)\n", msg, milliSeconds, milliSecondsTimesHundred-milliSeconds*100, percent, percentTimesTen-percent*10);
992	}
993	else {
994		uint32_t secondsTimeTen = (partTime*10)/sUnitsPerSecond;
995		uint32_t seconds = secondsTimeTen/10;
996		uint32_t percentTimesTen = (partTime*1000)/totalTime;
997		uint32_t percent = percentTimesTen/10;
998		dyld::log("%s: %u.%u seconds (%u.%u%%)\n", msg, seconds, secondsTimeTen-seconds*10, percent, percentTimesTen-percent*10);
999	}
1000}
1001
1002static char* commatize(uint64_t in, char* out)
1003{
1004	uint64_t div10 = in / 10;
1005	uint8_t delta = in - div10*10;
1006	char* s = &out[32];
1007	int digitCount = 1;
1008	*s = '\0';
1009	*(--s) = '0' + delta;
1010	in = div10;
1011	while ( in != 0 ) {
1012		if ( (digitCount % 3) == 0 )
1013			*(--s) = ',';
1014		div10 = in / 10;
1015		delta = in - div10*10;
1016		*(--s) = '0' + delta;
1017		in = div10;
1018		++digitCount;
1019	}
1020	return s;
1021}
1022
1023
1024void ImageLoader::printStatistics(unsigned int imageCount, const InitializerTimingList& timingInfo)
1025{
1026	uint64_t totalTime = fgTotalLoadLibrariesTime + fgTotalRebaseTime + fgTotalBindTime + fgTotalWeakBindTime + fgTotalDOF + fgTotalInitTime;
1027	char commaNum1[40];
1028	char commaNum2[40];
1029
1030	printTime("total time", totalTime, totalTime);
1031#if __IPHONE_OS_VERSION_MIN_REQUIRED
1032	if ( fgImagesUsedFromSharedCache != 0 )
1033		dyld::log("total images loaded:  %d (%u from dyld shared cache)\n", imageCount, fgImagesUsedFromSharedCache);
1034	else
1035		dyld::log("total images loaded:  %d\n", imageCount);
1036#else
1037	dyld::log("total images loaded:  %d (%u from dyld shared cache)\n", imageCount, fgImagesUsedFromSharedCache);
1038#endif
1039	dyld::log("total segments mapped: %u, into %llu pages with %llu pages pre-fetched\n", fgTotalSegmentsMapped, fgTotalBytesMapped/4096, fgTotalBytesPreFetched/4096);
1040	printTime("total images loading time", fgTotalLoadLibrariesTime, totalTime);
1041	printTime("total dtrace DOF registration time", fgTotalDOF, totalTime);
1042	dyld::log("total rebase fixups:  %s\n", commatize(fgTotalRebaseFixups, commaNum1));
1043	printTime("total rebase fixups time", fgTotalRebaseTime, totalTime);
1044	dyld::log("total binding fixups: %s\n", commatize(fgTotalBindFixups, commaNum1));
1045	if ( fgTotalBindSymbolsResolved != 0 ) {
1046		uint32_t avgTimesTen = (fgTotalBindImageSearches * 10) / fgTotalBindSymbolsResolved;
1047		uint32_t avgInt = fgTotalBindImageSearches / fgTotalBindSymbolsResolved;
1048		uint32_t avgTenths = avgTimesTen - (avgInt*10);
1049		dyld::log("total binding symbol lookups: %s, average images searched per symbol: %u.%u\n",
1050				commatize(fgTotalBindSymbolsResolved, commaNum1), avgInt, avgTenths);
1051	}
1052	printTime("total binding fixups time", fgTotalBindTime, totalTime);
1053	printTime("total weak binding fixups time", fgTotalWeakBindTime, totalTime);
1054	dyld::log("total bindings lazily fixed up: %s of %s\n", commatize(fgTotalLazyBindFixups, commaNum1), commatize(fgTotalPossibleLazyBindFixups, commaNum2));
1055	printTime("total initializer time", fgTotalInitTime, totalTime);
1056	for (uintptr_t i=0; i < timingInfo.count; ++i) {
1057		dyld::log("%21s ", timingInfo.images[i].image->getShortName());
1058		printTime("", timingInfo.images[i].initTime, totalTime);
1059	}
1060
1061}
1062
1063
1064//
1065// copy path and add suffix to result
1066//
1067//  /path/foo.dylib		_debug   =>   /path/foo_debug.dylib
1068//  foo.dylib			_debug   =>   foo_debug.dylib
1069//  foo     			_debug   =>   foo_debug
1070//  /path/bar			_debug   =>   /path/bar_debug
1071//  /path/bar.A.dylib   _debug   =>   /path/bar.A_debug.dylib
1072//
1073void ImageLoader::addSuffix(const char* path, const char* suffix, char* result)
1074{
1075	strcpy(result, path);
1076
1077	char* start = strrchr(result, '/');
1078	if ( start != NULL )
1079		start++;
1080	else
1081		start = result;
1082
1083	char* dot = strrchr(start, '.');
1084	if ( dot != NULL ) {
1085		strcpy(dot, suffix);
1086		strcat(&dot[strlen(suffix)], &path[dot-result]);
1087	}
1088	else {
1089		strcat(result, suffix);
1090	}
1091}
1092
1093
1094VECTOR_NEVER_DESTRUCTED_IMPL(ImageLoader::InterposeTuple);
1095VECTOR_NEVER_DESTRUCTED_IMPL(ImagePair);
1096
1097
1098
1099