Loading...
--- dyld/dyld-640.2/dyld3/shared-cache/OptimizerObjC.cpp
+++ dyld/dyld-519.2.2/dyld3/shared-cache/OptimizerObjC.cpp
@@ -35,7 +35,7 @@
#include "CacheBuilder.h"
#include "FileAbstraction.hpp"
#include "MachOFileAbstraction.hpp"
-#include "MachOLoaded.h"
+
// Scan a C++ or Swift length-mangled field.
static bool scanMangledField(const char *&string, const char *end,
@@ -109,57 +109,37 @@
ContentAccessor(const DyldSharedCache* cache, Diagnostics& diag)
: _diagnostics(diag)
{
- _cacheStart = (uint8_t*)cache;
- _cacheUnslideAddr = cache->unslidLoadAddress();
- _slide = (uint64_t)cache - _cacheUnslideAddr;
-#if SUPPORT_ARCH_arm64e
- _chainedFixups = (strcmp(cache->archName(), "arm64e") == 0);
-#else
- _chainedFixups = false;
-#endif
- }
-
- // Converts from an on disk vmAddr to the real vmAddr
- // That is, for a chained fixup, decodes the chain, for a non-chained fixup, does nothing.
- uint64_t vmAddrForOnDiskVMAddr(uint64_t vmaddr) {
- if ( _chainedFixups ) {
- dyld3::MachOLoaded::ChainedFixupPointerOnDisk ptr;
- ptr.raw = vmaddr;
- assert(ptr.authRebase.bind == 0);
- if ( ptr.authRebase.auth ) {
- vmaddr = _cacheUnslideAddr + ptr.authRebase.target;
- }
- else {
- vmaddr = ptr.plainRebase.signExtendedTarget();
- }
- }
- return vmaddr;
+ __block int index = 0;
+ cache->forEachRegion(^(const void* content, uint64_t vmAddr, uint64_t size, uint32_t permissions) {
+ _regions[index++] = { (uint8_t*)content, (uint8_t*)content+size, vmAddr, vmAddr+size };
+ });
}
void* contentForVMAddr(uint64_t vmaddr) {
- vmaddr = vmAddrForOnDiskVMAddr(vmaddr);
- if ( vmaddr != 0 ) {
- uint64_t offset = vmaddr - _cacheUnslideAddr;
- return _cacheStart + offset;
- } else
- return nullptr;
+ for (const Info& info : _regions) {
+ if ( (info.startAddr <= vmaddr) && (vmaddr < info.endAddr) )
+ return (void*)(info.contentStart + vmaddr - info.startAddr);
+ }
+ if ( vmaddr != 0 )
+ _diagnostics.error("invalid vmaddr 0x%0llX in ObjC data", vmaddr);
+ return nullptr;
}
uint64_t vmAddrForContent(const void* content) {
- if ( content != nullptr )
- return _cacheUnslideAddr + ((uint8_t*)content - _cacheStart);
- else
- return 0;
+ for (const Info& info : _regions) {
+ if ( (info.contentStart <= content) && (content < info.contentEnd) )
+ return info.startAddr + ((uint8_t*)content - (uint8_t*)info.contentStart);
+ }
+ _diagnostics.error("invalid content pointer %p in ObjC data", content);
+ return 0;
}
Diagnostics& diagnostics() { return _diagnostics; }
private:
- Diagnostics& _diagnostics;
- uint64_t _slide;
- uint64_t _cacheUnslideAddr;
- uint8_t* _cacheStart;
- bool _chainedFixups;
+ struct Info { uint8_t* contentStart; uint8_t* contentEnd; uint64_t startAddr; uint64_t endAddr; };
+ Diagnostics& _diagnostics;
+ Info _regions[3];
};
@@ -187,10 +167,6 @@
return (pint_t)P::getP(_base[index]);
}
- pint_t getSectionVMAddress() const {
- return (pint_t)_section->addr();
- }
-
T get(pint_t index) const {
return (T)_cache->contentForVMAddr(getVMAddress(index));
}
@@ -277,7 +253,6 @@
{
_count++;
const char *s = (const char *)_cache->contentForVMAddr(oldValue);
- oldValue = (pint_t)_cache->vmAddrForOnDiskVMAddr(oldValue);
objc_opt::string_map::iterator element =
_selectorStrings.insert(objc_opt::string_map::value_type(s, oldValue)).first;
return (pint_t)element->second;
@@ -391,7 +366,7 @@
const char *writeProtocols(ContentAccessor* cache,
uint8_t *& rwdest, size_t& rwremaining,
uint8_t *& rodest, size_t& roremaining,
- CacheBuilder::ASLR_Tracker& aslrTracker,
+ std::vector<void*>& pointersInData,
pint_t protocolClassVMAddr)
{
if (_protocolCount == 0) return NULL;
@@ -455,7 +430,7 @@
iter->second = cache->vmAddrForContent(proto);
// Add new rebase entries.
- proto->addPointers(cache, aslrTracker);
+ proto->addPointers(pointersInData);
}
return NULL;
@@ -489,9 +464,7 @@
template <typename P>
-void doOptimizeObjC(DyldSharedCache* cache, bool forProduction, CacheBuilder::ASLR_Tracker& aslrTracker,
- CacheBuilder::LOH_Tracker& lohTracker,
- const std::map<void*, std::string>& missingWeakImports, Diagnostics& diag)
+void optimizeObjC(DyldSharedCache* cache, bool forProduction, std::vector<void*>& pointersForASLR, Diagnostics& diag)
{
typedef typename P::E E;
typedef typename P::uint_t pint_t;
@@ -590,7 +563,7 @@
}
else {
for (const macho_header<P>* mh : addressSortedDylibs) {
- hinfoROOptimizer.update(&cacheAccessor, mh, aslrTracker);
+ hinfoROOptimizer.update(&cacheAccessor, mh, pointersForASLR);
}
}
@@ -605,7 +578,7 @@
}
else {
for (const macho_header<P>* mh : addressSortedDylibs) {
- hinfoRWOptimizer.update(&cacheAccessor, mh, aslrTracker);
+ hinfoRWOptimizer.update(&cacheAccessor, mh, pointersForASLR);
}
}
@@ -667,7 +640,7 @@
if (forProduction) {
WeakClassDetector<P> weakopt;
noMissingWeakSuperclasses =
- weakopt.noMissingWeakSuperclasses(&cacheAccessor, missingWeakImports, sizeSortedDylibs);
+ weakopt.noMissingWeakSuperclasses(&cacheAccessor, sizeSortedDylibs);
// Shared cache does not currently support unbound weak references.
// Here we assert that there are none. If support is added later then
@@ -744,7 +717,7 @@
err = protocolOptimizer.writeProtocols(&cacheAccessor,
optRWData, optRWRemaining,
optROData, optRORemaining,
- aslrTracker, protocolClassVMAddr);
+ pointersForASLR, protocolClassVMAddr);
if (err) {
diag.warning("%s", err);
return;
@@ -831,120 +804,17 @@
diag.verbose(" %lu/%llu bytes (%d%%) used in libobjc read/write optimization section\n",
rwSize, optRWSection->size(), percent(rwSize, optRWSection->size()));
diag.verbose(" wrote objc metadata optimization version %d\n", objc_opt::VERSION);
-
- // Now that objc has uniqued the selector references, we can apply the LOHs so that ADRP/LDR -> ADRP/ADD
- if (forProduction) {
- uint64_t lohADRPCount = 0;
- uint64_t lohLDRCount = 0;
-
- for (auto& targetAndInstructions : lohTracker) {
- uint64_t targetVMAddr = targetAndInstructions.first;
- if (!selOptimizer.isSelectorRefAddress((pint_t)targetVMAddr))
- continue;
-
- std::set<void*>& instructions = targetAndInstructions.second;
- // We do 2 passes over the instructions. The first to validate them and the second
- // to actually update them.
- for (unsigned pass = 0; pass != 2; ++pass) {
- uint32_t adrpCount = 0;
- uint32_t ldrCount = 0;
- for (void* instructionAddress : instructions) {
- uint32_t& instruction = *(uint32_t*)instructionAddress;
- uint64_t instructionVMAddr = cacheAccessor.vmAddrForContent(&instruction);
- uint64_t selRefContent = *(uint64_t*)cacheAccessor.contentForVMAddr(targetVMAddr);
- const char* selectorString = (const char*)cacheAccessor.contentForVMAddr(selRefContent);
- uint64_t selectorStringVMAddr = cacheAccessor.vmAddrForContent(selectorString);
-
- if ( (instruction & 0x9F000000) == 0x90000000 ) {
- // ADRP
- int64_t pageDistance = ((selectorStringVMAddr & ~0xFFF) - (instructionVMAddr & ~0xFFF));
- int64_t newPage21 = pageDistance >> 12;
-
- if (pass == 0) {
- if ( (newPage21 > 2097151) || (newPage21 < -2097151) ) {
- diag.verbose("Out of bounds ADRP selector reference target\n");
- instructions.clear();
- break;
- }
- ++adrpCount;
- }
-
- if (pass == 1) {
- instruction = (instruction & 0x9F00001F) | ((newPage21 << 29) & 0x60000000) | ((newPage21 << 3) & 0x00FFFFE0);
- ++lohADRPCount;
- }
- continue;
- }
-
- if ( (instruction & 0x3B000000) == 0x39000000 ) {
- // LDR/STR. STR shouldn't be possible as this is a selref!
- if (pass == 0) {
- if ( (instruction & 0xC0C00000) != 0xC0400000 ) {
- // Not a load, or dest reg isn't xN, or uses sign extension
- diag.verbose("Bad LDR for selector reference optimisation\n");
- instructions.clear();
- break;
- }
- if ( (instruction & 0x04000000) != 0 ) {
- // Loading a float
- diag.verbose("Bad LDR for selector reference optimisation\n");
- instructions.clear();
- break;
- }
- ++ldrCount;
- }
-
- if (pass == 1) {
- uint32_t ldrDestReg = (instruction & 0x1F);
- uint32_t ldrBaseReg = ((instruction >> 5) & 0x1F);
-
- // Convert the LDR to an ADD
- instruction = 0x91000000;
- instruction |= ldrDestReg;
- instruction |= ldrBaseReg << 5;
- instruction |= (selectorStringVMAddr & 0xFFF) << 10;
-
- ++lohLDRCount;
- }
- continue;
- }
-
- if ( (instruction & 0xFFC00000) == 0x91000000 ) {
- // ADD imm12
- // We don't support ADDs.
- diag.verbose("Bad ADD for selector reference optimisation\n");
- instructions.clear();
- break;
- }
-
- diag.verbose("Unknown instruction for selref optimisation\n");
- instructions.clear();
- break;
- }
- if (pass == 0) {
- // If we didn't see at least one ADRP/LDR in pass one then don't optimize this location
- if ((adrpCount == 0) || (ldrCount == 0)) {
- instructions.clear();
- break;
- }
- }
- }
- }
-
- diag.verbose(" Optimized %lld ADRP LOHs\n", lohADRPCount);
- diag.verbose(" Optimized %lld LDR LOHs\n", lohLDRCount);
- }
}
} // anon namespace
-void CacheBuilder::optimizeObjC()
+void optimizeObjC(DyldSharedCache* cache, bool is64, bool customerCache, std::vector<void*>& pointersForASLR, Diagnostics& diag)
{
- if ( _archLayout->is64 )
- doOptimizeObjC<Pointer64<LittleEndian>>((DyldSharedCache*)_readExecuteRegion.buffer, _options.optimizeStubs, _aslrTracker, _lohTracker, _missingWeakImports, _diagnostics);
+ if ( is64 )
+ optimizeObjC<Pointer64<LittleEndian>>(cache, customerCache, pointersForASLR, diag);
else
- doOptimizeObjC<Pointer32<LittleEndian>>((DyldSharedCache*)_readExecuteRegion.buffer, _options.optimizeStubs, _aslrTracker, _lohTracker, _missingWeakImports, _diagnostics);
+ optimizeObjC<Pointer32<LittleEndian>>(cache, customerCache, pointersForASLR, diag);
}