Loading...
--- dyld/dyld-750.6/dyld3/shared-cache/OptimizerLinkedit.cpp
+++ dyld/dyld-852/dyld3/shared-cache/OptimizerLinkedit.cpp
@@ -53,7 +53,12 @@
public:
// add a string and symbol table entry index to be updated later
void add(uint32_t symbolIndex, const char* symbolName) {
- _map[symbolName].push_back(symbolIndex);
+ _map[symbolName].push_back({ symbolIndex, false });
+ }
+
+ // add a string and symbol table entry index to be updated later
+ void addIndirect(uint32_t symbolIndex, const char* symbolName) {
+ _map[symbolName].push_back({ symbolIndex, true });
}
// copy sorted strings to buffer and update all symbol's string offsets
@@ -66,8 +71,13 @@
// append string to pool
strcpy(&dstStringPool[poolOffset], symName.c_str());
// set each string offset of each symbol using it
- for (uint32_t symbolIndex : entry.second) {
- symbolTable[symbolIndex].set_n_strx(poolOffset);
+ for (std::pair<uint32_t, bool> symbolIndexAndIndirect : entry.second) {
+ if ( symbolIndexAndIndirect.second ) {
+ // Indirect
+ symbolTable[symbolIndexAndIndirect.first].set_n_value(poolOffset);
+ } else {
+ symbolTable[symbolIndexAndIndirect.first].set_n_strx(poolOffset);
+ }
}
poolOffset += symName.size() + 1;
}
@@ -85,7 +95,7 @@
private:
- std::map<std::string, std::vector<uint32_t>> _map;
+ std::map<std::string, std::vector<std::pair<uint32_t, bool>>> _map;
};
@@ -103,11 +113,12 @@
template <typename P>
class LinkeditOptimizer {
public:
- LinkeditOptimizer(void* cacheBuffer, macho_header<P>* mh, Diagnostics& diag);
+ LinkeditOptimizer(const void* containerBuffer, macho_header<P>* mh, const char* dylibID,
+ Diagnostics& diag);
uint32_t linkeditSize() { return _linkeditSize; }
uint64_t linkeditAddr() { return _linkeditAddr; }
- const char* installName() { return _installName; }
+ const char* dylibID() { return _dylibID; }
void copyWeakBindingInfo(uint8_t* newLinkEditContent, uint32_t& offset);
void copyLazyBindingInfo(uint8_t* newLinkEditContent, uint32_t& offset);
void copyBindingInfo(uint8_t* newLinkEditContent, uint32_t& offset);
@@ -124,6 +135,9 @@
uint32_t sharedSymbolTableStartOffset, uint32_t sharedSymbolTableCount,
uint32_t sharedSymbolStringsOffset, uint32_t sharedSymbolStringsSize);
+ typedef CacheBuilder::DylibStripMode DylibStripMode;
+ void setStripMode(DylibStripMode stripMode);
+
macho_header<P>* machHeader() { return _mh; }
const std::vector<const char*> getDownwardDependents() { return _downDependentPaths; }
const std::vector<const char*> getAllDependents() { return _allDependentPaths; }
@@ -138,8 +152,11 @@
const std::vector<macho_segment_command<P>*>& segCmds() { return _segCmds; }
- static void optimizeLinkedit(CacheBuilder& builder);
- static void mergeLinkedits(CacheBuilder& builder, std::vector<LinkeditOptimizer<P>*>& optimizers);
+ static void optimizeLinkedit(CacheBuilder& builder, const void* containerBuffer,
+ CacheBuilder::UnmappedRegion* localSymbolsRegion,
+ const std::vector<std::tuple<const mach_header*, const char*, DylibStripMode>>& images);
+ static void mergeLinkedits(CacheBuilder& builder, CacheBuilder::UnmappedRegion* localSymbolsRegion,
+ std::vector<LinkeditOptimizer<P>*>& optimizers);
private:
@@ -147,12 +164,12 @@
typedef typename P::E E;
macho_header<P>* _mh;
- void* _cacheBuffer;
+ const void* _containerBuffer;
Diagnostics& _diagnostics;
uint32_t _linkeditSize = 0;
uint64_t _linkeditAddr = 0;
const uint8_t* _linkeditBias = nullptr;
- const char* _installName = nullptr;
+ const char* _dylibID = nullptr;
macho_symtab_command<P>* _symTabCmd = nullptr;
macho_dysymtab_command<P>* _dynSymTabCmd = nullptr;
macho_dyld_info_command<P>* _dyldInfo = nullptr;
@@ -182,13 +199,14 @@
uint32_t _newDataInCodeOffset = 0;
uint32_t _newIndirectSymbolTableOffset = 0;
uint64_t _dyldSectionAddr = 0;
+ DylibStripMode _stripMode = DylibStripMode::stripAll;
};
-
-template <typename P>
-LinkeditOptimizer<P>::LinkeditOptimizer(void* cacheBuffer, macho_header<P>* mh, Diagnostics& diag)
-: _mh(mh), _cacheBuffer(cacheBuffer), _diagnostics(diag)
+template <typename P>
+LinkeditOptimizer<P>::LinkeditOptimizer(const void* containerBuffer, macho_header<P>* mh,
+ const char* dylibID, Diagnostics& diag)
+: _mh(mh), _dylibID(dylibID), _containerBuffer(containerBuffer), _diagnostics(diag)
{
const unsigned origLoadCommandsSize = mh->sizeofcmds();
unsigned bytesRemaining = origLoadCommandsSize;
@@ -204,9 +222,6 @@
for (uint32_t i = 0; i < cmdCount; ++i) {
bool remove = false;
switch (cmd->cmd()) {
- case LC_ID_DYLIB:
- _installName = ((macho_dylib_command<P>*)cmd)->name();
- break;
case LC_SYMTAB:
_symTabCmd = (macho_symtab_command<P>*)cmd;
break;
@@ -309,6 +324,11 @@
mh->set_sizeofcmds(origLoadCommandsSize - bytesRemaining);
}
+template <typename P>
+void LinkeditOptimizer<P>::setStripMode(DylibStripMode stripMode) {
+ _stripMode = stripMode;
+}
+
/*
static void dumpLoadCommands(const uint8_t* mheader)
{
@@ -412,20 +432,22 @@
_symTabCmd->set_strsize(sharedSymbolStringsSize);
// update dynamic symbol table to have proper offsets into shared symbol table
- _dynSymTabCmd->set_ilocalsym(0);
- _dynSymTabCmd->set_nlocalsym(_newLocalSymbolCount);
- _dynSymTabCmd->set_iextdefsym(_newExportedSymbolsStartIndex-_newLocalSymbolsStartIndex);
- _dynSymTabCmd->set_nextdefsym(_newExportedSymbolCount);
- _dynSymTabCmd->set_iundefsym(_newImportedSymbolsStartIndex-_newLocalSymbolsStartIndex);
- _dynSymTabCmd->set_nundefsym(_newImportedSymbolCount);
- _dynSymTabCmd->set_tocoff(0);
- _dynSymTabCmd->set_ntoc(0);
- _dynSymTabCmd->set_modtaboff(0);
- _dynSymTabCmd->set_nmodtab(0);
- _dynSymTabCmd->set_indirectsymoff(mergedLinkeditStartOffset + _newIndirectSymbolTableOffset);
- _dynSymTabCmd->set_extreloff(0);
- _dynSymTabCmd->set_locreloff(0);
- _dynSymTabCmd->set_nlocrel(0);
+ if ( _dynSymTabCmd != nullptr ) {
+ _dynSymTabCmd->set_ilocalsym(0);
+ _dynSymTabCmd->set_nlocalsym(_newLocalSymbolCount);
+ _dynSymTabCmd->set_iextdefsym(_newExportedSymbolsStartIndex-_newLocalSymbolsStartIndex);
+ _dynSymTabCmd->set_nextdefsym(_newExportedSymbolCount);
+ _dynSymTabCmd->set_iundefsym(_newImportedSymbolsStartIndex-_newLocalSymbolsStartIndex);
+ _dynSymTabCmd->set_nundefsym(_newImportedSymbolCount);
+ _dynSymTabCmd->set_tocoff(0);
+ _dynSymTabCmd->set_ntoc(0);
+ _dynSymTabCmd->set_modtaboff(0);
+ _dynSymTabCmd->set_nmodtab(0);
+ _dynSymTabCmd->set_indirectsymoff(mergedLinkeditStartOffset + _newIndirectSymbolTableOffset);
+ _dynSymTabCmd->set_extreloff(0);
+ _dynSymTabCmd->set_locreloff(0);
+ _dynSymTabCmd->set_nlocrel(0);
+ }
// update dyld info
if ( _dyldInfo != nullptr ) {
@@ -533,11 +555,27 @@
bool redact, std::vector<LocalSymbolInfo>& localSymbolInfos,
std::vector<macho_nlist<P>>& unmappedLocalSymbols, SortedStringPool<P>& localSymbolsStringPool)
{
- LocalSymbolInfo localInfo;
- localInfo.dylibOffset = (uint32_t)(((uint8_t*)_mh) - (uint8_t*)_cacheBuffer);
+ localSymbolInfos.push_back(LocalSymbolInfo());
+
+ LocalSymbolInfo& localInfo = localSymbolInfos.back();
+ localInfo.dylibOffset = (uint32_t)(((uint8_t*)_mh) - (uint8_t*)_containerBuffer);
localInfo.nlistStartIndex = (uint32_t)unmappedLocalSymbols.size();
localInfo.nlistCount = 0;
_newLocalSymbolsStartIndex = symbolIndex;
+ _newLocalSymbolCount = 0;
+
+ switch (_stripMode) {
+ case CacheBuilder::DylibStripMode::stripNone:
+ case CacheBuilder::DylibStripMode::stripExports:
+ break;
+ case CacheBuilder::DylibStripMode::stripLocals:
+ case CacheBuilder::DylibStripMode::stripAll:
+ return;
+ }
+
+ if ( _dynSymTabCmd == nullptr )
+ return;
+
const char* strings = (char*)&_linkeditBias[_symTabCmd->stroff()];
const macho_nlist<P>* const symbolTable = (macho_nlist<P>*)(&_linkeditBias[_symTabCmd->symoff()]);
const macho_nlist<P>* const firstExport = &symbolTable[_dynSymTabCmd->ilocalsym()];
@@ -570,7 +608,6 @@
}
_newLocalSymbolCount = symbolIndex - _newLocalSymbolsStartIndex;
localInfo.nlistCount = (uint32_t)unmappedLocalSymbols.size() - localInfo.nlistStartIndex;
- localSymbolInfos.push_back(localInfo);
}
@@ -578,6 +615,20 @@
void LinkeditOptimizer<P>::copyExportedSymbols(uint8_t* newLinkEditContent, SortedStringPool<P>& stringPool, uint32_t& offset, uint32_t& symbolIndex)
{
_newExportedSymbolsStartIndex = symbolIndex;
+ _newExportedSymbolCount = 0;
+
+ switch (_stripMode) {
+ case CacheBuilder::DylibStripMode::stripNone:
+ case CacheBuilder::DylibStripMode::stripLocals:
+ break;
+ case CacheBuilder::DylibStripMode::stripExports:
+ case CacheBuilder::DylibStripMode::stripAll:
+ return;
+ }
+
+ if ( _dynSymTabCmd == nullptr )
+ return;
+
const char* strings = (char*)&_linkeditBias[_symTabCmd->stroff()];
const macho_nlist<P>* const symbolTable = (macho_nlist<P>*)(&_linkeditBias[_symTabCmd->symoff()]);
const macho_nlist<P>* const firstExport = &symbolTable[_dynSymTabCmd->iextdefsym()];
@@ -606,6 +657,20 @@
void LinkeditOptimizer<P>::copyImportedSymbols(uint8_t* newLinkEditContent, SortedStringPool<P>& stringPool, uint32_t& offset, uint32_t& symbolIndex)
{
_newImportedSymbolsStartIndex = symbolIndex;
+ _newImportedSymbolCount = 0;
+
+ if ( _dynSymTabCmd == nullptr )
+ return;
+
+ switch (_stripMode) {
+ case CacheBuilder::DylibStripMode::stripNone:
+ break;
+ case CacheBuilder::DylibStripMode::stripLocals:
+ case CacheBuilder::DylibStripMode::stripExports:
+ case CacheBuilder::DylibStripMode::stripAll:
+ return;
+ }
+
const char* strings = (char*)&_linkeditBias[_symTabCmd->stroff()];
const macho_nlist<P>* const symbolTable = (macho_nlist<P>*)(&_linkeditBias[_symTabCmd->symoff()]);
const macho_nlist<P>* const firstImport = &symbolTable[_dynSymTabCmd->iundefsym()];
@@ -630,6 +695,10 @@
void LinkeditOptimizer<P>::copyIndirectSymbolTable(uint8_t* newLinkEditContent, uint32_t& offset)
{
_newIndirectSymbolTableOffset = offset;
+
+ if ( _dynSymTabCmd == nullptr )
+ return;
+
const uint32_t* const indirectTable = (uint32_t*)&_linkeditBias[_dynSymTabCmd->indirectsymoff()];
uint32_t* newIndirectTable = (uint32_t*)&newLinkEditContent[offset];
for (uint32_t i=0; i < _dynSymTabCmd->nindirectsyms(); ++i) {
@@ -643,7 +712,9 @@
}
template <typename P>
-void LinkeditOptimizer<P>::mergeLinkedits(CacheBuilder& builder, std::vector<LinkeditOptimizer<P>*>& optimizers)
+void LinkeditOptimizer<P>::mergeLinkedits(CacheBuilder& builder,
+ CacheBuilder::UnmappedRegion* localSymbolsRegion,
+ std::vector<LinkeditOptimizer<P>*>& optimizers)
{
// allocate space for new linkedit data
uint64_t totalUnoptLinkeditsSize = builder._readOnlyRegion.sizeInUse - builder._nonLinkEditReadOnlySize;
@@ -693,9 +764,11 @@
builder._diagnostics.verbose(" lazy bindings size: %5uKB\n", (offset-startLazyBindingsInfosOffset)/1024);
}
+ bool unmapLocals = ( builder._options.localSymbolMode == DyldSharedCache::LocalSymbolsMode::unmap );
+
// copy symbol table entries
std::vector<macho_nlist<P>> unmappedLocalSymbols;
- if ( builder._options.excludeLocalSymbols )
+ if ( unmapLocals )
unmappedLocalSymbols.reserve(0x01000000);
std::vector<LocalSymbolInfo> localSymbolInfos;
localSymbolInfos.reserve(optimizers.size());
@@ -705,7 +778,7 @@
uint32_t sharedSymbolTableExportsCount = 0;
uint32_t sharedSymbolTableImportsCount = 0;
for (LinkeditOptimizer<P>* op : optimizers) {
- op->copyLocalSymbols(newLinkEdit, stringPool, offset, symbolIndex, builder._options.excludeLocalSymbols,
+ op->copyLocalSymbols(newLinkEdit, stringPool, offset, symbolIndex, unmapLocals,
localSymbolInfos, unmappedLocalSymbols, localSymbolsStringPool);
uint32_t x = symbolIndex;
op->copyExportedSymbols(newLinkEdit, stringPool, offset, symbolIndex);
@@ -747,7 +820,6 @@
uint64_t newLinkeditAlignedSize = align(offset, 14);
builder._diagnostics.verbose(" symbol table size: %5uKB (%d exports, %d imports)\n", (sharedSymbolTableEndOffset-sharedSymbolTableStartOffset)/1024, sharedSymbolTableExportsCount, sharedSymbolTableImportsCount);
builder._diagnostics.verbose(" symbol string pool size: %5uKB\n", sharedSymbolStringsSize/1024);
- builder._sharedStringsPoolVmOffset = (uint32_t)((builder._readOnlyRegion.unslidLoadAddress - builder._readExecuteRegion.unslidLoadAddress) + builder._nonLinkEditReadOnlySize + sharedSymbolStringsOffset);
// overwrite mapped LINKEDIT area in cache with new merged LINKEDIT content
builder._diagnostics.verbose("LINKEDITS optimized from %uMB to %uMB\n", (uint32_t)totalUnoptLinkeditsSize/(1024*1024), (uint32_t)newLinkeditUnalignedSize/(1024*1024));
@@ -756,7 +828,7 @@
builder._readOnlyRegion.sizeInUse = builder._nonLinkEditReadOnlySize + newLinkeditAlignedSize;
// overwrite end of un-opt linkedits to create a new unmapped region for local symbols
- if ( builder._options.excludeLocalSymbols ) {
+ if ( unmapLocals ) {
const uint32_t entriesOffset = sizeof(dyld_cache_local_symbols_info);
const uint32_t entriesCount = (uint32_t)localSymbolInfos.size();
const uint32_t nlistOffset = (uint32_t)align(entriesOffset + entriesCount * sizeof(dyld_cache_local_symbols_info), 4); // 16-byte align start
@@ -787,13 +859,10 @@
::memcpy(newLocalsSymbolTable, &unmappedLocalSymbols[0], nlistCount*sizeof(macho_nlist<P>));
// copy string pool
localSymbolsStringPool.copyPoolAndUpdateOffsets(((char*)infoHeader)+stringsOffset, newLocalsSymbolTable);
- // update cache header
- DyldSharedCache* cacheHeader = (DyldSharedCache*)builder._readExecuteRegion.buffer;
- cacheHeader->header.localSymbolsSize = localsBufferSize;
// return buffer of local symbols, caller to free() it
- builder._localSymbolsRegion.buffer = (uint8_t*)localsBuffer;
- builder._localSymbolsRegion.bufferSize = localsBufferSize;
- builder._localSymbolsRegion.sizeInUse = localsBufferSize;
+ localSymbolsRegion->buffer = (uint8_t*)localsBuffer;
+ localSymbolsRegion->bufferSize = localsBufferSize;
+ localSymbolsRegion->sizeInUse = localsBufferSize;
}
else {
builder._diagnostics.warning("could not allocate local symbols");
@@ -812,14 +881,16 @@
template <typename P>
-void LinkeditOptimizer<P>::optimizeLinkedit(CacheBuilder& builder)
-{
- DyldSharedCache* cache = (DyldSharedCache*)builder._readExecuteRegion.buffer;
+void LinkeditOptimizer<P>::optimizeLinkedit(CacheBuilder& builder, const void* containerBuffer,
+ CacheBuilder::UnmappedRegion* localSymbolsRegion,
+ const std::vector<std::tuple<const mach_header*, const char*, DylibStripMode>>& images)
+{
// construct a LinkeditOptimizer for each image
__block std::vector<LinkeditOptimizer<P>*> optimizers;
- cache->forEachImage(^(const mach_header* mh, const char*) {
- optimizers.push_back(new LinkeditOptimizer<P>(cache, (macho_header<P>*)mh, builder._diagnostics));
- });
+ for (std::tuple<const mach_header*, const char*, DylibStripMode> image : images) {
+ optimizers.push_back(new LinkeditOptimizer<P>(containerBuffer, (macho_header<P>*)std::get<0>(image), std::get<1>(image), builder._diagnostics));
+ optimizers.back()->setStripMode(std::get<2>(image));
+ }
#if 0
// add optimizer for each branch pool
for (uint64_t poolOffset : branchPoolOffsets) {
@@ -828,22 +899,26 @@
}
#endif
// merge linkedit info
- mergeLinkedits(builder, optimizers);
+ mergeLinkedits(builder, localSymbolsRegion, optimizers);
// delete optimizers
for (LinkeditOptimizer<P>* op : optimizers)
delete op;
}
-void CacheBuilder::optimizeLinkedit()
-{
+void CacheBuilder::optimizeLinkedit(UnmappedRegion* localSymbolsRegion,
+ const std::vector<std::tuple<const mach_header*, const char*, DylibStripMode>>& images)
+{
+ const void* buffer = (const void*)_fullAllocatedBuffer;
if ( _is64 ) {
- return LinkeditOptimizer<Pointer64<LittleEndian>>::optimizeLinkedit(*this);
+ return LinkeditOptimizer<Pointer64<LittleEndian>>::optimizeLinkedit(*this, buffer,
+ localSymbolsRegion, images);
}
else {
- return LinkeditOptimizer<Pointer32<LittleEndian>>::optimizeLinkedit(*this);
- }
-}
-
-
-
+ return LinkeditOptimizer<Pointer32<LittleEndian>>::optimizeLinkedit(*this, buffer,
+ localSymbolsRegion, images);
+ }
+}
+
+
+