Loading...
--- dyld/dyld-44.17/src/ImageLoaderMachO.cpp
+++ dyld/dyld-43.1/src/ImageLoaderMachO.cpp
@@ -38,10 +38,6 @@
#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"
@@ -79,7 +75,6 @@
uint32_t ImageLoaderMachO::fgHintedBinaryTreeSearchs = 0;
uint32_t ImageLoaderMachO::fgUnhintedBinaryTreeSearchs = 0;
-uint32_t ImageLoaderMachO::fgCountOfImagesWithWeakExports = 0;
//#define LINKEDIT_USAGE_DEBUG 1
@@ -181,12 +176,6 @@
this->parseLoadCmds();
}
-ImageLoaderMachO::~ImageLoaderMachO()
-{
- // keep count of images with weak exports
- if ( this->hasCoalescedExports() )
- --fgCountOfImagesWithWeakExports;
-}
@@ -199,8 +188,7 @@
const struct load_command* cmd = cmds;
for (unsigned long i = 0; i < cmd_count; ++i) {
if ( cmd->cmd == LC_SEGMENT_COMMAND ) {
- if ( (((struct macho_segment_command*)cmd)->vmsize != 0) || !fIsSplitSeg )
- fSegments.push_back(new SegmentMachO((struct macho_segment_command*)cmd, this, fileData));
+ fSegments.push_back(new SegmentMachO((struct macho_segment_command*)cmd, this, fileData));
}
cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
}
@@ -906,10 +894,6 @@
fMachOData = (uint8_t*)(seg->getActualLoadAddress());
}
}
-
- // 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;
@@ -1785,34 +1769,6 @@
}
}
-// returns if 'addr' is within the address range of section 'sectionIndex'
-// fSlide is not used. 'addr' is assumed to be a prebound address in this image
-bool ImageLoaderMachO::isAddrInSection(uintptr_t addr, uint8_t sectionIndex)
-{
- uint8_t currentSectionIndex = 1;
- 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 (unsigned long i = 0; i < cmd_count; ++i) {
- if ( cmd->cmd == LC_SEGMENT_COMMAND ) {
- const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
- if ( (currentSectionIndex <= sectionIndex) && (sectionIndex < currentSectionIndex+seg->nsects) ) {
- // 'sectionIndex' is in this segment, get section info
- const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
- const struct macho_section* const section = §ionsStart[sectionIndex-currentSectionIndex];
- return ( (section->addr <= addr) && (addr < section->addr+section->size) );
- }
- else {
- // 'sectionIndex' not in this segment, skip to next segment
- currentSectionIndex += seg->nsects;
- }
- }
- cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
- }
-
- return false;
-}
-
void ImageLoaderMachO::doBindExternalRelocations(const LinkContext& context, bool onlyCoalescedSymbols)
{
const uintptr_t relocBase = this->getRelocBase();
@@ -1842,31 +1798,12 @@
continue;
uintptr_t* location = ((uintptr_t*)(reloc->r_address + relocBase));
uintptr_t value = *location;
- #if __i386__
- if ( reloc->r_pcrel ) {
- value += (uintptr_t)location + 4 - fSlide;
- }
- #endif
if ( prebound ) {
// we are doing relocations, so prebinding was not usable
- // in a prebound executable, the n_value field of an undefined symbol is set to the address where the symbol was found when prebound
+ // in a prebound executable, the n_value field is set to the address where the symbol was found when prebound
// so, subtracting that gives the initial displacement which we need to add to the newly found symbol address
- // if mach-o relocation structs had an "addend" field this complication would not be necessary.
- if ( ((undefinedSymbol->n_type & N_TYPE) == N_SECT) && ((undefinedSymbol->n_desc & N_WEAK_DEF) != 0) ) {
- // weak symbols need special casing, since *location may have been prebound to a definition in another image.
- // If *location is currently prebound to somewhere in the same section as the weak definition, we assume
- // that we can subtract off the weak symbol address to get the addend.
- // If prebound elsewhere, we've lost the addend and have to assume it is zero.
- // The prebinding to elsewhere only happens with 10.4+ update_prebinding which only operates on a small set of Apple dylibs
- if ( (value == undefinedSymbol->n_value) || this->isAddrInSection(value, undefinedSymbol->n_sect) )
- value -= undefinedSymbol->n_value;
- else
- value = 0;
- }
- else {
- // is undefined or non-weak symbol, so do subtraction to get addend
- value -= undefinedSymbol->n_value;
- }
+ // if mach-o relocation structs had an "addend" field this would not be necessary.
+ value -= undefinedSymbol->n_value;
}
// if undefinedSymbol is same as last time, then symbolAddr and image will resolve to the same too
if ( undefinedSymbol != lastUndefinedSymbol ) {
@@ -1890,20 +1827,7 @@
}
}
value += symbolAddr;
- #if __i386__
- if ( reloc->r_pcrel ) {
- *location = value - ((uintptr_t)location + 4);
- }
- else {
- // don't dirty page if prebound value was correct
- if ( !prebound || (*location != value) )
- *location = value;
- }
- #else
- // don't dirty page if prebound value was correct
- if ( !prebound || (*location != value) )
- *location = value;
- #endif
+ *location = value;
}
break;
default:
@@ -1940,40 +1864,6 @@
{
Segment* seg = fSegments[0];
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;
}
@@ -1994,39 +1884,38 @@
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;
- symbolIndex = indirectTable[indirectTableOffset + lazyIndex];
+ 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];
+ }
}
}
- #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;
@@ -2035,7 +1924,6 @@
}
throw "lazy pointer not found";
}
-
@@ -2056,37 +1944,26 @@
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 elementSize = sizeof(uintptr_t);
- uint32_t elementCount = sect->size / elementSize;
+ const uint32_t pointerCount = sect->size / sizeof(uintptr_t);
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 += elementCount;
+ fgTotalPossibleLazyBindFixups += pointerCount;
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;
- uint8_t* ptrToBind = (uint8_t*)(sect->addr + fSlide);
- for (uint32_t j=0; j < elementCount; ++j, ptrToBind += elementSize) {
+ uintptr_t* const symbolPointers = (uintptr_t*)(sect->addr + fSlide);
+ for (uint32_t j=0; j < pointerCount; ++j) {
uint32_t symbolIndex = indirectTable[indirectTableOffset + j];
if ( symbolIndex == INDIRECT_SYMBOL_LOCAL) {
- *((uintptr_t*)ptrToBind) += this->fSlide;
+ symbolPointers[j] += this->fSlide;
}
else if ( symbolIndex == INDIRECT_SYMBOL_ABS) {
// do nothing since already has absolute address
@@ -2124,13 +2001,27 @@
continue;
uintptr_t symbolAddr;
symbolAddr = resolveUndefined(context, sym, twoLevel, &image);
-
- // update pointer
- symbolAddr = this->bindIndirectSymbol((uintptr_t*)ptrToBind, sect, &fStrings[sym->n_un.n_strx], symbolAddr, image, context);
+ 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 stats
- fgTotalBindFixups += elementCount;
+ fgTotalBindFixups += pointerCount;
}
}
break;
@@ -2169,10 +2060,9 @@
// 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(const LinkContext& context)
+
+
+void ImageLoaderMachO::setupLazyPointerHandler()
{
if ( fDATAdyld != NULL ) {
struct DATAdyld* dd = (struct DATAdyld*)(fDATAdyld->addr + fSlide);
@@ -2191,42 +2081,6 @@
// 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
@@ -2253,13 +2107,13 @@
void ImageLoaderMachO::doBind(const LinkContext& context, BindingLaziness bindness)
{
// set dyld entry points in image
- this->setupLazyPointerHandler(context);
+ this->setupLazyPointerHandler();
// 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, unless this is the only image with weak symbols
- if ( this->needsCoalescing() && (fgCountOfImagesWithWeakExports > 1) ) {
+ // if image has coalesced symbols, then these need to be rebound
+ if ( this->needsCoalescing() ) {
this->doBindExternalRelocations(context, true);
this->doBindIndirectSymbolPointers(context, kLazyAndNonLazy, true);
}
@@ -2364,7 +2218,6 @@
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());