From: Apple Date: Tue, 21 Feb 2006 18:15:49 +0000 (+0000) Subject: dyld-44.17.tar.gz X-Git-Tag: mac-os-x-1044x86^0 X-Git-Url: https://git.saurik.com/apple/dyld.git/commitdiff_plain/a3afc0087327db0d95e867b54c3e279121d68893 dyld-44.17.tar.gz --- diff --git a/src/ImageLoader.cpp b/src/ImageLoader.cpp index a249245..2461374 100644 --- a/src/ImageLoader.cpp +++ b/src/ImageLoader.cpp @@ -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 diff --git a/src/ImageLoaderMachO.cpp b/src/ImageLoaderMachO.cpp index 3328e89..4dfdac2 100644 --- a/src/ImageLoaderMachO.cpp +++ b/src/ImageLoaderMachO.cpp @@ -38,6 +38,10 @@ #include #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 = §ionsStart[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 = §ionsStart[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 = §ionsStart[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()); diff --git a/src/ImageLoaderMachO.h b/src/ImageLoaderMachO.h index b540479..6a1220d 100644 --- a/src/ImageLoaderMachO.h +++ b/src/ImageLoaderMachO.h @@ -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; }; diff --git a/src/dyld.cpp b/src/dyld.cpp index 2017ba6..86c469c 100644 --- a/src/dyld.cpp +++ b/src/dyld.cpp @@ -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::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::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); diff --git a/src/dyldAPIs.cpp b/src/dyldAPIs.cpp index 7620fe6..584ca60 100644 --- a/src/dyldAPIs.cpp +++ b/src/dyldAPIs.cpp @@ -33,6 +33,7 @@ #include #include #include +#include extern "C" mach_port_name_t task_self_trap(void); // can't include 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(¤tTime, 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++; } diff --git a/src/glue.c b/src/glue.c index f627e56..1cd36ff 100644 --- a/src/glue.c +++ b/src/glue.c @@ -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; +} diff --git a/src/stub_binding_helper.s b/src/stub_binding_helper.s index af9c2d5..2e1e924 100644 --- a/src/stub_binding_helper.s +++ b/src/stub_binding_helper.s @@ -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 diff --git a/unit-tests/test-cases/flat-prebound/Makefile b/unit-tests/test-cases/flat-prebound/Makefile index b30c674..8727921 100644 --- a/unit-tests/test-cases/flat-prebound/Makefile +++ b/unit-tests/test-cases/flat-prebound/Makefile @@ -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 index 0000000..4bb9ecb --- /dev/null +++ b/unit-tests/test-cases/pthread-keys/Makefile @@ -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 index 0000000..e1832d8 --- /dev/null +++ b/unit-tests/test-cases/pthread-keys/main.c @@ -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 +#include +#include + +#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; +}