SharedCacheBuilder.h [plain text]
#ifndef SharedCacheBuilder_h
#define SharedCacheBuilder_h
#include "CacheBuilder.h"
#include "DyldSharedCache.h"
#include "ClosureFileSystem.h"
class SharedCacheBuilder : public CacheBuilder {
public:
SharedCacheBuilder(const DyldSharedCache::CreateOptions& options, const dyld3::closure::FileSystem& fileSystem);
void build(std::vector<InputFile>& inputFiles,
std::vector<DyldSharedCache::FileAlias>& aliases);
void build(const std::vector<LoadedMachO>& dylibs,
const std::vector<LoadedMachO>& otherOsDylibsInput,
const std::vector<LoadedMachO>& osExecutables,
std::vector<DyldSharedCache::FileAlias>& aliases);
void build(const std::vector<DyldSharedCache::MappedMachO>& dylibsToCache,
const std::vector<DyldSharedCache::MappedMachO>& otherOsDylibs,
const std::vector<DyldSharedCache::MappedMachO>& osExecutables,
std::vector<DyldSharedCache::FileAlias>& aliases);
void writeFile(const std::string& path);
void writeBuffer(uint8_t*& buffer, uint64_t& size);
void writeMapFile(const std::string& path);
std::string getMapFileBuffer(const std::string& cacheDisposition) const;
void deleteBuffer();
const std::set<std::string> warnings();
const std::set<const dyld3::MachOAnalyzer*> evictions();
const bool agileSignature();
const std::string cdHashFirst();
const std::string cdHashSecond();
const std::string uuid() const;
void forEachCacheDylib(void (^callback)(const std::string& path));
private:
void writeSlideInfoV1();
template <typename P> void writeSlideInfoV2(const bool bitmap[], unsigned dataPageCount);
template <typename P> bool makeRebaseChainV2(uint8_t* pageContent, uint16_t lastLocationOffset, uint16_t newOffset, const struct dyld_cache_slide_info2* info);
template <typename P> void addPageStartsV2(uint8_t* pageContent, const bool bitmap[], const struct dyld_cache_slide_info2* info,
std::vector<uint16_t>& pageStarts, std::vector<uint16_t>& pageExtras);
void writeSlideInfoV3(const bool bitmap[], unsigned dataPageCoun);
uint16_t pageStartV3(uint8_t* pageContent, uint32_t pageSize, const bool bitmap[]);
void setPointerContentV3(dyld3::MachOLoaded::ChainedFixupPointerOnDisk* loc, uint64_t targetVMAddr, size_t next);
template <typename P> void writeSlideInfoV4(const bool bitmap[], unsigned dataPageCount);
template <typename P> bool makeRebaseChainV4(uint8_t* pageContent, uint16_t lastLocationOffset, uint16_t newOffset, const struct dyld_cache_slide_info4* info);
template <typename P> void addPageStartsV4(uint8_t* pageContent, const bool bitmap[], const struct dyld_cache_slide_info4* info,
std::vector<uint16_t>& pageStarts, std::vector<uint16_t>& pageExtras);
struct ArchLayout
{
uint64_t sharedMemoryStart;
uint64_t sharedMemorySize;
uint64_t textAndDataMaxSize;
uint64_t sharedRegionPadding;
uint64_t pointerDeltaMask;
const char* archName;
uint16_t csPageSize;
uint8_t sharedRegionAlignP2;
uint8_t slideInfoBytesPerPage;
bool sharedRegionsAreDiscontiguous;
bool is64;
bool useValueAdd;
};
static const ArchLayout _s_archLayout[];
static const char* const _s_neverStubEliminateDylibs[];
static const char* const _s_neverStubEliminateSymbols[];
void makeSortedDylibs(const std::vector<LoadedMachO>& dylibs, const std::unordered_map<std::string, unsigned> sortOrder);
void processSelectorStrings(const std::vector<LoadedMachO>& executables);
void parseCoalescableSegments();
void assignSegmentAddresses();
uint64_t cacheOverflowAmount();
size_t evictLeafDylibs(uint64_t reductionTarget, std::vector<const LoadedMachO*>& overflowDylibs);
void fipsSign();
void codeSign();
uint64_t pathHash(const char* path);
void writeCacheHeader();
void findDylibAndSegment(const void* contentPtr, std::string& dylibName, std::string& segName);
void addImageArray();
void buildImageArray(std::vector<DyldSharedCache::FileAlias>& aliases);
void addOtherImageArray(const std::vector<LoadedMachO>&, std::vector<const LoadedMachO*>& overflowDylibs);
void addClosures(const std::vector<LoadedMachO>&);
void markPaddingInaccessible();
bool writeCache(void (^cacheSizeCallback)(uint64_t size), bool (^copyCallback)(const uint8_t* src, uint64_t size, uint64_t dstOffset));
void optimizeObjC();
uint32_t computeReadOnlyObjC(uint32_t selRefCount, uint32_t classDefCount, uint32_t protocolDefCount);
uint32_t computeReadWriteObjC(uint32_t imageCount, uint32_t protocolDefCount);
void optimizeAwayStubs();
typedef std::unordered_map<std::string, const dyld3::MachOAnalyzer*> InstallNameToMA;
typedef uint64_t CacheOffset;
UnmappedRegion _codeSignatureRegion;
std::set<const dyld3::MachOAnalyzer*> _evictions;
const ArchLayout* _archLayout = nullptr;
uint32_t _aliasCount = 0;
uint64_t _slideInfoFileOffset = 0;
uint64_t _slideInfoBufferSizeAllocated = 0;
uint8_t* _objcReadOnlyBuffer = nullptr;
uint64_t _objcReadOnlyBufferSizeUsed = 0;
uint64_t _objcReadOnlyBufferSizeAllocated = 0;
uint8_t* _objcReadWriteBuffer = nullptr;
uint64_t _objcReadWriteBufferSizeAllocated = 0;
uint64_t _selectorStringsFromExecutables = 0;
InstallNameToMA _installNameToCacheDylib;
std::unordered_map<std::string, uint32_t> _dataDirtySegsOrder;
std::map<void*, std::string> _missingWeakImports;
const dyld3::closure::ImageArray* _imageArray = nullptr;
uint8_t _cdHashFirst[20];
uint8_t _cdHashSecond[20];
bool _someDylibsUsedChainedFixups = false;
std::unordered_map<const dyld3::MachOLoaded*, std::set<CacheOffset>> _dylibToItsExports;
std::set<std::pair<const dyld3::MachOLoaded*, CacheOffset>> _dylibWeakExports;
std::unordered_map<CacheOffset, std::vector<dyld_cache_patchable_location>> _exportsToUses;
std::unordered_map<CacheOffset, std::string> _exportsToName;
};
#endif