#ifndef LLD_ELF_CONFIG_H
#define LLD_ELF_CONFIG_H
#include "lld/Common/CommonLinkerContext.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/ADT/CachedHashString.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/CachePruning.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/GlobPattern.h"
#include "llvm/Support/TarWriter.h"
#include <atomic>
#include <memory>
#include <mutex>
#include <optional>
#include <vector>
namespace lld::elf {
class InputFile;
class BinaryFile;
class BitcodeFile;
class ELFFileBase;
class SharedFile;
class InputSectionBase;
class EhInputSection;
class Defined;
class Undefined;
class Symbol;
class SymbolTable;
class BitcodeCompiler;
class OutputSection;
class LinkerScript;
class TargetInfo;
struct Ctx;
struct Partition;
struct PhdrEntry;
class BssSection;
class GdbIndexSection;
class GotPltSection;
class GotSection;
class IBTPltSection;
class IgotPltSection;
class InputSection;
class IpltSection;
class MipsGotSection;
class MipsRldMapSection;
class PPC32Got2Section;
class PPC64LongBranchTargetSection;
class PltSection;
class RelocationBaseSection;
class RelroPaddingSection;
class StringTableSection;
class SymbolTableBaseSection;
class SymtabShndxSection;
class SyntheticSection;
enum ELFKind : uint8_t {
ELFNoneKind,
ELF32LEKind,
ELF32BEKind,
ELF64LEKind,
ELF64BEKind
};
enum class BsymbolicKind { None, NonWeakFunctions, Functions, NonWeak, All };
enum class BuildIdKind { None, Fast, Md5, Sha1, Hexstring, Uuid };
enum class CGProfileSortKind { None, Hfsort, Cdsort };
enum class DiscardPolicy { Default, All, Locals, None };
enum class ICFLevel { None, Safe, All };
enum class StripPolicy { None, All, Debug };
enum class UnresolvedPolicy { ReportError, Warn, Ignore };
enum class OrphanHandlingPolicy { Place, Warn, Error };
enum class SortSectionPolicy {
Default,
None,
Alignment,
Name,
Priority,
Reverse,
};
enum class Target2Policy { Abs, Rel, GotRel };
enum class ARMVFPArgKind { Default, Base, VFP, ToolChain };
enum class SeparateSegmentKind { None, Code, Loadable };
enum class GnuStackKind { None, Exec, NoExec };
enum LtoKind : uint8_t {UnifiedThin, UnifiedRegular, Default};
enum class GcsPolicy { Implicit, Never, Always };
enum class ZicfilpPolicy { Implicit, Never, Unlabeled, FuncSig };
enum class ZicfissPolicy { Implicit, Never, Always };
enum class ReportPolicy { None, Warning, Error };
struct AArch64PauthAbiCoreInfo {
uint64_t platform;
uint64_t version;
bool isValid() const { return platform || version; }
static constexpr size_t size() { return sizeof(platform) + sizeof(version); }
bool operator==(const AArch64PauthAbiCoreInfo &other) const {
return platform == other.platform && version == other.version;
}
bool operator!=(const AArch64PauthAbiCoreInfo &other) const {
return !(*this == other);
}
};
struct SymbolVersion {
llvm::StringRef name;
bool isExternCpp;
bool hasWildcard;
};
struct VersionDefinition {
llvm::StringRef name;
uint16_t id;
SmallVector<SymbolVersion, 0> nonLocalPatterns;
SmallVector<SymbolVersion, 0> localPatterns;
};
class LinkerDriver {
public:
LinkerDriver(Ctx &ctx);
LinkerDriver(LinkerDriver &) = delete;
void linkerMain(ArrayRef<const char *> args);
void addFile(StringRef path, bool withLOption);
void addLibrary(StringRef name);
private:
Ctx &ctx;
void createFiles(llvm::opt::InputArgList &args);
void inferMachineType();
template <class ELFT> void link(llvm::opt::InputArgList &args);
template <class ELFT> void compileBitcodeFiles(bool skipLinkedOutput);
bool tryAddFatLTOFile(MemoryBufferRef mb, StringRef archiveName,
uint64_t offsetInArchive, bool lazy);
bool inWholeArchive = false;
bool inLib = false;
std::unique_ptr<BitcodeCompiler> lto;
SmallVector<std::unique_ptr<InputFile>, 0> files, ltoObjectFiles;
public:
uint32_t nextGroupId;
bool isInGroup;
std::unique_ptr<InputFile> armCmseImpLib;
SmallVector<std::pair<StringRef, unsigned>, 0> archiveFiles;
};
struct Config {
uint8_t osabi = 0;
uint32_t andFeatures = 0;
llvm::CachePruningPolicy thinLTOCachePolicy;
llvm::SetVector<llvm::CachedHashString> dependencyFiles;
llvm::StringMap<uint64_t> sectionStartMap;
llvm::StringRef bfdname;
llvm::StringRef chroot;
llvm::StringRef dependencyFile;
llvm::StringRef dwoDir;
llvm::StringRef dynamicLinker;
llvm::StringRef entry;
llvm::StringRef emulation;
llvm::StringRef fini;
llvm::StringRef init;
llvm::StringRef ltoAAPipeline;
llvm::StringRef ltoCSProfileFile;
llvm::StringRef ltoNewPmPasses;
llvm::StringRef ltoObjPath;
llvm::StringRef ltoSampleProfile;
llvm::StringRef mapFile;
llvm::StringRef outputFile;
llvm::StringRef optRemarksFilename;
std::optional<uint64_t> optRemarksHotnessThreshold = 0;
llvm::StringRef optRemarksPasses;
llvm::StringRef optRemarksFormat;
llvm::StringRef optStatsFilename;
llvm::StringRef progName;
llvm::StringRef printArchiveStats;
llvm::StringRef printSymbolOrder;
llvm::StringRef soName;
llvm::StringRef sysroot;
llvm::StringRef thinLTOCacheDir;
llvm::StringRef thinLTOIndexOnlyArg;
llvm::StringRef whyExtract;
llvm::SmallVector<llvm::GlobPattern, 0> whyLive;
llvm::StringRef cmseInputLib;
llvm::StringRef cmseOutputLib;
ReportPolicy zBtiReport = ReportPolicy::None;
ReportPolicy zCetReport = ReportPolicy::None;
ReportPolicy zPauthReport = ReportPolicy::None;
ReportPolicy zGcsReport = ReportPolicy::None;
ReportPolicy zGcsReportDynamic = ReportPolicy::None;
ReportPolicy zExecuteOnlyReport = ReportPolicy::None;
ReportPolicy zZicfilpUnlabeledReport = ReportPolicy::None;
ReportPolicy zZicfilpFuncSigReport = ReportPolicy::None;
ReportPolicy zZicfissReport = ReportPolicy::None;
bool ltoBBAddrMap;
llvm::StringRef ltoBasicBlockSections;
std::pair<llvm::StringRef, llvm::StringRef> thinLTOObjectSuffixReplace;
llvm::StringRef thinLTOPrefixReplaceOld;
llvm::StringRef thinLTOPrefixReplaceNew;
llvm::StringRef thinLTOPrefixReplaceNativeObject;
std::string rpath;
llvm::SmallVector<VersionDefinition, 0> versionDefinitions;
llvm::SmallVector<llvm::StringRef, 0> auxiliaryList;
llvm::SmallVector<llvm::StringRef, 0> filterList;
llvm::SmallVector<llvm::StringRef, 0> passPlugins;
llvm::SmallVector<llvm::StringRef, 0> searchPaths;
llvm::SmallVector<llvm::StringRef, 0> symbolOrderingFile;
llvm::SmallVector<llvm::StringRef, 0> thinLTOModulesToCompile;
llvm::StringRef dtltoDistributor;
llvm::SmallVector<llvm::StringRef, 0> dtltoDistributorArgs;
llvm::StringRef dtltoCompiler;
llvm::SmallVector<llvm::StringRef, 0> dtltoCompilerPrependArgs;
llvm::SmallVector<llvm::StringRef, 0> dtltoCompilerArgs;
llvm::SmallVector<llvm::StringRef, 0> undefined;
llvm::SmallVector<SymbolVersion, 0> dynamicList;
llvm::SmallVector<uint8_t, 0> buildIdVector;
llvm::SmallVector<llvm::StringRef, 0> mllvmOpts;
llvm::MapVector<std::pair<const InputSectionBase *, const InputSectionBase *>,
uint64_t>
callGraphProfile;
bool cmseImplib = false;
bool allowMultipleDefinition;
bool fatLTOObjects;
bool androidPackDynRelocs = false;
bool armHasArmISA = false;
bool armHasThumb2ISA = false;
bool armHasBlx = false;
bool armHasMovtMovw = false;
bool armJ1J2BranchEncoding = false;
bool armCMSESupport = false;
bool asNeeded = false;
bool armBe8 = false;
BsymbolicKind bsymbolic = BsymbolicKind::None;
CGProfileSortKind callGraphProfileSort;
llvm::StringRef irpgoProfilePath;
bool bpStartupFunctionSort = false;
bool bpCompressionSortStartupFunctions = false;
bool bpFunctionOrderForCompression = false;
bool bpDataOrderForCompression = false;
bool bpVerboseSectionOrderer = false;
bool branchToBranch = false;
bool checkSections;
bool checkDynamicRelocs;
std::optional<llvm::DebugCompressionType> compressDebugSections;
llvm::SmallVector<
std::tuple<llvm::GlobPattern, llvm::DebugCompressionType, unsigned>, 0>
compressSections;
bool cref;
llvm::SmallVector<std::pair<llvm::GlobPattern, uint64_t>, 0>
deadRelocInNonAlloc;
bool debugNames;
bool demangle = true;
bool dependentLibraries;
bool disableVerify;
bool ehFrameHdr;
bool emitLLVM;
bool emitRelocs;
bool enableNewDtags;
bool enableNonContiguousRegions;
bool executeOnly;
bool exportDynamic;
bool fixCortexA53Errata843419;
bool fixCortexA8;
bool formatBinary = false;
bool fortranCommon;
bool gcSections;
bool gdbIndex;
bool gnuHash = false;
bool gnuUnique;
bool ignoreDataAddressEquality;
bool ignoreFunctionAddressEquality;
bool ltoCSProfileGenerate;
bool ltoPGOWarnMismatch;
bool ltoDebugPassManager;
bool ltoEmitAsm;
bool ltoUniqueBasicBlockSectionNames;
bool ltoValidateAllVtablesHaveTypeInfos;
bool ltoWholeProgramVisibility;
bool mergeArmExidx;
bool mipsN32Abi = false;
bool mmapOutputFile;
bool nmagic;
bool noinhibitExec;
bool nostdlib;
bool oFormatBinary;
bool omagic;
bool optEB = false;
bool optEL = false;
bool optimizeBBJumps;
bool optRemarksWithHotness;
bool picThunk;
bool pie;
llvm::StringRef printGcSections;
bool printIcfSections;
bool printMemoryUsage;
std::optional<uint64_t> randomizeSectionPadding;
bool rejectMismatch;
bool relax;
bool relaxGP;
bool relocatable;
bool resolveGroups;
bool relrGlibc = false;
bool relrPackDynRelocs = false;
llvm::DenseSet<llvm::StringRef> saveTempsArgs;
llvm::SmallVector<std::pair<llvm::GlobPattern, uint32_t>, 0> shuffleSections;
bool singleRoRx;
bool singleXoRx;
bool shared;
bool symbolic;
bool isStatic = false;
bool sysvHash = false;
bool target1Rel;
bool trace;
bool thinLTOEmitImportsFiles;
bool thinLTOEmitIndexFiles;
bool thinLTOIndexOnly;
bool timeTraceEnabled;
bool tocOptimize;
bool pcRelOptimize;
bool undefinedVersion;
bool unique;
bool useAndroidRelrTags = false;
bool warnBackrefs;
llvm::SmallVector<llvm::GlobPattern, 0> warnBackrefsExclude;
bool warnCommon;
bool warnMissingEntry;
bool warnSymbolOrdering;
bool writeAddends;
bool zCombreloc;
bool zCopyreloc;
bool zDynamicUndefined;
bool zForceBti;
bool zForceIbt;
bool zGlobal;
bool zHazardplt;
bool zIfuncNoplt;
bool zInitfirst;
bool zInterpose;
bool zKeepDataSectionPrefix;
bool zKeepTextSectionPrefix;
bool zLrodataAfterBss;
bool zNoBtCfi;
bool zNodefaultlib;
bool zNodelete;
bool zNodlopen;
bool zNow;
bool zOrigin;
bool zPacPlt;
bool zRelro;
bool zRodynamic;
bool zSectionHeader;
bool zShstk;
bool zStartStopGC;
uint8_t zStartStopVisibility;
bool zText;
bool zRetpolineplt;
bool zWxneeded;
ZicfilpPolicy zZicfilp;
ZicfissPolicy zZicfiss;
DiscardPolicy discard;
GnuStackKind zGnustack;
ICFLevel icf;
OrphanHandlingPolicy orphanHandling;
SortSectionPolicy sortSection;
StripPolicy strip;
UnresolvedPolicy unresolvedSymbols;
UnresolvedPolicy unresolvedSymbolsInShlib;
Target2Policy target2;
GcsPolicy zGcs;
bool power10Stubs;
ARMVFPArgKind armVFPArgs = ARMVFPArgKind::Default;
BuildIdKind buildId = BuildIdKind::None;
SeparateSegmentKind zSeparate;
ELFKind ekind = ELFNoneKind;
uint16_t emachine = llvm::ELF::EM_NONE;
std::optional<uint64_t> imageBase;
uint64_t commonPageSize;
uint64_t maxPageSize;
uint64_t mipsGotSize;
uint64_t zStackSize;
unsigned ltoPartitions;
unsigned ltoo;
llvm::CodeGenOptLevel ltoCgo;
unsigned optimize;
StringRef thinLTOJobs;
unsigned timeTraceGranularity;
int32_t splitStackAdjustSize;
SmallVector<uint8_t, 0> packageMetadata;
bool copyRelocs;
bool is64;
bool isLE;
llvm::endianness endianness;
bool isMips64EL;
bool hasTlsIe = false;
uint32_t eflags = 0;
bool isRela;
bool isPic;
int wordsize;
int androidMemtagMode;
bool androidMemtagHeap;
bool androidMemtagStack;
LtoKind ltoKind = LtoKind::Default;
unsigned threadCount;
llvm::DenseMap<llvm::StringRef, llvm::StringRef> remapInputs;
llvm::SmallVector<std::pair<llvm::GlobPattern, llvm::StringRef>, 0>
remapInputsWildcards;
};
struct SymbolAux {
uint32_t gotIdx = -1;
uint32_t pltIdx = -1;
uint32_t tlsDescIdx = -1;
uint32_t tlsGdIdx = -1;
};
struct DuplicateSymbol {
const Symbol *sym;
const InputFile *file;
InputSectionBase *section;
uint64_t value;
};
struct UndefinedDiag {
Undefined *sym;
struct Loc {
InputSectionBase *sec;
uint64_t offset;
};
SmallVector<Loc, 0> locs;
bool isWarning;
};
struct InStruct {
std::unique_ptr<InputSection> attributes;
std::unique_ptr<SyntheticSection> hexagonAttributes;
std::unique_ptr<SyntheticSection> riscvAttributes;
std::unique_ptr<BssSection> bss;
std::unique_ptr<BssSection> bssRelRo;
std::unique_ptr<SyntheticSection> gnuProperty;
std::unique_ptr<SyntheticSection> gnuStack;
std::unique_ptr<GotSection> got;
std::unique_ptr<GotPltSection> gotPlt;
std::unique_ptr<IgotPltSection> igotPlt;
std::unique_ptr<RelroPaddingSection> relroPadding;
std::unique_ptr<SyntheticSection> armCmseSGSection;
std::unique_ptr<PPC64LongBranchTargetSection> ppc64LongBranchTarget;
std::unique_ptr<SyntheticSection> mipsAbiFlags;
std::unique_ptr<MipsGotSection> mipsGot;
std::unique_ptr<SyntheticSection> mipsOptions;
std::unique_ptr<SyntheticSection> mipsReginfo;
std::unique_ptr<MipsRldMapSection> mipsRldMap;
std::unique_ptr<SyntheticSection> partEnd;
std::unique_ptr<SyntheticSection> partIndex;
std::unique_ptr<PltSection> plt;
std::unique_ptr<IpltSection> iplt;
std::unique_ptr<PPC32Got2Section> ppc32Got2;
std::unique_ptr<IBTPltSection> ibtPlt;
std::unique_ptr<RelocationBaseSection> relaPlt;
std::unique_ptr<SyntheticSection> debugNames;
std::unique_ptr<GdbIndexSection> gdbIndex;
std::unique_ptr<StringTableSection> shStrTab;
std::unique_ptr<StringTableSection> strTab;
std::unique_ptr<SymbolTableBaseSection> symTab;
std::unique_ptr<SymtabShndxSection> symTabShndx;
};
struct Ctx : CommonLinkerContext {
Config arg;
LinkerDriver driver;
LinkerScript *script;
std::unique_ptr<TargetInfo> target;
uint8_t *bufferStart = nullptr;
Partition *mainPart = nullptr;
PhdrEntry *tlsPhdr = nullptr;
struct OutSections {
std::unique_ptr<OutputSection> elfHeader;
std::unique_ptr<OutputSection> programHeaders;
OutputSection *preinitArray = nullptr;
OutputSection *initArray = nullptr;
OutputSection *finiArray = nullptr;
};
OutSections out;
SmallVector<OutputSection *, 0> outputSections;
std::vector<Partition> partitions;
InStruct in;
struct ElfSym {
Defined *bss;
Defined *etext1;
Defined *etext2;
Defined *edata1;
Defined *edata2;
Defined *end1;
Defined *end2;
Defined *globalOffsetTable;
Defined *mipsGp;
Defined *mipsGpDisp;
Defined *mipsLocalGp;
Defined *riscvGlobalPointer;
Defined *relaIpltStart;
Defined *relaIpltEnd;
Defined *tlsModuleBase;
};
ElfSym sym{};
std::unique_ptr<SymbolTable> symtab;
SmallVector<Symbol *, 0> synthesizedSymbols;
SmallVector<std::unique_ptr<MemoryBuffer>> memoryBuffers;
SmallVector<ELFFileBase *, 0> objectFiles;
SmallVector<SharedFile *, 0> sharedFiles;
SmallVector<BinaryFile *, 0> binaryFiles;
SmallVector<BitcodeFile *, 0> bitcodeFiles;
SmallVector<BitcodeFile *, 0> lazyBitcodeFiles;
SmallVector<InputSectionBase *, 0> inputSections;
SmallVector<EhInputSection *, 0> ehInputSections;
SmallVector<SymbolAux, 0> symAux;
SmallVector<DuplicateSymbol, 0> duplicates;
std::mutex relocMutex;
SmallVector<UndefinedDiag, 0> undefErrs;
SmallVector<std::pair<Symbol *, unsigned>, 0> nonPrevailingSyms;
SmallVector<std::tuple<std::string, const InputFile *, const Symbol &>, 0>
whyExtractRecords;
llvm::DenseMap<const Symbol *,
std::pair<const InputFile *, const InputFile *>>
backwardReferences;
llvm::SmallSet<llvm::StringRef, 0> auxiliaryFiles;
std::unique_ptr<llvm::TarWriter> tar;
InputFile *internalFile = nullptr;
Undefined *dummySym = nullptr;
bool hasDynsym = false;
std::atomic<bool> hasSympart{false};
std::atomic<bool> hasTlsIe{false};
std::atomic<bool> needsTlsLd{false};
bool ltoAllVtablesHaveTypeInfos = false;
uint32_t vernauxNum = 0;
unsigned scriptSymOrderCounter = 1;
llvm::DenseMap<const Symbol *, unsigned> scriptSymOrder;
llvm::DenseSet<std::pair<const Symbol *, uint64_t>> ppc64noTocRelax;
Ctx();
llvm::raw_fd_ostream openAuxiliaryFile(llvm::StringRef, std::error_code &);
std::optional<AArch64PauthAbiCoreInfo> aarch64PauthAbiCoreInfo;
};
static inline ArrayRef<VersionDefinition> namedVersionDefs(Ctx &ctx) {
return llvm::ArrayRef(ctx.arg.versionDefinitions).slice(2);
}
struct ELFSyncStream : SyncStream {
Ctx &ctx;
ELFSyncStream(Ctx &ctx, DiagLevel level)
: SyncStream(ctx.e, level), ctx(ctx) {}
};
template <typename T>
std::enable_if_t<!std::is_pointer_v<std::remove_reference_t<T>>,
const ELFSyncStream &>
operator<<(const ELFSyncStream &s, T &&v) {
s.os << std::forward<T>(v);
return s;
}
inline const ELFSyncStream &operator<<(const ELFSyncStream &s, const char *v) {
s.os << v;
return s;
}
inline const ELFSyncStream &operator<<(const ELFSyncStream &s, Error v) {
s.os << llvm::toString(std::move(v));
return s;
}
ELFSyncStream Log(Ctx &ctx);
ELFSyncStream Msg(Ctx &ctx);
ELFSyncStream Warn(Ctx &ctx);
ELFSyncStream Err(Ctx &ctx);
ELFSyncStream ErrAlways(Ctx &ctx);
ELFSyncStream Fatal(Ctx &ctx);
uint64_t errCount(Ctx &ctx);
ELFSyncStream InternalErr(Ctx &ctx, const uint8_t *buf);
#define CHECK2(E, S) lld::check2((E), [&] { return toStr(ctx, S); })
inline DiagLevel toDiagLevel(ReportPolicy policy) {
if (policy == ReportPolicy::Error)
return DiagLevel::Err;
else if (policy == ReportPolicy::Warning)
return DiagLevel::Warn;
return DiagLevel::None;
}
}
#endif