diff options
| author | 2020-08-03 15:06:44 +0000 | |
|---|---|---|
| committer | 2020-08-03 15:06:44 +0000 | |
| commit | b64793999546ed8adebaeebd9d8345d18db8927d (patch) | |
| tree | 4357c27b561d73b0e089727c6ed659f2ceff5f47 /gnu/llvm/tools/lld/lib/Driver/DarwinLdDriver.cpp | |
| parent | Add support for UTF-8 DISPLAY-HINTs with octet length. For now only (diff) | |
| download | wireguard-openbsd-b64793999546ed8adebaeebd9d8345d18db8927d.tar.xz wireguard-openbsd-b64793999546ed8adebaeebd9d8345d18db8927d.zip | |
Remove LLVM 8.0.1 files.
Diffstat (limited to 'gnu/llvm/tools/lld/lib/Driver/DarwinLdDriver.cpp')
| -rw-r--r-- | gnu/llvm/tools/lld/lib/Driver/DarwinLdDriver.cpp | 1230 |
1 files changed, 0 insertions, 1230 deletions
diff --git a/gnu/llvm/tools/lld/lib/Driver/DarwinLdDriver.cpp b/gnu/llvm/tools/lld/lib/Driver/DarwinLdDriver.cpp deleted file mode 100644 index bbac230df45..00000000000 --- a/gnu/llvm/tools/lld/lib/Driver/DarwinLdDriver.cpp +++ /dev/null @@ -1,1230 +0,0 @@ -//===- lib/Driver/DarwinLdDriver.cpp --------------------------------------===// -// -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// -/// Concrete instance of the Driver for darwin's ld. -/// -//===----------------------------------------------------------------------===// - -#include "lld/Common/Args.h" -#include "lld/Common/ErrorHandler.h" -#include "lld/Common/LLVM.h" -#include "lld/Core/ArchiveLibraryFile.h" -#include "lld/Core/Error.h" -#include "lld/Core/File.h" -#include "lld/Core/Instrumentation.h" -#include "lld/Core/LinkingContext.h" -#include "lld/Core/Node.h" -#include "lld/Core/PassManager.h" -#include "lld/Core/Resolver.h" -#include "lld/Core/SharedLibraryFile.h" -#include "lld/Core/Simple.h" -#include "lld/ReaderWriter/MachOLinkingContext.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Twine.h" -#include "llvm/BinaryFormat/MachO.h" -#include "llvm/Option/Arg.h" -#include "llvm/Option/ArgList.h" -#include "llvm/Option/OptTable.h" -#include "llvm/Option/Option.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/ErrorOr.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/raw_ostream.h" -#include <algorithm> -#include <cstdint> -#include <memory> -#include <string> -#include <system_error> -#include <utility> -#include <vector> - -using namespace lld; - -namespace { - -// Create enum with OPT_xxx values for each option in DarwinLdOptions.td -enum { - OPT_INVALID = 0, -#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ - HELP, META, VALUES) \ - OPT_##ID, -#include "DarwinLdOptions.inc" -#undef OPTION -}; - -// Create prefix string literals used in DarwinLdOptions.td -#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE; -#include "DarwinLdOptions.inc" -#undef PREFIX - -// Create table mapping all options defined in DarwinLdOptions.td -static const llvm::opt::OptTable::Info InfoTable[] = { -#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ - HELPTEXT, METAVAR, VALUES) \ - {PREFIX, NAME, HELPTEXT, \ - METAVAR, OPT_##ID, llvm::opt::Option::KIND##Class, \ - PARAM, FLAGS, OPT_##GROUP, \ - OPT_##ALIAS, ALIASARGS, VALUES}, -#include "DarwinLdOptions.inc" -#undef OPTION -}; - -// Create OptTable class for parsing actual command line arguments -class DarwinLdOptTable : public llvm::opt::OptTable { -public: - DarwinLdOptTable() : OptTable(InfoTable) {} -}; - -static std::vector<std::unique_ptr<File>> -makeErrorFile(StringRef path, std::error_code ec) { - std::vector<std::unique_ptr<File>> result; - result.push_back(llvm::make_unique<ErrorFile>(path, ec)); - return result; -} - -static std::vector<std::unique_ptr<File>> -parseMemberFiles(std::unique_ptr<File> file) { - std::vector<std::unique_ptr<File>> members; - if (auto *archive = dyn_cast<ArchiveLibraryFile>(file.get())) { - if (std::error_code ec = archive->parseAllMembers(members)) - return makeErrorFile(file->path(), ec); - } else { - members.push_back(std::move(file)); - } - return members; -} - -std::vector<std::unique_ptr<File>> loadFile(MachOLinkingContext &ctx, - StringRef path, bool wholeArchive, - bool upwardDylib) { - if (ctx.logInputFiles()) - message(path); - - ErrorOr<std::unique_ptr<MemoryBuffer>> mbOrErr = ctx.getMemoryBuffer(path); - if (std::error_code ec = mbOrErr.getError()) - return makeErrorFile(path, ec); - ErrorOr<std::unique_ptr<File>> fileOrErr = - ctx.registry().loadFile(std::move(mbOrErr.get())); - if (std::error_code ec = fileOrErr.getError()) - return makeErrorFile(path, ec); - std::unique_ptr<File> &file = fileOrErr.get(); - - // If file is a dylib, inform LinkingContext about it. - if (SharedLibraryFile *shl = dyn_cast<SharedLibraryFile>(file.get())) { - if (std::error_code ec = shl->parse()) - return makeErrorFile(path, ec); - ctx.registerDylib(reinterpret_cast<mach_o::MachODylibFile *>(shl), - upwardDylib); - } - if (wholeArchive) - return parseMemberFiles(std::move(file)); - std::vector<std::unique_ptr<File>> files; - files.push_back(std::move(file)); - return files; -} - -} // end anonymous namespace - -// Test may be running on Windows. Canonicalize the path -// separator to '/' to get consistent outputs for tests. -static std::string canonicalizePath(StringRef path) { - char sep = llvm::sys::path::get_separator().front(); - if (sep != '/') { - std::string fixedPath = path; - std::replace(fixedPath.begin(), fixedPath.end(), sep, '/'); - return fixedPath; - } else { - return path; - } -} - -static void addFile(StringRef path, MachOLinkingContext &ctx, - bool loadWholeArchive, bool upwardDylib) { - std::vector<std::unique_ptr<File>> files = - loadFile(ctx, path, loadWholeArchive, upwardDylib); - for (std::unique_ptr<File> &file : files) - ctx.getNodes().push_back(llvm::make_unique<FileNode>(std::move(file))); -} - -// Export lists are one symbol per line. Blank lines are ignored. -// Trailing comments start with #. -static std::error_code parseExportsList(StringRef exportFilePath, - MachOLinkingContext &ctx) { - // Map in export list file. - ErrorOr<std::unique_ptr<MemoryBuffer>> mb = - MemoryBuffer::getFileOrSTDIN(exportFilePath); - if (std::error_code ec = mb.getError()) - return ec; - ctx.addInputFileDependency(exportFilePath); - StringRef buffer = mb->get()->getBuffer(); - while (!buffer.empty()) { - // Split off each line in the file. - std::pair<StringRef, StringRef> lineAndRest = buffer.split('\n'); - StringRef line = lineAndRest.first; - // Ignore trailing # comments. - std::pair<StringRef, StringRef> symAndComment = line.split('#'); - StringRef sym = symAndComment.first.trim(); - if (!sym.empty()) - ctx.addExportSymbol(sym); - buffer = lineAndRest.second; - } - return std::error_code(); -} - -/// Order files are one symbol per line. Blank lines are ignored. -/// Trailing comments start with #. Symbol names can be prefixed with an -/// architecture name and/or .o leaf name. Examples: -/// _foo -/// bar.o:_bar -/// libfrob.a(bar.o):_bar -/// x86_64:_foo64 -static std::error_code parseOrderFile(StringRef orderFilePath, - MachOLinkingContext &ctx) { - // Map in order file. - ErrorOr<std::unique_ptr<MemoryBuffer>> mb = - MemoryBuffer::getFileOrSTDIN(orderFilePath); - if (std::error_code ec = mb.getError()) - return ec; - ctx.addInputFileDependency(orderFilePath); - StringRef buffer = mb->get()->getBuffer(); - while (!buffer.empty()) { - // Split off each line in the file. - std::pair<StringRef, StringRef> lineAndRest = buffer.split('\n'); - StringRef line = lineAndRest.first; - buffer = lineAndRest.second; - // Ignore trailing # comments. - std::pair<StringRef, StringRef> symAndComment = line.split('#'); - if (symAndComment.first.empty()) - continue; - StringRef sym = symAndComment.first.trim(); - if (sym.empty()) - continue; - // Check for prefix. - StringRef prefix; - std::pair<StringRef, StringRef> prefixAndSym = sym.split(':'); - if (!prefixAndSym.second.empty()) { - sym = prefixAndSym.second; - prefix = prefixAndSym.first; - if (!prefix.endswith(".o") && !prefix.endswith(".o)")) { - // If arch name prefix does not match arch being linked, ignore symbol. - if (!ctx.archName().equals(prefix)) - continue; - prefix = ""; - } - } else - sym = prefixAndSym.first; - if (!sym.empty()) { - ctx.appendOrderedSymbol(sym, prefix); - //llvm::errs() << sym << ", prefix=" << prefix << "\n"; - } - } - return std::error_code(); -} - -// -// There are two variants of the -filelist option: -// -// -filelist <path> -// In this variant, the path is to a text file which contains one file path -// per line. There are no comments or trimming of whitespace. -// -// -fileList <path>,<dir> -// In this variant, the path is to a text file which contains a partial path -// per line. The <dir> prefix is prepended to each partial path. -// -static llvm::Error loadFileList(StringRef fileListPath, - MachOLinkingContext &ctx, bool forceLoad) { - // If there is a comma, split off <dir>. - std::pair<StringRef, StringRef> opt = fileListPath.split(','); - StringRef filePath = opt.first; - StringRef dirName = opt.second; - ctx.addInputFileDependency(filePath); - // Map in file list file. - ErrorOr<std::unique_ptr<MemoryBuffer>> mb = - MemoryBuffer::getFileOrSTDIN(filePath); - if (std::error_code ec = mb.getError()) - return llvm::errorCodeToError(ec); - StringRef buffer = mb->get()->getBuffer(); - while (!buffer.empty()) { - // Split off each line in the file. - std::pair<StringRef, StringRef> lineAndRest = buffer.split('\n'); - StringRef line = lineAndRest.first; - StringRef path; - if (!dirName.empty()) { - // If there is a <dir> then prepend dir to each line. - SmallString<256> fullPath; - fullPath.assign(dirName); - llvm::sys::path::append(fullPath, Twine(line)); - path = ctx.copy(fullPath.str()); - } else { - // No <dir> use whole line as input file path. - path = ctx.copy(line); - } - if (!ctx.pathExists(path)) { - return llvm::make_error<GenericError>(Twine("File not found '") - + path - + "'"); - } - if (ctx.testingFileUsage()) { - message("Found filelist entry " + canonicalizePath(path)); - } - addFile(path, ctx, forceLoad, false); - buffer = lineAndRest.second; - } - return llvm::Error::success(); -} - -/// Parse number assuming it is base 16, but allow 0x prefix. -static bool parseNumberBase16(StringRef numStr, uint64_t &baseAddress) { - if (numStr.startswith_lower("0x")) - numStr = numStr.drop_front(2); - return numStr.getAsInteger(16, baseAddress); -} - -static void parseLLVMOptions(const LinkingContext &ctx) { - // Honor -mllvm - if (!ctx.llvmOptions().empty()) { - unsigned numArgs = ctx.llvmOptions().size(); - auto **args = new const char *[numArgs + 2]; - args[0] = "lld (LLVM option parsing)"; - for (unsigned i = 0; i != numArgs; ++i) - args[i + 1] = ctx.llvmOptions()[i]; - args[numArgs + 1] = nullptr; - llvm::cl::ParseCommandLineOptions(numArgs + 1, args); - } -} - -namespace lld { -namespace mach_o { - -bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx) { - // Parse command line options using DarwinLdOptions.td - DarwinLdOptTable table; - unsigned missingIndex; - unsigned missingCount; - llvm::opt::InputArgList parsedArgs = - table.ParseArgs(args.slice(1), missingIndex, missingCount); - if (missingCount) { - error("missing arg value for '" + - Twine(parsedArgs.getArgString(missingIndex)) + "' expected " + - Twine(missingCount) + " argument(s)."); - return false; - } - - for (auto unknownArg : parsedArgs.filtered(OPT_UNKNOWN)) { - warn("ignoring unknown argument: " + - Twine(unknownArg->getAsString(parsedArgs))); - } - - errorHandler().Verbose = parsedArgs.hasArg(OPT_v); - errorHandler().ErrorLimit = args::getInteger(parsedArgs, OPT_error_limit, 20); - - // Figure out output kind ( -dylib, -r, -bundle, -preload, or -static ) - llvm::MachO::HeaderFileType fileType = llvm::MachO::MH_EXECUTE; - bool isStaticExecutable = false; - if (llvm::opt::Arg *kind = parsedArgs.getLastArg( - OPT_dylib, OPT_relocatable, OPT_bundle, OPT_static, OPT_preload)) { - switch (kind->getOption().getID()) { - case OPT_dylib: - fileType = llvm::MachO::MH_DYLIB; - break; - case OPT_relocatable: - fileType = llvm::MachO::MH_OBJECT; - break; - case OPT_bundle: - fileType = llvm::MachO::MH_BUNDLE; - break; - case OPT_static: - fileType = llvm::MachO::MH_EXECUTE; - isStaticExecutable = true; - break; - case OPT_preload: - fileType = llvm::MachO::MH_PRELOAD; - break; - } - } - - // Handle -arch xxx - MachOLinkingContext::Arch arch = MachOLinkingContext::arch_unknown; - if (llvm::opt::Arg *archStr = parsedArgs.getLastArg(OPT_arch)) { - arch = MachOLinkingContext::archFromName(archStr->getValue()); - if (arch == MachOLinkingContext::arch_unknown) { - error("unknown arch named '" + Twine(archStr->getValue()) + "'"); - return false; - } - } - // If no -arch specified, scan input files to find first non-fat .o file. - if (arch == MachOLinkingContext::arch_unknown) { - for (auto &inFile : parsedArgs.filtered(OPT_INPUT)) { - // This is expensive because it opens and maps the file. But that is - // ok because no -arch is rare. - if (MachOLinkingContext::isThinObjectFile(inFile->getValue(), arch)) - break; - } - if (arch == MachOLinkingContext::arch_unknown && - !parsedArgs.getLastArg(OPT_test_file_usage)) { - // If no -arch and no options at all, print usage message. - if (parsedArgs.size() == 0) { - table.PrintHelp(llvm::outs(), - (std::string(args[0]) + " [options] file...").c_str(), - "LLVM Linker", false); - } else { - error("-arch not specified and could not be inferred"); - } - return false; - } - } - - // Handle -macosx_version_min or -ios_version_min - MachOLinkingContext::OS os = MachOLinkingContext::OS::unknown; - uint32_t minOSVersion = 0; - if (llvm::opt::Arg *minOS = - parsedArgs.getLastArg(OPT_macosx_version_min, OPT_ios_version_min, - OPT_ios_simulator_version_min)) { - switch (minOS->getOption().getID()) { - case OPT_macosx_version_min: - os = MachOLinkingContext::OS::macOSX; - if (MachOLinkingContext::parsePackedVersion(minOS->getValue(), - minOSVersion)) { - error("malformed macosx_version_min value"); - return false; - } - break; - case OPT_ios_version_min: - os = MachOLinkingContext::OS::iOS; - if (MachOLinkingContext::parsePackedVersion(minOS->getValue(), - minOSVersion)) { - error("malformed ios_version_min value"); - return false; - } - break; - case OPT_ios_simulator_version_min: - os = MachOLinkingContext::OS::iOS_simulator; - if (MachOLinkingContext::parsePackedVersion(minOS->getValue(), - minOSVersion)) { - error("malformed ios_simulator_version_min value"); - return false; - } - break; - } - } else { - // No min-os version on command line, check environment variables - } - - // Handle export_dynamic - // FIXME: Should we warn when this applies to something other than a static - // executable or dylib? Those are the only cases where this has an effect. - // Note, this has to come before ctx.configure() so that we get the correct - // value for _globalsAreDeadStripRoots. - bool exportDynamicSymbols = parsedArgs.hasArg(OPT_export_dynamic); - - // Now that there's enough information parsed in, let the linking context - // set up default values. - ctx.configure(fileType, arch, os, minOSVersion, exportDynamicSymbols); - - // Handle -e xxx - if (llvm::opt::Arg *entry = parsedArgs.getLastArg(OPT_entry)) - ctx.setEntrySymbolName(entry->getValue()); - - // Handle -o xxx - if (llvm::opt::Arg *outpath = parsedArgs.getLastArg(OPT_output)) - ctx.setOutputPath(outpath->getValue()); - else - ctx.setOutputPath("a.out"); - - // Handle -image_base XXX and -seg1addr XXXX - if (llvm::opt::Arg *imageBase = parsedArgs.getLastArg(OPT_image_base)) { - uint64_t baseAddress; - if (parseNumberBase16(imageBase->getValue(), baseAddress)) { - error("image_base expects a hex number"); - return false; - } else if (baseAddress < ctx.pageZeroSize()) { - error("image_base overlaps with __PAGEZERO"); - return false; - } else if (baseAddress % ctx.pageSize()) { - error("image_base must be a multiple of page size (0x" + - llvm::utohexstr(ctx.pageSize()) + ")"); - return false; - } - - ctx.setBaseAddress(baseAddress); - } - - // Handle -dead_strip - if (parsedArgs.getLastArg(OPT_dead_strip)) - ctx.setDeadStripping(true); - - bool globalWholeArchive = false; - // Handle -all_load - if (parsedArgs.getLastArg(OPT_all_load)) - globalWholeArchive = true; - - // Handle -install_name - if (llvm::opt::Arg *installName = parsedArgs.getLastArg(OPT_install_name)) - ctx.setInstallName(installName->getValue()); - else - ctx.setInstallName(ctx.outputPath()); - - // Handle -mark_dead_strippable_dylib - if (parsedArgs.getLastArg(OPT_mark_dead_strippable_dylib)) - ctx.setDeadStrippableDylib(true); - - // Handle -compatibility_version and -current_version - if (llvm::opt::Arg *vers = parsedArgs.getLastArg(OPT_compatibility_version)) { - if (ctx.outputMachOType() != llvm::MachO::MH_DYLIB) { - error("-compatibility_version can only be used with -dylib"); - return false; - } - uint32_t parsedVers; - if (MachOLinkingContext::parsePackedVersion(vers->getValue(), parsedVers)) { - error("-compatibility_version value is malformed"); - return false; - } - ctx.setCompatibilityVersion(parsedVers); - } - - if (llvm::opt::Arg *vers = parsedArgs.getLastArg(OPT_current_version)) { - if (ctx.outputMachOType() != llvm::MachO::MH_DYLIB) { - error("-current_version can only be used with -dylib"); - return false; - } - uint32_t parsedVers; - if (MachOLinkingContext::parsePackedVersion(vers->getValue(), parsedVers)) { - error("-current_version value is malformed"); - return false; - } - ctx.setCurrentVersion(parsedVers); - } - - // Handle -bundle_loader - if (llvm::opt::Arg *loader = parsedArgs.getLastArg(OPT_bundle_loader)) - ctx.setBundleLoader(loader->getValue()); - - // Handle -sectalign segname sectname align - for (auto &alignArg : parsedArgs.filtered(OPT_sectalign)) { - const char* segName = alignArg->getValue(0); - const char* sectName = alignArg->getValue(1); - const char* alignStr = alignArg->getValue(2); - if ((alignStr[0] == '0') && (alignStr[1] == 'x')) - alignStr += 2; - unsigned long long alignValue; - if (llvm::getAsUnsignedInteger(alignStr, 16, alignValue)) { - error("-sectalign alignment value '" + Twine(alignStr) + - "' not a valid number"); - return false; - } - uint16_t align = 1 << llvm::countTrailingZeros(alignValue); - if (!llvm::isPowerOf2_64(alignValue)) { - std::string Msg; - llvm::raw_string_ostream OS(Msg); - OS << "alignment for '-sectalign " << segName << " " << sectName - << llvm::format(" 0x%llX", alignValue) - << "' is not a power of two, using " << llvm::format("0x%08X", align); - OS.flush(); - warn(Msg); - } - ctx.addSectionAlignment(segName, sectName, align); - } - - // Handle -mllvm - for (auto &llvmArg : parsedArgs.filtered(OPT_mllvm)) { - ctx.appendLLVMOption(llvmArg->getValue()); - } - - // Handle -print_atoms - if (parsedArgs.getLastArg(OPT_print_atoms)) - ctx.setPrintAtoms(); - - // Handle -t (trace) option. - if (parsedArgs.getLastArg(OPT_t)) - ctx.setLogInputFiles(true); - - // Handle -demangle option. - if (parsedArgs.getLastArg(OPT_demangle)) - ctx.setDemangleSymbols(true); - - // Handle -keep_private_externs - if (parsedArgs.getLastArg(OPT_keep_private_externs)) { - ctx.setKeepPrivateExterns(true); - if (ctx.outputMachOType() != llvm::MachO::MH_OBJECT) - warn("-keep_private_externs only used in -r mode"); - } - - // Handle -dependency_info <path> used by Xcode. - if (llvm::opt::Arg *depInfo = parsedArgs.getLastArg(OPT_dependency_info)) - if (std::error_code ec = ctx.createDependencyFile(depInfo->getValue())) - warn(ec.message() + ", processing '-dependency_info " + - depInfo->getValue()); - - // In -test_file_usage mode, we'll be given an explicit list of paths that - // exist. We'll also be expected to print out information about how we located - // libraries and so on that the user specified, but not to actually do any - // linking. - if (parsedArgs.getLastArg(OPT_test_file_usage)) { - ctx.setTestingFileUsage(); - - // With paths existing by fiat, linking is not going to end well. - ctx.setDoNothing(true); - - // Only bother looking for an existence override if we're going to use it. - for (auto existingPath : parsedArgs.filtered(OPT_path_exists)) { - ctx.addExistingPathForDebug(existingPath->getValue()); - } - } - - // Register possible input file parsers. - if (!ctx.doNothing()) { - ctx.registry().addSupportMachOObjects(ctx); - ctx.registry().addSupportArchives(ctx.logInputFiles()); - ctx.registry().addSupportYamlFiles(); - } - - // Now construct the set of library search directories, following ld64's - // baroque set of accumulated hacks. Mostly, the algorithm constructs - // { syslibroots } x { libpaths } - // - // Unfortunately, there are numerous exceptions: - // 1. Only absolute paths get modified by syslibroot options. - // 2. If there is just 1 -syslibroot, system paths not found in it are - // skipped. - // 3. If the last -syslibroot is "/", all of them are ignored entirely. - // 4. If { syslibroots } x path == {}, the original path is kept. - std::vector<StringRef> sysLibRoots; - for (auto syslibRoot : parsedArgs.filtered(OPT_syslibroot)) { - sysLibRoots.push_back(syslibRoot->getValue()); - } - if (!sysLibRoots.empty()) { - // Ignore all if last -syslibroot is "/". - if (sysLibRoots.back() != "/") - ctx.setSysLibRoots(sysLibRoots); - } - - // Paths specified with -L come first, and are not considered system paths for - // the case where there is precisely 1 -syslibroot. - for (auto libPath : parsedArgs.filtered(OPT_L)) { - ctx.addModifiedSearchDir(libPath->getValue()); - } - - // Process -F directories (where to look for frameworks). - for (auto fwPath : parsedArgs.filtered(OPT_F)) { - ctx.addFrameworkSearchDir(fwPath->getValue()); - } - - // -Z suppresses the standard search paths. - if (!parsedArgs.hasArg(OPT_Z)) { - ctx.addModifiedSearchDir("/usr/lib", true); - ctx.addModifiedSearchDir("/usr/local/lib", true); - ctx.addFrameworkSearchDir("/Library/Frameworks", true); - ctx.addFrameworkSearchDir("/System/Library/Frameworks", true); - } - - // Now that we've constructed the final set of search paths, print out those - // search paths in verbose mode. - if (errorHandler().Verbose) { - message("Library search paths:"); - for (auto path : ctx.searchDirs()) { - message(" " + path); - } - message("Framework search paths:"); - for (auto path : ctx.frameworkDirs()) { - message(" " + path); - } - } - - // Handle -exported_symbols_list <file> - for (auto expFile : parsedArgs.filtered(OPT_exported_symbols_list)) { - if (ctx.exportMode() == MachOLinkingContext::ExportMode::blackList) { - error("-exported_symbols_list cannot be combined with " - "-unexported_symbol[s_list]"); - return false; - } - ctx.setExportMode(MachOLinkingContext::ExportMode::whiteList); - if (std::error_code ec = parseExportsList(expFile->getValue(), ctx)) { - error(ec.message() + ", processing '-exported_symbols_list " + - expFile->getValue()); - return false; - } - } - - // Handle -exported_symbol <symbol> - for (auto symbol : parsedArgs.filtered(OPT_exported_symbol)) { - if (ctx.exportMode() == MachOLinkingContext::ExportMode::blackList) { - error("-exported_symbol cannot be combined with " - "-unexported_symbol[s_list]"); - return false; - } - ctx.setExportMode(MachOLinkingContext::ExportMode::whiteList); - ctx.addExportSymbol(symbol->getValue()); - } - - // Handle -unexported_symbols_list <file> - for (auto expFile : parsedArgs.filtered(OPT_unexported_symbols_list)) { - if (ctx.exportMode() == MachOLinkingContext::ExportMode::whiteList) { - error("-unexported_symbols_list cannot be combined with " - "-exported_symbol[s_list]"); - return false; - } - ctx.setExportMode(MachOLinkingContext::ExportMode::blackList); - if (std::error_code ec = parseExportsList(expFile->getValue(), ctx)) { - error(ec.message() + ", processing '-unexported_symbols_list " + - expFile->getValue()); - return false; - } - } - - // Handle -unexported_symbol <symbol> - for (auto symbol : parsedArgs.filtered(OPT_unexported_symbol)) { - if (ctx.exportMode() == MachOLinkingContext::ExportMode::whiteList) { - error("-unexported_symbol cannot be combined with " - "-exported_symbol[s_list]"); - return false; - } - ctx.setExportMode(MachOLinkingContext::ExportMode::blackList); - ctx.addExportSymbol(symbol->getValue()); - } - - // Handle obosolete -multi_module and -single_module - if (llvm::opt::Arg *mod = - parsedArgs.getLastArg(OPT_multi_module, OPT_single_module)) { - if (mod->getOption().getID() == OPT_multi_module) - warn("-multi_module is obsolete and being ignored"); - else if (ctx.outputMachOType() != llvm::MachO::MH_DYLIB) - warn("-single_module being ignored. It is only for use when producing a " - "dylib"); - } - - // Handle obsolete ObjC options: -objc_gc_compaction, -objc_gc, -objc_gc_only - if (parsedArgs.getLastArg(OPT_objc_gc_compaction)) { - error("-objc_gc_compaction is not supported"); - return false; - } - - if (parsedArgs.getLastArg(OPT_objc_gc)) { - error("-objc_gc is not supported"); - return false; - } - - if (parsedArgs.getLastArg(OPT_objc_gc_only)) { - error("-objc_gc_only is not supported"); - return false; - } - - // Handle -pie or -no_pie - if (llvm::opt::Arg *pie = parsedArgs.getLastArg(OPT_pie, OPT_no_pie)) { - switch (ctx.outputMachOType()) { - case llvm::MachO::MH_EXECUTE: - switch (ctx.os()) { - case MachOLinkingContext::OS::macOSX: - if ((minOSVersion < 0x000A0500) && - (pie->getOption().getID() == OPT_pie)) { - error("-pie can only be used when targeting Mac OS X 10.5 or later"); - return false; - } - break; - case MachOLinkingContext::OS::iOS: - if ((minOSVersion < 0x00040200) && - (pie->getOption().getID() == OPT_pie)) { - error("-pie can only be used when targeting iOS 4.2 or later"); - return false; - } - break; - case MachOLinkingContext::OS::iOS_simulator: - if (pie->getOption().getID() == OPT_no_pie) { - error("iOS simulator programs must be built PIE"); - return false; - } - break; - case MachOLinkingContext::OS::unknown: - break; - } - ctx.setPIE(pie->getOption().getID() == OPT_pie); - break; - case llvm::MachO::MH_PRELOAD: - break; - case llvm::MachO::MH_DYLIB: - case llvm::MachO::MH_BUNDLE: - warn(pie->getSpelling() + - " being ignored. It is only used when linking main executables"); - break; - default: - error(pie->getSpelling() + - " can only used when linking main executables"); - return false; - } - } - - // Handle -version_load_command or -no_version_load_command - { - bool flagOn = false; - bool flagOff = false; - if (auto *arg = parsedArgs.getLastArg(OPT_version_load_command, - OPT_no_version_load_command)) { - flagOn = arg->getOption().getID() == OPT_version_load_command; - flagOff = arg->getOption().getID() == OPT_no_version_load_command; - } - - // default to adding version load command for dynamic code, - // static code must opt-in - switch (ctx.outputMachOType()) { - case llvm::MachO::MH_OBJECT: - ctx.setGenerateVersionLoadCommand(false); - break; - case llvm::MachO::MH_EXECUTE: - // dynamic executables default to generating a version load command, - // while static exectuables only generate it if required. - if (isStaticExecutable) { - if (flagOn) - ctx.setGenerateVersionLoadCommand(true); - } else { - if (!flagOff) - ctx.setGenerateVersionLoadCommand(true); - } - break; - case llvm::MachO::MH_PRELOAD: - case llvm::MachO::MH_KEXT_BUNDLE: - if (flagOn) - ctx.setGenerateVersionLoadCommand(true); - break; - case llvm::MachO::MH_DYLINKER: - case llvm::MachO::MH_DYLIB: - case llvm::MachO::MH_BUNDLE: - if (!flagOff) - ctx.setGenerateVersionLoadCommand(true); - break; - case llvm::MachO::MH_FVMLIB: - case llvm::MachO::MH_DYLDLINK: - case llvm::MachO::MH_DYLIB_STUB: - case llvm::MachO::MH_DSYM: - // We don't generate load commands for these file types, even if - // forced on. - break; - } - } - - // Handle -function_starts or -no_function_starts - { - bool flagOn = false; - bool flagOff = false; - if (auto *arg = parsedArgs.getLastArg(OPT_function_starts, - OPT_no_function_starts)) { - flagOn = arg->getOption().getID() == OPT_function_starts; - flagOff = arg->getOption().getID() == OPT_no_function_starts; - } - - // default to adding functions start for dynamic code, static code must - // opt-in - switch (ctx.outputMachOType()) { - case llvm::MachO::MH_OBJECT: - ctx.setGenerateFunctionStartsLoadCommand(false); - break; - case llvm::MachO::MH_EXECUTE: - // dynamic executables default to generating a version load command, - // while static exectuables only generate it if required. - if (isStaticExecutable) { - if (flagOn) - ctx.setGenerateFunctionStartsLoadCommand(true); - } else { - if (!flagOff) - ctx.setGenerateFunctionStartsLoadCommand(true); - } - break; - case llvm::MachO::MH_PRELOAD: - case llvm::MachO::MH_KEXT_BUNDLE: - if (flagOn) - ctx.setGenerateFunctionStartsLoadCommand(true); - break; - case llvm::MachO::MH_DYLINKER: - case llvm::MachO::MH_DYLIB: - case llvm::MachO::MH_BUNDLE: - if (!flagOff) - ctx.setGenerateFunctionStartsLoadCommand(true); - break; - case llvm::MachO::MH_FVMLIB: - case llvm::MachO::MH_DYLDLINK: - case llvm::MachO::MH_DYLIB_STUB: - case llvm::MachO::MH_DSYM: - // We don't generate load commands for these file types, even if - // forced on. - break; - } - } - - // Handle -data_in_code_info or -no_data_in_code_info - { - bool flagOn = false; - bool flagOff = false; - if (auto *arg = parsedArgs.getLastArg(OPT_data_in_code_info, - OPT_no_data_in_code_info)) { - flagOn = arg->getOption().getID() == OPT_data_in_code_info; - flagOff = arg->getOption().getID() == OPT_no_data_in_code_info; - } - - // default to adding data in code for dynamic code, static code must - // opt-in - switch (ctx.outputMachOType()) { - case llvm::MachO::MH_OBJECT: - if (!flagOff) - ctx.setGenerateDataInCodeLoadCommand(true); - break; - case llvm::MachO::MH_EXECUTE: - // dynamic executables default to generating a version load command, - // while static exectuables only generate it if required. - if (isStaticExecutable) { - if (flagOn) - ctx.setGenerateDataInCodeLoadCommand(true); - } else { - if (!flagOff) - ctx.setGenerateDataInCodeLoadCommand(true); - } - break; - case llvm::MachO::MH_PRELOAD: - case llvm::MachO::MH_KEXT_BUNDLE: - if (flagOn) - ctx.setGenerateDataInCodeLoadCommand(true); - break; - case llvm::MachO::MH_DYLINKER: - case llvm::MachO::MH_DYLIB: - case llvm::MachO::MH_BUNDLE: - if (!flagOff) - ctx.setGenerateDataInCodeLoadCommand(true); - break; - case llvm::MachO::MH_FVMLIB: - case llvm::MachO::MH_DYLDLINK: - case llvm::MachO::MH_DYLIB_STUB: - case llvm::MachO::MH_DSYM: - // We don't generate load commands for these file types, even if - // forced on. - break; - } - } - - // Handle sdk_version - if (llvm::opt::Arg *arg = parsedArgs.getLastArg(OPT_sdk_version)) { - uint32_t sdkVersion = 0; - if (MachOLinkingContext::parsePackedVersion(arg->getValue(), - sdkVersion)) { - error("malformed sdkVersion value"); - return false; - } - ctx.setSdkVersion(sdkVersion); - } else if (ctx.generateVersionLoadCommand()) { - // If we don't have an sdk version, but were going to emit a load command - // with min_version, then we need to give an warning as we have no sdk - // version to put in that command. - // FIXME: We need to decide whether to make this an error. - warn("-sdk_version is required when emitting min version load command. " - "Setting sdk version to match provided min version"); - ctx.setSdkVersion(ctx.osMinVersion()); - } - - // Handle source_version - if (llvm::opt::Arg *arg = parsedArgs.getLastArg(OPT_source_version)) { - uint64_t version = 0; - if (MachOLinkingContext::parsePackedVersion(arg->getValue(), - version)) { - error("malformed source_version value"); - return false; - } - ctx.setSourceVersion(version); - } - - // Handle stack_size - if (llvm::opt::Arg *stackSize = parsedArgs.getLastArg(OPT_stack_size)) { - uint64_t stackSizeVal; - if (parseNumberBase16(stackSize->getValue(), stackSizeVal)) { - error("stack_size expects a hex number"); - return false; - } - if ((stackSizeVal % ctx.pageSize()) != 0) { - error("stack_size must be a multiple of page size (0x" + - llvm::utohexstr(ctx.pageSize()) + ")"); - return false; - } - - ctx.setStackSize(stackSizeVal); - } - - // Handle debug info handling options: -S - if (parsedArgs.hasArg(OPT_S)) - ctx.setDebugInfoMode(MachOLinkingContext::DebugInfoMode::noDebugMap); - - // Handle -order_file <file> - for (auto orderFile : parsedArgs.filtered(OPT_order_file)) { - if (std::error_code ec = parseOrderFile(orderFile->getValue(), ctx)) { - error(ec.message() + ", processing '-order_file " + orderFile->getValue() - + "'"); - return false; - } - } - - // Handle -flat_namespace. - if (llvm::opt::Arg *ns = - parsedArgs.getLastArg(OPT_flat_namespace, OPT_twolevel_namespace)) { - if (ns->getOption().getID() == OPT_flat_namespace) - ctx.setUseFlatNamespace(true); - } - - // Handle -undefined - if (llvm::opt::Arg *undef = parsedArgs.getLastArg(OPT_undefined)) { - MachOLinkingContext::UndefinedMode UndefMode; - if (StringRef(undef->getValue()).equals("error")) - UndefMode = MachOLinkingContext::UndefinedMode::error; - else if (StringRef(undef->getValue()).equals("warning")) - UndefMode = MachOLinkingContext::UndefinedMode::warning; - else if (StringRef(undef->getValue()).equals("suppress")) - UndefMode = MachOLinkingContext::UndefinedMode::suppress; - else if (StringRef(undef->getValue()).equals("dynamic_lookup")) - UndefMode = MachOLinkingContext::UndefinedMode::dynamicLookup; - else { - error("invalid option to -undefined [ warning | error | suppress | " - "dynamic_lookup ]"); - return false; - } - - if (ctx.useFlatNamespace()) { - // If we're using -flat_namespace then 'warning', 'suppress' and - // 'dynamic_lookup' are all equivalent, so map them to 'suppress'. - if (UndefMode != MachOLinkingContext::UndefinedMode::error) - UndefMode = MachOLinkingContext::UndefinedMode::suppress; - } else { - // If we're using -twolevel_namespace then 'warning' and 'suppress' are - // illegal. Emit a diagnostic if they've been (mis)used. - if (UndefMode == MachOLinkingContext::UndefinedMode::warning || - UndefMode == MachOLinkingContext::UndefinedMode::suppress) { - error("can't use -undefined warning or suppress with " - "-twolevel_namespace"); - return false; - } - } - - ctx.setUndefinedMode(UndefMode); - } - - // Handle -no_objc_category_merging. - if (parsedArgs.getLastArg(OPT_no_objc_category_merging)) - ctx.setMergeObjCCategories(false); - - // Handle -rpath <path> - if (parsedArgs.hasArg(OPT_rpath)) { - switch (ctx.outputMachOType()) { - case llvm::MachO::MH_EXECUTE: - case llvm::MachO::MH_DYLIB: - case llvm::MachO::MH_BUNDLE: - if (!ctx.minOS("10.5", "2.0")) { - if (ctx.os() == MachOLinkingContext::OS::macOSX) - error("-rpath can only be used when targeting OS X 10.5 or later"); - else - error("-rpath can only be used when targeting iOS 2.0 or later"); - return false; - } - break; - default: - error("-rpath can only be used when creating a dynamic final linked " - "image"); - return false; - } - - for (auto rPath : parsedArgs.filtered(OPT_rpath)) { - ctx.addRpath(rPath->getValue()); - } - } - - // Parse the LLVM options before we process files in case the file handling - // makes use of things like LLVM_DEBUG(). - parseLLVMOptions(ctx); - - // Handle input files and sectcreate. - for (auto &arg : parsedArgs) { - bool upward; - llvm::Optional<StringRef> resolvedPath; - switch (arg->getOption().getID()) { - default: - continue; - case OPT_INPUT: - addFile(arg->getValue(), ctx, globalWholeArchive, false); - break; - case OPT_upward_library: - addFile(arg->getValue(), ctx, false, true); - break; - case OPT_force_load: - addFile(arg->getValue(), ctx, true, false); - break; - case OPT_l: - case OPT_upward_l: - upward = (arg->getOption().getID() == OPT_upward_l); - resolvedPath = ctx.searchLibrary(arg->getValue()); - if (!resolvedPath) { - error("Unable to find library for " + arg->getSpelling() + - arg->getValue()); - return false; - } else if (ctx.testingFileUsage()) { - message(Twine("Found ") + (upward ? "upward " : " ") + "library " + - canonicalizePath(resolvedPath.getValue())); - } - addFile(resolvedPath.getValue(), ctx, globalWholeArchive, upward); - break; - case OPT_framework: - case OPT_upward_framework: - upward = (arg->getOption().getID() == OPT_upward_framework); - resolvedPath = ctx.findPathForFramework(arg->getValue()); - if (!resolvedPath) { - error("Unable to find framework for " + arg->getSpelling() + " " + - arg->getValue()); - return false; - } else if (ctx.testingFileUsage()) { - message(Twine("Found ") + (upward ? "upward " : " ") + "framework " + - canonicalizePath(resolvedPath.getValue())); - } - addFile(resolvedPath.getValue(), ctx, globalWholeArchive, upward); - break; - case OPT_filelist: - if (auto ec = loadFileList(arg->getValue(), ctx, globalWholeArchive)) { - handleAllErrors(std::move(ec), [&](const llvm::ErrorInfoBase &EI) { - error(EI.message() + ", processing '-filelist " + arg->getValue()); - }); - return false; - } - break; - case OPT_sectcreate: { - const char* seg = arg->getValue(0); - const char* sect = arg->getValue(1); - const char* fileName = arg->getValue(2); - - ErrorOr<std::unique_ptr<MemoryBuffer>> contentOrErr = - MemoryBuffer::getFile(fileName); - - if (!contentOrErr) { - error("can't open -sectcreate file " + Twine(fileName)); - return false; - } - - ctx.addSectCreateSection(seg, sect, std::move(*contentOrErr)); - } - break; - } - } - - if (ctx.getNodes().empty()) { - error("No input files"); - return false; - } - - // Validate the combination of options used. - return ctx.validate(); -} - -static void createFiles(MachOLinkingContext &ctx, bool Implicit) { - std::vector<std::unique_ptr<File>> Files; - if (Implicit) - ctx.createImplicitFiles(Files); - else - ctx.createInternalFiles(Files); - for (auto i = Files.rbegin(), e = Files.rend(); i != e; ++i) { - auto &members = ctx.getNodes(); - members.insert(members.begin(), llvm::make_unique<FileNode>(std::move(*i))); - } -} - -/// This is where the link is actually performed. -bool link(llvm::ArrayRef<const char *> args, bool CanExitEarly, - raw_ostream &Error) { - errorHandler().LogName = args::getFilenameWithoutExe(args[0]); - errorHandler().ErrorLimitExceededMsg = - "too many errors emitted, stopping now (use " - "'-error-limit 0' to see all errors)"; - errorHandler().ErrorOS = &Error; - errorHandler().ExitEarly = CanExitEarly; - errorHandler().ColorDiagnostics = Error.has_colors(); - - MachOLinkingContext ctx; - if (!parse(args, ctx)) - return false; - if (ctx.doNothing()) - return true; - if (ctx.getNodes().empty()) - return false; - - for (std::unique_ptr<Node> &ie : ctx.getNodes()) - if (FileNode *node = dyn_cast<FileNode>(ie.get())) - node->getFile()->parse(); - - createFiles(ctx, false /* Implicit */); - - // Give target a chance to add files - createFiles(ctx, true /* Implicit */); - - // Give target a chance to postprocess input files. - // Mach-O uses this chance to move all object files before library files. - ctx.finalizeInputFiles(); - - // Do core linking. - ScopedTask resolveTask(getDefaultDomain(), "Resolve"); - Resolver resolver(ctx); - if (!resolver.resolve()) - return false; - SimpleFile *merged = nullptr; - { - std::unique_ptr<SimpleFile> mergedFile = resolver.resultFile(); - merged = mergedFile.get(); - auto &members = ctx.getNodes(); - members.insert(members.begin(), - llvm::make_unique<FileNode>(std::move(mergedFile))); - } - resolveTask.end(); - - // Run passes on linked atoms. - ScopedTask passTask(getDefaultDomain(), "Passes"); - PassManager pm; - ctx.addPasses(pm); - if (auto ec = pm.runOnFile(*merged)) { - // FIXME: This should be passed to logAllUnhandledErrors but it needs - // to be passed a Twine instead of a string. - *errorHandler().ErrorOS << "Failed to run passes on file '" - << ctx.outputPath() << "': "; - logAllUnhandledErrors(std::move(ec), *errorHandler().ErrorOS, - std::string()); - return false; - } - - passTask.end(); - - // Give linked atoms to Writer to generate output file. - ScopedTask writeTask(getDefaultDomain(), "Write"); - if (auto ec = ctx.writeFile(*merged)) { - // FIXME: This should be passed to logAllUnhandledErrors but it needs - // to be passed a Twine instead of a string. - *errorHandler().ErrorOS << "Failed to write file '" << ctx.outputPath() - << "': "; - logAllUnhandledErrors(std::move(ec), *errorHandler().ErrorOS, - std::string()); - return false; - } - - // Call exit() if we can to avoid calling destructors. - if (CanExitEarly) - exitLld(errorCount() ? 1 : 0); - - - return true; -} - -} // end namespace mach_o -} // end namespace lld |
