F939F219078F1A2100AC144F /* dyld_debug.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = dyld_debug.h; path = "include/mach-o/dyld_debug.h"; sourceTree = "<group>"; };
F99EE6AE06B48D4200BF1992 /* dlfcn.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = dlfcn.h; path = include/dlfcn.h; sourceTree = "<group>"; };
F9B01E3D0739ABDE00CF981B /* dyld.exp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.exports; name = dyld.exp; path = src/dyld.exp; sourceTree = SOURCE_ROOT; };
- F9ED4C980630A76000DF4E74 /* dyld */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dyld; sourceTree = BUILT_PRODUCTS_DIR; };
+ F9ED4C980630A76000DF4E74 /* dyld */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylinker"; includeInIndex = 0; path = dyld; sourceTree = BUILT_PRODUCTS_DIR; };
F9ED4C9F0630A76B00DF4E74 /* libdyldapis.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libdyldapis.a; sourceTree = BUILT_PRODUCTS_DIR; };
F9ED4CC60630A7F100DF4E74 /* dyld_gdb.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = dyld_gdb.cpp; path = src/dyld_gdb.cpp; sourceTree = SOURCE_ROOT; };
F9ED4CC70630A7F100DF4E74 /* dyld.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = dyld.cpp; path = src/dyld.cpp; sourceTree = SOURCE_ROOT; };
struct macho_routines_command : public routines_command {};
#endif
+ #define POINTER_RELOC GENERIC_RELOC_VANILLA
uint32_t ImageLoaderMachO::fgHintedBinaryTreeSearchs = 0;
uint32_t ImageLoaderMachO::fgUnhintedBinaryTreeSearchs = 0;
}
sNextAltLoadAddress += 0x00100000; // skip ahead 1MB and try again
if ( (sNextAltLoadAddress & 0xF0000000) == 0x90000000 )
+ sNextAltLoadAddress = 0xB0000000;
+ if ( (sNextAltLoadAddress & 0xF0000000) == 0xF0000000 )
throw "can't map split seg anywhere";
foundRoom = false;
break;
return info;
}
+uintptr_t ImageLoaderMachO::getFirstWritableSegmentAddress()
+{
+ // in split segment libraries r_address is offset from first writable segment
+ for (std::vector<class Segment*>::iterator it=fSegments.begin(); it != fSegments.end(); ++it) {
+ if ( (*it)->writeable() ) {
+ return (*it)->getActualLoadAddress();
+ }
+ }
+ throw "no writable segment";
+}
uintptr_t ImageLoaderMachO::getRelocBase()
{
+#if __ppc__ || __i386__
if ( fIsSplitSeg ) {
// in split segment libraries r_address is offset from first writable segment
- const unsigned int segmentCount = fSegments.size();
- for(unsigned int i=0; i < segmentCount; ++i){
- Segment* seg = fSegments[i];
- if ( seg->writeable() ) {
- return seg->getActualLoadAddress();
- }
- }
+ return getFirstWritableSegmentAddress();
}
+#endif
// in non-split segment libraries r_address is offset from first segment
return fSegments[0]->getActualLoadAddress();
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) {
+ #if __ppc__ || __ppc64__ || __i386__
if ( (reloc->r_address & R_SCATTERED) == 0 ) {
if ( reloc->r_symbolnum == R_ABS ) {
// ignore absolute relocations
throw "bad local scattered relocation length";
}
}
+ #endif
}
// if there were __TEXT fixups, restore write protection
}
}
+
return NULL;
}
for (const relocation_info* reloc=relocsStart; reloc < relocsEnd; ++reloc) {
if (reloc->r_length == RELOC_SIZE) {
switch(reloc->r_type) {
- case GENERIC_RELOC_VANILLA:
+ case POINTER_RELOC:
{
const struct macho_nlist* undefinedSymbol = &fSymbolTable[reloc->r_symbolnum];
// if only processing coalesced symbols and this one does not require coalesceing, skip to next
void doBindExternalRelocations(const LinkContext& context, bool onlyCoalescedSymbols);
uintptr_t resolveUndefined(const LinkContext& context, const struct macho_nlist* symbol, bool twoLevel, ImageLoader **foundIn);
uintptr_t getRelocBase();
+ uintptr_t getFirstWritableSegmentAddress();
void doImageInit(const LinkContext& context);
void doModInitFunctions(const LinkContext& context);
void setupLazyPointerHandler(const LinkContext& context);
/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
*
- * Copyright (c) 2004-2005 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2004-2006 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
}
}
+
static void checkEnvironmentVariables(const char* envp[], bool ignoreEnviron)
{
const char* home = NULL;
sEnv.LD_LIBRARY_PATH = parseColonList(path);
}
}
-
+
// default value for DYLD_FALLBACK_FRAMEWORK_PATH, if not set in environment
if ( sEnv.DYLD_FALLBACK_FRAMEWORK_PATH == NULL ) {
const char** paths = sFrameworkFallbackPaths;
- if ( home != NULL ) {
- if ( riskyUser() )
- removePathWithPrefix(paths, "$HOME");
- else
- paths_expand_roots(paths, "$HOME", home);
- }
+ if ( home == NULL )
+ removePathWithPrefix(paths, "$HOME");
+ else
+ paths_expand_roots(paths, "$HOME", home);
sEnv.DYLD_FALLBACK_FRAMEWORK_PATH = paths;
}
// default value for DYLD_FALLBACK_LIBRARY_PATH, if not set in environment
if ( sEnv.DYLD_FALLBACK_LIBRARY_PATH == NULL ) {
const char** paths = sLibraryFallbackPaths;
- if ( home != NULL ) {
- if ( riskyUser() )
- removePathWithPrefix(paths, "$HOME");
- else
- paths_expand_roots(paths, "$HOME", home);
- }
+ if ( home == NULL )
+ removePathWithPrefix(paths, "$HOME");
+ else
+ paths_expand_roots(paths, "$HOME", home);
sEnv.DYLD_FALLBACK_LIBRARY_PATH = paths;
}
}
return image;
}
- return NULL;
+ throw "main executable not a known format";
}
// Hack for transition of rdar://problem/3933738
// Can be removed later.
// Allow C++ runtime to call getsectdatafromheader or getsectdatafromheader_64
-#if __ppc64__
+#if __LP64__
#undef getsectdatafromheader
const void* getsectdatafromheader(struct mach_header* mh, const char* segname, const char* sectname, unsigned long* size)
{
#define RELOC_SIZE 2
#endif
+ #define POINTER_RELOC GENERIC_RELOC_VANILLA
//
// Code to bootstrap dyld into a runnable state
}
}
-
//
// If the kernel does not load dyld at its preferred address, we need to apply
// fixups to various initialized parts of the __DATA segment
//
static void rebaseDyld(const struct macho_header* mh, intptr_t slide)
{
- // get interesting pointers into dyld
+ // rebase non-lazy pointers (which all point internal to dyld, since dyld uses no shared libraries)
+ // and get interesting pointers into dyld
const uint32_t cmd_count = mh->ncmds;
const struct load_command* const cmds = (struct load_command*)(((char*)mh)+sizeof(macho_header));
const struct load_command* cmd = cmds;
const struct macho_segment_command* linkEditSeg = NULL;
const struct dysymtab_command* dynamicSymbolTable = NULL;
- const struct macho_section* nonLazySection = NULL;
for (uint32_t i = 0; i < cmd_count; ++i) {
switch (cmd->cmd) {
case LC_SEGMENT_COMMAND:
const struct macho_section* const sectionsEnd = §ionsStart[seg->nsects];
for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
const uint8_t type = sect->flags & SECTION_TYPE;
- if ( type == S_NON_LAZY_SYMBOL_POINTERS )
- nonLazySection = sect;
+ if ( type == S_NON_LAZY_SYMBOL_POINTERS ) {
+ // rebase non-lazy pointers (which all point internal to dyld, since dyld uses no shared libraries)
+ const uint32_t pointerCount = sect->size / sizeof(uintptr_t);
+ uintptr_t* const symbolPointers = (uintptr_t*)(sect->addr + slide);
+ for (uint32_t j=0; j < pointerCount; ++j) {
+ symbolPointers[j] += slide;
+ }
+ }
}
}
break;
const relocation_info* const relocsStart = (struct relocation_info*)(linkEditSeg->vmaddr + slide + dynamicSymbolTable->locreloff - linkEditSeg->fileoff);
const relocation_info* const relocsEnd = &relocsStart[dynamicSymbolTable->nlocrel];
for (const relocation_info* reloc=relocsStart; reloc < relocsEnd; ++reloc) {
- if ( (reloc->r_address & R_SCATTERED) == 0 ) {
- if (reloc->r_length == RELOC_SIZE) {
- switch(reloc->r_type) {
- case GENERIC_RELOC_VANILLA:
- *((uintptr_t*)(reloc->r_address + relocBase)) += slide;
- break;
- }
- }
- }
- else {
- const struct scattered_relocation_info* sreloc = (struct scattered_relocation_info*)reloc;
- if (sreloc->r_length == RELOC_SIZE) {
- uintptr_t* locationToFix = (uintptr_t*)(sreloc->r_address + relocBase);
- switch(sreloc->r_type) {
- case GENERIC_RELOC_VANILLA:
- #if __ppc__ || __ppc64__
- case PPC_RELOC_PB_LA_PTR:
- #elif __i386__
- case GENERIC_RELOC_PB_LA_PTR:
- #endif
- // Note the use of PB_LA_PTR is unique here. Seems like ld should strip out all lazy pointers
- // but it does not. But, since all lazy-pointers point within dyld, they can be slid too
- *locationToFix += slide;
- break;
- }
- }
- }
+ #if __ppc__ || __ppc64__ || __i36__
+ if ( (reloc->r_address & R_SCATTERED) != 0 )
+ throw "scattered relocation in dyld";
+ #endif
+ if ( reloc->r_length != RELOC_SIZE )
+ throw "relocation in dyld has wrong size";
+
+ if ( reloc->r_type != POINTER_RELOC )
+ throw "relocation in dyld has wrong type";
+
+ // update pointer by amount dyld slid
+ *((uintptr_t*)(reloc->r_address + relocBase)) += slide;
}
-
- // rebase non-lazy pointers (which all point internal to dyld, since dyld uses no shared libraries)
- if ( nonLazySection != NULL ) {
- const uint32_t pointerCount = nonLazySection->size / sizeof(uintptr_t);
- uintptr_t* const symbolPointers = (uintptr_t*)(nonLazySection->addr + slide);
- for (uint32_t j=0; j < pointerCount; ++j) {
- symbolPointers[j] += slide;
- }
- }
-
-
}
+
//
// For some reason the kernel loads dyld with __TEXT and __LINKEDIT writable
// rdar://problem/3702311
L_end:
#endif /* __i386__ */
+
+
#if __ppc__ || __ppc64__
#include <architecture/ppc/mode_independent_asm.h>
/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
+
#if __ppc__ || __ppc64__
#include <architecture/ppc/mode_independent_asm.h>
/*
--- /dev/null
+##
+# Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+#
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+#
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+#
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+ifeq "-arch ppc" "$(ARCH)"
+ CXX_VERSION = g++-3.3
+else
+ CXX_VERSION = ${CXX}
+endif
+
+run: all
+ ./main
+
+all: main test.bundle
+
+main : main.c
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+test.bundle : bundle.cxx
+ ${CC} ${CXXFLAGS} -bundle -o test.bundle bundle.cxx
+
+clean:
+ ${RM} ${RMFLAGS} *~ main test.bundle
+
+
--- /dev/null
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <stdio.h>
+
+extern "C"
+void foo()
+{
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <mach-o/dyld.h>
+
+#include "test.h" // PASS(), FAIL()
+
+///
+/// The point of this test is to load and unload a bundle and
+/// verify that the address->image cache is properly invalidated. rdar://problem/4212667
+///
+
+typedef void (*fooProc)();
+
+// test.bundle
+void doit()
+{
+ NSObjectFileImage ofi;
+ if ( NSCreateObjectFileImageFromFile("test.bundle", &ofi) != NSObjectFileImageSuccess ) {
+ FAIL("NSCreateObjectFileImageFromFile failed");
+ exit(0);
+ }
+
+ NSModule mod = NSLinkModule(ofi,"test.bundle", NSLINKMODULE_OPTION_PRIVATE | NSLINKMODULE_OPTION_BINDNOW | NSLINKMODULE_OPTION_RETURN_ON_ERROR);
+ if ( mod == NULL ) {
+ FAIL("NSLinkModule failed");
+ exit(0);
+ }
+
+ NSSymbol sym = NSLookupSymbolInModule(mod, "_foo");
+ if ( sym == NULL ) {
+ FAIL("NSLookupSymbolInModule failed");
+ exit(0);
+ }
+
+ fooProc func = (fooProc)NSAddressOfSymbol(sym);
+ (*func)();
+
+ if ( !NSUnLinkModule(mod, NSUNLINKMODULE_OPTION_NONE) ) {
+ FAIL("NSUnLinkModule failed");
+ exit(0);
+ }
+
+ if ( !NSDestroyObjectFileImage(ofi) ) {
+ FAIL("NSDestroyObjectFileImage failed");
+ exit(0);
+ }
+}
+
+
+static void myRemoveImage(const struct mach_header *mh, intptr_t vmaddr_slide)
+{
+ // calling _dyld_get_image_header_containing_address() during the remove image hook
+ // could cause dyld to not flush the address->image cache
+ _dyld_get_image_header_containing_address(mh);
+}
+
+
+int main()
+{
+ _dyld_register_func_for_remove_image(&myRemoveImage);
+
+ doit();
+ doit();
+ doit();
+
+ PASS("bundle-reload");
+ return 0;
+}
+
/*
- * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2005-2006 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
int main(int argc, const char *argv[])
{
const char* rhs = getenv("DYLD_INSERT_LIBRARIES");
- if ( rhs == NULL )
- FAIL("insert-libraries-with-suid DYLD_INSERT_LIBRARIES not set");
- else if ( rhs[0] != '\0' )
+ if ( (rhs != NULL) && (rhs[0] != '\0') )
FAIL("insert-libraries-with-suid DYLD_INSERT_LIBRARIES not cleared");
else
PASS("insert-libraries-with-suid");
--- /dev/null
+##
+# Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+#
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+#
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+#
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ export DYLD_INSERT_LIBRARIES=/ && export DYLD_PRINT_LIBRARIES=/ && export DYLD_PREBIND_DEBUG=/ && ./main
+
+all: main
+
+main: main.c
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+ sudo chown root main
+ sudo chmod 4755 main
+
+clean:
+ ${RM} ${RMFLAGS} *~ main
+
--- /dev/null
+/*
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <string.h> // strcmp(), strncmp()
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+//
+// binaries set to run as some other user id never see any DYLD_ environment variables
+//
+
+int main(int argc, const char* argv[], const char* envp[])
+{
+ for(const char** p = envp; *p != NULL; p++) {
+ //fprintf(stderr, "%s\n", *p);
+ if ( strncmp(*p, "DYLD_", 5) == 0 ) {
+ FAIL("suid-environ: found %s", *p);
+ return EXIT_SUCCESS;
+ }
+ }
+ PASS("suid-environ");
+ return EXIT_SUCCESS;
+}