]> git.saurik.com Git - apple/dyld.git/commitdiff
dyld-44.17.tar.gz mac-os-x-1044x86 mac-os-x-1045x86 mac-os-x-1046x86 v44.17
authorApple <opensource@apple.com>
Tue, 21 Feb 2006 18:15:49 +0000 (18:15 +0000)
committerApple <opensource@apple.com>
Tue, 21 Feb 2006 18:15:49 +0000 (18:15 +0000)
src/ImageLoader.cpp
src/ImageLoaderMachO.cpp
src/ImageLoaderMachO.h
src/dyld.cpp
src/dyldAPIs.cpp
src/glue.c
src/stub_binding_helper.s
unit-tests/test-cases/flat-prebound/Makefile
unit-tests/test-cases/pthread-keys/Makefile [new file with mode: 0644]
unit-tests/test-cases/pthread-keys/main.c [new file with mode: 0644]

index a249245b23284afea3ae6753e99bd013d4ec0e64..246137421b82b0269f5cf78b38e03e1990e1a59a 100644 (file)
@@ -843,7 +843,7 @@ uint64_t ImageLoader::copyAndMap(const char* tempFile, uint8_t** fileToPrebind,
        struct statfs statfs_buf;
        if ( fstatfs(dst, &statfs_buf) != 0 )
                throwf("can't fstatfs(), errno=%d for %s", errno, tempFile);
-       uint64_t freespace = statfs_buf.f_bavail * statfs_buf.f_bsize;
+       uint64_t freespace = (uint64_t)statfs_buf.f_bavail * (uint64_t)statfs_buf.f_bsize;
        
        // closing notes:  
        //              ok to close file after mapped in
index 3328e89e20ccac18842ae54ceece00968f14025e..4dfdac26cab76e3856664409df32d9647b4fd4a6 100644 (file)
        #include <mach-o/ppc/reloc.h>
 #endif
 
+#ifndef S_ATTR_SELF_MODIFYING_CODE
+  #define S_ATTR_SELF_MODIFYING_CODE 0x04000000
+#endif
+
 #include "ImageLoaderMachO.h"
 #include "mach-o/dyld_gdb.h"
 
@@ -75,6 +79,7 @@ extern "C" void sys_icache_invalidate(void *, size_t);
 
 uint32_t ImageLoaderMachO::fgHintedBinaryTreeSearchs = 0;
 uint32_t ImageLoaderMachO::fgUnhintedBinaryTreeSearchs = 0;
+uint32_t ImageLoaderMachO::fgCountOfImagesWithWeakExports = 0;
 
 
 //#define LINKEDIT_USAGE_DEBUG 1
@@ -176,6 +181,12 @@ ImageLoaderMachO::ImageLoaderMachO(const char* path, int fd, const uint8_t first
        this->parseLoadCmds();
 }
 
+ImageLoaderMachO::~ImageLoaderMachO()
+{
+       // keep count of images with weak exports
+       if ( this->hasCoalescedExports() )
+               --fgCountOfImagesWithWeakExports;
+}
 
 
 
@@ -188,7 +199,8 @@ void ImageLoaderMachO::instantiateSegments(const uint8_t* fileData)
        const struct load_command* cmd = cmds;
        for (unsigned long i = 0; i < cmd_count; ++i) {
                if ( cmd->cmd == LC_SEGMENT_COMMAND ) {
-                       fSegments.push_back(new SegmentMachO((struct macho_segment_command*)cmd, this, fileData));
+                       if ( (((struct macho_segment_command*)cmd)->vmsize != 0) || !fIsSplitSeg )
+                               fSegments.push_back(new SegmentMachO((struct macho_segment_command*)cmd, this, fileData));
                }
                cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
        }
@@ -895,6 +907,10 @@ void ImageLoaderMachO::parseLoadCmds()
                }
        }
 
+       // keep count of prebound images with weak exports
+       if ( this->hasCoalescedExports() )
+               ++fgCountOfImagesWithWeakExports;
+
        // walk load commands (mapped in at start of __TEXT segment)
        const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
        const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
@@ -1926,6 +1942,40 @@ const void* ImageLoaderMachO::getBaseAddress() const
        return (const void*)seg->getActualLoadAddress();
 }
 
+uintptr_t ImageLoaderMachO::bindIndirectSymbol(uintptr_t* ptrToBind, const struct macho_section* sect, const char* symbolName, uintptr_t targetAddr, ImageLoader* targetImage, const LinkContext& context)
+{
+       if ( context.verboseBind ) {
+               const char* path = NULL;
+               if ( targetImage != NULL )
+                       path = targetImage->getShortName();
+               fprintf(stderr, "dyld: bind: %s:%s$%s = %s:%s, *0x%08lx = 0x%08lx\n",
+                               this->getShortName(), symbolName, (((sect->flags & SECTION_TYPE)==S_NON_LAZY_SYMBOL_POINTERS) ? "non_lazy_ptr" : "lazy_ptr"),
+                               path, symbolName, (uintptr_t)ptrToBind, targetAddr);
+       }
+       if ( context.bindingHandler != NULL ) {
+               const char* path = NULL;
+               if ( targetImage != NULL )
+                       path = targetImage->getShortName();
+               targetAddr = (uintptr_t)context.bindingHandler(path, symbolName, (void *)targetAddr);
+       }
+#if __i386__
+       // i386 has special self-modifying stubs that change from "CALL rel32" to "JMP rel32"
+       if ( ((sect->flags & SECTION_TYPE) == S_SYMBOL_STUBS) && ((sect->flags & S_ATTR_SELF_MODIFYING_CODE) != 0) && (sect->reserved2 == 5) ) {
+               uint8_t* const jmpTableEntryToPatch = (uint8_t*)ptrToBind;
+               uint32_t rel32 = targetAddr - (((uint32_t)ptrToBind)+5);
+               //fprintf(stderr, "rewriting stub at %p\n", jmpTableEntryToPatch);
+               jmpTableEntryToPatch[0] = 0xE9; // JMP rel32
+               jmpTableEntryToPatch[1] = rel32 & 0xFF;
+               jmpTableEntryToPatch[2] = (rel32 >> 8) & 0xFF;
+               jmpTableEntryToPatch[3] = (rel32 >> 16) & 0xFF;
+               jmpTableEntryToPatch[4] = (rel32 >> 24) & 0xFF;
+       }
+       else
+#endif
+       *ptrToBind = targetAddr;
+       return targetAddr;
+}
+
 
 uintptr_t ImageLoaderMachO::doBindLazySymbol(uintptr_t* lazyPointer, const LinkContext& context)
 {
@@ -1944,38 +1994,39 @@ uintptr_t ImageLoaderMachO::doBindLazySymbol(uintptr_t* lazyPointer, const LinkC
                                        const struct macho_section* const sectionsEnd = &sectionsStart[seg->nsects];
                                        for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
                                                const uint8_t type = sect->flags & SECTION_TYPE;
+                                               uint32_t symbolIndex = INDIRECT_SYMBOL_LOCAL;
                                                if ( type == S_LAZY_SYMBOL_POINTERS ) {
                                                        const uint32_t pointerCount = sect->size / sizeof(uintptr_t);
                                                        uintptr_t* const symbolPointers = (uintptr_t*)(sect->addr + fSlide);
                                                        if ( (lazyPointer >= symbolPointers) && (lazyPointer < &symbolPointers[pointerCount]) ) {
                                                                const uint32_t indirectTableOffset = sect->reserved1;
                                                                const uint32_t lazyIndex = lazyPointer - symbolPointers;
-                                                               uint32_t symbolIndex = indirectTable[indirectTableOffset + lazyIndex];
-                                                               if ( symbolIndex != INDIRECT_SYMBOL_ABS && symbolIndex != INDIRECT_SYMBOL_LOCAL ) {
-                                                                       ImageLoader *image = NULL;
-                                                                       const char *path = NULL;
-                                                                       uintptr_t symbolAddr = this->resolveUndefined(context,  &fSymbolTable[symbolIndex], twoLevel, &image);
-                                                                       if ( context.verboseBind ) {
-                                                                               if(NULL == path && NULL != image) {
-                                                                                       path = image->getShortName();
-                                                                               }
-                                                                               fprintf(stderr, "dyld: bind: %s:%s$%s = %s:%s, *0x%08lx = 0x%08lx\n",
-                                                                                               this->getShortName(), &fStrings[fSymbolTable[symbolIndex].n_un.n_strx], "lazy_ptr",
-                                                                                               path, &fStrings[fSymbolTable[symbolIndex].n_un.n_strx], (uintptr_t)&symbolPointers[lazyIndex], symbolAddr);
-                                                                       }
-                                                                       if ( NULL != context.bindingHandler ) {
-                                                                               if(NULL == path && NULL != image) {
-                                                                                       path = image->getPath();
-                                                                               }
-                                                                               symbolAddr = (uintptr_t)context.bindingHandler(path, &fStrings[fSymbolTable[symbolIndex].n_un.n_strx], (void *)symbolAddr);
-                                                                       }
-                                                                       symbolPointers[lazyIndex] = symbolAddr;
-                                                                       // update stats
-                                                                       fgTotalLazyBindFixups++;
-                                                                       return symbolPointers[lazyIndex];
-                                                               }
+                                                               symbolIndex = indirectTable[indirectTableOffset + lazyIndex];
                                                        }
                                                }
+                                       #if __i386__
+                                               else if ( (type == S_SYMBOL_STUBS) && (sect->flags & S_ATTR_SELF_MODIFYING_CODE) && (sect->reserved2 == 5) ) {
+                                                       // 5 bytes stubs on i386 are new "fast stubs"
+                                                       uint8_t* const jmpTableBase = (uint8_t*)(sect->addr + fSlide);
+                                                       uint8_t* const jmpTableEnd = jmpTableBase + sect->size;
+                                                       // initial CALL instruction in jump table leaves pointer to next entry, so back up
+                                                       uint8_t* const jmpTableEntryToPatch = ((uint8_t*)lazyPointer) - 5;  
+                                                       lazyPointer = (uintptr_t*)jmpTableEntryToPatch; 
+                                                       if ( (jmpTableEntryToPatch >= jmpTableBase) && (jmpTableEntryToPatch < jmpTableEnd) ) {
+                                                               const uint32_t indirectTableOffset = sect->reserved1;
+                                                               const uint32_t entryIndex = (jmpTableEntryToPatch - jmpTableBase)/5;
+                                                               symbolIndex = indirectTable[indirectTableOffset + entryIndex];
+                                                       }
+                                               }
+                                       #endif
+                                               if ( symbolIndex != INDIRECT_SYMBOL_ABS && symbolIndex != INDIRECT_SYMBOL_LOCAL ) {
+                                                       const char* symbolName = &fStrings[fSymbolTable[symbolIndex].n_un.n_strx];
+                                                       ImageLoader* image = NULL;
+                                                       uintptr_t symbolAddr = this->resolveUndefined(context,  &fSymbolTable[symbolIndex], twoLevel, &image);
+                                                       symbolAddr = this->bindIndirectSymbol(lazyPointer, sect, symbolName, symbolAddr, image,  context);
+                                                       ++fgTotalLazyBindFixups;
+                                                       return symbolAddr;
+                                               }
                                        }
                                }
                                break;
@@ -1987,6 +2038,7 @@ uintptr_t ImageLoaderMachO::doBindLazySymbol(uintptr_t* lazyPointer, const LinkC
 
 
 
+
 void ImageLoaderMachO::doBindIndirectSymbolPointers(const LinkContext& context, BindingLaziness bindness, bool onlyCoalescedSymbols)
 {
        // scan for all non-lazy-pointer sections 
@@ -2004,26 +2056,37 @@ void ImageLoaderMachO::doBindIndirectSymbolPointers(const LinkContext& context,
                                        const struct macho_section* const sectionsEnd = &sectionsStart[seg->nsects];
                                        for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
                                                const uint8_t type = sect->flags & SECTION_TYPE;
-                                               const uint32_t pointerCount = sect->size / sizeof(uintptr_t);
+                                               uint32_t elementSize = sizeof(uintptr_t);
+                                               uint32_t elementCount = sect->size / elementSize;
                                                if ( type == S_NON_LAZY_SYMBOL_POINTERS ) {
                                                        if ( (bindness == kLazyOnly) || (bindness == kLazyOnlyNoDependents) )
                                                                continue;
                                                }
                                                else if ( type == S_LAZY_SYMBOL_POINTERS ) {
                                                        // process each symbol pointer in this section
-                                                       fgTotalPossibleLazyBindFixups += pointerCount;
+                                                       fgTotalPossibleLazyBindFixups += elementCount;
                                                        if ( bindness == kNonLazyOnly )
                                                                continue;
                                                }
+                               #if __i386__
+                                               else if ( (type == S_SYMBOL_STUBS) && (sect->flags & S_ATTR_SELF_MODIFYING_CODE) && (sect->reserved2 == 5) ) {
+                                                       // process each jmp entry in this section
+                                                       elementCount = sect->size / 5;
+                                                       elementSize = 5;
+                                                       fgTotalPossibleLazyBindFixups += elementCount;
+                                                       if ( bindness == kNonLazyOnly )
+                                                               continue;
+                                               }
+                               #endif
                                                else {
                                                        continue;
                                                }
                                                const uint32_t indirectTableOffset = sect->reserved1;
-                                               uintptr_t* const symbolPointers = (uintptr_t*)(sect->addr + fSlide);
-                                               for (uint32_t j=0; j < pointerCount; ++j) {
+                                               uint8_t* ptrToBind = (uint8_t*)(sect->addr + fSlide);
+                                               for (uint32_t j=0; j < elementCount; ++j, ptrToBind += elementSize) {
                                                        uint32_t symbolIndex = indirectTable[indirectTableOffset + j];
                                                        if ( symbolIndex == INDIRECT_SYMBOL_LOCAL) {
-                                                               symbolPointers[j] += this->fSlide;
+                                                               *((uintptr_t*)ptrToBind) += this->fSlide;
                                                        }
                                                        else if ( symbolIndex == INDIRECT_SYMBOL_ABS) {
                                                                // do nothing since already has absolute address
@@ -2061,27 +2124,13 @@ void ImageLoaderMachO::doBindIndirectSymbolPointers(const LinkContext& context,
                                                                        continue;
                                                                uintptr_t symbolAddr;
                                                                        symbolAddr = resolveUndefined(context, sym, twoLevel, &image);
-                                                               if ( context.verboseBind ) {
-                                                                       const char *path = NULL;
-                                                                       if(NULL != image) {
-                                                                               path = image->getShortName();
-                                                                       }
-                                                                       const char *typeName;
-                                                                       if ( type == S_LAZY_SYMBOL_POINTERS ) {
-                                                                               typeName = "lazy_ptr";
-                                                                       }
-                                                                       else {
-                                                                               typeName = "non_lazy_ptr";
-                                                                       }
-                                                                       fprintf(stderr, "dyld: bind: %s:%s$%s = %s:%s, *0x%08lx = 0x%08lx\n",
-                                                                                       this->getShortName(), &fStrings[sym->n_un.n_strx], typeName,
-                                                                                       path, &fStrings[sym->n_un.n_strx], (uintptr_t)&symbolPointers[j], symbolAddr);
-                                                               }
-                                                               symbolPointers[j] = symbolAddr;
+                                                                       
+                                                               // update pointer
+                                                               symbolAddr = this->bindIndirectSymbol((uintptr_t*)ptrToBind, sect, &fStrings[sym->n_un.n_strx], symbolAddr, image,  context);
                                                        }
                                                }
                                                // update stats
-                                               fgTotalBindFixups += pointerCount;
+                                               fgTotalBindFixups += elementCount;
                                        }
                                }
                                break;
@@ -2120,9 +2169,10 @@ struct DATAdyld {
 // These are defined in dyldStartup.s
 extern "C" void stub_binding_helper();
 extern "C" bool dyld_func_lookup(const char* name, uintptr_t* address);
+extern "C" void fast_stub_binding_helper_interface();
 
 
-void ImageLoaderMachO::setupLazyPointerHandler()
+void ImageLoaderMachO::setupLazyPointerHandler(const LinkContext& context)
 {
        if ( fDATAdyld != NULL ) {
                struct DATAdyld* dd = (struct DATAdyld*)(fDATAdyld->addr + fSlide);
@@ -2141,6 +2191,42 @@ void ImageLoaderMachO::setupLazyPointerHandler()
                //      save = dd->stubBindHelper;      
 #endif
        }
+#if __i386__
+       if ( ! this->usablePrebinding(context) || !this->usesTwoLevelNameSpace() ) {
+               // reset all "fast" stubs
+               const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
+               const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
+               const struct load_command* cmd = cmds;
+               for (uint32_t i = 0; i < cmd_count; ++i) {
+                       switch (cmd->cmd) {
+                               case LC_SEGMENT_COMMAND:
+                               {
+                                       const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
+                                       const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
+                                       const struct macho_section* const sectionsEnd = &sectionsStart[seg->nsects];
+                                       for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
+                                               const uint8_t type = sect->flags & SECTION_TYPE;
+                                               if ( (type == S_SYMBOL_STUBS) && (sect->flags & S_ATTR_SELF_MODIFYING_CODE) && (sect->reserved2 == 5) ) {
+                                                       // reset each jmp entry in this section
+                                                       uint8_t* start = (uint8_t*)(sect->addr + this->fSlide);
+                                                       uint8_t* end = start + sect->size;
+                                                       uintptr_t dyldHandler = (uintptr_t)&fast_stub_binding_helper_interface;
+                                                       for (uint8_t* entry = start; entry < end; entry += 5) {
+                                                               uint32_t rel32 = dyldHandler - (((uint32_t)entry)+5);
+                                                               entry[0] = 0xE8; // CALL rel32
+                                                               entry[1] = rel32 & 0xFF;
+                                                               entry[2] = (rel32 >> 8) & 0xFF;
+                                                               entry[3] = (rel32 >> 16) & 0xFF;
+                                                               entry[4] = (rel32 >> 24) & 0xFF;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+               }
+       }
+#endif
 }
 
 bool ImageLoaderMachO::usablePrebinding(const LinkContext& context) const
@@ -2167,13 +2253,13 @@ bool ImageLoaderMachO::usablePrebinding(const LinkContext& context) const
 void ImageLoaderMachO::doBind(const LinkContext& context, BindingLaziness bindness)
 {
        // set dyld entry points in image
-       this->setupLazyPointerHandler();
+       this->setupLazyPointerHandler(context);
 
        // if prebound and loaded at prebound address, and all libraries are same as when this was prebound, then no need to bind
        // note: flat-namespace binaries need to be imports rebound (even if correctly prebound)
        if ( this->usablePrebinding(context) && this->usesTwoLevelNameSpace() ) {
-               // if image has coalesced symbols, then these need to be rebound
-               if ( this->needsCoalescing() ) {
+               // if image has coalesced symbols, then these need to be rebound, unless this is the only image with weak symbols
+               if ( this->needsCoalescing() && (fgCountOfImagesWithWeakExports > 1) ) {
                        this->doBindExternalRelocations(context, true);
                        this->doBindIndirectSymbolPointers(context, kLazyAndNonLazy, true);
                }
@@ -2278,6 +2364,7 @@ void ImageLoaderMachO::printStatistics(unsigned int imageCount)
        ImageLoader::printStatistics(imageCount);
        fprintf(stderr, "total hinted binary tree searches:    %d\n", fgHintedBinaryTreeSearchs);
        fprintf(stderr, "total unhinted binary tree searches:  %d\n", fgUnhintedBinaryTreeSearchs);
+       fprintf(stderr, "total images with weak exports:  %d\n", fgCountOfImagesWithWeakExports);
        
 #if LINKEDIT_USAGE_DEBUG
        fprintf(stderr, "linkedit pages accessed (%lu):\n", sLinkEditPageBuckets.size());
index b5404795df0db67eb3ef07b5f9d1f513937b5783..6a1220d8353dab7c898ab8ded9f675cb5300150b 100644 (file)
@@ -43,7 +43,7 @@ class ImageLoaderMachO : public ImageLoader {
 public:
                                                                                ImageLoaderMachO(const char* path, int fd, const uint8_t firstPage[4096], uint64_t offset, uint64_t len, const struct stat& info, const LinkContext& context);
                                                                                ImageLoaderMachO(const char* moduleName, const struct mach_header* mh, uint64_t len, const LinkContext& context);
-       virtual                                                         ~ImageLoaderMachO()  {}
+       virtual                                                         ~ImageLoaderMachO();
 
        const char*                                                     getInstallPath() const;
        virtual void*                                           getMain() const;
@@ -107,13 +107,14 @@ private:
 
                        void            init();
                        void            parseLoadCmds();
+                       uintptr_t       bindIndirectSymbol(uintptr_t* ptrToBind, const struct macho_section* sect, const char* symbolName, uintptr_t targetAddr, ImageLoader* targetImage, const LinkContext& context);
                        void            doBindIndirectSymbolPointers(const LinkContext& context, BindingLaziness bindness, bool onlyCoalescedSymbols);
                        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();
                        void            doImageInit(const LinkContext& context);
                        void            doModInitFunctions(const LinkContext& context);
-                       void            setupLazyPointerHandler();
+                       void            setupLazyPointerHandler(const LinkContext& context);
                        void            applyPrebindingToDATA(uint8_t* fileToPrebind);
                        void            applyPrebindingToLoadCommands(const LinkContext& context, uint8_t* fileToPrebind, time_t timestamp);
                        void            applyPrebindingToLinkEdit(const LinkContext& context, uint8_t* fileToPrebind);
@@ -158,6 +159,7 @@ private:
 
        static uint32_t                                 fgHintedBinaryTreeSearchs;
        static uint32_t                                 fgUnhintedBinaryTreeSearchs;
+       static uint32_t                                 fgCountOfImagesWithWeakExports;
 };
 
 
index 2017ba6318b98ae199de6325c63a19c2f675602b..86c469c8ad4d96adfaf413a8abad1eb81c357d25 100644 (file)
@@ -241,10 +241,6 @@ static void addImage(ImageLoader* image)
 
 void removeImage(ImageLoader* image)
 {
-       // flush find-by-address cache
-       if ( sLastImageByAddressCache == image )
-               sLastImageByAddressCache = NULL;
-
        // if in termination list, pull it out and run terminator
        for (std::vector<ImageLoader*>::iterator it=sImageFilesNeedingTermination.begin(); it != sImageFilesNeedingTermination.end(); it++) {
                if ( *it == image ) {
@@ -277,6 +273,10 @@ void removeImage(ImageLoader* image)
                }
        }
        
+       // flush find-by-address cache
+       if ( sLastImageByAddressCache == image )
+               sLastImageByAddressCache = NULL;
+
        // if in announcement list, pull it out 
        for (std::vector<ImageLoader*>::iterator it=sImagesToNotifyAboutOtherImages.begin(); it != sImagesToNotifyAboutOtherImages.end(); it++) {
                if ( *it == image ) {
@@ -821,6 +821,20 @@ ImageLoader* findImageContainingAddress(const void* addr)
        return NULL;
 }
 
+ImageLoader* findImageContainingAddressThreadSafe(const void* addr)
+{
+       // do exhastive search 
+       // todo: consider maintaining a list sorted by address ranges and do a binary search on that
+       const unsigned int imageCount = sAllImages.size();
+       for(unsigned int i=0; i < imageCount; ++i) {
+               ImageLoader* anImage = sAllImages[i];
+               if ( anImage->containsAddress(addr) ) {
+                       return anImage;
+               }
+       }
+       return NULL;
+}
+
 
 void forEachImageDo( void (*callback)(ImageLoader*, void* userData), void* userData)
 {
@@ -1700,8 +1714,17 @@ uintptr_t bindLazySymbol(const mach_header* mh, uintptr_t* lazyPointer)
 #endif
        // lookup and bind lazy pointer and get target address
        try {
+               ImageLoader* target;
+       #if __i386__
+               // fast stubs pass NULL for mh and image is instead found via the location of stub (aka lazyPointer)
+               if ( mh == NULL )
+                       target = dyld::findImageContainingAddressThreadSafe(lazyPointer);
+               else
+                       target = dyld::findImageByMachHeader(mh);
+       #else
                // note, target should always be mach-o, because only mach-o lazy handler wired up to this
-               ImageLoader* target = dyld::findImageByMachHeader(mh);
+               target = dyld::findImageByMachHeader(mh);
+       #endif
                if ( target == NULL )
                        throw "image not found for lazy pointer";
                result = target->doBindLazySymbol(lazyPointer, gLinkContext);
@@ -1937,6 +1960,17 @@ void link(ImageLoader* image, ImageLoader::BindingLaziness bindness, ImageLoader
 }
 
 
+//
+// _pthread_keys is partitioned in a lower part that dyld will use; libSystem
+// will use the upper part.  We set __pthread_tsd_first to 1 as the start of
+// the lower part.  Libc will take #1 and c++ exceptions will take #2.  There
+// is one free key=3 left.
+//
+extern "C" {
+       extern int __pthread_tsd_first;
+}
+
 //
 // Entry point for dyld.  The kernel loads dyld and jumps to __dyld_start which
 // sets up some registers and call this function.
@@ -1946,8 +1980,16 @@ void link(ImageLoader* image, ImageLoader::BindingLaziness bindness, ImageLoader
 uintptr_t
 _main(const struct mach_header* mainExecutableMH, int argc, const char* argv[], const char* envp[], const char* apple[])
 {      
+       // set pthread keys to dyld range
+       __pthread_tsd_first = 1;
+       
+       bool isEmulated = checkEmulation();
        // Pickup the pointer to the exec path.
        sExecPath = apple[0];
+       if (isEmulated) {
+               // under Rosetta 
+               sExecPath = strdup(apple[0] + strlen(apple[0]) + 1);
+       }
        if ( sExecPath[0] != '/' ) {
                // have relative path, use cwd to make absolute
                char cwdbuff[MAXPATHLEN];
@@ -1962,7 +2004,6 @@ _main(const struct mach_header* mainExecutableMH, int argc, const char* argv[],
        }
        uintptr_t result = 0;
        sMainExecutableMachHeader = mainExecutableMH;
-       bool isEmulated = checkEmulation();
        checkEnvironmentVariables(envp, isEmulated);
        if ( sEnv.DYLD_PRINT_OPTS ) 
                printOptions(argv);
index 7620fe683f9649479bb9c2c7c1b3fd371ebbb3e3..584ca602e46fbe8e2aab96173e3ae27947c8acea 100644 (file)
@@ -33,6 +33,7 @@
 #include <string.h>
 #include <mach/mach.h>
 #include <sys/time.h>
+#include <sys/sysctl.h>
 
 extern "C" mach_port_name_t    task_self_trap(void);  // can't include <System/mach/mach_traps.h> because it is missing extern C
 
@@ -1557,6 +1558,29 @@ static void _dyld_update_prebinding(int pathCount, const char* paths[], uint32_t
                else {
                        uint32_t imageCount = preboundImages.size();
                        uint32_t imageNumber = 1;
+
+                       // on Intel system, update_prebinding is run twice: i386, then emulated ppc
+                       // calculate fudge factors so that progress output represents both runs
+                       int denomFactor = 1;
+                       int numerAddend = 0;
+                       if (UPDATE_PREBINDING_PROGRESS & flags) {
+               #if __i386__
+                               // i386 half runs first, just double denominator
+                               denomFactor = 2;
+               #endif  
+               #if __ppc__
+                               // if emulated ppc, double denominator and shift numerator
+                               int mib[] = { CTL_KERN, KERN_CLASSIC, getpid() };
+                               int is_emulated = 0;
+                               size_t len = sizeof(int);
+                               int ret = sysctl(mib, 3, &is_emulated, &len, NULL, 0);
+                               if ((ret != -1) && is_emulated) {
+                                       denomFactor = 2;
+                                       numerAddend = imageCount;
+                               }
+               #endif
+                       }
+
                        // tell each image to write itself out re-prebound
                        struct timeval currentTime = { 0 , 0 };
                        gettimeofday(&currentTime, NULL);
@@ -1566,7 +1590,7 @@ static void _dyld_update_prebinding(int pathCount, const char* paths[], uint32_t
                                uint64_t freespace = (*it)->reprebind(dyld::gLinkContext, timestamp);
                                updatedImages.push_back(*it);
                                if(UPDATE_PREBINDING_PROGRESS & flags) {
-                                       fprintf(stdout, "update_prebinding: progress: %3u/%u\n", imageNumber, imageCount);
+                                       fprintf(stdout, "update_prebinding: progress: %3u/%u\n", imageNumber+numerAddend, imageCount*denomFactor);
                                        fflush(stdout);
                                        imageNumber++;
                                }
index f627e568458b83b33cd1c5c4b434940986f9387f..1cd36ff000934883883b15c2c24619a8231dea1c 100644 (file)
@@ -115,7 +115,12 @@ char* __hldtoa(/*long*/ double e, const char *xdigs, int ndigits, int *decpt, in
 
 int __fegetfltrounds(void) 
 {
-       return 1;                                       /* FE_NEAREST */
+       return 1;                                       /* FE_NEAREST */
+}
+
+int fegetround(void) 
+{
+       return 1;
 }
 
 /*
@@ -127,6 +132,7 @@ struct tm* localtime(const time_t* t)
        return (struct tm*)NULL;
 }
 
+
 /*
  * On ppc64, the C++ runtime references strftime & wcsftime, but they
  * never actually get called, and they try to use all the localtime()
@@ -154,3 +160,8 @@ char* __ldtoa(long double *ld, int mode, int ndigits, int *decpt, int *sign, cha
 {
        return "__ldtoa";
 }
+
+int __hexnan_D2A(const char **sp, void *fpi, unsigned long *x0)
+{
+       return 0;
+}
index af9c2d51b0bd89a675ff04bfa5d581f06cc6644a..2e1e924a78602fba975b30f7bc1b6111aa7ec4ff 100644 (file)
@@ -57,6 +57,9 @@
 
     .text
     .align 4,0x90
+       .globl _fast_stub_binding_helper_interface
+_fast_stub_binding_helper_interface:
+       pushl           $0
     .globl _stub_binding_helper_interface
 _stub_binding_helper_interface:
        pushl           %ebp
@@ -65,20 +68,20 @@ _stub_binding_helper_interface:
        movl            %eax,EAX_SAVE(%esp)             # save registers that might be used as parameters
        movl            %ecx,ECX_SAVE(%esp)
        movl            %edx,EDX_SAVE(%esp)
-       movdqu          %xmm0,XMMM0_SAVE(%esp)
-       movdqu          %xmm1,XMMM1_SAVE(%esp)
-       movdqu          %xmm2,XMMM2_SAVE(%esp)
-       movdqu          %xmm3,XMMM3_SAVE(%esp)
+       movdqa          %xmm0,XMMM0_SAVE(%esp)
+       movdqa          %xmm1,XMMM1_SAVE(%esp)
+       movdqa          %xmm2,XMMM2_SAVE(%esp)
+       movdqa          %xmm3,XMMM3_SAVE(%esp)
        movl            MH_PARAM_BP(%ebp),%eax  # call dyld::bindLazySymbol(mh, lazy_ptr)
        movl            %eax,MH_PARAM_OUT(%esp)
        movl            LP_PARAM_BP(%ebp),%eax
        movl            %eax,LP_PARAM_OUT(%esp)
        call            __ZN4dyld14bindLazySymbolEPK11mach_headerPm
        movl            %eax,RESULT_BP(%ebp)    # store target for ret
-       movdqu          XMMM0_SAVE(%esp),%xmm0  # restore registers
-       movdqu          XMMM1_SAVE(%esp),%xmm1
-       movdqu          XMMM2_SAVE(%esp),%xmm2
-       movdqu          XMMM3_SAVE(%esp),%xmm3
+       movdqa          XMMM0_SAVE(%esp),%xmm0  # restore registers
+       movdqa          XMMM1_SAVE(%esp),%xmm1
+       movdqa          XMMM2_SAVE(%esp),%xmm2
+       movdqa          XMMM3_SAVE(%esp),%xmm3
        movl            EAX_SAVE(%esp),%eax
        movl            ECX_SAVE(%esp),%ecx
        movl            EDX_SAVE(%esp),%edx
index b30c6742cdaa8c4b45f0f3c2f8bb0745d070059e..872792161b1658395a5467a14352d1a5486b01bc 100644 (file)
@@ -29,15 +29,15 @@ run: all
 all: main 
 
 main : main.c libfoo.dylib
-       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c libfoo.dylib
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c libfoo.dylib 
 
 
 libfoo.dylib : foo.c libbar.dylib
-       ${CC} ${CCFLAGS} -dynamiclib foo.c -o libfoo.dylib libbar.dylib -flat_namespace -prebind -seg1addr 20000
+       export MACOSX_DEPLOYMENT_TARGET=10.2 && ${CC} ${CCFLAGS} -dynamiclib foo.c -o libfoo.dylib libbar.dylib -flat_namespace -prebind -seg1addr 20000
 
 
 libbar.dylib : bar.c
-       ${CC} ${CCFLAGS} -dynamiclib bar.c -o libbar.dylib -prebind -seg1addr 30000
+       export MACOSX_DEPLOYMENT_TARGET=10.2 && ${CC} ${CCFLAGS} -dynamiclib bar.c -o libbar.dylib -prebind -seg1addr 30000
 
 
 
diff --git a/unit-tests/test-cases/pthread-keys/Makefile b/unit-tests/test-cases/pthread-keys/Makefile
new file mode 100644 (file)
index 0000000..4bb9ecb
--- /dev/null
@@ -0,0 +1,35 @@
+##
+# 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
+
+run: main
+       ./main
+
+
+main : main.c
+       ${CC} -I${TESTROOT}/include main.c -o main
+
+
+clean:
+       ${RM} ${RMFLAGS} *~  main 
diff --git a/unit-tests/test-cases/pthread-keys/main.c b/unit-tests/test-cases/pthread-keys/main.c
new file mode 100644 (file)
index 0000000..e1832d8
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * 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 <pthread.h>
+
+#include "test.h"
+
+///
+/// rdar://problem/4313830
+/// The key index for main executables starts at 4
+///
+
+int main()
+{
+       pthread_key_t key;
+       
+       int result = pthread_key_create(&key, NULL);
+       //printf("key=%u\n", key);
+       if ( result != 0 )
+               FAIL("pthread-keys creation failure");
+       else if ( key < 4 )
+               FAIL("pthread-keys key out of bounds");
+       else
+               PASS("pthread-keys");
+       return EXIT_SUCCESS;
+}