llvm/lld/ELF/Driver.cpp

//===- Driver.cpp ---------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// The driver drives the entire linking process. It is responsible for
// parsing command line options and doing whatever it is instructed to do.
//
// One notable thing in the LLD's driver when compared to other linkers is
// that the LLD's driver is agnostic on the host operating system.
// Other linkers usually have implicit default values (such as a dynamic
// linker path or library paths) for each host OS.
//
// I don't think implicit default values are useful because they are
// usually explicitly specified by the compiler ctx.driver. They can even
// be harmful when you are doing cross-linking. Therefore, in LLD, we
// simply trust the compiler driver to pass all required options and
// don't try to make effort on our side.
//
//===----------------------------------------------------------------------===//

#include "Driver.h"
#include "Config.h"
#include "ICF.h"
#include "InputFiles.h"
#include "InputSection.h"
#include "LTO.h"
#include "LinkerScript.h"
#include "MarkLive.h"
#include "OutputSections.h"
#include "ScriptParser.h"
#include "SymbolTable.h"
#include "Symbols.h"
#include "SyntheticSections.h"
#include "Target.h"
#include "Writer.h"
#include "lld/Common/Args.h"
#include "lld/Common/CommonLinkerContext.h"
#include "lld/Common/Driver.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Filesystem.h"
#include "lld/Common/Memory.h"
#include "lld/Common/Strings.h"
#include "lld/Common/TargetOptionsCommandFlags.h"
#include "lld/Common/Version.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/LTO/LTO.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/IRObjectFile.h"
#include "llvm/Remarks/HotnessThresholdParser.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/GlobPattern.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/Parallel.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/TarWriter.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/TimeProfiler.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdlib>
#include <tuple>
#include <utility>

usingnamespacellvm;
usingnamespacellvm::ELF;
usingnamespacellvm::object;
usingnamespacellvm::sys;
usingnamespacellvm::support;
usingnamespacelld;
usingnamespacelld::elf;

ConfigWrapper elf::config;
Ctx elf::ctx;

static void setConfigs(opt::InputArgList &args);
static void readConfigs(opt::InputArgList &args);

void elf::errorOrWarn(const Twine &msg) {}

void Ctx::reset() {}

llvm::raw_fd_ostream Ctx::openAuxiliaryFile(llvm::StringRef filename,
                                            std::error_code &ec) {}

namespace lld {
namespace elf {
bool link(ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
          llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput) {}
} // namespace elf
} // namespace lld

// Parses a linker -m option.
static std::tuple<ELFKind, uint16_t, uint8_t> parseEmulation(StringRef emul) {}

// Returns slices of MB by parsing MB as an archive file.
// Each slice consists of a member file in the archive.
std::vector<std::pair<MemoryBufferRef, uint64_t>> static getArchiveMembers(
    MemoryBufferRef mb) {}

static bool isBitcode(MemoryBufferRef mb) {}

bool LinkerDriver::tryAddFatLTOFile(MemoryBufferRef mb, StringRef archiveName,
                                    uint64_t offsetInArchive, bool lazy) {}

// Opens a file and create a file object. Path has to be resolved already.
void LinkerDriver::addFile(StringRef path, bool withLOption) {}

// Add a given library by searching it from input search paths.
void LinkerDriver::addLibrary(StringRef name) {}

// This function is called on startup. We need this for LTO since
// LTO calls LLVM functions to compile bitcode files to native code.
// Technically this can be delayed until we read bitcode files, but
// we don't bother to do lazily because the initialization is fast.
static void initLLVM() {}

// Some command line options or some combinations of them are not allowed.
// This function checks for such errors.
static void checkOptions() {}

static const char *getReproduceOption(opt::InputArgList &args) {}

static bool hasZOption(opt::InputArgList &args, StringRef key) {}

static bool getZFlag(opt::InputArgList &args, StringRef k1, StringRef k2,
                     bool defaultValue) {}

static SeparateSegmentKind getZSeparate(opt::InputArgList &args) {}

static GnuStackKind getZGnuStack(opt::InputArgList &args) {}

static uint8_t getZStartStopVisibility(opt::InputArgList &args) {}

static GcsPolicy getZGcs(opt::InputArgList &args) {}

// Report a warning for an unknown -z option.
static void checkZOptions(opt::InputArgList &args) {}

constexpr const char *saveTempsValues[] =;

void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {}

static std::string getRpath(opt::InputArgList &args) {}

// Determines what we should do if there are remaining unresolved
// symbols after the name resolution.
static void setUnresolvedSymbolPolicy(opt::InputArgList &args) {}

static Target2Policy getTarget2(opt::InputArgList &args) {}

static bool isOutputFormatBinary(opt::InputArgList &args) {}

static DiscardPolicy getDiscard(opt::InputArgList &args) {}

static StringRef getDynamicLinker(opt::InputArgList &args) {}

static int getMemtagMode(opt::InputArgList &args) {}

static ICFLevel getICF(opt::InputArgList &args) {}

static StripPolicy getStrip(opt::InputArgList &args) {}

static uint64_t parseSectionAddress(StringRef s, opt::InputArgList &args,
                                    const opt::Arg &arg) {}

static StringMap<uint64_t> getSectionStartMap(opt::InputArgList &args) {}

static SortSectionPolicy getSortSection(opt::InputArgList &args) {}

static OrphanHandlingPolicy getOrphanHandling(opt::InputArgList &args) {}

// Parse --build-id or --build-id=<style>. We handle "tree" as a
// synonym for "sha1" because all our hash functions including
// --build-id=sha1 are actually tree hashes for performance reasons.
static std::pair<BuildIdKind, SmallVector<uint8_t, 0>>
getBuildId(opt::InputArgList &args) {}

static std::pair<bool, bool> getPackDynRelocs(opt::InputArgList &args) {}

static void readCallGraph(MemoryBufferRef mb) {}

// If SHT_LLVM_CALL_GRAPH_PROFILE and its relocation section exist, returns
// true and populates cgProfile and symbolIndices.
template <class ELFT>
static bool
processCallGraphRelocations(SmallVector<uint32_t, 32> &symbolIndices,
                            ArrayRef<typename ELFT::CGProfile> &cgProfile,
                            ObjFile<ELFT> *inputObj) {}

template <class ELFT> static void readCallGraphsFromObjectFiles() {}

template <class ELFT>
static void ltoValidateAllVtablesHaveTypeInfos(opt::InputArgList &args) {}

static CGProfileSortKind getCGProfileSortKind(opt::InputArgList &args) {}

static DebugCompressionType getCompressionType(StringRef s, StringRef option) {}

static StringRef getAliasSpelling(opt::Arg *arg) {}

static std::pair<StringRef, StringRef> getOldNewOptions(opt::InputArgList &args,
                                                        unsigned id) {}

// Parse options of the form "old;new[;extra]".
static std::tuple<StringRef, StringRef, StringRef>
getOldNewOptionsExtra(opt::InputArgList &args, unsigned id) {}

// Parse the symbol ordering file and warn for any duplicate entries.
static SmallVector<StringRef, 0> getSymbolOrderingFile(MemoryBufferRef mb) {}

static bool getIsRela(opt::InputArgList &args) {}

static void parseClangOption(StringRef opt, const Twine &msg) {}

// Checks the parameter of the bti-report and cet-report options.
static bool isValidReportString(StringRef arg) {}

// Process a remap pattern 'from-glob=to-file'.
static bool remapInputs(StringRef line, const Twine &location) {}

// Initializes Config members by the command line options.
static void readConfigs(opt::InputArgList &args) {}

// Some Config members do not directly correspond to any particular
// command line options, but computed based on other Config values.
// This function initialize such members. See Config.h for the details
// of these values.
static void setConfigs(opt::InputArgList &args) {}

static bool isFormatBinary(StringRef s) {}

void LinkerDriver::createFiles(opt::InputArgList &args) {}

// If -m <machine_type> was not given, infer it from object files.
void LinkerDriver::inferMachineType() {}

// Parse -z max-page-size=<value>. The default value is defined by
// each target.
static uint64_t getMaxPageSize(opt::InputArgList &args) {}

// Parse -z common-page-size=<value>. The default value is defined by
// each target.
static uint64_t getCommonPageSize(opt::InputArgList &args) {}

// Parses --image-base option.
static std::optional<uint64_t> getImageBase(opt::InputArgList &args) {}

// Parses `--exclude-libs=lib,lib,...`.
// The library names may be delimited by commas or colons.
static DenseSet<StringRef> getExcludeLibs(opt::InputArgList &args) {}

// Handles the --exclude-libs option. If a static library file is specified
// by the --exclude-libs option, all public symbols from the archive become
// private unless otherwise specified by version scripts or something.
// A special library name "ALL" means all archive files.
//
// This is not a popular option, but some programs such as bionic libc use it.
static void excludeLibs(opt::InputArgList &args) {}

// Force Sym to be entered in the output.
static void handleUndefined(Symbol *sym, const char *option) {}

// As an extension to GNU linkers, lld supports a variant of `-u`
// which accepts wildcard patterns. All symbols that match a given
// pattern are handled as if they were given by `-u`.
static void handleUndefinedGlob(StringRef arg) {}

static void handleLibcall(StringRef name) {}

static void writeArchiveStats() {}

static void writeWhyExtract() {}

static void reportBackrefs() {}

// Handle --dependency-file=<path>. If that option is given, lld creates a
// file at a given path with the following contents:
//
//   <output-file>: <input-file> ...
//
//   <input-file>:
//
// where <output-file> is a pathname of an output file and <input-file>
// ... is a list of pathnames of all input files. `make` command can read a
// file in the above format and interpret it as a dependency info. We write
// phony targets for every <input-file> to avoid an error when that file is
// removed.
//
// This option is useful if you want to make your final executable to depend
// on all input files including system libraries. Here is why.
//
// When you write a Makefile, you usually write it so that the final
// executable depends on all user-generated object files. Normally, you
// don't make your executable to depend on system libraries (such as libc)
// because you don't know the exact paths of libraries, even though system
// libraries that are linked to your executable statically are technically a
// part of your program. By using --dependency-file option, you can make
// lld to dump dependency info so that you can maintain exact dependencies
// easily.
static void writeDependencyFile() {}

// Replaces common symbols with defined symbols reside in .bss sections.
// This function is called after all symbol names are resolved. As a
// result, the passes after the symbol resolution won't see any
// symbols of type CommonSymbol.
static void replaceCommonSymbols() {}

// The section referred to by `s` is considered address-significant. Set the
// keepUnique flag on the section if appropriate.
static void markAddrsig(Symbol *s) {}

// Record sections that define symbols mentioned in --keep-unique <symbol>
// and symbols referred to by address-significance tables. These sections are
// ineligible for ICF.
template <class ELFT>
static void findKeepUniqueSections(opt::InputArgList &args) {}

// This function reads a symbol partition specification section. These sections
// are used to control which partition a symbol is allocated to. See
// https://lld.llvm.org/Partitions.html for more details on partitions.
template <typename ELFT>
static void readSymbolPartitionSection(InputSectionBase *s) {}

static void markBuffersAsDontNeed(bool skipLinkedOutput) {}

// This function is where all the optimizations of link-time
// optimization takes place. When LTO is in use, some input files are
// not in native object file format but in the LLVM bitcode format.
// This function compiles bitcode files into a few big native files
// using LLVM functions and replaces bitcode symbols with the results.
// Because all bitcode files that the program consists of are passed to
// the compiler at once, it can do a whole-program optimization.
template <class ELFT>
void LinkerDriver::compileBitcodeFiles(bool skipLinkedOutput) {}

// The --wrap option is a feature to rename symbols so that you can write
// wrappers for existing functions. If you pass `--wrap=foo`, all
// occurrences of symbol `foo` are resolved to `__wrap_foo` (so, you are
// expected to write `__wrap_foo` function as a wrapper). The original
// symbol becomes accessible as `__real_foo`, so you can call that from your
// wrapper.
//
// This data structure is instantiated for each --wrap option.
struct WrappedSymbol {};

// Handles --wrap option.
//
// This function instantiates wrapper symbols. At this point, they seem
// like they are not being used at all, so we explicitly set some flags so
// that LTO won't eliminate them.
static std::vector<WrappedSymbol> addWrappedSymbols(opt::InputArgList &args) {}

static void combineVersionedSymbol(Symbol &sym,
                                   DenseMap<Symbol *, Symbol *> &map) {}

// Do renaming for --wrap and foo@v1 by updating pointers to symbols.
//
// When this function is executed, only InputFiles and symbol table
// contain pointers to symbol objects. We visit them to replace pointers,
// so that wrapped symbols are swapped as instructed by the command line.
static void redirectSymbols(ArrayRef<WrappedSymbol> wrapped) {}

static void reportMissingFeature(StringRef config, const Twine &report) {}

static void checkAndReportMissingFeature(StringRef config, uint32_t features,
                                         uint32_t mask, const Twine &report) {}

// To enable CET (x86's hardware-assisted control flow enforcement), each
// source file must be compiled with -fcf-protection. Object files compiled
// with the flag contain feature flags indicating that they are compatible
// with CET. We enable the feature only when all object files are compatible
// with CET.
//
// This is also the case with AARCH64's BTI and PAC which use the similar
// GNU_PROPERTY_AARCH64_FEATURE_1_AND mechanism.
//
// For AArch64 PAuth-enabled object files, the core info of all of them must
// match. Missing info for some object files with matching info for remaining
// ones can be allowed (see -z pauth-report).
static void readSecurityNotes() {}

static void initSectionsAndLocalSyms(ELFFileBase *file, bool ignoreComdats) {}

static void postParseObjectFile(ELFFileBase *file) {}

// Do actual linking. Note that when this function is called,
// all linker scripts have already been parsed.
template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {}