280 lines · c
1//===- Driver.h -------------------------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLD_COFF_DRIVER_H10#define LLD_COFF_DRIVER_H11 12#include "Config.h"13#include "SymbolTable.h"14#include "lld/Common/LLVM.h"15#include "lld/Common/Reproduce.h"16#include "llvm/ADT/StringRef.h"17#include "llvm/ADT/StringSet.h"18#include "llvm/Object/Archive.h"19#include "llvm/Object/COFF.h"20#include "llvm/Option/Arg.h"21#include "llvm/Option/ArgList.h"22#include "llvm/Support/FileSystem.h"23#include "llvm/Support/TarWriter.h"24#include "llvm/WindowsDriver/MSVCPaths.h"25#include <memory>26#include <optional>27#include <set>28#include <vector>29 30namespace lld::coff {31 32using llvm::COFF::MachineTypes;33using llvm::COFF::WindowsSubsystem;34using std::optional;35 36class COFFOptTable : public llvm::opt::GenericOptTable {37public:38 COFFOptTable();39};40 41// The result of parsing the .drective section. The /export: and /include:42// options are handled separately because they reference symbols, and the number43// of symbols can be quite large. The LLVM Option library will perform at least44// one memory allocation per argument, and that is prohibitively slow for45// parsing directives.46struct ParsedDirectives {47 std::vector<StringRef> exports;48 std::vector<StringRef> includes;49 std::vector<StringRef> excludes;50 llvm::opt::InputArgList args;51};52 53class ArgParser {54public:55 ArgParser(COFFLinkerContext &ctx);56 57 // Parses command line options.58 llvm::opt::InputArgList parse(llvm::ArrayRef<const char *> args);59 60 // Tokenizes a given string and then parses as command line options.61 llvm::opt::InputArgList parse(StringRef s) { return parse(tokenize(s)); }62 63 // Tokenizes a given string and then parses as command line options in64 // .drectve section. /EXPORT options are returned in second element65 // to be processed in fastpath.66 ParsedDirectives parseDirectives(StringRef s);67 68private:69 // Concatenate LINK environment variable.70 void addLINK(SmallVector<const char *, 256> &argv);71 72 std::vector<const char *> tokenize(StringRef s);73 74 COFFLinkerContext &ctx;75};76 77class LinkerDriver {78public:79 LinkerDriver(COFFLinkerContext &ctx) : ctx(ctx) {}80 81 void linkerMain(llvm::ArrayRef<const char *> args);82 83 void addFile(InputFile *file);84 85 void addClangLibSearchPaths(const std::string &argv0);86 87 // Used by ArchiveFile to enqueue members.88 void enqueueArchiveMember(const Archive::Child &c, const Archive::Symbol &sym,89 StringRef parentName);90 91 void enqueuePDB(StringRef Path) { enqueuePath(Path, false, false); }92 93 MemoryBufferRef takeBuffer(std::unique_ptr<MemoryBuffer> mb);94 95 void enqueuePath(StringRef path, bool wholeArchive, bool lazy);96 97 // Returns a list of chunks of selected symbols.98 std::vector<Chunk *> getChunks() const;99 100 std::unique_ptr<llvm::TarWriter> tar; // for /linkrepro101 102 void pullArm64ECIcallHelper();103 104private:105 // Searches a file from search paths.106 std::optional<StringRef> findFileIfNew(StringRef filename);107 std::optional<StringRef> findLibIfNew(StringRef filename);108 StringRef findFile(StringRef filename);109 StringRef findLib(StringRef filename);110 StringRef findLibMinGW(StringRef filename);111 112 // Determines the location of the sysroot based on `args`, environment, etc.113 void detectWinSysRoot(const llvm::opt::InputArgList &args);114 115 // Adds various search paths based on the sysroot. Must only be called once116 // config.machine has been set.117 void addWinSysRootLibSearchPaths();118 119 void setMachine(llvm::COFF::MachineTypes machine);120 llvm::Triple::ArchType getArch();121 122 uint64_t getDefaultImageBase();123 124 bool isDecorated(StringRef sym);125 126 std::string getMapFile(const llvm::opt::InputArgList &args,127 llvm::opt::OptSpecifier os,128 llvm::opt::OptSpecifier osFile);129 130 std::string getImplibPath();131 132 // The import name is calculated as follows:133 //134 // | LIBRARY w/ ext | LIBRARY w/o ext | no LIBRARY135 // -----+----------------+---------------------+------------------136 // LINK | {value} | {value}.{.dll/.exe} | {output name}137 // LIB | {value} | {value}.dll | {output name}.dll138 //139 std::string getImportName(bool asLib);140 141 void createImportLibrary(bool asLib);142 143 // Used by the resolver to parse .drectve section contents.144 void parseDirectives(InputFile *file);145 146 // Parse an /order file. If an option is given, the linker places COMDAT147 // sections int he same order as their names appear in the given file.148 void parseOrderFile(StringRef arg);149 150 void parseCallGraphFile(StringRef path);151 152 void parsePDBAltPath();153 154 // Parses LIB environment which contains a list of search paths.155 void addLibSearchPaths();156 157 // Library search path. The first element is always "" (current directory).158 std::vector<StringRef> searchPaths;159 160 // Convert resource files and potentially merge input resource object161 // trees into one resource tree.162 void convertResources();163 164 void maybeExportMinGWSymbols(const llvm::opt::InputArgList &args);165 166 // We don't want to add the same file more than once.167 // Files are uniquified by their filesystem and file number.168 std::set<llvm::sys::fs::UniqueID> visitedFiles;169 170 std::set<std::string> visitedLibs;171 172 void addBuffer(std::unique_ptr<MemoryBuffer> mb, bool wholeArchive,173 bool lazy);174 void addArchiveBuffer(MemoryBufferRef mbref, StringRef symName,175 StringRef parentName, uint64_t offsetInArchive);176 void addThinArchiveBuffer(MemoryBufferRef mbref, StringRef symName);177 178 void enqueueTask(std::function<void()> task);179 bool run();180 181 std::list<std::function<void()>> taskQueue;182 std::vector<MemoryBufferRef> resources;183 184 llvm::DenseSet<StringRef> excludedSymbols;185 186 COFFLinkerContext &ctx;187 188 llvm::ToolsetLayout vsLayout = llvm::ToolsetLayout::OlderVS;189 std::string vcToolChainPath;190 llvm::SmallString<128> diaPath;191 bool useWinSysRootLibPath = false;192 llvm::SmallString<128> universalCRTLibPath;193 int sdkMajor = 0;194 llvm::SmallString<128> windowsSdkLibPath;195 196 // Functions below this line are defined in DriverUtils.cpp.197 198 void printHelp(const char *argv0);199 200 // Parses a string in the form of "<integer>[,<integer>]".201 void parseNumbers(StringRef arg, uint64_t *addr, uint64_t *size = nullptr);202 203 void parseGuard(StringRef arg);204 205 // Parses a string in the form of "<integer>[.<integer>]".206 // Minor's default value is 0.207 void parseVersion(StringRef arg, uint32_t *major, uint32_t *minor);208 209 // Parses a string in the form of "<subsystem>[,<integer>[.<integer>]]".210 void parseSubsystem(StringRef arg, WindowsSubsystem *sys, uint32_t *major,211 uint32_t *minor, bool *gotVersion = nullptr);212 213 void parseMerge(StringRef);214 void parsePDBPageSize(StringRef);215 void parseSection(StringRef);216 void parseSectionLayout(StringRef);217 218 void parseSameAddress(StringRef);219 220 // Parses a MS-DOS stub file221 void parseDosStub(StringRef path);222 223 // Parses a string in the form of "[:<integer>]"224 void parseFunctionPadMin(llvm::opt::Arg *a);225 226 // Parses a string in the form of "[:<integer>]"227 void parseDependentLoadFlags(llvm::opt::Arg *a);228 229 // Parses a string in the form of "EMBED[,=<integer>]|NO".230 void parseManifest(StringRef arg);231 232 // Parses a string in the form of "level=<string>|uiAccess=<string>"233 void parseManifestUAC(StringRef arg);234 235 // Parses a string in the form of "cd|net[,(cd|net)]*"236 void parseSwaprun(StringRef arg);237 238 // Create a resource file containing a manifest XML.239 std::unique_ptr<MemoryBuffer> createManifestRes();240 void createSideBySideManifest();241 std::string createDefaultXml();242 std::string createManifestXmlWithInternalMt(StringRef defaultXml);243 std::string createManifestXmlWithExternalMt(StringRef defaultXml);244 std::string createManifestXml();245 246 std::unique_ptr<llvm::WritableMemoryBuffer>247 createMemoryBufferForManifestRes(size_t manifestRes);248 249 // Used for dllexported symbols.250 Export parseExport(StringRef arg);251 252 // Parses a string in the form of "key=value" and check253 // if value matches previous values for the key.254 // This feature used in the directive section to reject255 // incompatible objects.256 void checkFailIfMismatch(StringRef arg, InputFile *source);257 258 // Convert Windows resource files (.res files) to a .obj file.259 MemoryBufferRef convertResToCOFF(ArrayRef<MemoryBufferRef> mbs,260 ArrayRef<ObjFile *> objs);261 262 // Create export thunks for exported and patchable Arm64EC function symbols.263 void createECExportThunks();264 void maybeCreateECExportThunk(StringRef name, Symbol *&sym);265 266 bool ltoCompilationDone = false;267};268 269// Create enum with OPT_xxx values for each option in Options.td270enum {271 OPT_INVALID = 0,272#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),273#include "Options.inc"274#undef OPTION275};276 277} // namespace lld::coff278 279#endif280