Loading...
src/ImageLoaderMachOClassic.cpp dyld-239.4 dyld-195.6
--- dyld/dyld-239.4/src/ImageLoaderMachOClassic.cpp
+++ dyld/dyld-195.6/src/ImageLoaderMachOClassic.cpp
@@ -44,6 +44,9 @@
 #include <libkern/OSAtomic.h>
 #include <libkern/OSCacheControl.h>
 
+#if __ppc__ || __ppc64__
+	#include <mach-o/ppc/reloc.h>
+#endif
 #if __x86_64__
 	#include <mach-o/x86_64/reloc.h>
 #endif
@@ -53,6 +56,14 @@
 
 #include "ImageLoaderMachOClassic.h"
 #include "mach-o/dyld_images.h"
+
+// optimize strcmp for ppc
+#if __ppc__
+	#include <ppc_intrinsics.h>
+#else
+	#define astrcmp(a,b) strcmp(a,b)
+#endif
+
 
 // in dyldStartup.s
 extern "C" void fast_stub_binding_helper_interface();
@@ -136,8 +147,11 @@
 		// record info about file  
 		image->setFileInfo(info.st_dev, info.st_ino, info.st_mtime);
 
+	#if CODESIGNING_SUPPORT
 		// if this image is code signed, let kernel validate signature before mapping any pages from image
-		image->loadCodeSignature(codeSigCmd, fd, offsetInFat, context);
+		if ( codeSigCmd != NULL )
+			image->loadCodeSignature(codeSigCmd, fd, offsetInFat);
+	#endif
 		
 		// mmap segments
 		image->mapSegmentsClassic(fd, offsetInFat, lenInFat, info.st_size, context);
@@ -149,12 +163,11 @@
 		const char* installName = image->getInstallPath();
 		if ( (installName != NULL) && (strcmp(installName, path) == 0) && (path[0] == '/') )
 			image->setPathUnowned(installName);
-		else if ( (path[0] != '/') || (strstr(path, "../") != NULL) ) {
-			// rdar://problem/10733082 Fix up @path based paths during introspection
+		else if ( path[0] != '/' ) {
 			// rdar://problem/5135363 turn relative paths into absolute paths so gdb, Symbolication can later find them
 			char realPath[MAXPATHLEN];
-			if ( fcntl(fd, F_GETPATH, realPath) == 0 ) 
-				image->setPaths(path, realPath);
+			if ( realpath(path, realPath) != NULL )
+				image->setPath(realPath);
 			else
 				image->setPath(path);
 		}
@@ -716,6 +729,33 @@
 }
 
 
+#if __ppc__
+static inline void otherRelocsPPC(uintptr_t* locationToFix, uint8_t relocationType, uint16_t otherHalf, uintptr_t slide)
+{
+	// low 16 bits of 32-bit ppc instructions need fixing
+	struct ppcInstruction { uint16_t opcode; int16_t immediateValue; };
+	ppcInstruction* instruction = (ppcInstruction*)locationToFix;
+	//uint32_t before = *((uint32_t*)locationToFix);
+	switch ( relocationType )
+	{
+		case PPC_RELOC_LO16: 
+			instruction->immediateValue = ((otherHalf << 16) | instruction->immediateValue) + slide;
+			break;
+		case PPC_RELOC_HI16: 
+			instruction->immediateValue = ((((instruction->immediateValue << 16) | otherHalf) + slide) >> 16);
+			break;
+		case PPC_RELOC_HA16: 
+			int16_t signedOtherHalf = (int16_t)(otherHalf & 0xffff);
+			uint32_t temp = (instruction->immediateValue << 16) + signedOtherHalf + slide;
+			if ( (temp & 0x00008000) != 0 )
+				temp += 0x00008000;
+			instruction->immediateValue = temp >> 16;
+	}
+	//uint32_t after = *((uint32_t*)locationToFix);
+	//dyld::log("dyld: ppc fixup %0p type %d from 0x%08X to 0x%08X\n", locationToFix, relocationType, before, after);
+}
+#endif
+
 #if PREBOUND_IMAGE_SUPPORT
 void ImageLoaderMachOClassic::resetPreboundLazyPointers(const LinkContext& context)
 {
@@ -730,6 +770,11 @@
 			if (sreloc->r_length == RELOC_SIZE) {
 				uintptr_t* locationToFix = (uintptr_t*)(sreloc->r_address + relocBase);
 				switch(sreloc->r_type) {
+		#if __ppc__ 
+					case PPC_RELOC_PB_LA_PTR:
+						*locationToFix = sreloc->r_value + slide;
+						break;
+		#endif
 		#if __i386__
 					case GENERIC_RELOC_PB_LA_PTR:
 						*locationToFix = sreloc->r_value + slide;
@@ -764,7 +809,6 @@
 	const relocation_info* const relocsStart = (struct relocation_info*)(&fLinkEditBase[fDynamicInfo->locreloff]);
 	const relocation_info* const relocsEnd = &relocsStart[fDynamicInfo->nlocrel];
 	for (const relocation_info* reloc=relocsStart; reloc < relocsEnd; ++reloc) {
-		uintptr_t rebaseAddr;
 		try {
 	#if LINKEDIT_USAGE_DEBUG
 			noteAccessedLinkEditAddress(reloc);
@@ -779,12 +823,7 @@
 				throw "bad local relocation pc_rel";
 			if ( reloc->r_extern != 0 ) 
 				throw "extern relocation found with local relocations";
-			rebaseAddr = reloc->r_address + relocBase;
-			if ( ! this->containsAddress((void*)rebaseAddr) )
-				dyld::throwf("local reloc %p not in mapped image\n", (void*)rebaseAddr);
-			*((uintptr_t*)rebaseAddr) += slide;
-			if ( context.verboseRebase )
-				dyld::log("dyld: rebase: %s:*0x%08lX += 0x%08lX\n", this->getShortName(), rebaseAddr, slide);
+			*((uintptr_t*)(reloc->r_address + relocBase)) += slide;
 		#else	
 			if ( (reloc->r_address & R_SCATTERED) == 0 ) {
 				if ( reloc->r_symbolnum == R_ABS ) {
@@ -793,13 +832,17 @@
 				else if (reloc->r_length == RELOC_SIZE) {
 					switch(reloc->r_type) {
 						case GENERIC_RELOC_VANILLA:
-							rebaseAddr = reloc->r_address + relocBase;
-							if ( ! this->containsAddress((void*)rebaseAddr) )
-								dyld::throwf("local reloc %p not in mapped image\n", (void*)rebaseAddr);
-							*((uintptr_t*)rebaseAddr) += slide;
-							if ( context.verboseRebase )
-								dyld::log("dyld: rebase: %s:*0x%08lX += 0x%08lX\n", this->getShortName(), rebaseAddr, slide);
+							*((uintptr_t*)(reloc->r_address + relocBase)) += slide;
 							break;
+			#if __ppc__
+						case PPC_RELOC_HI16: 
+						case PPC_RELOC_LO16: 
+						case PPC_RELOC_HA16: 
+							// some tools leave object file relocations in linked images
+							otherRelocsPPC((uintptr_t*)(reloc->r_address + relocBase), reloc->r_type, reloc[1].r_address, slide);
+							++reloc; // these relocations come in pairs, skip next
+							break;
+			#endif
 						default:
 							throw "unknown local relocation type";
 					}
@@ -814,13 +857,26 @@
 					uintptr_t* locationToFix = (uintptr_t*)(sreloc->r_address + relocBase);
 					switch(sreloc->r_type) {
 						case GENERIC_RELOC_VANILLA:
-							if ( ! this->containsAddress((void*)locationToFix) ) 
-								dyld::throwf("local scattered reloc %p not in mapped image\n", locationToFix);
 							*locationToFix += slide;
-							if ( context.verboseRebase )
-								dyld::log("dyld: rebase: %s:*0x%08lX += 0x%08lX\n", this->getShortName(), (uintptr_t)locationToFix, slide);
 							break;
-			#if __i386__
+			#if __ppc__
+						case PPC_RELOC_HI16: 
+						case PPC_RELOC_LO16: 
+						case PPC_RELOC_HA16: 
+							// Metrowerks compiler sometimes leaves object file relocations in linked images???
+							++reloc; // these relocations come in pairs, get next one
+							otherRelocsPPC(locationToFix, sreloc->r_type, reloc->r_address, slide);
+							break;
+						case PPC_RELOC_PB_LA_PTR:
+							// do nothing
+							break;
+			#elif __ppc64__
+						case PPC_RELOC_PB_LA_PTR:
+							// needed for compatibility with ppc64 binaries built with the first ld64
+							// which used PPC_RELOC_PB_LA_PTR relocs instead of GENERIC_RELOC_VANILLA for lazy pointers
+							*locationToFix += slide;
+							break;
+			#elif __i386__
 						case GENERIC_RELOC_PB_LA_PTR:
 							// do nothing
 							break;
@@ -876,7 +932,7 @@
 		noteAccessedLinkEditAddress(pivot);
 		noteAccessedLinkEditAddress(pivotStr);
 #endif
-		int cmp = strcmp(key, pivotStr);
+		int cmp = astrcmp(key, pivotStr);
 		if ( cmp == 0 )
 			return pivot;
 		if ( cmp > 0 ) {
@@ -908,7 +964,7 @@
 		noteAccessedLinkEditAddress(pivot);
 		noteAccessedLinkEditAddress(pivotStr);
 #endif
-		int cmp = strcmp(key, pivotStr);
+		int cmp = astrcmp(key, pivotStr);
 		if ( cmp == 0 )
 			return pivot;
 		if ( cmp > 0 ) {
@@ -950,7 +1006,7 @@
 }
 
 
-uintptr_t ImageLoaderMachOClassic::exportedSymbolAddress(const LinkContext& context, const Symbol* symbol, const ImageLoader* requestor, bool runResolver) const
+uintptr_t ImageLoaderMachOClassic::exportedSymbolAddress(const LinkContext& context, const Symbol* symbol, bool runResolver) const
 {
 	const struct macho_nlist* sym = (macho_nlist*)symbol;
 	uintptr_t result = sym->n_value + fSlide;
@@ -1055,8 +1111,8 @@
 		}
 		const Symbol* sym;
 		if ( context.flatExportFinder(symbolName, &sym, foundIn) ) {
-			if ( *foundIn != this )
-				context.addDynamicReference(this, const_cast<ImageLoader*>(*foundIn));
+			if ( (*foundIn != this) && !(*foundIn)->neverUnload() )
+					this->addDynamicReference(*foundIn);
 			return (*foundIn)->getExportedSymbolAddress(sym, context, this);
 		}
 		// if a bundle is loaded privately the above will not find its exports
@@ -1078,8 +1134,8 @@
 		if ( !context.prebinding && !dontCoalesce && (symbolIsWeakReference(undefinedSymbol) || symbolIsWeakDefinition(undefinedSymbol)) ) {
 			const Symbol* sym;
 			if ( context.coalescedExportFinder(symbolName, &sym, foundIn) ) {
-				if ( *foundIn != this )
-					context.addDynamicReference(this, const_cast<ImageLoader*>(*foundIn));
+				if ( (*foundIn != this) && !(*foundIn)->neverUnload() )
+					this->addDynamicReference(*foundIn);
 				return (*foundIn)->getExportedSymbolAddress(sym, context, this);
 			}
 			//throwSymbolNotFound(context, symbolName, this->getPath(), "coalesced namespace");
@@ -1210,8 +1266,6 @@
 					{
 						const struct macho_nlist* undefinedSymbol = &fSymbolTable[reloc->r_symbolnum];
 						uintptr_t* location = ((uintptr_t*)(reloc->r_address + relocBase));
-						if ( ! this->containsAddress((void*)location) )
-							dyld::throwf("external reloc %p not in mapped image %s\n", (void*)location, this->getPath());
 						uintptr_t value = *location;
 						bool symbolAddrCached = true;
 					#if __i386__
@@ -1683,9 +1737,8 @@
 		}
 		cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
 	}
-	if ( boundSomething && (targetImage != this) ) {
-		context.addDynamicReference(this, targetImage);
-	}
+	if ( boundSomething && (targetImage != this) && !targetImage->neverUnload() )
+		this->addDynamicReference(targetImage);
 	
 	// mark that this symbol has already been bound, so we don't try to bind again
 	it.type = 1;