Loading...
--- dyld/dyld-43/src/ImageLoader.cpp
+++ dyld/dyld-46.16/src/ImageLoader.cpp
@@ -31,6 +31,8 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
+#include <sys/param.h>
+#include <sys/mount.h>
#include "ImageLoader.h"
@@ -46,7 +48,7 @@
uint64_t ImageLoader::fgTotalNotifyTime;
uint64_t ImageLoader::fgTotalInitTime;
uintptr_t ImageLoader::fgNextSplitSegAddress = 0x90000000;
-uintptr_t Segment::fgNextNonSplitSegAddress = 0x8FE00000;
+uintptr_t Segment::fgNextNonSplitSegAddress = 0x8F000000;
@@ -262,21 +264,22 @@
return ( --fReferenceCount == 0 );
}
-
-const ImageLoader::Symbol* ImageLoader::resolveSymbol(const char* name, bool searchSelf, ImageLoader** foundIn) const
+// private method that handles circular dependencies by only search any image once
+const ImageLoader::Symbol* ImageLoader::findExportedSymbolInDependentImagesExcept(const char* name, std::set<const ImageLoader*>& dontSearchImages, ImageLoader** foundIn) const
{
const ImageLoader::Symbol* sym;
// search self
- if ( searchSelf ) {
+ if ( dontSearchImages.count(this) == 0 ) {
sym = this->findExportedSymbol(name, NULL, false, foundIn);
if ( sym != NULL )
return sym;
+ dontSearchImages.insert(this);
}
// search directly dependent libraries
for (uint32_t i=0; i < fLibrariesCount; ++i) {
ImageLoader* dependentImage = fLibraries[i].image;
- if ( dependentImage != NULL ) {
+ if ( (dependentImage != NULL) && (dontSearchImages.count(dependentImage) == 0) ) {
const ImageLoader::Symbol* sym = dependentImage->findExportedSymbol(name, NULL, false, foundIn);
if ( sym != NULL )
return sym;
@@ -286,16 +289,30 @@
// search indirectly dependent libraries
for (uint32_t i=0; i < fLibrariesCount; ++i) {
ImageLoader* dependentImage = fLibraries[i].image;
- if ( dependentImage != NULL ) {
- const ImageLoader::Symbol* sym = dependentImage->resolveSymbol(name, false, foundIn);
+ if ( (dependentImage != NULL) && (dontSearchImages.count(dependentImage) == 0) ) {
+ const ImageLoader::Symbol* sym = dependentImage->findExportedSymbolInDependentImagesExcept(name, dontSearchImages, foundIn);
if ( sym != NULL )
return sym;
+ dontSearchImages.insert(dependentImage);
}
}
return NULL;
}
+
+const ImageLoader::Symbol* ImageLoader::findExportedSymbolInDependentImages(const char* name, ImageLoader** foundIn) const
+{
+ std::set<const ImageLoader*> dontSearchImages;
+ dontSearchImages.insert(this); // don't search this image
+ return this->findExportedSymbolInDependentImagesExcept(name, dontSearchImages, foundIn);
+}
+
+const ImageLoader::Symbol* ImageLoader::findExportedSymbolInImageOrDependentImages(const char* name, ImageLoader** foundIn) const
+{
+ std::set<const ImageLoader*> dontSearchImages;
+ return this->findExportedSymbolInDependentImagesExcept(name, dontSearchImages, foundIn);
+}
void ImageLoader::link(const LinkContext& context, BindingLaziness bindness, InitializerRunning inits, uint32_t notifyCount)
@@ -489,6 +506,7 @@
const char* referencedFrom = this->getPath();
char buf[strlen(requiredLib.name)+strlen(referencedFrom)+strlen(formatString)+strlen(msg)+2];
sprintf(buf, formatString, requiredLib.name, referencedFrom, msg);
+ fLibrariesLoaded = false;
throw strdup(buf); // this is a leak if exception doesn't halt program
}
// ok if weak library not found
@@ -688,7 +706,7 @@
}
}
-void ImageLoader::reprebindCommit(const LinkContext& context, bool commit)
+void ImageLoader::reprebindCommit(const LinkContext& context, bool commit, bool unmapOld)
{
// do nothing on unprebound images
if ( ! this->isPrebindable() )
@@ -705,7 +723,9 @@
}
// recreate temp file name
char tempFilePath[PATH_MAX];
- ImageLoader::addSuffix(realFilePath, "_redoprebinding", tempFilePath);
+ char suffix[64];
+ sprintf(suffix, "_redoprebinding%d", getpid());
+ ImageLoader::addSuffix(realFilePath, suffix, tempFilePath);
if ( commit ) {
// all files successfully reprebound, so do swap
@@ -718,6 +738,9 @@
else
throwf("can't swap temporary re-prebound file: rename(%s,%s) returned errno=%d", tempFilePath, realFilePath, errno);
}
+ else if ( unmapOld ) {
+ this->prebindUnmap(context);
+ }
}
else {
// something went wrong during prebinding, delete the temp files
@@ -725,25 +748,32 @@
}
}
-void ImageLoader::reprebind(const LinkContext& context, time_t timestamp)
+uint64_t ImageLoader::reprebind(const LinkContext& context, time_t timestamp)
{
// do nothing on unprebound images
if ( ! this->isPrebindable() )
- return;
+ return INT64_MAX;
// do nothing if prebinding is up to date
if ( this->usablePrebinding(context) ) {
if ( context.verbosePrebinding )
fprintf(stderr, "dyld: no need to re-prebind: %s\n", this->getPath());
- return;
- }
+ return INT64_MAX;
+ }
+ // recreate temp file name
+ char realFilePath[PATH_MAX];
+ if ( realpath(this->getPath(), realFilePath) == NULL ) {
+ throwf("realpath() failed on %s, errno=%d", this->getPath(), errno);
+ }
+ char tempFilePath[PATH_MAX];
+ char suffix[64];
+ sprintf(suffix, "_redoprebinding%d", getpid());
+ ImageLoader::addSuffix(realFilePath, suffix, tempFilePath);
+
// make copy of file and map it in
- char tempFilePath[PATH_MAX];
- realpath(this->getPath(), tempFilePath);
- ImageLoader::addSuffix(this->getPath(), "_redoprebinding", tempFilePath);
uint8_t* fileToPrebind;
uint64_t fileToPrebindSize;
- this->copyAndMap(tempFilePath, &fileToPrebind, &fileToPrebindSize);
+ uint64_t freespace = this->copyAndMap(tempFilePath, &fileToPrebind, &fileToPrebindSize);
// do format specific prebinding
this->doPrebinding(context, timestamp, fileToPrebind);
@@ -758,10 +788,12 @@
// log
if ( context.verbosePrebinding )
- fprintf(stderr, "dyld: re-prebound: %s\n", this->getPath());
-}
-
-void ImageLoader::copyAndMap(const char* tempFile, uint8_t** fileToPrebind, uint64_t* fileToPrebindSize)
+ fprintf(stderr, "dyld: re-prebound: %p %s\n", this->machHeader(), this->getPath());
+
+ return freespace;
+}
+
+uint64_t ImageLoader::copyAndMap(const char* tempFile, uint8_t** fileToPrebind, uint64_t* fileToPrebindSize)
{
// reopen dylib
int src = open(this->getPath(), O_RDONLY);
@@ -778,16 +810,16 @@
int dst = open(tempFile, O_CREAT | O_RDWR | O_TRUNC, stat_buf.st_mode);
if ( dst == -1 )
throw "can't create temp image";
-
+
// mark source as "don't cache"
(void)fcntl(src, F_NOCACHE, 1);
// we want to cache the dst because we are about to map it in and modify it
// copy permission bits
if ( chmod(tempFile, stat_buf.st_mode & 07777) == -1 )
- throw "can't chmod temp image";
+ throwf("can't chmod temp image. errno=%d for %s", errno, this->getPath());
if ( chown(tempFile, stat_buf.st_uid, stat_buf.st_gid) == -1)
- throw "can't chown temp image";
+ throwf("can't chown temp image. errno=%d for %s", errno, this->getPath());
// copy contents
ssize_t len;
@@ -801,7 +833,8 @@
throw "can't allcoate copy buffer";
}
while ( (len = read(src, buffer, kBufferSize)) > 0 ) {
- write(dst, buffer, len);
+ if ( write(dst, buffer, len) == -1 )
+ throwf("write failure copying dylib errno=%d for %s", errno, this->getPath());
}
// map in dst file
@@ -810,6 +843,12 @@
if ( *fileToPrebind == (uint8_t*)(-1) )
throw "can't mmap temp image";
+ // get free space remaining on dst volume
+ struct statfs statfs_buf;
+ if ( fstatfs(dst, &statfs_buf) != 0 )
+ throwf("can't fstatfs(), errno=%d for %s", errno, tempFile);
+ uint64_t freespace = (uint64_t)statfs_buf.f_bavail * (uint64_t)statfs_buf.f_bsize;
+
// closing notes:
// ok to close file after mapped in
// ok to throw above without closing file because the throw will terminate update_prebinding
@@ -817,6 +856,8 @@
int result2 = close(src);
if ( (result1 != 0) || (result2 != 0) )
throw "can't close file";
+
+ return freespace;
}
@@ -826,7 +867,7 @@
if ( sUnitsPerSecond == 0 ) {
struct mach_timebase_info timeBaseInfo;
if ( mach_timebase_info(&timeBaseInfo) == KERN_SUCCESS ) {
- sUnitsPerSecond = timeBaseInfo.denom;
+ sUnitsPerSecond = 1000000000ULL * timeBaseInfo.denom / timeBaseInfo.numer;
}
}
if ( partTime < sUnitsPerSecond ) {
@@ -838,7 +879,7 @@
}
else {
uint32_t secondsTimeTen = (partTime*10)/sUnitsPerSecond;
- uint32_t seconds = secondsTimeTen/100;
+ uint32_t seconds = secondsTimeTen/10;
uint32_t percentTimesTen = (partTime*1000)/totalTime;
uint32_t percent = percentTimesTen/10;
fprintf(stderr, "%s: %u.%u seconds (%u.%u%%)\n", msg, seconds, secondsTimeTen-seconds*10, percent, percentTimesTen-percent*10);
@@ -872,7 +913,7 @@
fprintf(stderr, "total images loaded: %d (%d used prebinding)\n", imageCount, fgImagesWithUsedPrebinding);
printTime("total images loading time", fgTotalLoadLibrariesTime, totalTime);
fprintf(stderr, "total rebase fixups: %s\n", commatize(fgTotalRebaseFixups, commaNum1));
- printTime("total rebase fixups time", fgTotalRebaseFixups, totalTime);
+ printTime("total rebase fixups time", fgTotalRebaseTime, totalTime);
fprintf(stderr, "total binding fixups: %s\n", commatize(fgTotalBindFixups, commaNum1));
printTime("total binding fixups time", fgTotalBindTime, totalTime);
fprintf(stderr, "total bindings lazily fixed up: %s of %s\n", commatize(fgTotalLazyBindFixups, commaNum1), commatize(fgTotalPossibleLazyBindFixups, commaNum2));