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
26#ifndef __IMAGELOADER__
27#define __IMAGELOADER__
28
29#include <sys/types.h>
30#include <unistd.h>
31#include <stdlib.h>
32#include <mach/mach_time.h> // struct mach_timebase_info
33#include <mach/mach_init.h> // struct mach_thread_self
34#include <mach/shared_region.h>
35#include <mach-o/loader.h>
36#include <mach-o/nlist.h>
37#include <stdint.h>
38#include <stdlib.h>
39#include <TargetConditionals.h>
40#include <vector>
41#include <new>
42
43#if __MAC_OS_X_VERSION_MIN_REQUIRED
44	#include <CrashReporterClient.h>
45#else
46	// work around until iOS has CrashReporterClient.h
47	#define CRSetCrashLogMessage(x)
48	#define CRSetCrashLogMessage2(x)
49#endif
50
51#define LOG_BINDINGS 0
52
53#include "mach-o/dyld_images.h"
54#include "mach-o/dyld_priv.h"
55
56#if __i386__
57	#define SHARED_REGION_BASE SHARED_REGION_BASE_I386
58	#define SHARED_REGION_SIZE SHARED_REGION_SIZE_I386
59#elif __x86_64__
60	#define SHARED_REGION_BASE SHARED_REGION_BASE_X86_64
61	#define SHARED_REGION_SIZE SHARED_REGION_SIZE_X86_64
62#elif __arm__
63	#define SHARED_REGION_BASE SHARED_REGION_BASE_ARM
64	#define SHARED_REGION_SIZE SHARED_REGION_SIZE_ARM
65#endif
66
67#ifndef EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER
68	#define EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER 0x10
69#endif
70#ifndef EXPORT_SYMBOL_FLAGS_REEXPORT
71	#define EXPORT_SYMBOL_FLAGS_REEXPORT 0x08
72#endif
73
74#ifndef LC_MAIN
75	#define LC_MAIN (0x28|LC_REQ_DYLD) /* replacement for LC_UNIXTHREAD */
76	struct entry_point_command {
77		uint32_t  cmd;	/* LC_MAIN only used in MH_EXECUTE filetypes */
78		uint32_t  cmdsize;	/* 24 */
79		uint64_t  entryoff;	/* file (__TEXT) offset of main() */
80		uint64_t  stacksize;/* if not zero, initial stack size */
81	};
82#endif
83
84#if __IPHONE_OS_VERSION_MIN_REQUIRED
85	#define SPLIT_SEG_SHARED_REGION_SUPPORT 0
86	#define SPLIT_SEG_DYLIB_SUPPORT			0
87	#define PREBOUND_IMAGE_SUPPORT			0
88	#define TEXT_RELOC_SUPPORT				__i386__
89	#define DYLD_SHARED_CACHE_SUPPORT		__arm__
90	#define SUPPORT_OLD_CRT_INITIALIZATION	0
91	#define SUPPORT_LC_DYLD_ENVIRONMENT		0
92	#define SUPPORT_VERSIONED_PATHS			0
93	#define SUPPORT_CLASSIC_MACHO			__arm__
94	#define CORESYMBOLICATION_SUPPORT		__arm__
95	#define INITIAL_IMAGE_COUNT				256
96#else
97	#define SPLIT_SEG_SHARED_REGION_SUPPORT 0
98	#define SPLIT_SEG_DYLIB_SUPPORT			__i386__
99	#define PREBOUND_IMAGE_SUPPORT			__i386__
100	#define TEXT_RELOC_SUPPORT				__i386__
101	#define DYLD_SHARED_CACHE_SUPPORT		1
102	#define SUPPORT_OLD_CRT_INITIALIZATION	__i386__
103	#define SUPPORT_LC_DYLD_ENVIRONMENT		(__i386__ || __x86_64__)
104	#define SUPPORT_VERSIONED_PATHS			1
105	#define SUPPORT_CLASSIC_MACHO			1
106	#define CORESYMBOLICATION_SUPPORT		1
107	#define INITIAL_IMAGE_COUNT				200
108#endif
109
110
111
112// <rdar://problem/13590567> optimize away dyld's initializers
113#define VECTOR_NEVER_DESTRUCTED(type) \
114	namespace std { \
115		template <> \
116		__vector_base<type, std::allocator<type> >::~__vector_base() { } \
117	}
118#define VECTOR_NEVER_DESTRUCTED_EXTERN(type) \
119       namespace std { \
120               template <> \
121               __vector_base<type, std::allocator<type> >::~__vector_base(); \
122       }
123#define VECTOR_NEVER_DESTRUCTED_IMPL(type) \
124       namespace std { \
125               template <> \
126               __vector_base<type, std::allocator<type> >::~__vector_base() { } \
127       }
128
129// utilities
130namespace dyld {
131	extern __attribute__((noreturn)) void throwf(const char* format, ...)  __attribute__((format(printf, 1, 2)));
132	extern void log(const char* format, ...)  __attribute__((format(printf, 1, 2)));
133	extern void warn(const char* format, ...)  __attribute__((format(printf, 1, 2)));
134	extern const char* mkstringf(const char* format, ...)  __attribute__((format(printf, 1, 2)));
135#if LOG_BINDINGS
136	extern void logBindings(const char* format, ...)  __attribute__((format(printf, 1, 2)));
137#endif
138}
139extern "C" 	int   vm_alloc(vm_address_t* addr, vm_size_t size, uint32_t flags);
140extern "C" 	void* xmmap(void* addr, size_t len, int prot, int flags, int fd, off_t offset);
141
142
143#if __LP64__
144	struct macho_header				: public mach_header_64  {};
145	struct macho_nlist				: public nlist_64  {};
146#else
147	struct macho_header				: public mach_header  {};
148	struct macho_nlist				: public nlist  {};
149#endif
150
151
152struct ProgramVars
153{
154	const void*		mh;
155	int*			NXArgcPtr;
156	const char***	NXArgvPtr;
157	const char***	environPtr;
158	const char**	__prognamePtr;
159};
160
161
162
163//
164// ImageLoader is an abstract base class.  To support loading a particular executable
165// file format, you make a concrete subclass of ImageLoader.
166//
167// For each executable file (dynamic shared object) in use, an ImageLoader is instantiated.
168//
169// The ImageLoader base class does the work of linking together images, but it knows nothing
170// about any particular file format.
171//
172//
173class ImageLoader {
174public:
175
176	typedef uint32_t DefinitionFlags;
177	static const DefinitionFlags kNoDefinitionOptions = 0;
178	static const DefinitionFlags kWeakDefinition = 1;
179
180	typedef uint32_t ReferenceFlags;
181	static const ReferenceFlags kNoReferenceOptions = 0;
182	static const ReferenceFlags kWeakReference = 1;
183	static const ReferenceFlags kTentativeDefinition = 2;
184
185	enum PrebindMode { kUseAllPrebinding, kUseSplitSegPrebinding, kUseAllButAppPredbinding, kUseNoPrebinding };
186	enum BindingOptions { kBindingNone, kBindingLazyPointers, kBindingNeverSetLazyPointers };
187	enum SharedRegionMode { kUseSharedRegion, kUsePrivateSharedRegion, kDontUseSharedRegion, kSharedRegionIsSharedCache };
188
189	struct Symbol;  // abstact symbol
190
191	struct MappedRegion {
192		uintptr_t	address;
193		size_t		size;
194	};
195
196	struct RPathChain {
197		RPathChain(const RPathChain* n, std::vector<const char*>* p) : next(n), paths(p) {};
198		const RPathChain*			next;
199		std::vector<const char*>*	paths;
200	};
201
202	struct DOFInfo {
203		void*				dof;
204		const mach_header*	imageHeader;
205		const char*			imageShortName;
206	};
207
208	struct DynamicReference {
209		ImageLoader* from;
210		ImageLoader* to;
211	};
212
213	struct LinkContext {
214		ImageLoader*	(*loadLibrary)(const char* libraryName, bool search, const char* origin, const RPathChain* rpaths);
215		void			(*terminationRecorder)(ImageLoader* image);
216		bool			(*flatExportFinder)(const char* name, const Symbol** sym, const ImageLoader** image);
217		bool			(*coalescedExportFinder)(const char* name, const Symbol** sym, const ImageLoader** image);
218		unsigned int	(*getCoalescedImages)(ImageLoader* images[]);
219		void			(*undefinedHandler)(const char* name);
220		MappedRegion*	(*getAllMappedRegions)(MappedRegion*);
221		void *			(*bindingHandler)(const char *, const char *, void *);
222		void			(*notifySingle)(dyld_image_states, const ImageLoader* image);
223		void			(*notifyBatch)(dyld_image_states state);
224		void			(*removeImage)(ImageLoader* image);
225		void			(*registerDOFs)(const std::vector<DOFInfo>& dofs);
226		void			(*clearAllDepths)();
227		void			(*printAllDepths)();
228		unsigned int	(*imageCount)();
229		void			(*setNewProgramVars)(const ProgramVars&);
230		bool			(*inSharedCache)(const char* path);
231		void			(*setErrorStrings)(unsigned errorCode, const char* errorClientOfDylibPath,
232										const char* errorTargetDylibPath, const char* errorSymbol);
233		ImageLoader*	(*findImageContainingAddress)(const void* addr);
234		void			(*addDynamicReference)(ImageLoader* from, ImageLoader* to);
235
236#if SUPPORT_OLD_CRT_INITIALIZATION
237		void			(*setRunInitialzersOldWay)();
238#endif
239		BindingOptions	bindingOptions;
240		int				argc;
241		const char**	argv;
242		const char**	envp;
243		const char**	apple;
244		const char*		progname;
245		ProgramVars		programVars;
246		ImageLoader*	mainExecutable;
247		const char*		imageSuffix;
248		const char**	rootPaths;
249		PrebindMode		prebindUsage;
250		SharedRegionMode sharedRegionMode;
251		bool			dyldLoadedAtSameAddressNeededBySharedCache;
252		bool			codeSigningEnforced;
253		bool			mainExecutableCodeSigned;
254		bool			preFetchDisabled;
255		bool			prebinding;
256		bool			bindFlat;
257		bool			linkingMainExecutable;
258		bool			startedInitializingMainExecutable;
259		bool			processIsRestricted;
260		bool			verboseOpts;
261		bool			verboseEnv;
262		bool			verboseMapping;
263		bool			verboseRebase;
264		bool			verboseBind;
265		bool			verboseWeakBind;
266		bool			verboseInit;
267		bool			verboseDOF;
268		bool			verbosePrebinding;
269		bool			verboseCoreSymbolication;
270		bool			verboseWarnings;
271		bool			verboseRPaths;
272		bool			verboseInterposing;
273		bool			verboseCodeSignatures;
274	};
275
276	struct CoalIterator
277	{
278		ImageLoader*	image;
279		const char*		symbolName;
280		unsigned int	loadOrder;
281		bool			weakSymbol;
282		bool			symbolMatches;
283		bool			done;
284		// the following are private to the ImageLoader subclass
285		uintptr_t		curIndex;
286		uintptr_t		endIndex;
287		uintptr_t		address;
288		uintptr_t		type;
289		uintptr_t		addend;
290	};
291
292	virtual	void			initializeCoalIterator(CoalIterator&, unsigned int loadOrder) = 0;
293	virtual	bool			incrementCoalIterator(CoalIterator&) = 0;
294	virtual	uintptr_t		getAddressCoalIterator(CoalIterator&, const LinkContext& context) = 0;
295	virtual	void			updateUsesCoalIterator(CoalIterator&, uintptr_t newAddr, ImageLoader* target, const LinkContext& context) = 0;
296
297	struct InitializerTimingList
298	{
299		uintptr_t	count;
300		struct {
301			ImageLoader*	image;
302			uint64_t		initTime;
303		}			images[1];
304	};
305
306
307										// constructor is protected, but anyone can delete an image
308	virtual								~ImageLoader();
309
310										// link() takes a newly instantiated ImageLoader and does all
311										// fixups needed to make it usable by the process
312	void								link(const LinkContext& context, bool forceLazysBound, bool preflight, bool neverUnload, const RPathChain& loaderRPaths);
313
314										// runInitializers() is normally called in link() but the main executable must
315										// run crt code before initializers
316	void								runInitializers(const LinkContext& context, InitializerTimingList& timingInfo);
317
318										// called after link() forces all lazy pointers to be bound
319	void								bindAllLazyPointers(const LinkContext& context, bool recursive);
320
321										// used by dyld to see if a requested library is already loaded (might be symlink)
322	bool								statMatch(const struct stat& stat_buf) const;
323
324										// get short name of this image
325	const char*							getShortName() const;
326
327										// get path used to load this image, not necessarily the "real" path
328	const char*							getPath() const { return fPath; }
329
330	uint32_t							getPathHash() const { return fPathHash; }
331
332										// get the "real" path for this image (e.g. no @rpath)
333	const char*							getRealPath() const;
334
335										// get path this image is intended to be placed on disk or NULL if no preferred install location
336	virtual const char*					getInstallPath() const = 0;
337
338										// image was loaded with NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME and all clients are looking for install path
339	bool								matchInstallPath() const;
340	void								setMatchInstallPath(bool);
341
342										// mark that this image's exported symbols should be ignored when linking other images (e.g. RTLD_LOCAL)
343	void								setHideExports(bool hide = true);
344
345										// check if this image's exported symbols should be ignored when linking other images
346	bool								hasHiddenExports() const;
347
348										// checks if this image is already linked into the process
349	bool								isLinked() const;
350
351										// even if image is deleted, leave segments mapped in
352	void								setLeaveMapped();
353
354										// even if image is deleted, leave segments mapped in
355	bool								leaveMapped() { return fLeaveMapped; }
356
357										// image resides in dyld shared cache
358	virtual bool						inSharedCache() const = 0;
359
360										// checks if the specifed address is within one of this image's segments
361	virtual bool						containsAddress(const void* addr) const;
362
363										// checks if the specifed symbol is within this image's symbol table
364	virtual bool						containsSymbol(const void* addr) const = 0;
365
366										// checks if the specifed address range overlaps any of this image's segments
367	virtual bool						overlapsWithAddressRange(const void* start, const void* end) const;
368
369										// adds to list of ranges of memory mapped in
370	void								getMappedRegions(MappedRegion*& region) const;
371
372										// st_mtime from stat() on file
373	time_t								lastModified() const;
374
375										// only valid for main executables, returns a pointer its entry point from LC_UNIXTHREAD
376	virtual void*						getThreadPC() const = 0;
377
378										// only valid for main executables, returns a pointer its main from LC_<MAIN
379	virtual void*						getMain() const = 0;
380
381										// dyld API's require each image to have an associated mach_header
382	virtual const struct mach_header*   machHeader() const = 0;
383
384										// dyld API's require each image to have a slide (actual load address minus preferred load address)
385	virtual uintptr_t					getSlide() const = 0;
386
387										// last address mapped by image
388	virtual const void*					getEnd() const = 0;
389
390										// image has exports that participate in runtime coalescing
391	virtual bool						hasCoalescedExports() const = 0;
392
393										// search symbol table of definitions in this image for requested name
394	virtual const Symbol*				findExportedSymbol(const char* name, bool searchReExports, const ImageLoader** foundIn) const = 0;
395
396										// gets address of implementation (code) of the specified exported symbol
397	virtual uintptr_t					getExportedSymbolAddress(const Symbol* sym, const LinkContext& context,
398													const ImageLoader* requestor=NULL, bool runResolver=false) const = 0;
399
400										// gets attributes of the specified exported symbol
401	virtual DefinitionFlags				getExportedSymbolInfo(const Symbol* sym) const = 0;
402
403										// gets name of the specified exported symbol
404	virtual const char*					getExportedSymbolName(const Symbol* sym) const = 0;
405
406										// gets how many symbols are exported by this image
407	virtual uint32_t					getExportedSymbolCount() const = 0;
408
409										// gets the i'th exported symbol
410	virtual const Symbol*				getIndexedExportedSymbol(uint32_t index) const = 0;
411
412										// find exported symbol as if imported by this image
413										// used by RTLD_NEXT
414	virtual const Symbol*				findExportedSymbolInDependentImages(const char* name, const LinkContext& context, const ImageLoader** foundIn) const;
415
416										// find exported symbol as if imported by this image
417										// used by RTLD_SELF
418	virtual const Symbol*				findExportedSymbolInImageOrDependentImages(const char* name, const LinkContext& context, const ImageLoader** foundIn) const;
419
420										// gets how many symbols are imported by this image
421	virtual uint32_t					getImportedSymbolCount() const = 0;
422
423										// gets the i'th imported symbol
424	virtual const Symbol*				getIndexedImportedSymbol(uint32_t index) const = 0;
425
426										// gets attributes of the specified imported symbol
427	virtual ReferenceFlags				getImportedSymbolInfo(const Symbol* sym) const = 0;
428
429										// gets name of the specified imported symbol
430	virtual const char*					getImportedSymbolName(const Symbol* sym) const = 0;
431
432										// find the closest symbol before addr
433	virtual const char*					findClosestSymbol(const void* addr, const void** closestAddr) const = 0;
434
435										// checks if this image is a bundle and can be loaded but not linked
436	virtual bool						isBundle() const = 0;
437
438										// checks if this image is a dylib
439	virtual bool						isDylib() const = 0;
440
441										// checks if this image is a main executable
442	virtual bool						isExecutable() const = 0;
443
444										// checks if this image is a main executable
445	virtual bool						isPositionIndependentExecutable() const = 0;
446
447										// only for main executable
448	virtual bool						forceFlat() const = 0;
449
450										// called at runtime when a lazily bound function is first called
451	virtual uintptr_t					doBindLazySymbol(uintptr_t* lazyPointer, const LinkContext& context) = 0;
452
453										// called at runtime when a fast lazily bound function is first called
454	virtual uintptr_t					doBindFastLazySymbol(uint32_t lazyBindingInfoOffset, const LinkContext& context,
455															void (*lock)(), void (*unlock)()) = 0;
456
457										// calls termination routines (e.g. C++ static destructors for image)
458	virtual void						doTermination(const LinkContext& context) = 0;
459
460										// return if this image has initialization routines
461	virtual bool						needsInitialization() = 0;
462
463										// return if this image has specified section and set start and length
464	virtual bool						getSectionContent(const char* segmentName, const char* sectionName, void** start, size_t* length) = 0;
465
466										// fills in info about __eh_frame and __unwind_info sections
467	virtual void						getUnwindInfo(dyld_unwind_sections* info) = 0;
468
469										// given a pointer into an image, find which segment and section it is in
470	virtual bool						findSection(const void* imageInterior, const char** segmentName, const char** sectionName, size_t* sectionOffset) = 0;
471
472										// the image supports being prebound
473	virtual bool						isPrebindable() const = 0;
474
475										// the image is prebindable and its prebinding is valid
476	virtual bool						usablePrebinding(const LinkContext& context) const = 0;
477
478										// add all RPATH paths this image contains
479	virtual	void						getRPaths(const LinkContext& context, std::vector<const char*>&) const = 0;
480
481										// image has or uses weak definitions that need runtime coalescing
482	virtual bool						participatesInCoalescing() const = 0;
483
484										// if image has a UUID, copy into parameter and return true
485	virtual	bool						getUUID(uuid_t) const = 0;
486
487
488//
489// A segment is a chunk of an executable file that is mapped into memory.
490//
491	virtual unsigned int				segmentCount() const = 0;
492	virtual const char*					segName(unsigned int) const = 0;
493	virtual uintptr_t					segSize(unsigned int) const = 0;
494	virtual uintptr_t					segFileSize(unsigned int) const = 0;
495	virtual bool						segHasTrailingZeroFill(unsigned int) = 0;
496	virtual uintptr_t					segFileOffset(unsigned int) const = 0;
497	virtual bool						segReadable(unsigned int) const = 0;
498	virtual bool						segWriteable(unsigned int) const = 0;
499	virtual bool						segExecutable(unsigned int) const = 0;
500	virtual bool						segUnaccessible(unsigned int) const = 0;
501	virtual bool						segHasPreferredLoadAddress(unsigned int) const = 0;
502	virtual uintptr_t					segPreferredLoadAddress(unsigned int) const = 0;
503	virtual uintptr_t					segActualLoadAddress(unsigned int) const = 0;
504	virtual uintptr_t					segActualEndAddress(unsigned int) const = 0;
505
506
507	virtual uint32_t					sdkVersion() const = 0;
508
509										// if the image contains interposing functions, register them
510	virtual void						registerInterposing() = 0;
511
512										// when resolving symbols look in subImage if symbol can't be found
513	void								reExport(ImageLoader* subImage);
514
515	void								weakBind(const LinkContext& context);
516
517	void								applyInterposing(const LinkContext& context);
518
519	dyld_image_states					getState() { return (dyld_image_states)fState; }
520
521										// used to sort images bottom-up
522	int									compare(const ImageLoader* right) const;
523
524	void								incrementDlopenReferenceCount() { ++fDlopenReferenceCount; }
525
526	bool								decrementDlopenReferenceCount();
527
528	void								printReferenceCounts();
529
530	uint32_t							dlopenCount() const { return fDlopenReferenceCount; }
531
532	void								setCanUnload() { fNeverUnload = false; fLeaveMapped = false; }
533
534	bool								neverUnload() const { return fNeverUnload; }
535
536	void								setNeverUnload() { fNeverUnload = true; fLeaveMapped = true; }
537	void								setNeverUnloadRecursive();
538
539	bool								isReferencedDownward() { return fIsReferencedDownward; }
540
541
542										// triggered by DYLD_PRINT_STATISTICS to write info on work done and how fast
543	static void							printStatistics(unsigned int imageCount, const InitializerTimingList& timingInfo);
544
545										// used with DYLD_IMAGE_SUFFIX
546	static void							addSuffix(const char* path, const char* suffix, char* result);
547
548	static uint32_t						hash(const char*);
549
550										// used instead of directly deleting image
551	static void							deleteImage(ImageLoader*);
552
553			bool						dependsOn(ImageLoader* image);
554
555 			void						setPath(const char* path);
556			void						setPaths(const char* path, const char* realPath);
557			void						setPathUnowned(const char* path);
558
559			void						clearDepth() { fDepth = 0; }
560			int							getDepth() { return fDepth; }
561
562			void						setBeingRemoved() { fBeingRemoved = true; }
563			bool						isBeingRemoved() const { return fBeingRemoved; }
564
565			void						markNotUsed() { fMarkedInUse = false; }
566			void						markedUsedRecursive(const std::vector<DynamicReference>&);
567			bool						isMarkedInUse() const	{ return fMarkedInUse; }
568
569			void						setAddFuncNotified() { fAddFuncNotified = true; }
570			bool						addFuncNotified() const { return fAddFuncNotified; }
571
572	struct InterposeTuple {
573		uintptr_t		replacement;
574		ImageLoader*	replacementImage;	// don't apply replacement to this image
575		uintptr_t		replacee;
576	};
577
578protected:
579	// abstract base class so all constructors protected
580					ImageLoader(const char* path, unsigned int libCount);
581					ImageLoader(const ImageLoader&);
582	void			operator=(const ImageLoader&);
583	void			operator delete(void* image) throw() { ::free(image); }
584
585
586	struct LibraryInfo {
587		uint32_t		checksum;
588		uint32_t		minVersion;
589		uint32_t		maxVersion;
590	};
591
592	struct DependentLibrary {
593		ImageLoader*	image;
594		uint32_t		required : 1,
595						checksumMatches : 1,
596						isReExported : 1,
597						isSubFramework : 1;
598	};
599
600	struct DependentLibraryInfo {
601		const char*			name;
602		LibraryInfo			info;
603		bool				required;
604		bool				reExported;
605		bool				upward;
606	};
607
608
609	typedef void (*Initializer)(int argc, const char* argv[], const char* envp[], const char* apple[], const ProgramVars* vars);
610	typedef void (*Terminator)(void);
611
612
613
614	unsigned int			libraryCount() const { return fLibraryCount; }
615	virtual ImageLoader*	libImage(unsigned int) const = 0;
616	virtual bool			libReExported(unsigned int) const = 0;
617	virtual bool			libIsUpward(unsigned int) const = 0;
618	virtual void			setLibImage(unsigned int, ImageLoader*, bool, bool) = 0;
619
620						// To link() an image, its dependent libraries are loaded, it is rebased, bound, and initialized.
621						// These methods do the above, exactly once, and it the right order
622	void				recursiveLoadLibraries(const LinkContext& context, bool preflightOnly, const RPathChain& loaderRPaths);
623	void				recursiveUnLoadMappedLibraries(const LinkContext& context);
624	unsigned int		recursiveUpdateDepth(unsigned int maxDepth);
625	void				recursiveValidate(const LinkContext& context);
626	void				recursiveRebase(const LinkContext& context);
627	void				recursiveBind(const LinkContext& context, bool forceLazysBound, bool neverUnload);
628	void				recursiveApplyInterposing(const LinkContext& context);
629	void				recursiveGetDOFSections(const LinkContext& context, std::vector<DOFInfo>& dofs);
630	void				recursiveInitialization(const LinkContext& context, mach_port_t this_thread, ImageLoader::InitializerTimingList&);
631
632								// fill in information about dependent libraries (array length is fLibraryCount)
633	virtual void				doGetDependentLibraries(DependentLibraryInfo libs[]) = 0;
634
635								// called on images that are libraries, returns info about itself
636	virtual LibraryInfo			doGetLibraryInfo() = 0;
637
638								// do any fix ups in this image that depend only on the load address of the image
639	virtual void				doRebase(const LinkContext& context) = 0;
640
641								// do any symbolic fix ups in this image
642	virtual void				doBind(const LinkContext& context, bool forceLazysBound) = 0;
643
644								// called later via API to force all lazy pointer to be bound
645	virtual void				doBindJustLazies(const LinkContext& context) = 0;
646
647								// if image has any dtrace DOF sections, append them to list to be registered
648	virtual void				doGetDOFSections(const LinkContext& context, std::vector<DOFInfo>& dofs) = 0;
649
650								// do interpose
651	virtual void				doInterpose(const LinkContext& context) = 0;
652
653								// run any initialization routines in this image
654	virtual bool				doInitialization(const LinkContext& context) = 0;
655
656								// return if this image has termination routines
657	virtual bool				needsTermination() = 0;
658
659								// support for runtimes in which segments don't have to maintain their relative positions
660	virtual bool				segmentsMustSlideTogether() const = 0;
661
662								// built with PIC code and can load at any address
663	virtual bool				segmentsCanSlide() const = 0;
664
665								// set how much all segments slide
666	virtual void				setSlide(intptr_t slide) = 0;
667
668								// returns if all dependent libraries checksum's were as expected and none slide
669			bool				allDependentLibrariesAsWhenPreBound() const;
670
671								// in mach-o a child tells it parent to re-export, instead of the other way around...
672	virtual	bool				isSubframeworkOf(const LinkContext& context, const ImageLoader* image) const = 0;
673
674								// in mach-o a parent library knows name of sub libraries it re-exports..
675	virtual	bool				hasSubLibrary(const LinkContext& context, const ImageLoader* child) const  = 0;
676
677								// set fState to dyld_image_state_memory_mapped
678	void						setMapped(const LinkContext& context);
679
680	void						setFileInfo(dev_t device, ino_t inode, time_t modDate);
681
682	static uintptr_t			fgNextPIEDylibAddress;
683	static uint32_t				fgImagesWithUsedPrebinding;
684	static uint32_t				fgImagesUsedFromSharedCache;
685	static uint32_t				fgImagesHasWeakDefinitions;
686	static uint32_t				fgImagesRequiringCoalescing;
687	static uint32_t				fgTotalRebaseFixups;
688	static uint32_t				fgTotalBindFixups;
689	static uint32_t				fgTotalBindSymbolsResolved;
690	static uint32_t				fgTotalBindImageSearches;
691	static uint32_t				fgTotalLazyBindFixups;
692	static uint32_t				fgTotalPossibleLazyBindFixups;
693	static uint32_t				fgTotalSegmentsMapped;
694	static uint64_t				fgTotalBytesMapped;
695	static uint64_t				fgTotalBytesPreFetched;
696	static uint64_t				fgTotalLoadLibrariesTime;
697	static uint64_t				fgTotalRebaseTime;
698	static uint64_t				fgTotalBindTime;
699	static uint64_t				fgTotalWeakBindTime;
700	static uint64_t				fgTotalDOF;
701	static uint64_t				fgTotalInitTime;
702	static std::vector<InterposeTuple>	fgInterposingTuples;
703
704	const char*					fPath;
705	const char*					fRealPath;
706	dev_t						fDevice;
707	ino_t						fInode;
708	time_t						fLastModified;
709	uint32_t					fPathHash;
710	uint32_t					fDlopenReferenceCount;	// count of how many dlopens have been done on this image
711
712private:
713	struct recursive_lock {
714						recursive_lock(mach_port_t t) : thread(t), count(0) {}
715		mach_port_t		thread;
716		int				count;
717	};
718	void						recursiveSpinLock(recursive_lock&);
719	void						recursiveSpinUnLock();
720
721	const ImageLoader::Symbol*	findExportedSymbolInDependentImagesExcept(const char* name, const ImageLoader** dsiStart,
722										const ImageLoader**& dsiCur, const ImageLoader** dsiEnd, const ImageLoader** foundIn) const;
723
724
725
726	recursive_lock*				fInitializerRecursiveLock;
727	uint16_t					fDepth;
728	uint16_t					fLoadOrder;
729	uint32_t					fState : 8,
730								fLibraryCount : 10,
731								fAllLibraryChecksumsAndLoadAddressesMatch : 1,
732								fLeaveMapped : 1,		// when unloaded, leave image mapped in cause some other code may have pointers into it
733								fNeverUnload : 1,		// image was statically loaded by main executable
734								fHideSymbols : 1,		// ignore this image's exported symbols when linking other images
735								fMatchByInstallName : 1,// look at image's install-path not its load path
736								fInterposed : 1,
737								fRegisteredDOF : 1,
738								fAllLazyPointersBound : 1,
739								fMarkedInUse : 1,
740								fBeingRemoved : 1,
741								fAddFuncNotified : 1,
742								fPathOwnedByImage : 1,
743								fIsReferencedDownward : 1,
744								fWeakSymbolsBound : 1;
745
746	static uint16_t				fgLoadOrdinal;
747};
748
749
750VECTOR_NEVER_DESTRUCTED_EXTERN(ImageLoader::InterposeTuple);
751
752
753#endif
754
755