Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 1 | //===- DriverUtils.cpp ----------------------------------------------------===// |
| 2 | // |
Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 +0000 | [diff] [blame] | 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-exception |
Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | // |
Fangrui Song | f596d82 | 2022-10-01 15:12:50 -0700 | [diff] [blame] | 9 | // This file contains utility functions for the ctx.driver. Because there |
Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 10 | // are so many small functions, we created this separate file to make |
| 11 | // Driver.cpp less cluttered. |
| 12 | // |
| 13 | //===----------------------------------------------------------------------===// |
| 14 | |
Fangrui Song | 27bb799 | 2022-02-07 21:53:34 -0800 | [diff] [blame] | 15 | #include "Config.h" |
Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 16 | #include "Driver.h" |
Alexandre Ganea | 83d59e0 | 2022-01-20 14:53:18 -0500 | [diff] [blame] | 17 | #include "lld/Common/CommonLinkerContext.h" |
Rui Ueyama | 3f85170 | 2017-10-02 21:00:41 +0000 | [diff] [blame] | 18 | #include "lld/Common/Reproduce.h" |
Rui Ueyama | af2312f | 2016-05-04 23:12:55 +0000 | [diff] [blame] | 19 | #include "llvm/Option/Option.h" |
Rui Ueyama | eeb22f8 | 2015-09-25 15:37:33 +0000 | [diff] [blame] | 20 | #include "llvm/Support/CommandLine.h" |
Rui Ueyama | 4b02ca9 | 2015-10-11 03:28:39 +0000 | [diff] [blame] | 21 | #include "llvm/Support/FileSystem.h" |
Rui Ueyama | 4b02ca9 | 2015-10-11 03:28:39 +0000 | [diff] [blame] | 22 | #include "llvm/Support/Path.h" |
James Henderson | 439341b | 2020-11-03 14:41:09 +0000 | [diff] [blame] | 23 | #include "llvm/Support/TimeProfiler.h" |
Archibald Elliott | d768bf9 | 2023-02-10 09:59:46 +0000 | [diff] [blame] | 24 | #include "llvm/TargetParser/Host.h" |
Archibald Elliott | 62c7f03 | 2023-02-07 12:21:51 +0000 | [diff] [blame] | 25 | #include "llvm/TargetParser/Triple.h" |
Fangrui Song | 4191fda | 2022-11-26 19:19:15 -0800 | [diff] [blame] | 26 | #include <optional> |
Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 27 | |
| 28 | using namespace llvm; |
Rui Ueyama | cf0dd1e | 2016-04-26 20:41:32 +0000 | [diff] [blame] | 29 | using namespace llvm::sys; |
Rafael Espindola | eed9725 | 2018-02-06 18:12:41 +0000 | [diff] [blame] | 30 | using namespace llvm::opt; |
Fangrui Song | 07837b8 | 2020-05-14 22:18:58 -0700 | [diff] [blame] | 31 | using namespace lld; |
| 32 | using namespace lld::elf; |
Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 33 | |
| 34 | // Create OptTable |
| 35 | |
Chandler Carruth | dd647e3 | 2024-12-11 15:44:44 -0800 | [diff] [blame] | 36 | #define OPTTABLE_STR_TABLE_CODE |
Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 37 | #include "Options.inc" |
Chandler Carruth | dd647e3 | 2024-12-11 15:44:44 -0800 | [diff] [blame] | 38 | #undef OPTTABLE_STR_TABLE_CODE |
| 39 | |
| 40 | // Create prefix string literals used in Options.td |
| 41 | #define OPTTABLE_PREFIXES_TABLE_CODE |
| 42 | #include "Options.inc" |
| 43 | #undef OPTTABLE_PREFIXES_TABLE_CODE |
Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 44 | |
| 45 | // Create table mapping all options defined in Options.td |
serge-sans-paille | 07d9ab9 | 2022-12-23 13:25:58 +0100 | [diff] [blame] | 46 | static constexpr opt::OptTable::Info optInfo[] = { |
Jan Svoboda | 3f092f3 | 2023-08-04 11:19:09 -0700 | [diff] [blame] | 47 | #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), |
Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 48 | #include "Options.inc" |
| 49 | #undef OPTION |
| 50 | }; |
| 51 | |
Chandler Carruth | dd647e3 | 2024-12-11 15:44:44 -0800 | [diff] [blame] | 52 | ELFOptTable::ELFOptTable() |
| 53 | : GenericOptTable(OptionStrTable, OptionPrefixesTable, optInfo) {} |
Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 54 | |
Fangrui Song | bf6e259 | 2021-10-25 12:52:06 -0700 | [diff] [blame] | 55 | // Set color diagnostics according to --color-diagnostics={auto,always,never} |
| 56 | // or --no-color-diagnostics flags. |
Fangrui Song | 942928f | 2024-11-14 23:04:18 -0800 | [diff] [blame] | 57 | static void handleColorDiagnostics(Ctx &ctx, opt::InputArgList &args) { |
Fangrui Song | cbcdb52 | 2022-07-25 01:14:53 -0700 | [diff] [blame] | 58 | auto *arg = args.getLastArg(OPT_color_diagnostics); |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 59 | if (!arg) |
Bob Haarman | b8a59c8 | 2017-10-25 22:28:38 +0000 | [diff] [blame] | 60 | return; |
Fangrui Song | cbcdb52 | 2022-07-25 01:14:53 -0700 | [diff] [blame] | 61 | StringRef s = arg->getValue(); |
| 62 | if (s == "always") |
Fangrui Song | 8f238f6 | 2024-11-16 22:28:54 -0800 | [diff] [blame] | 63 | ctx.e.errs().enable_colors(true); |
Fangrui Song | cbcdb52 | 2022-07-25 01:14:53 -0700 | [diff] [blame] | 64 | else if (s == "never") |
Fangrui Song | 8f238f6 | 2024-11-16 22:28:54 -0800 | [diff] [blame] | 65 | ctx.e.errs().enable_colors(false); |
Fangrui Song | cbcdb52 | 2022-07-25 01:14:53 -0700 | [diff] [blame] | 66 | else if (s != "auto") |
Fangrui Song | 09c2c5e | 2024-11-06 22:04:52 -0800 | [diff] [blame] | 67 | ErrAlways(ctx) << "unknown option: --color-diagnostics=" << s; |
Rui Ueyama | 398f55f | 2016-12-20 02:17:24 +0000 | [diff] [blame] | 68 | } |
| 69 | |
Fangrui Song | e24457a | 2024-11-14 22:17:10 -0800 | [diff] [blame] | 70 | static cl::TokenizerCallback getQuotingStyle(Ctx &ctx, |
| 71 | opt::InputArgList &args) { |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 72 | if (auto *arg = args.getLastArg(OPT_rsp_quoting)) { |
| 73 | StringRef s = arg->getValue(); |
| 74 | if (s != "windows" && s != "posix") |
Fangrui Song | 09c2c5e | 2024-11-06 22:04:52 -0800 | [diff] [blame] | 75 | ErrAlways(ctx) << "invalid response file quoting: " << s; |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 76 | if (s == "windows") |
Davide Italiano | f296a7e | 2016-07-06 21:24:34 +0000 | [diff] [blame] | 77 | return cl::TokenizeWindowsCommandLine; |
| 78 | return cl::TokenizeGNUCommandLine; |
| 79 | } |
Sam Clegg | 928e9e1 | 2020-03-04 11:29:45 -0800 | [diff] [blame] | 80 | if (Triple(sys::getProcessTriple()).isOSWindows()) |
Davide Italiano | f296a7e | 2016-07-06 21:24:34 +0000 | [diff] [blame] | 81 | return cl::TokenizeWindowsCommandLine; |
| 82 | return cl::TokenizeGNUCommandLine; |
| 83 | } |
| 84 | |
Rui Ueyama | 0dd56dc | 2018-05-22 02:53:11 +0000 | [diff] [blame] | 85 | // Gold LTO plugin takes a `--plugin-opt foo=bar` option as an alias for |
| 86 | // `--plugin-opt=foo=bar`. We want to handle `--plugin-opt=foo=` as an |
| 87 | // option name and `bar` as a value. Unfortunately, OptParser cannot |
| 88 | // handle an option with a space in it. |
| 89 | // |
| 90 | // In this function, we concatenate command line arguments so that |
| 91 | // `--plugin-opt <foo>` is converted to `--plugin-opt=<foo>`. This is a |
| 92 | // bit hacky, but looks like it is still better than handling --plugin-opt |
| 93 | // options by hand. |
Fangrui Song | 7d13775 | 2024-11-16 15:48:01 -0800 | [diff] [blame] | 94 | static void concatLTOPluginOptions(Ctx &ctx, |
| 95 | SmallVectorImpl<const char *> &args) { |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 96 | SmallVector<const char *, 256> v; |
| 97 | for (size_t i = 0, e = args.size(); i != e; ++i) { |
| 98 | StringRef s = args[i]; |
| 99 | if ((s == "-plugin-opt" || s == "--plugin-opt") && i + 1 != e) { |
Fangrui Song | 2991a4e | 2024-11-16 22:34:12 -0800 | [diff] [blame] | 100 | v.push_back(ctx.saver.save(s + "=" + args[i + 1]).data()); |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 101 | ++i; |
Rui Ueyama | 0dd56dc | 2018-05-22 02:53:11 +0000 | [diff] [blame] | 102 | } else { |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 103 | v.push_back(args[i]); |
Rui Ueyama | 0dd56dc | 2018-05-22 02:53:11 +0000 | [diff] [blame] | 104 | } |
| 105 | } |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 106 | args = std::move(v); |
Rui Ueyama | 0dd56dc | 2018-05-22 02:53:11 +0000 | [diff] [blame] | 107 | } |
| 108 | |
Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 109 | // Parses a given list of options. |
Fangrui Song | e24457a | 2024-11-14 22:17:10 -0800 | [diff] [blame] | 110 | opt::InputArgList ELFOptTable::parse(Ctx &ctx, ArrayRef<const char *> argv) { |
Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 111 | // Make InputArgList from string vectors. |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 112 | unsigned missingIndex; |
| 113 | unsigned missingCount; |
| 114 | SmallVector<const char *, 256> vec(argv.data(), argv.data() + argv.size()); |
Davide Italiano | f296a7e | 2016-07-06 21:24:34 +0000 | [diff] [blame] | 115 | |
| 116 | // We need to get the quoting style for response files before parsing all |
| 117 | // options so we parse here before and ignore all the options but |
| 118 | // --rsp-quoting. |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 119 | opt::InputArgList args = this->ParseArgs(vec, missingIndex, missingCount); |
Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 120 | |
Rui Ueyama | 398f55f | 2016-12-20 02:17:24 +0000 | [diff] [blame] | 121 | // Expand response files (arguments in the form of @<filename>) |
| 122 | // and then parse the argument again. |
Fangrui Song | 2991a4e | 2024-11-16 22:34:12 -0800 | [diff] [blame] | 123 | cl::ExpandResponseFiles(ctx.saver, getQuotingStyle(ctx, args), vec); |
Fangrui Song | 7d13775 | 2024-11-16 15:48:01 -0800 | [diff] [blame] | 124 | concatLTOPluginOptions(ctx, vec); |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 125 | args = this->ParseArgs(vec, missingIndex, missingCount); |
Rui Ueyama | 398f55f | 2016-12-20 02:17:24 +0000 | [diff] [blame] | 126 | |
Fangrui Song | 942928f | 2024-11-14 23:04:18 -0800 | [diff] [blame] | 127 | handleColorDiagnostics(ctx, args); |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 128 | if (missingCount) |
Fangrui Song | 483516f | 2024-11-16 20:32:44 -0800 | [diff] [blame] | 129 | ErrAlways(ctx) << args.getArgString(missingIndex) << ": missing argument"; |
Rui Ueyama | d5b5ab7 | 2015-09-24 18:55:33 +0000 | [diff] [blame] | 130 | |
Nico Weber | 11b7625 | 2020-11-23 10:51:56 -0500 | [diff] [blame] | 131 | for (opt::Arg *arg : args.filtered(OPT_UNKNOWN)) { |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 132 | std::string nearest; |
| 133 | if (findNearest(arg->getAsString(args), nearest) > 1) |
Fangrui Song | 09c2c5e | 2024-11-06 22:04:52 -0800 | [diff] [blame] | 134 | ErrAlways(ctx) << "unknown argument '" << arg->getAsString(args) << "'"; |
Nico Weber | 54743d5 | 2019-05-07 13:48:30 +0000 | [diff] [blame] | 135 | else |
Fangrui Song | 09c2c5e | 2024-11-06 22:04:52 -0800 | [diff] [blame] | 136 | ErrAlways(ctx) << "unknown argument '" << arg->getAsString(args) |
| 137 | << "', did you mean '" << nearest << "'"; |
Nico Weber | 54743d5 | 2019-05-07 13:48:30 +0000 | [diff] [blame] | 138 | } |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 139 | return args; |
Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 140 | } |
Rui Ueyama | 4b02ca9 | 2015-10-11 03:28:39 +0000 | [diff] [blame] | 141 | |
Fangrui Song | a7550e1 | 2024-09-25 22:04:45 -0700 | [diff] [blame] | 142 | void elf::printHelp(Ctx &ctx) { |
Fangrui Song | 8f238f6 | 2024-11-16 22:28:54 -0800 | [diff] [blame] | 143 | auto &outs = ctx.e.outs(); |
Fangrui Song | f1e2d58 | 2021-06-24 14:47:03 -0700 | [diff] [blame] | 144 | ELFOptTable().printHelp( |
Fangrui Song | dc6229b | 2024-11-16 18:25:50 -0800 | [diff] [blame] | 145 | outs, (ctx.arg.progName + " [options] file...").str().c_str(), "lld", |
| 146 | false /*ShowHidden*/, true /*ShowAllAliases*/); |
| 147 | outs << "\n"; |
Rui Ueyama | b57412e | 2017-03-23 01:00:22 +0000 | [diff] [blame] | 148 | |
Fangrui Song | bf6e259 | 2021-10-25 12:52:06 -0700 | [diff] [blame] | 149 | // Scripts generated by Libtool versions up to 2021-10 expect /: supported |
| 150 | // targets:.* elf/ in a message for the --help option. If it doesn't match, |
| 151 | // the scripts assume that the linker doesn't support very basic features |
| 152 | // such as shared libraries. Therefore, we need to print out at least "elf". |
Fangrui Song | dc6229b | 2024-11-16 18:25:50 -0800 | [diff] [blame] | 153 | outs << ctx.arg.progName << ": supported targets: elf\n"; |
Rui Ueyama | 1eb9f44 | 2016-02-28 03:18:09 +0000 | [diff] [blame] | 154 | } |
| 155 | |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 156 | static std::string rewritePath(StringRef s) { |
| 157 | if (fs::exists(s)) |
| 158 | return relativeToRoot(s); |
Benjamin Kramer | adcd026 | 2020-01-28 20:23:46 +0100 | [diff] [blame] | 159 | return std::string(s); |
Rui Ueyama | c94dad9 | 2019-02-22 23:59:43 +0000 | [diff] [blame] | 160 | } |
| 161 | |
Rui Ueyama | fe65877 | 2016-05-15 17:10:23 +0000 | [diff] [blame] | 162 | // Reconstructs command line arguments so that so that you can re-run |
| 163 | // the same command with the same inputs. This is for --reproduce. |
Fangrui Song | 07837b8 | 2020-05-14 22:18:58 -0700 | [diff] [blame] | 164 | std::string elf::createResponseFile(const opt::InputArgList &args) { |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 165 | SmallString<0> data; |
| 166 | raw_svector_ostream os(data); |
| 167 | os << "--chroot .\n"; |
Rui Ueyama | fe65877 | 2016-05-15 17:10:23 +0000 | [diff] [blame] | 168 | |
| 169 | // Copy the command line to the output while rewriting paths. |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 170 | for (auto *arg : args) { |
| 171 | switch (arg->getOption().getID()) { |
Rui Ueyama | aa00e96 | 2016-04-30 21:40:04 +0000 | [diff] [blame] | 172 | case OPT_reproduce: |
| 173 | break; |
Rui Ueyama | 2796ae3 | 2016-04-30 22:46:47 +0000 | [diff] [blame] | 174 | case OPT_INPUT: |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 175 | os << quote(rewritePath(arg->getValue())) << "\n"; |
Rui Ueyama | aa00e96 | 2016-04-30 21:40:04 +0000 | [diff] [blame] | 176 | break; |
Rafael Espindola | bba8716 | 2017-02-01 18:04:45 +0000 | [diff] [blame] | 177 | case OPT_o: |
Alex Brachet | 7baf1db | 2022-07-29 16:17:33 +0000 | [diff] [blame] | 178 | case OPT_Map: |
Fangrui Song | 6aeffa1 | 2024-11-24 17:23:52 -0800 | [diff] [blame] | 179 | case OPT_dependency_file: |
Fangrui Song | dde41c6 | 2022-08-01 22:06:46 -0700 | [diff] [blame] | 180 | case OPT_print_archive_stats: |
| 181 | case OPT_why_extract: |
Alex Brachet | 7baf1db | 2022-07-29 16:17:33 +0000 | [diff] [blame] | 182 | // If an output path contains directories, "lld @response.txt" will |
| 183 | // likely fail because the archive we are creating doesn't contain empty |
Rafael Espindola | bba8716 | 2017-02-01 18:04:45 +0000 | [diff] [blame] | 184 | // directories for the output path (-o doesn't create directories). |
| 185 | // Strip directories to prevent the issue. |
Fangrui Song | dde41c6 | 2022-08-01 22:06:46 -0700 | [diff] [blame] | 186 | os << arg->getSpelling(); |
| 187 | if (arg->getOption().getRenderStyle() == opt::Option::RenderSeparateStyle) |
| 188 | os << ' '; |
| 189 | os << quote(path::filename(arg->getValue())) << '\n'; |
Rafael Espindola | bba8716 | 2017-02-01 18:04:45 +0000 | [diff] [blame] | 190 | break; |
Hongtao Yu | 5b8db12 | 2021-02-05 17:56:45 -0800 | [diff] [blame] | 191 | case OPT_lto_sample_profile: |
| 192 | os << arg->getSpelling() << quote(rewritePath(arg->getValue())) << "\n"; |
| 193 | break; |
Nico Weber | 4431c21 | 2020-11-30 19:54:04 -0500 | [diff] [blame] | 194 | case OPT_call_graph_ordering_file: |
Fangrui Song | f02a27d | 2024-04-19 09:09:41 -0700 | [diff] [blame] | 195 | case OPT_default_script: |
Rui Ueyama | 2796ae3 | 2016-04-30 22:46:47 +0000 | [diff] [blame] | 196 | case OPT_dynamic_list: |
Fangrui Song | b894071 | 2022-07-25 01:20:32 -0700 | [diff] [blame] | 197 | case OPT_export_dynamic_symbol_list: |
Nico Weber | 4431c21 | 2020-11-30 19:54:04 -0500 | [diff] [blame] | 198 | case OPT_just_symbols: |
George Rimar | 4f37d57 | 2017-07-21 16:27:26 +0000 | [diff] [blame] | 199 | case OPT_library_path: |
Fangrui Song | 39c20a6 | 2023-04-26 13:18:55 -0700 | [diff] [blame] | 200 | case OPT_remap_inputs_file: |
Nico Weber | 4431c21 | 2020-11-30 19:54:04 -0500 | [diff] [blame] | 201 | case OPT_retain_symbols_file: |
Rui Ueyama | 2796ae3 | 2016-04-30 22:46:47 +0000 | [diff] [blame] | 202 | case OPT_rpath: |
| 203 | case OPT_script: |
James Henderson | 1304e8d | 2017-09-06 10:10:49 +0000 | [diff] [blame] | 204 | case OPT_symbol_ordering_file: |
Alexander Richardson | d642494 | 2017-11-20 15:49:48 +0000 | [diff] [blame] | 205 | case OPT_sysroot: |
Rui Ueyama | 2796ae3 | 2016-04-30 22:46:47 +0000 | [diff] [blame] | 206 | case OPT_version_script: |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 207 | os << arg->getSpelling() << " " << quote(rewritePath(arg->getValue())) |
Peter Collingbourne | feee210 | 2016-07-26 02:00:42 +0000 | [diff] [blame] | 208 | << "\n"; |
Rui Ueyama | 2796ae3 | 2016-04-30 22:46:47 +0000 | [diff] [blame] | 209 | break; |
Rui Ueyama | aa00e96 | 2016-04-30 21:40:04 +0000 | [diff] [blame] | 210 | default: |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 211 | os << toString(*arg) << "\n"; |
Rui Ueyama | aa00e96 | 2016-04-30 21:40:04 +0000 | [diff] [blame] | 212 | } |
| 213 | } |
Kazu Hirata | 21730eb | 2024-01-22 00:13:23 -0800 | [diff] [blame] | 214 | return std::string(data); |
Rui Ueyama | cf0dd1e | 2016-04-26 20:41:32 +0000 | [diff] [blame] | 215 | } |
| 216 | |
Rui Ueyama | ec75220 | 2016-11-19 19:23:56 +0000 | [diff] [blame] | 217 | // Find a file by concatenating given paths. If a resulting path |
| 218 | // starts with "=", the character is replaced with a --sysroot value. |
Fangrui Song | dd326b1 | 2024-10-11 21:10:05 -0700 | [diff] [blame] | 219 | static std::optional<std::string> findFile(Ctx &ctx, StringRef path1, |
Fangrui Song | 4191fda | 2022-11-26 19:19:15 -0800 | [diff] [blame] | 220 | const Twine &path2) { |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 221 | SmallString<128> s; |
Fangrui Song | 8d85c96 | 2023-06-05 14:36:19 -0700 | [diff] [blame] | 222 | if (path1.starts_with("=")) |
Fangrui Song | a7e14e2 | 2024-09-21 22:54:37 -0700 | [diff] [blame] | 223 | path::append(s, ctx.arg.sysroot, path1.substr(1), path2); |
Rui Ueyama | 4b02ca9 | 2015-10-11 03:28:39 +0000 | [diff] [blame] | 224 | else |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 225 | path::append(s, path1, path2); |
Rui Ueyama | ec75220 | 2016-11-19 19:23:56 +0000 | [diff] [blame] | 226 | |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 227 | if (fs::exists(s)) |
Jonas Devlieghere | 3e24242 | 2020-01-29 21:30:21 -0800 | [diff] [blame] | 228 | return std::string(s); |
Fangrui Song | 4191fda | 2022-11-26 19:19:15 -0800 | [diff] [blame] | 229 | return std::nullopt; |
Rui Ueyama | ec75220 | 2016-11-19 19:23:56 +0000 | [diff] [blame] | 230 | } |
| 231 | |
Fangrui Song | 4986510 | 2024-10-06 11:27:24 -0700 | [diff] [blame] | 232 | std::optional<std::string> elf::findFromSearchPaths(Ctx &ctx, StringRef path) { |
Fangrui Song | a7e14e2 | 2024-09-21 22:54:37 -0700 | [diff] [blame] | 233 | for (StringRef dir : ctx.arg.searchPaths) |
Fangrui Song | dd326b1 | 2024-10-11 21:10:05 -0700 | [diff] [blame] | 234 | if (std::optional<std::string> s = findFile(ctx, dir, path)) |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 235 | return s; |
Fangrui Song | 4191fda | 2022-11-26 19:19:15 -0800 | [diff] [blame] | 236 | return std::nullopt; |
Rui Ueyama | ec75220 | 2016-11-19 19:23:56 +0000 | [diff] [blame] | 237 | } |
| 238 | |
Ben Dunbobbin | 1d16515 | 2019-05-17 03:44:15 +0000 | [diff] [blame] | 239 | // This is for -l<basename>. We'll look for lib<basename>.so or lib<basename>.a from |
Rui Ueyama | 1cb6318 | 2016-11-19 19:26:52 +0000 | [diff] [blame] | 240 | // search paths. |
Fangrui Song | 4986510 | 2024-10-06 11:27:24 -0700 | [diff] [blame] | 241 | std::optional<std::string> elf::searchLibraryBaseName(Ctx &ctx, |
| 242 | StringRef name) { |
Fangrui Song | a7e14e2 | 2024-09-21 22:54:37 -0700 | [diff] [blame] | 243 | for (StringRef dir : ctx.arg.searchPaths) { |
| 244 | if (!ctx.arg.isStatic) |
Fangrui Song | dd326b1 | 2024-10-11 21:10:05 -0700 | [diff] [blame] | 245 | if (std::optional<std::string> s = |
| 246 | findFile(ctx, dir, "lib" + name + ".so")) |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 247 | return s; |
Fangrui Song | dd326b1 | 2024-10-11 21:10:05 -0700 | [diff] [blame] | 248 | if (std::optional<std::string> s = findFile(ctx, dir, "lib" + name + ".a")) |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 249 | return s; |
Rui Ueyama | ec75220 | 2016-11-19 19:23:56 +0000 | [diff] [blame] | 250 | } |
Fangrui Song | 4191fda | 2022-11-26 19:19:15 -0800 | [diff] [blame] | 251 | return std::nullopt; |
Rui Ueyama | 4b02ca9 | 2015-10-11 03:28:39 +0000 | [diff] [blame] | 252 | } |
Alexander Richardson | 1de7847 | 2017-11-20 15:43:20 +0000 | [diff] [blame] | 253 | |
Ben Dunbobbin | 1d16515 | 2019-05-17 03:44:15 +0000 | [diff] [blame] | 254 | // This is for -l<namespec>. |
Fangrui Song | 4986510 | 2024-10-06 11:27:24 -0700 | [diff] [blame] | 255 | std::optional<std::string> elf::searchLibrary(Ctx &ctx, StringRef name) { |
James Henderson | 439341b | 2020-11-03 14:41:09 +0000 | [diff] [blame] | 256 | llvm::TimeTraceScope timeScope("Locate library", name); |
Fangrui Song | 8d85c96 | 2023-06-05 14:36:19 -0700 | [diff] [blame] | 257 | if (name.starts_with(":")) |
Fangrui Song | 4986510 | 2024-10-06 11:27:24 -0700 | [diff] [blame] | 258 | return findFromSearchPaths(ctx, name.substr(1)); |
| 259 | return searchLibraryBaseName(ctx, name); |
Ben Dunbobbin | 1d16515 | 2019-05-17 03:44:15 +0000 | [diff] [blame] | 260 | } |
| 261 | |
Fangrui Song | c60f85d | 2018-07-25 21:53:18 +0000 | [diff] [blame] | 262 | // If a linker/version script doesn't exist in the current directory, we also |
| 263 | // look for the script in the '-L' search paths. This matches the behaviour of |
| 264 | // '-T', --version-script=, and linker script INPUT() command in ld.bfd. |
Fangrui Song | 4986510 | 2024-10-06 11:27:24 -0700 | [diff] [blame] | 265 | std::optional<std::string> elf::searchScript(Ctx &ctx, StringRef name) { |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 266 | if (fs::exists(name)) |
| 267 | return name.str(); |
Fangrui Song | 4986510 | 2024-10-06 11:27:24 -0700 | [diff] [blame] | 268 | return findFromSearchPaths(ctx, name); |
Alexander Richardson | 1de7847 | 2017-11-20 15:43:20 +0000 | [diff] [blame] | 269 | } |