//===- Config.h -------------------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef LLD_MACHO_CONFIG_H #define LLD_MACHO_CONFIG_H #include "llvm/ADT/CachedHashString.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" #include "llvm/BinaryFormat/MachO.h" #include "llvm/Support/CachePruning.h" #include "llvm/Support/GlobPattern.h" #include "llvm/Support/VersionTuple.h" #include "llvm/TextAPI/Architecture.h" #include "llvm/TextAPI/Platform.h" #include "llvm/TextAPI/Target.h" #include namespace lld { namespace macho { class InputSection; class Symbol; struct SymbolPriorityEntry; using NamePair = std::pair; using SectionRenameMap = llvm::DenseMap; using SegmentRenameMap = llvm::DenseMap; struct PlatformInfo { llvm::MachO::Target target; llvm::VersionTuple minimum; llvm::VersionTuple sdk; }; inline uint32_t encodeVersion(const llvm::VersionTuple &version) { return ((version.getMajor() << 020) | (version.getMinor().getValueOr(0) << 010) | version.getSubminor().getValueOr(0)); } enum class NamespaceKind { twolevel, flat, }; enum class UndefinedSymbolTreatment { unknown, error, warning, suppress, dynamic_lookup, }; enum class ICFLevel { unknown, none, safe, all, }; struct SectionAlign { llvm::StringRef segName; llvm::StringRef sectName; uint32_t align; }; struct SegmentProtection { llvm::StringRef name; uint32_t maxProt; uint32_t initProt; }; class SymbolPatterns { public: // GlobPattern can also match literals, // but we prefer the O(1) lookup of DenseSet. llvm::DenseSet literals; std::vector globs; bool empty() const { return literals.empty() && globs.empty(); } void clear(); void insert(llvm::StringRef symbolName); bool matchLiteral(llvm::StringRef symbolName) const; bool matchGlob(llvm::StringRef symbolName) const; bool match(llvm::StringRef symbolName) const; }; struct Configuration { Symbol *entry = nullptr; bool hasReexports = false; bool allLoad = false; bool applicationExtension = false; bool archMultiple = false; bool exportDynamic = false; bool forceLoadObjC = false; bool forceLoadSwift = false; bool staticLink = false; bool implicitDylibs = false; bool isPic = false; bool headerPadMaxInstallNames = false; bool ltoNewPassManager = LLVM_ENABLE_NEW_PASS_MANAGER; bool markDeadStrippableDylib = false; bool printDylibSearch = false; bool printEachFile = false; bool printWhyLoad = false; bool searchDylibsFirst = false; bool saveTemps = false; bool adhocCodesign = false; bool emitFunctionStarts = false; bool emitBitcodeBundle = false; bool emitDataInCodeInfo = false; bool emitEncryptionInfo = false; bool timeTraceEnabled = false; bool dataConst = false; bool dedupLiterals = true; bool omitDebugInfo = false; bool warnDylibInstallName = false; uint32_t headerPad; uint32_t dylibCompatibilityVersion = 0; uint32_t dylibCurrentVersion = 0; uint32_t timeTraceGranularity = 500; unsigned optimize; std::string progName; // For `clang -arch arm64 -arch x86_64`, clang will: // 1. invoke the linker twice, to write one temporary output per arch // 2. invoke `lipo` to merge the two outputs into a single file // `outputFile` is the name of the temporary file the linker writes to. // `finalOutput `is the name of the file lipo writes to after the link. llvm::StringRef outputFile; llvm::StringRef finalOutput; llvm::StringRef installName; llvm::StringRef mapFile; llvm::StringRef ltoObjPath; llvm::StringRef thinLTOJobs; llvm::StringRef umbrella; uint32_t ltoo = 2; llvm::CachePruningPolicy thinLTOCachePolicy; llvm::StringRef thinLTOCacheDir; bool deadStripDylibs = false; bool demangle = false; bool deadStrip = false; bool errorForArchMismatch = false; PlatformInfo platformInfo; NamespaceKind namespaceKind = NamespaceKind::twolevel; UndefinedSymbolTreatment undefinedSymbolTreatment = UndefinedSymbolTreatment::error; ICFLevel icfLevel = ICFLevel::none; llvm::MachO::HeaderFileType outputType; std::vector systemLibraryRoots; std::vector librarySearchPaths; std::vector frameworkSearchPaths; std::vector runtimePaths; std::vector astPaths; std::vector explicitUndefineds; llvm::StringSet<> explicitDynamicLookups; // There are typically few custom sectionAlignments or segmentProtections, // so use a vector instead of a map. std::vector sectionAlignments; std::vector segmentProtections; llvm::DenseMap priorities; llvm::MapVector, uint64_t> callGraphProfile; bool callGraphProfileSort = false; llvm::StringRef printSymbolOrder; SectionRenameMap sectionRenameMap; SegmentRenameMap segmentRenameMap; SymbolPatterns exportedSymbols; SymbolPatterns unexportedSymbols; bool zeroModTime = false; llvm::StringRef osoPrefix; llvm::MachO::Architecture arch() const { return platformInfo.target.Arch; } llvm::MachO::PlatformType platform() const { return platformInfo.target.Platform; } }; // The symbol with the highest priority should be ordered first in the output // section (modulo input section contiguity constraints). Using priority // (highest first) instead of order (lowest first) has the convenient property // that the default-constructed zero priority -- for symbols/sections without a // user-defined order -- naturally ends up putting them at the end of the // output. struct SymbolPriorityEntry { // The priority given to a matching symbol, regardless of which object file // it originated from. size_t anyObjectFile = 0; // The priority given to a matching symbol from a particular object file. llvm::DenseMap objectFiles; }; // Whether to force-load an archive. enum class ForceLoad { Default, // Apply -all_load or -ObjC behaviors if those flags are enabled Yes, // Always load the archive, regardless of other flags No, // Never load the archive, regardless of other flags }; extern std::unique_ptr config; } // namespace macho } // namespace lld #endif