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// work around until conformance work is complete rdar://problem/4508801
26#define __srr0	srr0
27#define __eip	eip
28#define __rip	rip
29
30#define __STDC_LIMIT_MACROS
31#include <string.h>
32#include <fcntl.h>
33#include <errno.h>
34#include <sys/types.h>
35#include <sys/fcntl.h>
36#include <sys/stat.h>
37#include <sys/mman.h>
38#include <mach/mach.h>
39#include <mach/thread_status.h>
40#include <mach-o/loader.h>
41#include <mach-o/nlist.h>
42#include <sys/sysctl.h>
43#include <sys/syscall.h>
44#include <libkern/OSAtomic.h>
45#include <libkern/OSCacheControl.h>
46#include <stdint.h>
47#include <System/sys/codesign.h>
48
49#include "ImageLoaderMachO.h"
50#include "ImageLoaderMachOCompressed.h"
51#if SUPPORT_CLASSIC_MACHO
52#include "ImageLoaderMachOClassic.h"
53#endif
54#include "mach-o/dyld_images.h"
55
56// <rdar://problem/8718137> use stack guard random value to add padding between dylibs
57extern "C" long __stack_chk_guard;
58
59#ifndef LC_LOAD_UPWARD_DYLIB
60	#define	LC_LOAD_UPWARD_DYLIB (0x23|LC_REQ_DYLD)	/* load of dylib whose initializers run later */
61#endif
62
63// relocation_info.r_length field has value 3 for 64-bit executables and value 2 for 32-bit executables
64#if __LP64__
65	#define LC_SEGMENT_COMMAND		LC_SEGMENT_64
66	#define LC_ROUTINES_COMMAND		LC_ROUTINES_64
67	#define LC_SEGMENT_COMMAND_WRONG LC_SEGMENT
68	struct macho_segment_command	: public segment_command_64  {};
69	struct macho_section			: public section_64  {};
70	struct macho_routines_command	: public routines_command_64  {};
71#else
72	#define LC_SEGMENT_COMMAND		LC_SEGMENT
73	#define LC_ROUTINES_COMMAND		LC_ROUTINES
74	#define LC_SEGMENT_COMMAND_WRONG LC_SEGMENT_64
75	struct macho_segment_command	: public segment_command {};
76	struct macho_section			: public section  {};
77	struct macho_routines_command	: public routines_command  {};
78#endif
79
80uint32_t ImageLoaderMachO::fgSymbolTableBinarySearchs = 0;
81uint32_t ImageLoaderMachO::fgSymbolTrieSearchs = 0;
82
83
84ImageLoaderMachO::ImageLoaderMachO(const macho_header* mh, const char* path, unsigned int segCount,
85																uint32_t segOffsets[], unsigned int libCount)
86 : ImageLoader(path, libCount), fMachOData((uint8_t*)mh), fLinkEditBase(NULL), fSlide(0),
87	fEHFrameSectionOffset(0), fUnwindInfoSectionOffset(0), fDylibIDOffset(0),
88	fSegmentsCount(segCount), fIsSplitSeg(false), fInSharedCache(false),
89#if TEXT_RELOC_SUPPORT
90	fTextSegmentRebases(false),
91	fTextSegmentBinds(false),
92#endif
93#if __i386__
94	fReadOnlyImportSegment(false),
95#endif
96	fHasSubLibraries(false), fHasSubUmbrella(false), fInUmbrella(false), fHasDOFSections(false), fHasDashInit(false),
97	fHasInitializers(false), fHasTerminators(false), fRegisteredAsRequiresCoalescing(false)
98{
99	fIsSplitSeg = ((mh->flags & MH_SPLIT_SEGS) != 0);
100
101	// construct SegmentMachO object for each LC_SEGMENT cmd using "placement new" to put
102	// each SegmentMachO object in array at end of ImageLoaderMachO object
103	const uint32_t cmd_count = mh->ncmds;
104	const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
105	const struct load_command* cmd = cmds;
106	for (uint32_t i = 0, segIndex=0; i < cmd_count; ++i) {
107		if ( cmd->cmd == LC_SEGMENT_COMMAND ) {
108			const struct macho_segment_command* segCmd = (struct macho_segment_command*)cmd;
109			// ignore zero-sized segments
110			if ( segCmd->vmsize != 0 ) {
111				// record offset of load command
112				segOffsets[segIndex++] = (uint8_t*)segCmd - fMachOData;
113			}
114		}
115		cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
116	}
117
118}
119
120
121// determine if this mach-o file has classic or compressed LINKEDIT and number of segments it has
122void ImageLoaderMachO::sniffLoadCommands(const macho_header* mh, const char* path, bool* compressed,
123											unsigned int* segCount, unsigned int* libCount, const LinkContext& context,
124											const linkedit_data_command** codeSigCmd)
125{
126	*compressed = false;
127	*segCount = 0;
128	*libCount = 0;
129	*codeSigCmd = NULL;
130	struct macho_segment_command* segCmd;
131	bool foundLoadCommandSegment = false;
132	uint32_t loadCommandSegmentIndex = 0xFFFFFFFF;
133	uintptr_t loadCommandSegmentVMStart = 0;
134	uintptr_t loadCommandSegmentVMEnd = 0;
135
136	const uint32_t cmd_count = mh->ncmds;
137	const struct load_command* const startCmds    = (struct load_command*)(((uint8_t*)mh) + sizeof(macho_header));
138	const struct load_command* const endCmds = (struct load_command*)(((uint8_t*)mh) + sizeof(macho_header) + mh->sizeofcmds);
139	const struct load_command* cmd = startCmds;
140	for (uint32_t i = 0; i < cmd_count; ++i) {
141		switch (cmd->cmd) {
142			case LC_DYLD_INFO:
143			case LC_DYLD_INFO_ONLY:
144				*compressed = true;
145				break;
146			case LC_SEGMENT_COMMAND:
147				segCmd = (struct macho_segment_command*)cmd;
148				// ignore zero-sized segments
149				if ( segCmd->vmsize != 0 )
150					*segCount += 1;
151				// <rdar://problem/7942521> all load commands must be in an executable segment
152				if ( context.codeSigningEnforced && (segCmd->fileoff < mh->sizeofcmds) && (segCmd->filesize != 0) ) {
153					if ( (segCmd->fileoff != 0) || (segCmd->filesize < (mh->sizeofcmds+sizeof(macho_header))) )
154						dyld::throwf("malformed mach-o image: segment %s does not span all load commands", segCmd->segname);
155					if ( segCmd->initprot != (VM_PROT_READ | VM_PROT_EXECUTE) )
156						dyld::throwf("malformed mach-o image: load commands found in segment %s with wrong permissions", segCmd->segname);
157					if ( foundLoadCommandSegment )
158						throw "load commands in multiple segments";
159					foundLoadCommandSegment = true;
160					loadCommandSegmentIndex = i;
161					loadCommandSegmentVMStart = segCmd->vmaddr;
162					loadCommandSegmentVMEnd   = segCmd->vmaddr + segCmd->vmsize;
163				}
164				break;
165			case LC_SEGMENT_COMMAND_WRONG:
166				dyld::throwf("malformed mach-o image: wrong LC_SEGMENT[_64] for architecture");
167				break;
168			case LC_LOAD_DYLIB:
169			case LC_LOAD_WEAK_DYLIB:
170			case LC_REEXPORT_DYLIB:
171			case LC_LOAD_UPWARD_DYLIB:
172				*libCount += 1;
173				break;
174			case LC_CODE_SIGNATURE:
175				*codeSigCmd = (struct linkedit_data_command*)cmd; // only support one LC_CODE_SIGNATURE per image
176				break;
177		}
178		uint32_t cmdLength = cmd->cmdsize;
179		cmd = (const struct load_command*)(((char*)cmd)+cmdLength);
180		if ( (cmd > endCmds) || (cmd < startCmds) ) {
181			dyld::throwf("malformed mach-o image: load command #%d length (%u) would exceed sizeofcmds (%u) in %s",
182							i, cmdLength, mh->sizeofcmds, path);
183		}
184	}
185
186	if ( context.codeSigningEnforced && !foundLoadCommandSegment )
187		throw "load commands not in a segment";
188	// <rdar://problem/13145644> verify another segment does not over-map load commands
189	cmd = startCmds;
190	if ( context.codeSigningEnforced ) {
191		for (uint32_t i = 0; i < cmd_count; ++i) {
192			switch (cmd->cmd) {
193				case LC_SEGMENT_COMMAND:
194					if ( i != loadCommandSegmentIndex ) {
195						segCmd = (struct macho_segment_command*)cmd;
196						uintptr_t start = segCmd->vmaddr;
197						uintptr_t end = segCmd->vmaddr + segCmd->vmsize;
198						if ( ((start <= loadCommandSegmentVMStart) && (end > loadCommandSegmentVMStart))
199						   || ((start >= loadCommandSegmentVMStart) && (start < loadCommandSegmentVMEnd)) )
200							dyld::throwf("malformed mach-o image: segment %s overlaps load commands", segCmd->segname);
201					}
202					break;
203			}
204			cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
205		}
206	}
207
208	// fSegmentsArrayCount is only 8-bits
209	if ( *segCount > 255 )
210		dyld::throwf("malformed mach-o image: more than 255 segments in %s", path);
211
212	// fSegmentsArrayCount is only 8-bits
213	if ( *libCount > 4095 )
214		dyld::throwf("malformed mach-o image: more than 4095 dependent libraries in %s", path);
215
216	if ( needsAddedLibSystemDepency(*libCount, mh) )
217		*libCount = 1;
218}
219
220
221
222// create image for main executable
223ImageLoader* ImageLoaderMachO::instantiateMainExecutable(const macho_header* mh, uintptr_t slide, const char* path, const LinkContext& context)
224{
225	//dyld::log("ImageLoader=%ld, ImageLoaderMachO=%ld, ImageLoaderMachOClassic=%ld, ImageLoaderMachOCompressed=%ld\n",
226	//	sizeof(ImageLoader), sizeof(ImageLoaderMachO), sizeof(ImageLoaderMachOClassic), sizeof(ImageLoaderMachOCompressed));
227	bool compressed;
228	unsigned int segCount;
229	unsigned int libCount;
230	const linkedit_data_command* codeSigCmd;
231	sniffLoadCommands(mh, path, &compressed, &segCount, &libCount, context, &codeSigCmd);
232	// instantiate concrete class based on content of load commands
233	if ( compressed )
234		return ImageLoaderMachOCompressed::instantiateMainExecutable(mh, slide, path, segCount, libCount, context);
235	else
236#if SUPPORT_CLASSIC_MACHO
237		return ImageLoaderMachOClassic::instantiateMainExecutable(mh, slide, path, segCount, libCount, context);
238#else
239		throw "missing LC_DYLD_INFO load command";
240#endif
241}
242
243
244// create image by mapping in a mach-o file
245ImageLoader* ImageLoaderMachO::instantiateFromFile(const char* path, int fd, const uint8_t firstPage[4096], uint64_t offsetInFat,
246									uint64_t lenInFat, const struct stat& info, const LinkContext& context)
247{
248	// get load commands
249	const unsigned int dataSize = sizeof(macho_header) + ((macho_header*)firstPage)->sizeofcmds;
250	uint8_t buffer[dataSize];
251	const uint8_t* fileData = firstPage;
252	if ( dataSize > 4096 ) {
253		// only read more if cmds take up more space than first page
254		fileData = buffer;
255		memcpy(buffer, firstPage, 4096);
256		pread(fd, &buffer[4096], dataSize-4096, offsetInFat+4096);
257	}
258
259	bool compressed;
260	unsigned int segCount;
261	unsigned int libCount;
262	const linkedit_data_command* codeSigCmd;
263	sniffLoadCommands((const macho_header*)fileData, path, &compressed, &segCount, &libCount, context, &codeSigCmd);
264	// instantiate concrete class based on content of load commands
265	if ( compressed )
266		return ImageLoaderMachOCompressed::instantiateFromFile(path, fd, fileData, offsetInFat, lenInFat, info, segCount, libCount, codeSigCmd, context);
267	else
268#if SUPPORT_CLASSIC_MACHO
269		return ImageLoaderMachOClassic::instantiateFromFile(path, fd, fileData, offsetInFat, lenInFat, info, segCount, libCount, codeSigCmd, context);
270#else
271		throw "missing LC_DYLD_INFO load command";
272#endif
273}
274
275// create image by using cached mach-o file
276ImageLoader* ImageLoaderMachO::instantiateFromCache(const macho_header* mh, const char* path, long slide, const struct stat& info, const LinkContext& context)
277{
278	// instantiate right concrete class
279	bool compressed;
280	unsigned int segCount;
281	unsigned int libCount;
282	const linkedit_data_command* codeSigCmd;
283	sniffLoadCommands(mh, path, &compressed, &segCount, &libCount, context, &codeSigCmd);
284	// instantiate concrete class based on content of load commands
285	if ( compressed )
286		return ImageLoaderMachOCompressed::instantiateFromCache(mh, path, slide, info, segCount, libCount, context);
287	else
288#if SUPPORT_CLASSIC_MACHO
289		return ImageLoaderMachOClassic::instantiateFromCache(mh, path, slide, info, segCount, libCount, context);
290#else
291		throw "missing LC_DYLD_INFO load command";
292#endif
293}
294
295// create image by copying an in-memory mach-o file
296ImageLoader* ImageLoaderMachO::instantiateFromMemory(const char* moduleName, const macho_header* mh, uint64_t len, const LinkContext& context)
297{
298	bool compressed;
299	unsigned int segCount;
300	unsigned int libCount;
301	const linkedit_data_command* sigcmd;
302	sniffLoadCommands(mh, moduleName, &compressed, &segCount, &libCount, context, &sigcmd);
303	// instantiate concrete class based on content of load commands
304	if ( compressed )
305		return ImageLoaderMachOCompressed::instantiateFromMemory(moduleName, mh, len, segCount, libCount, context);
306	else
307#if SUPPORT_CLASSIC_MACHO
308		return ImageLoaderMachOClassic::instantiateFromMemory(moduleName, mh, len, segCount, libCount, context);
309#else
310		throw "missing LC_DYLD_INFO load command";
311#endif
312}
313
314
315int ImageLoaderMachO::crashIfInvalidCodeSignature()
316{
317	// Now that segments are mapped in, try reading from first executable segment.
318	// If code signing is enabled the kernel will validate the code signature
319	// when paging in, and kill the process if invalid.
320	for(unsigned int i=0; i < fSegmentsCount; ++i) {
321		if ( (segFileOffset(i) == 0) && (segFileSize(i) != 0) ) {
322			// return read value to ensure compiler does not optimize away load
323			int* p = (int*)segActualLoadAddress(i);
324			return *p;
325		}
326	}
327	return 0;
328}
329
330
331void ImageLoaderMachO::parseLoadCmds()
332{
333	// now that segments are mapped in, get real fMachOData, fLinkEditBase, and fSlide
334	for(unsigned int i=0; i < fSegmentsCount; ++i) {
335		// set up pointer to __LINKEDIT segment
336		if ( strcmp(segName(i),"__LINKEDIT") == 0 )
337			fLinkEditBase = (uint8_t*)(segActualLoadAddress(i) - segFileOffset(i));
338#if TEXT_RELOC_SUPPORT
339		// __TEXT segment always starts at beginning of file and contains mach_header and load commands
340		if ( strcmp(segName(i),"__TEXT") == 0 ) {
341			if ( segHasRebaseFixUps(i) && (fSlide != 0) )
342				fTextSegmentRebases = true;
343			if ( segHasBindFixUps(i) )
344				fTextSegmentBinds = true;
345		}
346#endif
347#if __i386__
348		if ( segIsReadOnlyImport(i) )
349			fReadOnlyImportSegment = true;
350#endif
351		// some segment always starts at beginning of file and contains mach_header and load commands
352		if ( (segFileOffset(i) == 0) && (segFileSize(i) != 0) ) {
353			fMachOData = (uint8_t*)(segActualLoadAddress(i));
354		}
355	}
356
357	// keep count of prebound images with weak exports
358	if ( this->participatesInCoalescing() ) {
359		++fgImagesRequiringCoalescing;
360		fRegisteredAsRequiresCoalescing = true;
361		if ( this->hasCoalescedExports() )
362			++fgImagesHasWeakDefinitions;
363	}
364
365	// keep count of images used in shared cache
366	if ( fInSharedCache )
367		++fgImagesUsedFromSharedCache;
368
369	// walk load commands (mapped in at start of __TEXT segment)
370	const dyld_info_command* dyldInfo = NULL;
371	const macho_nlist* symbolTable = NULL;
372	const char* symbolTableStrings = NULL;
373	const struct load_command* firstUnknownCmd = NULL;
374	const struct version_min_command* minOSVersionCmd = NULL;
375	const dysymtab_command* dynSymbolTable = NULL;
376	const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
377	const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
378	const struct load_command* cmd = cmds;
379	for (uint32_t i = 0; i < cmd_count; ++i) {
380		switch (cmd->cmd) {
381			case LC_SYMTAB:
382				{
383					const struct symtab_command* symtab = (struct symtab_command*)cmd;
384					symbolTableStrings = (const char*)&fLinkEditBase[symtab->stroff];
385					symbolTable = (macho_nlist*)(&fLinkEditBase[symtab->symoff]);
386				}
387				break;
388			case LC_DYSYMTAB:
389				dynSymbolTable = (struct dysymtab_command*)cmd;
390				break;
391			case LC_SUB_UMBRELLA:
392				fHasSubUmbrella = true;
393				break;
394			case LC_SUB_FRAMEWORK:
395				fInUmbrella = true;
396				break;
397			case LC_SUB_LIBRARY:
398				fHasSubLibraries = true;
399				break;
400			case LC_ROUTINES_COMMAND:
401				fHasDashInit = true;
402				break;
403			case LC_DYLD_INFO:
404			case LC_DYLD_INFO_ONLY:
405				dyldInfo = (struct dyld_info_command*)cmd;
406				break;
407			case LC_SEGMENT_COMMAND:
408				{
409					const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
410					const bool isTextSeg = (strcmp(seg->segname, "__TEXT") == 0);
411					const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
412					const struct macho_section* const sectionsEnd = &sectionsStart[seg->nsects];
413					for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
414						const uint8_t type = sect->flags & SECTION_TYPE;
415						if ( type == S_MOD_INIT_FUNC_POINTERS )
416							fHasInitializers = true;
417						else if ( type == S_MOD_TERM_FUNC_POINTERS )
418							fHasTerminators = true;
419						else if ( type == S_DTRACE_DOF )
420							fHasDOFSections = true;
421						else if ( isTextSeg && (strcmp(sect->sectname, "__eh_frame") == 0) )
422							fEHFrameSectionOffset = (uint8_t*)sect - fMachOData;
423						else if ( isTextSeg && (strcmp(sect->sectname, "__unwind_info") == 0) )
424							fUnwindInfoSectionOffset = (uint8_t*)sect - fMachOData;;
425					}
426				}
427				break;
428			case LC_TWOLEVEL_HINTS:
429				// no longer supported
430				break;
431			case LC_ID_DYLIB:
432				{
433					fDylibIDOffset = (uint8_t*)cmd - fMachOData;
434				}
435				break;
436			case LC_RPATH:
437			case LC_LOAD_WEAK_DYLIB:
438		    case LC_REEXPORT_DYLIB:
439			case LC_LOAD_UPWARD_DYLIB:
440			case LC_MAIN:
441				// do nothing, just prevent LC_REQ_DYLD exception from occuring
442				break;
443			case LC_VERSION_MIN_MACOSX:
444			case LC_VERSION_MIN_IPHONEOS:
445				minOSVersionCmd = (version_min_command*)cmd;
446				break;
447			default:
448				if ( (cmd->cmd & LC_REQ_DYLD) != 0 ) {
449					if ( firstUnknownCmd == NULL )
450						firstUnknownCmd = cmd;
451				}
452				break;
453		}
454		cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
455	}
456	if ( firstUnknownCmd != NULL ) {
457		if ( minOSVersionCmd != NULL )  {
458			dyld::throwf("cannot load '%s' because it was built for OS version %u.%u (load command 0x%08X is unknown)",
459						 this->getShortName(),
460						 minOSVersionCmd->version >> 16, ((minOSVersionCmd->version >> 8) & 0xff),
461						 firstUnknownCmd->cmd);
462		}
463		else {
464			dyld::throwf("cannot load '%s' (load command 0x%08X is unknown)", this->getShortName(), firstUnknownCmd->cmd);
465		}
466	}
467
468
469	if ( dyldInfo != NULL )
470		this->setDyldInfo(dyldInfo);
471	if ( symbolTable != NULL)
472		this->setSymbolTableInfo(symbolTable, symbolTableStrings, dynSymbolTable);
473
474}
475
476// don't do this work in destructor because we need object to be full subclass
477// for UnmapSegments() to work
478void ImageLoaderMachO::destroy()
479{
480	// update count of images with weak exports
481	if ( fRegisteredAsRequiresCoalescing ) {
482		--fgImagesRequiringCoalescing;
483		if ( this->hasCoalescedExports() )
484			--fgImagesHasWeakDefinitions;
485	}
486
487	// keep count of images used in shared cache
488	if ( fInSharedCache )
489		--fgImagesUsedFromSharedCache;
490
491	// unmap image when done
492	UnmapSegments();
493}
494
495
496unsigned int ImageLoaderMachO::segmentCount() const
497{
498	return fSegmentsCount;
499}
500
501
502const macho_segment_command* ImageLoaderMachO::segLoadCommand(unsigned int segIndex) const
503{
504	uint32_t* lcOffsets = this->segmentCommandOffsets();
505	uint32_t lcOffset =	lcOffsets[segIndex];
506	return (macho_segment_command*)(&fMachOData[lcOffset]);
507}
508
509const char*	ImageLoaderMachO::segName(unsigned int segIndex) const
510{
511	return segLoadCommand(segIndex)->segname;
512}
513
514
515uintptr_t ImageLoaderMachO::segSize(unsigned int segIndex) const
516{
517	return segLoadCommand(segIndex)->vmsize;
518}
519
520
521uintptr_t ImageLoaderMachO::segFileSize(unsigned int segIndex) const
522{
523	return segLoadCommand(segIndex)->filesize;
524}
525
526
527bool ImageLoaderMachO::segHasTrailingZeroFill(unsigned int segIndex)
528{
529	return ( segWriteable(segIndex) && (segSize(segIndex) > segFileSize(segIndex)) );
530}
531
532
533uintptr_t ImageLoaderMachO::segFileOffset(unsigned int segIndex) const
534{
535	return segLoadCommand(segIndex)->fileoff;
536}
537
538
539bool ImageLoaderMachO::segReadable(unsigned int segIndex) const
540{
541	return ( (segLoadCommand(segIndex)->initprot & VM_PROT_READ) != 0);
542}
543
544
545bool ImageLoaderMachO::segWriteable(unsigned int segIndex) const
546{
547	return ( (segLoadCommand(segIndex)->initprot & VM_PROT_WRITE) != 0);
548}
549
550
551bool ImageLoaderMachO::segExecutable(unsigned int segIndex) const
552{
553	return ( (segLoadCommand(segIndex)->initprot & VM_PROT_EXECUTE) != 0);
554}
555
556
557bool ImageLoaderMachO::segUnaccessible(unsigned int segIndex) const
558{
559	return (segLoadCommand(segIndex)->initprot == 0);
560}
561
562bool ImageLoaderMachO::segHasPreferredLoadAddress(unsigned int segIndex) const
563{
564	return (segLoadCommand(segIndex)->vmaddr != 0);
565}
566
567uintptr_t ImageLoaderMachO::segPreferredLoadAddress(unsigned int segIndex) const
568{
569	return segLoadCommand(segIndex)->vmaddr;
570}
571
572uintptr_t ImageLoaderMachO::segActualLoadAddress(unsigned int segIndex) const
573{
574	return segLoadCommand(segIndex)->vmaddr + fSlide;
575}
576
577
578uintptr_t ImageLoaderMachO::segActualEndAddress(unsigned int segIndex) const
579{
580	return segActualLoadAddress(segIndex) + segSize(segIndex);
581}
582
583bool ImageLoaderMachO::segHasRebaseFixUps(unsigned int segIndex) const
584{
585	// scan sections for fix-up bit
586	const macho_segment_command* segCmd = segLoadCommand(segIndex);
587	const struct macho_section* const sectionsStart = (struct macho_section*)((char*)segCmd + sizeof(struct macho_segment_command));
588	const struct macho_section* const sectionsEnd = &sectionsStart[segCmd->nsects];
589	for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
590		if ( (sect->flags & S_ATTR_LOC_RELOC) != 0 )
591			return true;
592	}
593	return false;
594}
595
596bool ImageLoaderMachO::segHasBindFixUps(unsigned int segIndex) const
597{
598	// scan sections for fix-up bit
599	const macho_segment_command* segCmd = segLoadCommand(segIndex);
600	const struct macho_section* const sectionsStart = (struct macho_section*)((char*)segCmd + sizeof(struct macho_segment_command));
601	const struct macho_section* const sectionsEnd = &sectionsStart[segCmd->nsects];
602	for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
603		if ( (sect->flags & S_ATTR_EXT_RELOC) != 0 )
604			return true;
605	}
606	return false;
607}
608
609#if __i386__
610bool ImageLoaderMachO::segIsReadOnlyImport(unsigned int segIndex) const
611{
612	const macho_segment_command* segCmd = segLoadCommand(segIndex);
613	return (    (segCmd->initprot & VM_PROT_EXECUTE)
614			&& ((segCmd->initprot & VM_PROT_WRITE) == 0)
615			&& (strcmp(segCmd->segname, "__IMPORT") == 0) );
616}
617#endif
618
619
620void ImageLoaderMachO::UnmapSegments()
621{
622	// usually unmap image when done
623	if ( ! this->leaveMapped() && (this->getState() >= dyld_image_state_mapped) ) {
624		// unmap TEXT segment last because it contains load command being inspected
625		unsigned int textSegmentIndex = 0;
626		for(unsigned int i=0; i < fSegmentsCount; ++i) {
627			//dyld::log("unmap %s at 0x%08lX\n", seg->getName(), seg->getActualLoadAddress(this));
628			if ( strcmp(segName(i), "__TEXT") == 0 ) {
629				textSegmentIndex = i;
630			}
631			else {
632				// update stats
633				--ImageLoader::fgTotalSegmentsMapped;
634				ImageLoader::fgTotalBytesMapped -= segSize(i);
635				munmap((void*)segActualLoadAddress(i), segSize(i));
636			}
637		}
638		// now unmap TEXT
639		--ImageLoader::fgTotalSegmentsMapped;
640		ImageLoader::fgTotalBytesMapped -= segSize(textSegmentIndex);
641		munmap((void*)segActualLoadAddress(textSegmentIndex), segSize(textSegmentIndex));
642	}
643}
644
645
646// prefetch __DATA/__OBJC pages during launch, but not for dynamically loaded code
647void ImageLoaderMachO::preFetchDATA(int fd, uint64_t offsetInFat, const LinkContext& context)
648{
649	if ( context.linkingMainExecutable ) {
650		for(unsigned int i=0, e=segmentCount(); i < e; ++i) {
651			if ( segWriteable(i) && (segFileSize(i) > 0) ) {
652				// prefetch writable segment that have mmap'ed regions
653				radvisory advice;
654				advice.ra_offset = offsetInFat + segFileOffset(i);
655				advice.ra_count = segFileSize(i);
656				// limit prefetch to 1MB (256 pages)
657				if ( advice.ra_count > 1024*1024 )
658					advice.ra_count = 1024*1024;
659				// don't prefetch single pages, let them fault in
660				fgTotalBytesPreFetched += advice.ra_count;
661				fcntl(fd, F_RDADVISE, &advice);
662				if ( context.verboseMapping ) {
663					dyld::log("%18s prefetching 0x%0lX -> 0x%0lX\n",
664						segName(i), segActualLoadAddress(i), segActualLoadAddress(i)+advice.ra_count-1);
665				}
666			}
667		}
668	}
669}
670
671
672bool ImageLoaderMachO::segmentsMustSlideTogether() const
673{
674	return true;
675}
676
677bool ImageLoaderMachO::segmentsCanSlide() const
678{
679	return (this->isDylib() || this->isBundle() || this->isPositionIndependentExecutable());
680}
681
682bool ImageLoaderMachO::isBundle() const
683{
684	const macho_header* mh = (macho_header*)fMachOData;
685	return ( mh->filetype == MH_BUNDLE );
686}
687
688bool ImageLoaderMachO::isDylib() const
689{
690	const macho_header* mh = (macho_header*)fMachOData;
691	return ( mh->filetype == MH_DYLIB );
692}
693
694bool ImageLoaderMachO::isExecutable() const
695{
696	const macho_header* mh = (macho_header*)fMachOData;
697	return ( mh->filetype == MH_EXECUTE );
698}
699
700bool ImageLoaderMachO::isPositionIndependentExecutable() const
701{
702	const macho_header* mh = (macho_header*)fMachOData;
703	return ( (mh->filetype == MH_EXECUTE) && ((mh->flags & MH_PIE) != 0) );
704}
705
706
707bool ImageLoaderMachO::forceFlat() const
708{
709	const macho_header* mh = (macho_header*)fMachOData;
710	return ( (mh->flags & MH_FORCE_FLAT) != 0 );
711}
712
713bool ImageLoaderMachO::usesTwoLevelNameSpace() const
714{
715	const macho_header* mh = (macho_header*)fMachOData;
716	return ( (mh->flags & MH_TWOLEVEL) != 0 );
717}
718
719bool ImageLoaderMachO::isPrebindable() const
720{
721	const macho_header* mh = (macho_header*)fMachOData;
722	return ( (mh->flags & MH_PREBOUND) != 0 );
723}
724
725bool ImageLoaderMachO::hasCoalescedExports() const
726{
727	const macho_header* mh = (macho_header*)fMachOData;
728	return ( (mh->flags & MH_WEAK_DEFINES) != 0 );
729}
730
731bool ImageLoaderMachO::hasReferencesToWeakSymbols() const
732{
733	const macho_header* mh = (macho_header*)fMachOData;
734	return ( (mh->flags & MH_BINDS_TO_WEAK) != 0 );
735}
736
737bool ImageLoaderMachO::participatesInCoalescing() const
738{
739	const macho_header* mh = (macho_header*)fMachOData;
740	// if image is loaded with RTLD_LOCAL, then its symbols' visibility
741	// is reduced and it can't coalesce with other images
742	if ( this->hasHiddenExports() )
743		return false;
744	return ( (mh->flags & (MH_WEAK_DEFINES|MH_BINDS_TO_WEAK)) != 0 );
745}
746
747
748
749void ImageLoaderMachO::setSlide(intptr_t slide)
750{
751	fSlide = slide;
752}
753
754void ImageLoaderMachO::loadCodeSignature(const struct linkedit_data_command* codeSigCmd, int fd,  uint64_t offsetInFatFile, const LinkContext& context)
755{
756	// if dylib being loaded has no code signature load command
757	if ( codeSigCmd == NULL ) {
758#if __MAC_OS_X_VERSION_MIN_REQUIRED
759		bool codeSigningEnforced = context.codeSigningEnforced;
760		if ( context.mainExecutableCodeSigned && !codeSigningEnforced ) {
761			static bool codeSignEnforcementDynamicallyEnabled = false;
762			if ( !codeSignEnforcementDynamicallyEnabled ) {
763				uint32_t flags;
764				if ( csops(0, CS_OPS_STATUS, &flags, sizeof(flags)) != -1 ) {
765					if ( flags & CS_ENFORCEMENT ) {
766						codeSignEnforcementDynamicallyEnabled = true;
767					}
768				}
769			}
770			codeSigningEnforced = codeSignEnforcementDynamicallyEnabled;
771		}
772		// if we require dylibs to be code signed
773		if ( codeSigningEnforced  ) {
774			// if there is a non-load command based code signature, use it
775			off_t offset = (off_t)offsetInFatFile;
776			if ( fcntl(fd, F_FINDSIGS, &offset, sizeof(offset)) != -1 )
777				return;
778			// otherwise gracefully return from dlopen()
779			dyld::throwf("required code signature missing for '%s'\n", this->getPath());
780		}
781#endif
782	}
783	else {
784#if __MAC_OS_X_VERSION_MIN_REQUIRED
785		// <rdar://problem/13622786> ignore code signatures in binaries built with pre-10.9 tools
786		if ( this->sdkVersion() < DYLD_MACOSX_VERSION_10_9 ) {
787			return;
788		}
789#endif
790		fsignatures_t siginfo;
791		siginfo.fs_file_start=offsetInFatFile;				// start of mach-o slice in fat file
792		siginfo.fs_blob_start=(void*)(long)(codeSigCmd->dataoff);	// start of CD in mach-o file
793		siginfo.fs_blob_size=codeSigCmd->datasize;			// size of CD
794		int result = fcntl(fd, F_ADDFILESIGS, &siginfo);
795		if ( result == -1 ) {
796			if ( (errno == EPERM) || (errno == EBADEXEC) )
797				dyld::throwf("code signature invalid for '%s'\n", this->getPath());
798			if ( context.verboseCodeSignatures )
799				dyld::log("dyld: Failed registering code signature for %s, errno=%d\n", this->getPath(), errno);
800			else
801				dyld::log("dyld: Registered code signature for %s\n", this->getPath());
802		}
803	}
804}
805
806
807const char* ImageLoaderMachO::getInstallPath() const
808{
809	if ( fDylibIDOffset != 0 ) {
810		const dylib_command* dylibID = (dylib_command*)(&fMachOData[fDylibIDOffset]);
811		return (char*)dylibID + dylibID->dylib.name.offset;
812	}
813	return NULL;
814}
815
816void ImageLoaderMachO::registerInterposing()
817{
818	// mach-o files advertise interposing by having a __DATA __interpose section
819	struct InterposeData { uintptr_t replacement; uintptr_t replacee; };
820	const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
821	const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
822	const struct load_command* cmd = cmds;
823	for (uint32_t i = 0; i < cmd_count; ++i) {
824		switch (cmd->cmd) {
825			case LC_SEGMENT_COMMAND:
826				{
827					const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
828					const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
829					const struct macho_section* const sectionsEnd = &sectionsStart[seg->nsects];
830					for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
831						if ( ((sect->flags & SECTION_TYPE) == S_INTERPOSING) || ((strcmp(sect->sectname, "__interpose") == 0) && (strcmp(seg->segname, "__DATA") == 0)) ) {
832							const InterposeData* interposeArray = (InterposeData*)(sect->addr + fSlide);
833							const unsigned int count = sect->size / sizeof(InterposeData);
834							for (uint32_t i=0; i < count; ++i) {
835								ImageLoader::InterposeTuple tuple;
836								tuple.replacement		= interposeArray[i].replacement;
837								tuple.replacementImage	= this;
838								tuple.replacee			= interposeArray[i].replacee;
839								// <rdar://problem/7937695> verify that replacement is in this image
840								if ( this->containsAddress((void*)tuple.replacement) ) {
841									for (std::vector<InterposeTuple>::iterator it=fgInterposingTuples.begin(); it != fgInterposingTuples.end(); it++) {
842										if ( it->replacee == tuple.replacee ) {
843											tuple.replacee = it->replacement;
844										}
845									}
846									ImageLoader::fgInterposingTuples.push_back(tuple);
847								}
848							}
849						}
850					}
851				}
852				break;
853		}
854		cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
855	}
856}
857
858uint32_t ImageLoaderMachO::sdkVersion() const
859{
860	const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
861	const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
862	const struct load_command* cmd = cmds;
863	const struct version_min_command* versCmd;
864	for (uint32_t i = 0; i < cmd_count; ++i) {
865		switch ( cmd->cmd ) {
866			case LC_VERSION_MIN_MACOSX:
867			case LC_VERSION_MIN_IPHONEOS:
868				versCmd = (version_min_command*)cmd;
869				return versCmd->sdk;
870		}
871		cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
872	}
873	return 0;
874}
875
876void* ImageLoaderMachO::getThreadPC() const
877{
878	const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
879	const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
880	const struct load_command* cmd = cmds;
881	for (uint32_t i = 0; i < cmd_count; ++i) {
882		if ( cmd->cmd == LC_MAIN ) {
883			entry_point_command* mainCmd = (entry_point_command*)cmd;
884			void* entry = (void*)(mainCmd->entryoff + (char*)fMachOData);
885			// <rdar://problem/8543820&9228031> verify entry point is in image
886			if ( this->containsAddress(entry) )
887				return entry;
888			else
889				throw "LC_MAIN entryoff is out of range";
890		}
891		cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
892	}
893	return NULL;
894}
895
896
897void* ImageLoaderMachO::getMain() const
898{
899	const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
900	const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
901	const struct load_command* cmd = cmds;
902	for (uint32_t i = 0; i < cmd_count; ++i) {
903		switch (cmd->cmd) {
904			case LC_UNIXTHREAD:
905			{
906			#if __i386__
907				const i386_thread_state_t* registers = (i386_thread_state_t*)(((char*)cmd) + 16);
908				void* entry = (void*)(registers->eip + fSlide);
909			#elif __x86_64__
910				const x86_thread_state64_t* registers = (x86_thread_state64_t*)(((char*)cmd) + 16);
911				void* entry = (void*)(registers->rip + fSlide);
912			#elif __arm__
913				const arm_thread_state_t* registers = (arm_thread_state_t*)(((char*)cmd) + 16);
914				void* entry = (void*)(registers->__pc + fSlide);
915			#else
916				#warning need processor specific code
917			#endif
918				// <rdar://problem/8543820&9228031> verify entry point is in image
919				if ( this->containsAddress(entry) ) {
920					return entry;
921				}
922			}
923			break;
924		}
925		cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
926	}
927	throw "no valid entry point";
928}
929
930bool ImageLoaderMachO::needsAddedLibSystemDepency(unsigned int libCount, const macho_header* mh)
931{
932	// <rdar://problem/6357561> ensure that every image depends on something which depends on libSystem
933	if ( libCount > 1 )
934		return false;
935
936	// <rdar://problem/6409800> dyld implicit-libSystem breaks valgrind
937	if ( mh->filetype == MH_EXECUTE )
938		return false;
939
940	bool isNonOSdylib = false;
941	const uint32_t cmd_count = mh->ncmds;
942	const struct load_command* const cmds = (struct load_command*)((uint8_t*)mh+sizeof(macho_header));
943	const struct load_command* cmd = cmds;
944	for (uint32_t i = 0; i < cmd_count; ++i) {
945		switch (cmd->cmd) {
946			case LC_LOAD_DYLIB:
947			case LC_LOAD_WEAK_DYLIB:
948			case LC_REEXPORT_DYLIB:
949			case LC_LOAD_UPWARD_DYLIB:
950				return false;
951			case LC_ID_DYLIB:
952				{
953				const dylib_command* dylibID = (dylib_command*)cmd;
954				const char* installPath = (char*)cmd + dylibID->dylib.name.offset;
955				// It is OK for OS dylibs (libSystem or libmath or Rosetta shims) to have no dependents
956				// but all other dylibs must depend on libSystem for initialization to initialize libSystem first
957				// <rdar://problem/6497528> rosetta circular dependency spew
958				isNonOSdylib = ( (strncmp(installPath, "/usr/lib/", 9) != 0) && (strncmp(installPath, "/usr/libexec/oah/Shims", 9) != 0) );
959				}
960				break;
961		}
962		cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
963	}
964	return isNonOSdylib;
965}
966
967
968void ImageLoaderMachO::doGetDependentLibraries(DependentLibraryInfo libs[])
969{
970	if ( needsAddedLibSystemDepency(libraryCount(), (macho_header*)fMachOData) ) {
971		DependentLibraryInfo* lib = &libs[0];
972		lib->name = "/usr/lib/libSystem.B.dylib";
973		lib->info.checksum = 0;
974		lib->info.minVersion = 0;
975		lib->info.maxVersion = 0;
976		lib->required = false;
977		lib->reExported = false;
978		lib->upward = false;
979	}
980	else {
981		uint32_t index = 0;
982		const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
983		const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
984		const struct load_command* cmd = cmds;
985		for (uint32_t i = 0; i < cmd_count; ++i) {
986			switch (cmd->cmd) {
987				case LC_LOAD_DYLIB:
988				case LC_LOAD_WEAK_DYLIB:
989				case LC_REEXPORT_DYLIB:
990				case LC_LOAD_UPWARD_DYLIB:
991				{
992					const struct dylib_command* dylib = (struct dylib_command*)cmd;
993					DependentLibraryInfo* lib = &libs[index++];
994					lib->name = (char*)cmd + dylib->dylib.name.offset;
995					//lib->name = strdup((char*)cmd + dylib->dylib.name.offset);
996					lib->info.checksum = dylib->dylib.timestamp;
997					lib->info.minVersion = dylib->dylib.compatibility_version;
998					lib->info.maxVersion = dylib->dylib.current_version;
999					lib->required = (cmd->cmd != LC_LOAD_WEAK_DYLIB);
1000					lib->reExported = (cmd->cmd == LC_REEXPORT_DYLIB);
1001					lib->upward = (cmd->cmd == LC_LOAD_UPWARD_DYLIB);
1002				}
1003				break;
1004			}
1005			cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
1006		}
1007	}
1008}
1009
1010ImageLoader::LibraryInfo ImageLoaderMachO::doGetLibraryInfo()
1011{
1012	LibraryInfo info;
1013	if ( fDylibIDOffset != 0 ) {
1014		const dylib_command* dylibID = (dylib_command*)(&fMachOData[fDylibIDOffset]);
1015		info.minVersion = dylibID->dylib.compatibility_version;
1016		info.maxVersion = dylibID->dylib.current_version;
1017		info.checksum = dylibID->dylib.timestamp;
1018	}
1019	else {
1020		info.minVersion = 0;
1021		info.maxVersion = 0;
1022		info.checksum = 0;
1023	}
1024	return info;
1025}
1026
1027void ImageLoaderMachO::getRPaths(const LinkContext& context, std::vector<const char*>& paths) const
1028{
1029	const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
1030	const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
1031	const struct load_command* cmd = cmds;
1032	for (uint32_t i = 0; i < cmd_count; ++i) {
1033		switch (cmd->cmd) {
1034			case LC_RPATH:
1035				const char* pathToAdd = NULL;
1036				const char* path = (char*)cmd + ((struct rpath_command*)cmd)->path.offset;
1037				if ( strncmp(path, "@loader_path/", 13) == 0 ) {
1038					if ( context.processIsRestricted  && (context.mainExecutable == this) ) {
1039						dyld::warn("LC_RPATH %s in %s being ignored in restricted program because of @loader_path\n", path, this->getPath());
1040						break;
1041					}
1042					char resolvedPath[PATH_MAX];
1043					if ( realpath(this->getPath(), resolvedPath) != NULL ) {
1044						char newRealPath[strlen(resolvedPath) + strlen(path)];
1045						strcpy(newRealPath, resolvedPath);
1046						char* addPoint = strrchr(newRealPath,'/');
1047						if ( addPoint != NULL )
1048							strcpy(&addPoint[1], &path[13]);
1049						else
1050							strcpy(newRealPath, &path[13]);
1051						pathToAdd = strdup(newRealPath);
1052					}
1053				}
1054				else if ( strncmp(path, "@executable_path/", 17) == 0 ) {
1055					if ( context.processIsRestricted ) {
1056						dyld::warn("LC_RPATH %s in %s being ignored in restricted program because of @executable_path\n", path, this->getPath());
1057						break;
1058					}
1059					char resolvedPath[PATH_MAX];
1060					if ( realpath(context.mainExecutable->getPath(), resolvedPath) != NULL ) {
1061						char newRealPath[strlen(resolvedPath) + strlen(path)];
1062						strcpy(newRealPath, resolvedPath);
1063						char* addPoint = strrchr(newRealPath,'/');
1064						if ( addPoint != NULL )
1065							strcpy(&addPoint[1], &path[17]);
1066						else
1067							strcpy(newRealPath, &path[17]);
1068						pathToAdd = strdup(newRealPath);
1069					}
1070				}
1071				else if ( (path[0] != '/') && context.processIsRestricted ) {
1072					dyld::warn("LC_RPATH %s in %s being ignored in restricted program because it is a relative path\n", path, this->getPath());
1073					break;
1074				}
1075				else if ( (path[0] == '/') && (context.rootPaths != NULL) ) {
1076					// <rdar://problem/5869973> DYLD_ROOT_PATH should apply to LC_RPATH rpaths
1077					// DYLD_ROOT_PATH can be a list of paths, but at this point we can only support one, so use first combination that exists
1078					bool found = false;
1079					for(const char** rp = context.rootPaths; *rp != NULL; ++rp) {
1080						char newPath[PATH_MAX];
1081						strlcpy(newPath, *rp, PATH_MAX);
1082						strlcat(newPath, path, PATH_MAX);
1083						struct stat stat_buf;
1084						if ( stat(newPath, &stat_buf) != -1 ) {
1085							//dyld::log("combined DYLD_ROOT_PATH and LC_RPATH: %s\n", newPath);
1086							pathToAdd = strdup(newPath);
1087							found = true;
1088							break;
1089						}
1090					}
1091					if ( ! found ) {
1092						// make copy so that all elements of 'paths' can be freed
1093						pathToAdd = strdup(path);
1094					}
1095				}
1096				else {
1097					// make copy so that all elements of 'paths' can be freed
1098					pathToAdd = strdup(path);
1099				}
1100				if ( pathToAdd != NULL )
1101					paths.push_back(pathToAdd);
1102				break;
1103		}
1104		cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
1105	}
1106}
1107
1108bool ImageLoaderMachO::getUUID(uuid_t uuid) const
1109{
1110	const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
1111	const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
1112	const struct load_command* cmd = cmds;
1113	for (uint32_t i = 0; i < cmd_count; ++i) {
1114		switch (cmd->cmd) {
1115			case LC_UUID:
1116				uuid_command* uc = (uuid_command*)cmd;
1117				memcpy(uuid, uc->uuid, 16);
1118				return true;
1119		}
1120		cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
1121	}
1122	bzero(uuid, 16);
1123	return false;
1124}
1125
1126void ImageLoaderMachO::doRebase(const LinkContext& context)
1127{
1128	// if prebound and loaded at prebound address, then no need to rebase
1129	if ( this->usablePrebinding(context) ) {
1130		// skip rebasing because prebinding is valid
1131		++fgImagesWithUsedPrebinding; // bump totals for statistics
1132		return;
1133	}
1134
1135	// print why prebinding was not used
1136	if ( context.verbosePrebinding ) {
1137		if ( !this->isPrebindable() ) {
1138			dyld::log("dyld: image not prebound, so could not use prebinding in %s\n", this->getPath());
1139		}
1140		else if ( fSlide != 0 ) {
1141			dyld::log("dyld: image slid, so could not use prebinding in %s\n", this->getPath());
1142		}
1143		else if ( !this->allDependentLibrariesAsWhenPreBound() ) {
1144			dyld::log("dyld: dependent libraries changed, so could not use prebinding in %s\n", this->getPath());
1145		}
1146		else if ( !this->usesTwoLevelNameSpace() ){
1147			dyld::log("dyld: image uses flat-namespace so, parts of prebinding ignored %s\n", this->getPath());
1148		}
1149		else {
1150			dyld::log("dyld: environment variable disabled use of prebinding in %s\n", this->getPath());
1151		}
1152	}
1153
1154	//dyld::log("slide=0x%08lX for %s\n", slide, this->getPath());
1155
1156#if PREBOUND_IMAGE_SUPPORT
1157	// if prebound and we got here, then prebinding is not valid, so reset all lazy pointers
1158	// if this image is in the shared cache, do not reset, they will be bound in doBind()
1159	if ( this->isPrebindable() && !fInSharedCache )
1160		this->resetPreboundLazyPointers(context);
1161#endif
1162
1163	// if loaded at preferred address, no rebasing necessary
1164	if ( this->fSlide == 0 )
1165		return;
1166
1167#if TEXT_RELOC_SUPPORT
1168	// if there are __TEXT fixups, temporarily make __TEXT writable
1169	if ( fTextSegmentRebases )
1170		this->makeTextSegmentWritable(context, true);
1171#endif
1172
1173	// do actual rebasing
1174	this->rebase(context);
1175
1176#if TEXT_RELOC_SUPPORT
1177	// if there were __TEXT fixups, restore write protection
1178	if ( fTextSegmentRebases )
1179		this->makeTextSegmentWritable(context, false);
1180
1181#endif
1182}
1183
1184#if TEXT_RELOC_SUPPORT
1185void ImageLoaderMachO::makeTextSegmentWritable(const LinkContext& context, bool writeable)
1186{
1187	int textSegmentIndex = 0;
1188	for(unsigned int i=0; i < fSegmentsCount; ++i) {
1189		if ( strcmp(segName(i), "__TEXT") == 0 ) {
1190			textSegmentIndex = i;
1191			break;
1192		}
1193	}
1194
1195	if ( writeable ) {
1196		segMakeWritable(textSegmentIndex, context);
1197	}
1198	else {
1199	#if !__i386__ && !__x86_64__
1200		// some processors require range to be invalidated before it is made executable
1201		sys_icache_invalidate((void*)segActualLoadAddress(textSegmentIndex), segSize(textSegmentIndex));
1202	#endif
1203		segProtect(textSegmentIndex, context);
1204	}
1205}
1206#endif
1207
1208const ImageLoader::Symbol* ImageLoaderMachO::findExportedSymbol(const char* name, bool searchReExports, const ImageLoader** foundIn) const
1209{
1210	// look in this image first
1211	const ImageLoader::Symbol* result = this->findExportedSymbol(name, foundIn);
1212	if ( result != NULL )
1213		return result;
1214
1215	if ( searchReExports ) {
1216		for(unsigned int i=0; i < libraryCount(); ++i){
1217			if ( libReExported(i) ) {
1218				ImageLoader* image = libImage(i);
1219				if ( image != NULL ) {
1220					const Symbol* result = image->findExportedSymbol(name, searchReExports, foundIn);
1221					if ( result != NULL )
1222						return result;
1223				}
1224			}
1225		}
1226	}
1227
1228
1229	return NULL;
1230}
1231
1232
1233
1234uintptr_t ImageLoaderMachO::getExportedSymbolAddress(const Symbol* sym, const LinkContext& context,
1235											const ImageLoader* requestor, bool runResolver) const
1236{
1237	return this->getSymbolAddress(sym, requestor, context, runResolver);
1238}
1239
1240uintptr_t ImageLoaderMachO::getSymbolAddress(const Symbol* sym, const ImageLoader* requestor,
1241												const LinkContext& context, bool runResolver) const
1242{
1243	uintptr_t result = exportedSymbolAddress(context, sym, requestor, runResolver);
1244	// check for interposing overrides
1245	for (std::vector<InterposeTuple>::iterator it=fgInterposingTuples.begin(); it != fgInterposingTuples.end(); it++) {
1246		// replace all references to 'replacee' with 'replacement'
1247		if ( (result == it->replacee) && (requestor != it->replacementImage) ) {
1248			if ( context.verboseInterposing ) {
1249				dyld::log("dyld interposing: replace 0x%lX with 0x%lX in %s\n",
1250					it->replacee, it->replacement, this->getPath());
1251			}
1252			result = it->replacement;
1253		}
1254	}
1255	return result;
1256}
1257
1258ImageLoader::DefinitionFlags ImageLoaderMachO::getExportedSymbolInfo(const Symbol* sym) const
1259{
1260	if ( exportedSymbolIsWeakDefintion(sym) )
1261		return kWeakDefinition;
1262	else
1263		return kNoDefinitionOptions;
1264}
1265
1266const char* ImageLoaderMachO::getExportedSymbolName(const Symbol* sym) const
1267{
1268	return exportedSymbolName(sym);
1269}
1270
1271uint32_t ImageLoaderMachO::getExportedSymbolCount() const
1272{
1273	return exportedSymbolCount();
1274}
1275
1276
1277const ImageLoader::Symbol* ImageLoaderMachO::getIndexedExportedSymbol(uint32_t index) const
1278{
1279	return exportedSymbolIndexed(index);
1280}
1281
1282
1283uint32_t ImageLoaderMachO::getImportedSymbolCount() const
1284{
1285	return importedSymbolCount();
1286}
1287
1288
1289const ImageLoader::Symbol* ImageLoaderMachO::getIndexedImportedSymbol(uint32_t index) const
1290{
1291	return importedSymbolIndexed(index);
1292}
1293
1294
1295ImageLoader::ReferenceFlags ImageLoaderMachO::getImportedSymbolInfo(const ImageLoader::Symbol* sym) const
1296{
1297	ImageLoader::ReferenceFlags flags = kNoReferenceOptions;
1298	return flags;
1299}
1300
1301
1302const char* ImageLoaderMachO::getImportedSymbolName(const ImageLoader::Symbol* sym) const
1303{
1304	return importedSymbolName(sym);
1305}
1306
1307
1308bool ImageLoaderMachO::getSectionContent(const char* segmentName, const char* sectionName, void** start, size_t* length)
1309{
1310	const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
1311	const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
1312	const struct load_command* cmd = cmds;
1313	for (uint32_t i = 0; i < cmd_count; ++i) {
1314		switch (cmd->cmd) {
1315			case LC_SEGMENT_COMMAND:
1316				{
1317					const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
1318					const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
1319					const struct macho_section* const sectionsEnd = &sectionsStart[seg->nsects];
1320					for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
1321						if ( (strcmp(sect->segname, segmentName) == 0) && (strcmp(sect->sectname, sectionName) == 0) ) {
1322							*start = (uintptr_t*)(sect->addr + fSlide);
1323							*length = sect->size;
1324							return true;
1325						}
1326					}
1327				}
1328				break;
1329		}
1330		cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
1331	}
1332	*start = NULL;
1333	*length = 0;
1334	return false;
1335}
1336
1337void ImageLoaderMachO::getUnwindInfo(dyld_unwind_sections* info)
1338{
1339	info->mh = this->machHeader();
1340	info->dwarf_section = 0;
1341	info->dwarf_section_length = 0;
1342	info->compact_unwind_section = 0;
1343	info->compact_unwind_section_length = 0;
1344	if ( fEHFrameSectionOffset != 0 ) {
1345		const macho_section* sect = (macho_section*)&fMachOData[fEHFrameSectionOffset];
1346		info->dwarf_section = (void*)(sect->addr + fSlide);
1347		info->dwarf_section_length = sect->size;
1348	}
1349	if ( fUnwindInfoSectionOffset != 0 ) {
1350		const macho_section* sect = (macho_section*)&fMachOData[fUnwindInfoSectionOffset];
1351		info->compact_unwind_section = (void*)(sect->addr + fSlide);
1352		info->compact_unwind_section_length = sect->size;
1353	}
1354}
1355
1356
1357bool ImageLoaderMachO::findSection(const void* imageInterior, const char** segmentName, const char** sectionName, size_t* sectionOffset)
1358{
1359	const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
1360	const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
1361	const struct load_command* cmd = cmds;
1362	const uintptr_t unslidInteriorAddress = (uintptr_t)imageInterior - this->getSlide();
1363	for (uint32_t i = 0; i < cmd_count; ++i) {
1364		switch (cmd->cmd) {
1365			case LC_SEGMENT_COMMAND:
1366				{
1367					const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
1368					if ( (unslidInteriorAddress >= seg->vmaddr) && (unslidInteriorAddress < (seg->vmaddr+seg->vmsize)) ) {
1369						const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
1370						const struct macho_section* const sectionsEnd = &sectionsStart[seg->nsects];
1371						for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
1372							if ((sect->addr <= unslidInteriorAddress) && (unslidInteriorAddress < (sect->addr+sect->size))) {
1373								if ( segmentName != NULL )
1374									*segmentName = sect->segname;
1375								if ( sectionName != NULL )
1376									*sectionName = sect->sectname;
1377								if ( sectionOffset != NULL )
1378									*sectionOffset = unslidInteriorAddress - sect->addr;
1379								return true;
1380							}
1381						}
1382					}
1383				}
1384				break;
1385		}
1386		cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
1387	}
1388	return false;
1389}
1390
1391
1392void __attribute__((noreturn)) ImageLoaderMachO::throwSymbolNotFound(const LinkContext& context, const char* symbol,
1393																	const char* referencedFrom, const char* expectedIn)
1394{
1395	// record values for possible use by CrashReporter or Finder
1396	(*context.setErrorStrings)(dyld_error_kind_symbol_missing, referencedFrom, expectedIn, symbol);
1397	dyld::throwf("Symbol not found: %s\n  Referenced from: %s\n  Expected in: %s\n", symbol, referencedFrom, expectedIn);
1398}
1399
1400const mach_header* ImageLoaderMachO::machHeader() const
1401{
1402	return (mach_header*)fMachOData;
1403}
1404
1405uintptr_t ImageLoaderMachO::getSlide() const
1406{
1407	return fSlide;
1408}
1409
1410// hmm. maybe this should be up in ImageLoader??
1411const void* ImageLoaderMachO::getEnd() const
1412{
1413	uintptr_t lastAddress = 0;
1414	for(unsigned int i=0; i < fSegmentsCount; ++i) {
1415		uintptr_t segEnd = segActualEndAddress(i);
1416		if ( strcmp(segName(i), "__UNIXSTACK") != 0 ) {
1417			if ( segEnd > lastAddress )
1418				lastAddress = segEnd;
1419		}
1420	}
1421	return (const void*)lastAddress;
1422}
1423
1424
1425uintptr_t ImageLoaderMachO::bindLocation(const LinkContext& context, uintptr_t location, uintptr_t value,
1426										const ImageLoader* targetImage, uint8_t type, const char* symbolName,
1427										intptr_t addend, const char* msg)
1428{
1429	// log
1430	if ( context.verboseBind ) {
1431		if ( addend != 0 )
1432			dyld::log("dyld: %sbind: %s:0x%08lX = %s:%s, *0x%08lX = 0x%08lX + %ld\n",
1433						msg, this->getShortName(), (uintptr_t)location,
1434						((targetImage != NULL) ? targetImage->getShortName() : "<weak_import-missing>"),
1435						symbolName, (uintptr_t)location, value, addend);
1436		else
1437			dyld::log("dyld: %sbind: %s:0x%08lX = %s:%s, *0x%08lX = 0x%08lX\n",
1438						msg, this->getShortName(), (uintptr_t)location,
1439						((targetImage != NULL) ? targetImage->getShortName() : "<weak>import-missing>"),
1440						 symbolName, (uintptr_t)location, value);
1441	}
1442#if LOG_BINDINGS
1443//	dyld::logBindings("%s: %s\n", targetImage->getShortName(), symbolName);
1444#endif
1445
1446	// do actual update
1447	uintptr_t* locationToFix = (uintptr_t*)location;
1448	uint32_t* loc32;
1449	uintptr_t newValue = value+addend;
1450	uint32_t value32;
1451	switch (type) {
1452		case BIND_TYPE_POINTER:
1453			// test first so we don't needless dirty pages
1454			if ( *locationToFix != newValue )
1455				*locationToFix = newValue;
1456			break;
1457		case BIND_TYPE_TEXT_ABSOLUTE32:
1458			loc32 = (uint32_t*)locationToFix;
1459			value32 = (uint32_t)newValue;
1460			if ( *loc32 != value32 )
1461				*loc32 = value32;
1462			break;
1463		case BIND_TYPE_TEXT_PCREL32:
1464			loc32 = (uint32_t*)locationToFix;
1465			value32 = (uint32_t)newValue - (((uintptr_t)locationToFix) + 4);
1466			if ( *loc32 != value32 )
1467				*loc32 = value32;
1468			break;
1469		default:
1470			dyld::throwf("bad bind type %d", type);
1471	}
1472
1473	// update statistics
1474	++fgTotalBindFixups;
1475
1476	return newValue;
1477}
1478
1479
1480
1481
1482
1483#if SUPPORT_OLD_CRT_INITIALIZATION
1484// first 16 bytes of "start" in crt1.o
1485#if __i386__
1486	static uint8_t sStandardEntryPointInstructions[16] = { 0x6a, 0x00, 0x89, 0xe5, 0x83, 0xe4, 0xf0, 0x83, 0xec, 0x10, 0x8b, 0x5d, 0x04, 0x89, 0x5c, 0x24 };
1487#endif
1488#endif
1489
1490struct DATAdyld {
1491	void*			dyldLazyBinder;		// filled in at launch by dyld to point into dyld to &stub_binding_helper_interface
1492	void*			dyldFuncLookup;		// filled in at launch by dyld to point into dyld to &_dyld_func_lookup
1493	// the following only exist in main executables built for 10.5 or later
1494	ProgramVars		vars;
1495};
1496
1497// These are defined in dyldStartup.s
1498extern "C" void stub_binding_helper();
1499extern "C" bool dyld_func_lookup(const char* name, uintptr_t* address);
1500
1501
1502void ImageLoaderMachO::setupLazyPointerHandler(const LinkContext& context)
1503{
1504	const macho_header* mh = (macho_header*)fMachOData;
1505	const uint32_t cmd_count = mh->ncmds;
1506	const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
1507	const struct load_command* cmd;
1508	// There used to be some optimizations to skip this section scan, but we need to handle the
1509	// __dyld section in libdyld.dylib, so everything needs to be scanned for now.
1510	// <rdar://problem/10910062> CrashTracer: 1,295 crashes in bash at bash: getenv
1511	if ( true ) {
1512		cmd = cmds;
1513		for (uint32_t i = 0; i < cmd_count; ++i) {
1514			if ( cmd->cmd == LC_SEGMENT_COMMAND ) {
1515				const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
1516				if ( strcmp(seg->segname, "__DATA") == 0 ) {
1517					const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
1518					const struct macho_section* const sectionsEnd = &sectionsStart[seg->nsects];
1519					for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
1520						if ( strcmp(sect->sectname, "__dyld" ) == 0 ) {
1521							struct DATAdyld* dd = (struct DATAdyld*)(sect->addr + fSlide);
1522							if ( sect->size > offsetof(DATAdyld, dyldLazyBinder) ) {
1523								if ( dd->dyldLazyBinder != (void*)&stub_binding_helper )
1524									dd->dyldLazyBinder = (void*)&stub_binding_helper;
1525							}
1526							if ( sect->size > offsetof(DATAdyld, dyldFuncLookup) ) {
1527								if ( dd->dyldFuncLookup != (void*)&dyld_func_lookup )
1528									dd->dyldFuncLookup = (void*)&dyld_func_lookup;
1529							}
1530							if ( mh->filetype == MH_EXECUTE ) {
1531								// there are two ways to get the program variables
1532								if ( (sect->size > offsetof(DATAdyld, vars)) && (dd->vars.mh == mh) ) {
1533									// some really old binaries have space for vars, but it is zero filled
1534									// main executable has 10.5 style __dyld section that has program variable pointers
1535									context.setNewProgramVars(dd->vars);
1536								}
1537								else {
1538									// main executable is pre-10.5 and requires the symbols names to be looked up
1539									this->lookupProgramVars(context);
1540				#if SUPPORT_OLD_CRT_INITIALIZATION
1541									// If the first 16 bytes of the entry point's instructions do not
1542									// match what crt1.o supplies, then the program has a custom entry point.
1543									// This means it might be doing something that needs to be executed before
1544									// initializers are run.
1545									if ( memcmp(this->getMain(), sStandardEntryPointInstructions, 16) != 0 ) {
1546										if ( context.verboseInit )
1547											dyld::log("dyld: program uses non-standard entry point so delaying running of initializers\n");
1548										context.setRunInitialzersOldWay();
1549									}
1550				#endif
1551								}
1552							}
1553							else if ( mh->filetype == MH_DYLIB ) {
1554								const char* installPath = this->getInstallPath();
1555								if ( (installPath != NULL) && (strncmp(installPath, "/usr/lib/", 9) == 0) ) {
1556									if ( sect->size > offsetof(DATAdyld, vars) ) {
1557										// use ProgramVars from libdyld.dylib but tweak mh field to correct value
1558										dd->vars.mh = context.mainExecutable->machHeader();
1559										context.setNewProgramVars(dd->vars);
1560									}
1561								}
1562							}
1563						}
1564						else if ( (strcmp(sect->sectname, "__program_vars" ) == 0) && (mh->filetype == MH_EXECUTE) ) {
1565							// this is a Mac OS X 10.6 or later main executable
1566							struct ProgramVars* pv = (struct ProgramVars*)(sect->addr + fSlide);
1567							context.setNewProgramVars(*pv);
1568						}
1569					}
1570				}
1571			}
1572			cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
1573		}
1574	}
1575}
1576
1577
1578void ImageLoaderMachO::lookupProgramVars(const LinkContext& context) const
1579{
1580	ProgramVars vars = context.programVars;
1581	const ImageLoader::Symbol* sym;
1582
1583	// get mach header directly
1584	vars.mh = (macho_header*)fMachOData;
1585
1586	// lookup _NXArgc
1587	sym = this->findExportedSymbol("_NXArgc", false, NULL);
1588	if ( sym != NULL )
1589		vars.NXArgcPtr = (int*)this->getExportedSymbolAddress(sym, context, this, false);
1590
1591	// lookup _NXArgv
1592	sym = this->findExportedSymbol("_NXArgv", false, NULL);
1593	if ( sym != NULL )
1594		vars.NXArgvPtr = (const char***)this->getExportedSymbolAddress(sym, context, this, false);
1595
1596	// lookup _environ
1597	sym = this->findExportedSymbol("_environ", false, NULL);
1598	if ( sym != NULL )
1599		vars.environPtr = (const char***)this->getExportedSymbolAddress(sym, context, this, false);
1600
1601	// lookup __progname
1602	sym = this->findExportedSymbol("___progname", false, NULL);
1603	if ( sym != NULL )
1604		vars.__prognamePtr = (const char**)this->getExportedSymbolAddress(sym, context, this, false);
1605
1606	context.setNewProgramVars(vars);
1607}
1608
1609
1610bool ImageLoaderMachO::usablePrebinding(const LinkContext& context) const
1611{
1612	// if prebound and loaded at prebound address, and all libraries are same as when this was prebound, then no need to bind
1613	if ( ((this->isPrebindable() && (this->getSlide() == 0)) || fInSharedCache)
1614		&& this->usesTwoLevelNameSpace()
1615		&& this->allDependentLibrariesAsWhenPreBound() ) {
1616		// allow environment variables to disable prebinding
1617		if ( context.bindFlat )
1618			return false;
1619		switch ( context.prebindUsage ) {
1620			case kUseAllPrebinding:
1621				return true;
1622			case kUseSplitSegPrebinding:
1623				return this->fIsSplitSeg;
1624			case kUseAllButAppPredbinding:
1625				return (this != context.mainExecutable);
1626			case kUseNoPrebinding:
1627				return false;
1628		}
1629	}
1630	return false;
1631}
1632
1633
1634void ImageLoaderMachO::doImageInit(const LinkContext& context)
1635{
1636	if ( fHasDashInit ) {
1637		const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
1638		const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
1639		const struct load_command* cmd = cmds;
1640		for (uint32_t i = 0; i < cmd_count; ++i) {
1641			switch (cmd->cmd) {
1642				case LC_ROUTINES_COMMAND:
1643					Initializer func = (Initializer)(((struct macho_routines_command*)cmd)->init_address + fSlide);
1644					// <rdar://problem/8543820&9228031> verify initializers are in image
1645					if ( ! this->containsAddress((void*)func) ) {
1646						dyld::throwf("initializer function %p not in mapped image for %s\n", func, this->getPath());
1647					}
1648					if ( context.verboseInit )
1649						dyld::log("dyld: calling -init function %p in %s\n", func, this->getPath());
1650					func(context.argc, context.argv, context.envp, context.apple, &context.programVars);
1651					break;
1652			}
1653			cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
1654		}
1655	}
1656}
1657
1658void ImageLoaderMachO::doModInitFunctions(const LinkContext& context)
1659{
1660	if ( fHasInitializers ) {
1661		const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
1662		const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
1663		const struct load_command* cmd = cmds;
1664		for (uint32_t i = 0; i < cmd_count; ++i) {
1665			if ( cmd->cmd == LC_SEGMENT_COMMAND ) {
1666				const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
1667				const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
1668				const struct macho_section* const sectionsEnd = &sectionsStart[seg->nsects];
1669				for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
1670					const uint8_t type = sect->flags & SECTION_TYPE;
1671					if ( type == S_MOD_INIT_FUNC_POINTERS ) {
1672						Initializer* inits = (Initializer*)(sect->addr + fSlide);
1673						const uint32_t count = sect->size / sizeof(uintptr_t);
1674						for (uint32_t i=0; i < count; ++i) {
1675							Initializer func = inits[i];
1676							// <rdar://problem/8543820&9228031> verify initializers are in image
1677							if ( ! this->containsAddress((void*)func) ) {
1678								dyld::throwf("initializer function %p not in mapped image for %s\n", func, this->getPath());
1679							}
1680							if ( context.verboseInit )
1681								dyld::log("dyld: calling initializer function %p in %s\n", func, this->getPath());
1682							func(context.argc, context.argv, context.envp, context.apple, &context.programVars);
1683						}
1684					}
1685				}
1686			}
1687			cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
1688		}
1689	}
1690}
1691
1692
1693
1694
1695
1696
1697void ImageLoaderMachO::doGetDOFSections(const LinkContext& context, std::vector<ImageLoader::DOFInfo>& dofs)
1698{
1699	if ( fHasDOFSections ) {
1700		// walk load commands (mapped in at start of __TEXT segment)
1701		const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
1702		const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
1703		const struct load_command* cmd = cmds;
1704		for (uint32_t i = 0; i < cmd_count; ++i) {
1705			switch (cmd->cmd) {
1706				case LC_SEGMENT_COMMAND:
1707					{
1708						const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
1709						const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
1710						const struct macho_section* const sectionsEnd = &sectionsStart[seg->nsects];
1711						for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
1712							if ( (sect->flags & SECTION_TYPE) == S_DTRACE_DOF ) {
1713								ImageLoader::DOFInfo info;
1714								info.dof			= (void*)(sect->addr + fSlide);
1715								info.imageHeader	= this->machHeader();
1716								info.imageShortName = this->getShortName();
1717								dofs.push_back(info);
1718							}
1719						}
1720					}
1721					break;
1722			}
1723			cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
1724		}
1725	}
1726}
1727
1728
1729bool ImageLoaderMachO::doInitialization(const LinkContext& context)
1730{
1731	CRSetCrashLogMessage2(this->getPath());
1732
1733	// mach-o has -init and static initializers
1734	doImageInit(context);
1735	doModInitFunctions(context);
1736
1737	CRSetCrashLogMessage2(NULL);
1738
1739	return (fHasDashInit || fHasInitializers);
1740}
1741
1742bool ImageLoaderMachO::needsInitialization()
1743{
1744	return ( fHasDashInit || fHasInitializers );
1745}
1746
1747
1748bool ImageLoaderMachO::needsTermination()
1749{
1750	return fHasTerminators;
1751}
1752
1753
1754void ImageLoaderMachO::doTermination(const LinkContext& context)
1755{
1756	if ( fHasTerminators ) {
1757		const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
1758		const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
1759		const struct load_command* cmd = cmds;
1760		for (uint32_t i = 0; i < cmd_count; ++i) {
1761			if ( cmd->cmd == LC_SEGMENT_COMMAND ) {
1762				const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
1763				const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
1764				const struct macho_section* const sectionsEnd = &sectionsStart[seg->nsects];
1765				for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
1766					const uint8_t type = sect->flags & SECTION_TYPE;
1767					if ( type == S_MOD_TERM_FUNC_POINTERS ) {
1768						Terminator* terms = (Terminator*)(sect->addr + fSlide);
1769						const uint32_t count = sect->size / sizeof(uintptr_t);
1770						for (uint32_t i=count; i > 0; --i) {
1771							Terminator func = terms[i-1];
1772							// <rdar://problem/8543820&9228031> verify terminators are in image
1773							if ( ! this->containsAddress((void*)func) ) {
1774								dyld::throwf("termination function %p not in mapped image for %s\n", func, this->getPath());
1775							}
1776							if ( context.verboseInit )
1777								dyld::log("dyld: calling termination function %p in %s\n", func, this->getPath());
1778							func();
1779						}
1780					}
1781				}
1782			}
1783			cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
1784		}
1785	}
1786}
1787
1788
1789void ImageLoaderMachO::printStatistics(unsigned int imageCount, const InitializerTimingList& timingInfo)
1790{
1791	ImageLoader::printStatistics(imageCount, timingInfo);
1792	dyld::log("total symbol trie searches:    %d\n", fgSymbolTrieSearchs);
1793	dyld::log("total symbol table binary searches:    %d\n", fgSymbolTableBinarySearchs);
1794	dyld::log("total images defining weak symbols:  %u\n", fgImagesHasWeakDefinitions);
1795	dyld::log("total images using weak symbols:  %u\n", fgImagesRequiringCoalescing);
1796}
1797
1798
1799intptr_t ImageLoaderMachO::assignSegmentAddresses(const LinkContext& context)
1800{
1801	// preflight and calculate slide if needed
1802	const bool inPIE = (fgNextPIEDylibAddress != 0);
1803	intptr_t slide = 0;
1804	if ( this->segmentsCanSlide() && this->segmentsMustSlideTogether() ) {
1805		bool needsToSlide = false;
1806		bool imageHasPreferredLoadAddress = segHasPreferredLoadAddress(0);
1807		uintptr_t lowAddr = (unsigned long)(-1);
1808		uintptr_t highAddr = 0;
1809		for(unsigned int i=0, e=segmentCount(); i < e; ++i) {
1810			const uintptr_t segLow = segPreferredLoadAddress(i);
1811			const uintptr_t segHigh = (segLow + segSize(i) + 4095) & -4096;
1812			if ( segLow < lowAddr )
1813				lowAddr = segLow;
1814			if ( segHigh > highAddr )
1815				highAddr = segHigh;
1816
1817			if ( needsToSlide || !imageHasPreferredLoadAddress || inPIE || !reserveAddressRange(segPreferredLoadAddress(i), segSize(i)) )
1818				needsToSlide = true;
1819		}
1820		if ( needsToSlide ) {
1821			// find a chunk of address space to hold all segments
1822			uintptr_t addr = reserveAnAddressRange(highAddr-lowAddr, context);
1823			slide = addr - lowAddr;
1824		}
1825	}
1826	else if ( ! this->segmentsCanSlide() ) {
1827		for(unsigned int i=0, e=segmentCount(); i < e; ++i) {
1828			if ( strcmp(segName(i), "__PAGEZERO") == 0 )
1829				continue;
1830			if ( !reserveAddressRange(segPreferredLoadAddress(i), segSize(i)) )
1831				dyld::throwf("can't map unslidable segment %s to 0x%lX with size 0x%lX", segName(i), segPreferredLoadAddress(i), segSize(i));
1832		}
1833	}
1834	else {
1835		throw "mach-o does not support independently sliding segments";
1836	}
1837	return slide;
1838}
1839
1840
1841uintptr_t ImageLoaderMachO::reserveAnAddressRange(size_t length, const ImageLoader::LinkContext& context)
1842{
1843	vm_address_t addr = 0;
1844	vm_size_t size = length;
1845	// in PIE programs, load initial dylibs after main executable so they don't have fixed addresses either
1846	if ( fgNextPIEDylibAddress != 0 ) {
1847		 // add small (0-3 pages) random padding between dylibs
1848		addr = fgNextPIEDylibAddress + (__stack_chk_guard/fgNextPIEDylibAddress & (sizeof(long)-1))*4096;
1849		//dyld::log("padding 0x%08llX, guard=0x%08llX\n", (long long)(addr - fgNextPIEDylibAddress), (long long)(__stack_chk_guard));
1850		kern_return_t r = vm_alloc(&addr, size, VM_FLAGS_FIXED | VM_MAKE_TAG(VM_MEMORY_DYLIB));
1851		if ( r == KERN_SUCCESS ) {
1852			fgNextPIEDylibAddress = addr + size;
1853			return addr;
1854		}
1855		fgNextPIEDylibAddress = 0;
1856	}
1857	kern_return_t r = vm_alloc(&addr, size, VM_FLAGS_ANYWHERE | VM_MAKE_TAG(VM_MEMORY_DYLIB));
1858	if ( r != KERN_SUCCESS )
1859		throw "out of address space";
1860
1861	return addr;
1862}
1863
1864bool ImageLoaderMachO::reserveAddressRange(uintptr_t start, size_t length)
1865{
1866	vm_address_t addr = start;
1867	vm_size_t size = length;
1868	kern_return_t r = vm_alloc(&addr, size, VM_FLAGS_FIXED | VM_MAKE_TAG(VM_MEMORY_DYLIB));
1869	if ( r != KERN_SUCCESS )
1870		return false;
1871	return true;
1872}
1873
1874
1875
1876void ImageLoaderMachO::mapSegments(int fd, uint64_t offsetInFat, uint64_t lenInFat, uint64_t fileLen, const LinkContext& context)
1877{
1878	// find address range for image
1879	intptr_t slide = this->assignSegmentAddresses(context);
1880	if ( context.verboseMapping )
1881		dyld::log("dyld: Mapping %s\n", this->getPath());
1882	// map in all segments
1883	for(unsigned int i=0, e=segmentCount(); i < e; ++i) {
1884		vm_offset_t fileOffset = segFileOffset(i) + offsetInFat;
1885		vm_size_t size = segFileSize(i);
1886		uintptr_t requestedLoadAddress = segPreferredLoadAddress(i) + slide;
1887		int protection = 0;
1888		if ( !segUnaccessible(i) ) {
1889			// If has text-relocs, don't set x-bit initially.
1890			// Instead set it later after text-relocs have been done.
1891			// The iPhone OS does not like it when you make executable code writable.
1892			if ( segExecutable(i) && !(segHasRebaseFixUps(i) && (slide != 0)) )
1893				protection   |= PROT_EXEC;
1894			if ( segReadable(i) )
1895				protection   |= PROT_READ;
1896			if ( segWriteable(i) )
1897				protection   |= PROT_WRITE;
1898		}
1899	#if __i386__
1900		// initially map __IMPORT segments R/W so dyld can update them
1901		if ( segIsReadOnlyImport(i) )
1902			protection |= PROT_WRITE;
1903	#endif
1904		// wholly zero-fill segments have nothing to mmap() in
1905		if ( size > 0 ) {
1906			if ( (fileOffset+size) > fileLen ) {
1907				dyld::throwf("truncated mach-o error: segment %s extends to %llu which is past end of file %llu",
1908								segName(i), (uint64_t)(fileOffset+size), fileLen);
1909			}
1910			void* loadAddress = xmmap((void*)requestedLoadAddress, size, protection, MAP_FIXED | MAP_PRIVATE, fd, fileOffset);
1911			if ( loadAddress == ((void*)(-1)) ) {
1912				dyld::throwf("mmap() error %d at address=0x%08lX, size=0x%08lX segment=%s in Segment::map() mapping %s",
1913					errno, requestedLoadAddress, (uintptr_t)size, segName(i), getPath());
1914			}
1915		}
1916		// update stats
1917		++ImageLoader::fgTotalSegmentsMapped;
1918		ImageLoader::fgTotalBytesMapped += size;
1919		if ( context.verboseMapping )
1920			dyld::log("%18s at 0x%08lX->0x%08lX with permissions %c%c%c\n", segName(i), requestedLoadAddress, requestedLoadAddress+size-1,
1921				(protection & PROT_READ) ? 'r' : '.',  (protection & PROT_WRITE) ? 'w' : '.',  (protection & PROT_EXEC) ? 'x' : '.' );
1922	}
1923
1924	// update slide to reflect load location
1925	this->setSlide(slide);
1926}
1927
1928void ImageLoaderMachO::mapSegments(const void* memoryImage, uint64_t imageLen, const LinkContext& context)
1929{
1930	// find address range for image
1931	intptr_t slide = this->assignSegmentAddresses(context);
1932	if ( context.verboseMapping )
1933		dyld::log("dyld: Mapping memory %p\n", memoryImage);
1934	// map in all segments
1935	for(unsigned int i=0, e=segmentCount(); i < e; ++i) {
1936		vm_address_t loadAddress = segPreferredLoadAddress(i) + slide;
1937		vm_address_t srcAddr = (uintptr_t)memoryImage + segFileOffset(i);
1938		vm_size_t size = segFileSize(i);
1939		kern_return_t r = vm_copy(mach_task_self(), srcAddr, size, loadAddress);
1940		if ( r != KERN_SUCCESS )
1941			throw "can't map segment";
1942		if ( context.verboseMapping )
1943			dyld::log("%18s at 0x%08lX->0x%08lX\n", segName(i), (uintptr_t)loadAddress, (uintptr_t)loadAddress+size-1);
1944	}
1945	// update slide to reflect load location
1946	this->setSlide(slide);
1947	// set R/W permissions on all segments at slide location
1948	for(unsigned int i=0, e=segmentCount(); i < e; ++i) {
1949		segProtect(i, context);
1950	}
1951}
1952
1953
1954void ImageLoaderMachO::segProtect(unsigned int segIndex, const ImageLoader::LinkContext& context)
1955{
1956	vm_prot_t protection = 0;
1957	if ( !segUnaccessible(segIndex) ) {
1958		if ( segExecutable(segIndex) )
1959			protection   |= PROT_EXEC;
1960		if ( segReadable(segIndex) )
1961			protection   |= PROT_READ;
1962		if ( segWriteable(segIndex) )
1963			protection   |= PROT_WRITE;
1964	}
1965	vm_address_t addr = segActualLoadAddress(segIndex);
1966	vm_size_t size = segSize(segIndex);
1967	const bool setCurrentPermissions = false;
1968	kern_return_t r = vm_protect(mach_task_self(), addr, size, setCurrentPermissions, protection);
1969	if ( r != KERN_SUCCESS ) {
1970        dyld::throwf("vm_protect(0x%08llX, 0x%08llX, false, 0x%02X) failed, result=%d for segment %s in %s",
1971            (long long)addr, (long long)size, protection, r, segName(segIndex), this->getPath());
1972    }
1973	if ( context.verboseMapping ) {
1974		dyld::log("%18s at 0x%08lX->0x%08lX altered permissions to %c%c%c\n", segName(segIndex), (uintptr_t)addr, (uintptr_t)addr+size-1,
1975			(protection & PROT_READ) ? 'r' : '.',  (protection & PROT_WRITE) ? 'w' : '.',  (protection & PROT_EXEC) ? 'x' : '.' );
1976	}
1977}
1978
1979void ImageLoaderMachO::segMakeWritable(unsigned int segIndex, const ImageLoader::LinkContext& context)
1980{
1981	vm_address_t addr = segActualLoadAddress(segIndex);
1982	vm_size_t size = segSize(segIndex);
1983	const bool setCurrentPermissions = false;
1984	vm_prot_t protection = VM_PROT_WRITE | VM_PROT_READ;
1985	if ( segExecutable(segIndex) && !segHasRebaseFixUps(segIndex) )
1986		protection |= VM_PROT_EXECUTE;
1987	kern_return_t r = vm_protect(mach_task_self(), addr, size, setCurrentPermissions, protection);
1988	if ( r != KERN_SUCCESS ) {
1989        dyld::throwf("vm_protect(0x%08llX, 0x%08llX, false, 0x%02X) failed, result=%d for segment %s in %s",
1990            (long long)addr, (long long)size, protection, r, segName(segIndex), this->getPath());
1991    }
1992	if ( context.verboseMapping ) {
1993		dyld::log("%18s at 0x%08lX->0x%08lX altered permissions to %c%c%c\n", segName(segIndex), (uintptr_t)addr, (uintptr_t)addr+size-1,
1994			(protection & PROT_READ) ? 'r' : '.',  (protection & PROT_WRITE) ? 'w' : '.',  (protection & PROT_EXEC) ? 'x' : '.' );
1995	}
1996}
1997
1998
1999