Loading...
--- dyld/dyld-1340/cache_builder/CacheDylib.h
+++ /dev/null
@@ -1,324 +0,0 @@
-/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
-*
-* Copyright (c) 2017 Apple Inc. All rights reserved.
-*
-* @APPLE_LICENSE_HEADER_START@
-*
-* This file contains Original Code and/or Modifications of Original Code
-* as defined in and that are subject to the Apple Public Source License
-* Version 2.0 (the 'License'). You may not use this file except in
-* compliance with the License. Please obtain a copy of the License at
-* http://www.opensource.apple.com/apsl/ and read it before using this
-* file.
-*
-* The Original Code and all software distributed under the License are
-* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
-* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
-* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
-* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
-* Please see the License for the specific language governing rights and
-* limitations under the License.
-*
-* @APPLE_LICENSE_HEADER_END@
-*/
-
-#ifndef CacheDylib_hpp
-#define CacheDylib_hpp
-
-#include "CachePatching.h"
-#include "Chunk.h"
-#include "Diagnostics.h"
-#include "MachOFile.h"
-#include "NewAdjustDylibSegments.h"
-#include "ObjCVisitor.h"
-#include "SectionCoalescer.h"
-#include "SwiftVisitor.h"
-#include "Timer.h"
-#include "Image.h"
-
-#include <list>
-
-namespace cache_builder
-{
-
-struct BuilderConfig;
-struct InputFile;
-struct ObjCIMPCachesOptimizer;
-struct ObjCSelectorOptimizer;
-struct ObjCCategoryOptimizer;
-struct StubOptimizer;
-struct UnmappedSymbolsOptimizer;
-struct FunctionVariantsOptimizer;
-
-// A dylib which will be included in the cache
-struct CacheDylib
-{
-#if BUILDING_CACHE_BUILDER_UNIT_TESTS
- CacheDylib();
-#else
- CacheDylib() = delete;
-#endif
- CacheDylib(InputFile& inputFile);
- // create a CacheDylib *placeholder* with an install name only and no input mach-o
- CacheDylib(std::string_view installName);
- ~CacheDylib() = default;
-
- CacheDylib(const CacheDylib&) = delete;
- CacheDylib& operator=(const CacheDylib&) = delete;
-
- CacheDylib& operator=(CacheDylib&&) = default;
- CacheDylib(CacheDylib&&) = default;
-
- // Passes to create a valid CacheDylib from an input file
- void categorizeSegments(const BuilderConfig& config,
- objc_visitor::Visitor& objcVisitor);
- void categorizeLinkedit(const BuilderConfig& config);
-
- // Passes to run to add a CacheDylib to a SubCache
- void copyRawSegments(const BuilderConfig& config, Timer::AggregateTimer& timer);
- void applySplitSegInfo(Diagnostics& diag, const BuilderOptions& options,
- const BuilderConfig& config, Timer::AggregateTimer& timer,
- UnmappedSymbolsOptimizer& unmappedSymbolsOptimizer);
- void updateSymbolTables(Diagnostics& diag, const BuilderConfig& config, Timer::AggregateTimer& timer);
- std::vector<error::Error> calculateBindTargets(Diagnostics& diag, const BuilderConfig& config, Timer::AggregateTimer& timer,
- const std::vector<const CacheDylib *>& cacheDylibs,
- PatchInfo& dylibPatchInfo);
- void calcuatePatchInfo(Diagnostics& diag, const BuilderConfig& config, Timer::AggregateTimer& timer,
- PatchInfo& dylibPatchInfo);
- void bind(Diagnostics& diag, const BuilderConfig& config, Timer::AggregateTimer& timer,
- PatchInfo& dylibPatchInfo, FunctionVariantsOptimizer& functionVariantsOptimizer);
- void updateObjCSelectorReferences(Diagnostics& diag, const BuilderConfig& config, Timer::AggregateTimer& timer,
- ObjCSelectorOptimizer& objcSelectorOptimizer);
- void convertObjCMethodListsToOffsets(Diagnostics& diag, const BuilderConfig& config, Timer::AggregateTimer& timer,
- const Chunk* selectorStringsChunk);
- void sortObjCMethodLists(Diagnostics& diag, const BuilderConfig& config, Timer::AggregateTimer& timer,
- const Chunk* selectorStringsChunk);
- void optimizeLoadsFromConstants(const BuilderConfig& config, Timer::AggregateTimer& timer,
- const ObjCStringsChunk* selectorStringsChunk);
- error::Error emitObjCIMPCaches(const BuilderConfig& config, Timer::AggregateTimer& timer,
- const ObjCIMPCachesOptimizer& objcIMPCachesOptimizer,
- const ObjCStringsChunk* selectorStringsChunk);
- void optimizeStubs(const BuilderOptions& options, const BuilderConfig& config,
- Timer::AggregateTimer& timer, const StubOptimizer& stubOptimizer,
- const PatchInfo& dylibPatchInfo);
- void fipsSign(Timer::AggregateTimer& timer);
- void addObjcSegments(Diagnostics& diag, Timer::AggregateTimer& timer,
- const ObjCHeaderInfoReadOnlyChunk* headerInfoReadOnlyChunk,
- const ObjCImageInfoChunk* imageInfoChunk,
- const ObjCProtocolHashTableChunk* protocolHashTableChunk,
- const ObjCPreAttachedCategoriesChunk* preAttachedCategoriesChunk,
- const ObjCHeaderInfoReadWriteChunk* headerInfoReadWriteChunk,
- const ObjCCanonicalProtocolsChunk* canonicalProtocolsChunk);
- // remove all dylib link load commands, except libSystem
- void removeLinkedDylibs(Diagnostics& diag);
- void addLinkedDylib(Diagnostics& diag, const CacheDylib& dylib);
-
- void forEachCacheSection(void (^callback)(std::string_view segmentName,
- std::string_view sectionName,
- uint8_t* sectionBuffer,
- CacheVMAddress sectionVMAddr,
- CacheVMSize sectionVMSize,
- bool& stop));
-
- struct DependentDylib
- {
- enum class Kind
- {
- normal,
- weakLink,
- reexport,
- upward
- };
-
- Kind kind = Kind::normal;
- const CacheDylib* dylib = nullptr;
- };
-
- struct BindTarget
- {
- enum class Kind
- {
- absolute,
- inputImage,
- cacheImage
- };
-
- struct Absolute
- {
- uint64_t value;
- };
-
- struct InputImage
- {
- VMOffset targetRuntimeOffset;
- const CacheDylib* targetDylib;
- bool isWeakDef;
- bool isFunctionVariant;
- uint16_t functionVariantTableIndex;
- };
-
- struct CacheImage
- {
- VMOffset targetRuntimeOffset;
- const CacheDylib* targetDylib;
- bool isWeakDef;
- bool isFunctionVariant;
- uint16_t functionVariantTableIndex;
- };
-
- Kind kind = Kind::absolute;
- union
- {
- // Just to give a default constructor...
- uint64_t unusedRawValue = 0;
-
- Absolute absolute;
- InputImage inputImage;
- CacheImage cacheImage;
- };
- uint64_t addend = 0;
- bool isWeakImport;
-#if DEBUG
- CString name;
-#endif
- };
-
- // Map from where the GOT is located in the dylib to where its located in the coalesced section
- // We don't know the final VMAddr yet, but can map from GOTs in the client to the GOT+offset in the final cache
- typedef std::unordered_map<const InputDylibVMAddress, ChunkPlusOffset, InputDylibVMAddressHash, InputDylibVMAddressEqual> CoalescedGOTsMap;
-
- typedef std::pair<BindTarget, std::string> BindTargetAndName;
- enum class SearchMode
- {
- onlySelf,
- selfAndReexports
- };
-
- std::optional<BindTargetAndName> hasExportedSymbol(Diagnostics& diag, const char* symbolName, SearchMode mode) const;
-
- objc_visitor::Visitor makeCacheObjCVisitor(const BuilderConfig& config,
- const Chunk* selectorStringsChunk,
- const ObjCCanonicalProtocolsChunk* canonicalProtocolsChunk,
- const ObjCPreAttachedCategoriesChunk* categoriesChunk) const;
-
- metadata_visitor::SwiftVisitor makeCacheSwiftVisitor(const BuilderConfig& config,
- std::span<metadata_visitor::Segment> extraRegions) const;
-
- metadata_visitor::Visitor makeCacheVisitor(const BuilderConfig& config) const;
-
-private:
-
- // Helper method for calculateBindTargets()
- BindTargetAndName resolveSymbol(Diagnostics& diag, int libOrdinal, const char* symbolName, bool weakImport,
- const std::vector<const CacheDylib*>& cacheDylibs) const;
- std::optional<BindTargetAndName> findDyldMagicSymbolAddress(const char* fullSymbolName, std::string_view name) const;
-
- void calculateBindLocationPatchInfo(Diagnostics& diag, const BuilderConfig& config,
- const BindTarget& bindTarget, uint64_t addend,
- uint32_t bindOrdinal, uint32_t segIndex,
- InputDylibVMAddress fixupVMAddr, dyld3::MachOFile::PointerMetaData pmd,
- CoalescedGOTsMap& coalescedGOTs, CoalescedGOTsMap& coalescedAuthGOTs,
- CoalescedGOTsMap& coalescedAuthPtrs, PatchInfo& dylibPatchInfo);
-
- void bindLocation(Diagnostics& diag, const BuilderConfig& config,
- const BindTarget& bindTarget, uint64_t addend,
- uint32_t bindOrdinal, uint32_t segIndex,
- dyld3::MachOFile::ChainedFixupPointerOnDisk* fixupLoc,
- CacheVMAddress fixupVMAddr, dyld3::MachOFile::PointerMetaData pmd,
- CoalescedGOTsMap& coalescedGOTs, CoalescedGOTsMap& coalescedAuthGOTs,
- CoalescedGOTsMap& coalescedAuthPtrs, PatchInfo& dylibPatchInfo,
- FunctionVariantsOptimizer& functionVariantsOptimizer);
- void bindWithChainedFixups(Diagnostics& diag, const BuilderConfig& config,
- CoalescedGOTsMap& coalescedGOTs, CoalescedGOTsMap& coalescedAuthGOTs,
- CoalescedGOTsMap& coalescedAuthPtrs, PatchInfo& dylibPatchInfo,
- FunctionVariantsOptimizer& functionVariantsOptimizer);
- void bindWithOpcodeFixups(Diagnostics& diag, const BuilderConfig& config,
- CoalescedGOTsMap& coalescedGOTs, CoalescedGOTsMap& coalescedAuthGOTs,
- CoalescedGOTsMap& coalescedAuthPtrs, PatchInfo& dylibPatchInfo,
- FunctionVariantsOptimizer& functionVariantsOptimizer);
-
- void forEachReferenceToASelRef(Diagnostics &diags,
- void (^handler)(uint64_t kind, uint32_t* instrPtr, uint64_t selRefVMAddr)) const;
-
- // Part of IMP caches
- error::Error setObjCImpCachesPointers(const BuilderConfig& config,
- const ObjCIMPCachesOptimizer& objcIMPCachesOptimizer,
- const ObjCStringsChunk* selectorStringsChunk);
-
- // Part of the stub optimization
- typedef std::unordered_map<CacheVMAddress, CacheVMAddress,
- CacheVMAddressHash, CacheVMAddressEqual> OldToNewStubMap;
- CacheDylib::OldToNewStubMap buildStubMaps(const BuilderConfig& config,
- const StubOptimizer& stubOptimizer,
- const PatchInfo& dylibPatchInfo);
-
- typedef bool (^CallSiteHandler)(uint8_t callSiteKind, uint64_t callSiteAddr,
- uint64_t stubAddr, uint32_t& instruction);
- void forEachCallSiteToAStub(Diagnostics& diag, const CallSiteHandler handler);
-
- typedef std::unordered_map<CacheVMAddress, CacheVMAddress,
- CacheVMAddressHash, CacheVMAddressEqual> GOTToTargetMap;
- GOTToTargetMap getUniquedGOTTargets(const PatchInfo& dylibPatchInfo) const;
-
-#if DEBUG
- // Helper method to watch a memory location while building the cache. Called from copyRawSegments().
- void watchMemory(const DylibSegmentChunk& segment, std::string_view dylibInstallName,
- std::string_view dylibSegmentName, uint64_t dylibAddressInSegment) const;
-#endif
-
-
-public:
- InputFile* inputFile = nullptr;
- const dyld3::MachOFile* inputMF = nullptr;
- const mach_o::Header* inputHdr = nullptr;
- std::unique_ptr<mach_o::Image> inputImage = nullptr;
- InputDylibVMAddress inputLoadAddress;
- std::string_view installName;
- uint32_t cacheIndex;
- bool needsPatchTable = true;
- dyld3::MachOFile* cacheMF = nullptr;
- const mach_o::Header* cacheHdr = nullptr;
- CacheVMAddress cacheLoadAddress;
- std::vector<DylibSegmentChunk> segments;
- // This is a list due to iterator invalidation, ie, calculateSubCacheSymbolStrings() deletes
- // elements and Region holds pointers to them
- std::list<LinkeditDataChunk> linkeditChunks;
- std::vector<DependentDylib> dependents;
- // an unmodified list of linked libraries, used for symbol resolution
- std::vector<DependentDylib> inputDependents;
- std::vector<BindTarget> bindTargets;
- std::optional<uint32_t> weakBindTargetsStartIndex;
- std::unique_ptr<DylibSegmentsAdjustor> adjustor;
-
- // The final cache won't have split seg, but we need it in multiple places during building. So keep a copy
- const uint8_t* inputDylibSplitSegStart = nullptr;
- const uint8_t* inputDylibSplitSegEnd = nullptr;
-
- // The final cache won't have dyld info, but we need it in multiple places during building. So keep a copy
- const uint8_t* inputDylibRebaseStart = nullptr;
- const uint8_t* inputDylibRebaseEnd = nullptr;
- const uint8_t* inputDylibBindStart = nullptr;
- const uint8_t* inputDylibBindEnd = nullptr;
- const uint8_t* inputDylibLazyBindStart = nullptr;
- const uint8_t* inputDylibLazyBindEnd = nullptr;
- const uint8_t* inputDylibWeakBindStart = nullptr;
- const uint8_t* inputDylibWeakBindEnd = nullptr;
-
- // calculateSubCacheSymbolStrings() builds new nlists. We need to store them here until we can copy them in to the
- // final cache binary
- NListChunk optimizedSymbols;
- const SymbolStringsChunk* subCacheSymbolStrings = nullptr;
- std::vector<uint32_t> indirectSymbolTable;
-
- // calculateUniqueGOTs() uniques GOTs across dylibs. This stores the results for this dylib
- DylibSectionCoalescer optimizedSections;
-
- // In Universal caches, this dylib will be redirected to use these alternative stubs
- StubsChunk developmentStubs;
- StubsChunk customerStubs;
-};
-static_assert(std::is_move_constructible<CacheDylib>::value, "CacheDylib needs to be move constructible");
-
-} // namespace cache_builder
-
-#endif /* CacheDylib_hpp */