1
1
mirror of https://github.com/rui314/mold.git synced 2024-11-11 05:46:58 +03:00
mold/cmdline.cc

825 lines
30 KiB
C++
Raw Normal View History

2021-02-28 05:32:04 +03:00
#include "mold.h"
2021-04-09 04:08:56 +03:00
#include <sstream>
#include <sys/stat.h>
#include <sys/types.h>
2021-02-28 05:32:04 +03:00
#include <tbb/global_control.h>
#include <unistd.h>
2021-02-28 05:32:04 +03:00
#include <unordered_set>
2021-05-16 19:06:30 +03:00
static const char helpmsg[] = R"(
Options:
2021-05-08 11:50:09 +03:00
--help Report usage information
-v, --version Report version information
2021-05-10 13:12:12 +03:00
-V Report version and target information
2021-05-08 11:50:09 +03:00
-(, --start-group Ignored
-), --end-group Ignored
2021-05-08 14:40:41 +03:00
-C DIR, --directory DIR Change to DIR before doing anything
-E, --export-dynamic Put symbols in the dynamic symbol table
2021-05-08 11:50:09 +03:00
--no-export-dynamic
-F LIBNAME, --filter LIBNAME
2021-05-08 14:40:41 +03:00
Set DT_FILTER to the specified value
2021-05-08 11:50:09 +03:00
-I FILE, --dynamic-linker FILE
2021-05-08 14:40:41 +03:00
Set dynamic linker path
2021-05-08 11:50:09 +03:00
--no-dynamic-linker
2021-05-08 14:40:41 +03:00
-L DIR, --library-path DIR Add DIR to library search path
-M, --print-map Write map file to stdout
2021-05-10 13:12:12 +03:00
-N, --omagic Do not page align data, do not make text readonly
--no-omagic
2021-05-08 11:50:09 +03:00
-O NUMBER Ignored
2021-05-08 14:40:41 +03:00
-S, --strip-debug Strip .debug_* sections
-T FILE, --script FILE Read linker script
-X, --discard-locals Discard temporary local symbols
-e SYMBOL, --entry SYMBOL Set program entry point
-f SHLIB, --auxiliary SHLIB Set DT_AUXILIARY to the specified value
2021-05-08 11:50:09 +03:00
-h LIBNAME, --soname LIBNAME
2021-05-08 14:40:41 +03:00
Set shared library name
-l LIBNAME Search for a given library
2021-05-08 11:50:09 +03:00
-m EMULATION Ignored
2021-05-16 09:22:26 +03:00
-o FILE, --output FILE Set output filename
-r, --relocatable Generate relocatable output
2021-05-08 14:40:41 +03:00
-s, --strip-all Strip .symtab section
2021-05-08 11:50:09 +03:00
-u SYMBOL, --undefined SYMBOL
2021-05-08 14:40:41 +03:00
Force to resolve SYMBOL
--Bdynamic Link against shared libraries (default)
--Bstatic Do not link against shared libraries
--Bsymbolic Bind global symbols locally
--Bsymbolic-functions Bind global functions locally
--Map FILE Write map file to a given file
--allow-multiple-definition Allow multiple definitions
2021-05-08 14:40:41 +03:00
--as-needed Only set DT_NEEDED if used
2021-05-08 11:50:09 +03:00
--no-as-needed
--build-id [none,md5,sha1,sha256,uuid,HEXSTRING]
2021-05-08 14:40:41 +03:00
Generate build ID
2021-05-08 11:50:09 +03:00
--no-build-id
2021-05-08 14:40:41 +03:00
--chroot DIR Set a given path to root directory
2021-05-08 11:50:09 +03:00
--color-diagnostics Ignored
2021-06-03 16:22:29 +03:00
--compress-debug-sections [none,zlib,zlib-gabi,zlib-gnu]
2021-05-08 14:40:41 +03:00
Compress .debug_* sections
--demangle Demangle C++ symbols in log messages (default)
2021-05-08 11:50:09 +03:00
--no-demangle
2021-05-08 14:40:41 +03:00
--disable-new-dtags Ignored
--dynamic-list Read a list of dynamic symbols
--eh-frame-hdr Create .eh_frame_hdr section
2021-05-08 11:50:09 +03:00
--no-eh-frame-hdr
2021-05-08 14:40:41 +03:00
--enable-new-dtags Ignored
--exclude-libs LIB,LIB,.. Mark all symbols in given libraries hidden
2021-05-08 11:50:09 +03:00
--fatal-warnings Ignored
--no-fatal-warnings Ignored
2021-05-08 14:40:41 +03:00
--fini SYMBOL Call SYMBOL at unload-time
--fork Spawn a child process (default)
2021-05-08 11:50:09 +03:00
--no-fork
2021-05-08 14:40:41 +03:00
--gc-sections Remove unreferenced sections
2021-05-08 11:50:09 +03:00
--no-gc-sections
2021-05-08 14:40:41 +03:00
--gdb-index Ignored
2021-05-08 11:50:09 +03:00
--hash-style [sysv,gnu,both]
2021-05-08 14:40:41 +03:00
Set hash style
--icf Fold identical code
2021-05-08 11:50:09 +03:00
--no-icf
2021-05-21 11:28:51 +03:00
--image-base ADDR Set the base address to a given value
2021-05-08 14:40:41 +03:00
--init SYMBOL Call SYMBOl at load-time
--no-undefined Report undefined symbols (even with --shared)
--perf Print performance statistics
--pie, --pic-executable Create a position independent executable
2021-05-08 11:50:09 +03:00
--no-pie, --no-pic-executable
--plugin Ignored
--plugin-opt Ignored
2021-05-08 14:40:41 +03:00
--pop-state Pop state of flags governing input file handling
2021-05-08 11:50:09 +03:00
--preload
2021-05-08 14:40:41 +03:00
--print-gc-sections Print removed unreferenced sections
2021-05-08 11:50:09 +03:00
--no-print-gc-sections
2021-05-08 14:40:41 +03:00
--print-icf-sections Print folded identical sections
2021-05-08 11:50:09 +03:00
--no-print-icf-sections
2021-05-08 14:40:41 +03:00
--push-state Pop state of flags governing input file handling
--quick-exit Use quick_exit to exit (default)
2021-05-08 11:50:09 +03:00
--no-quick-exit
2021-05-08 14:40:41 +03:00
--relax Optimize instructions (default)
2021-05-08 11:50:09 +03:00
--no-relax
2021-05-08 14:40:41 +03:00
--repro Embed input files to .repro section
2021-05-26 16:48:53 +03:00
--retain-symbols-file FILE Keep only symbols listed in FILE
2021-05-08 14:40:41 +03:00
--rpath DIR Add DIR to runtime search path
--rpath-link DIR Ignored
--run COMMAND ARG... Run COMMAND with mold as /usr/bin/ld
--shared, --Bshareable Create a share library
2021-05-08 11:50:09 +03:00
--sort-common Ignored
--sort-section Ignored
2021-05-08 14:40:41 +03:00
--spare-dynamic-tags NUMBER Reserve give number of tags in .dynamic section
--static Do not link against shared libraries
--stats Print input statistics
--sysroot DIR Set target system root directory
--thread-count COUNT Use COUNT number of threads
--threads Use multiple threads (default)
2021-05-08 11:50:09 +03:00
--no-threads
2021-05-08 14:40:41 +03:00
--trace Print name of each input file
--version-script FILE Read version script
--warn-common Warn about common symbols
2021-05-08 11:50:09 +03:00
--no-warn-common
--warn-unresolved-symbols Report unresolved symbols as warnings
--error-unresolved-symbols
Report unresolved symbols as errors (default)
2021-05-08 14:40:41 +03:00
--whole-archive Include all objects from static archives
2021-05-08 11:50:09 +03:00
--no-whole-archive
2021-05-21 19:12:24 +03:00
--wrap SYMBOL Use wrapper function for a given symbol
2021-05-08 14:40:41 +03:00
-z defs Report undefined symbols (even with --shared)
2021-05-08 11:50:09 +03:00
-z nodefs
2021-06-17 07:32:39 +03:00
-z execstack Require executable stack
-z noexecstack
-z initfirst Mark DSO to be initialized first at runtime
-z interpose Mark object to interpose all DSOs but executable
2021-06-15 17:26:18 +03:00
-z keep-text-section-prefix Keep .text.{hot,unknown,unlikely,startup,exit} as separate sections in the final binary
-z nokeep-text-section-prefix
2021-06-17 07:32:39 +03:00
-z lazy Enable lazy function resolution (default)
2021-05-08 14:40:41 +03:00
-z nocopyreloc Do not create copy relocations
2021-06-17 07:32:39 +03:00
-z nodelete Mark DSO non-deletable at runtime
-z nodlopen Mark DSO not available to dlopen
-z now Disable lazy function resolution
-z relro Make some sections read-only after relocation (default)
-z norelro
-z text Report error if DT_TEXTREL is set
-z notext
-z textoff
mold: supported targets: elf32-i386 elf64-x86-64
mold: supported emulations: elf_i386 elf_x86_64)";
2021-05-08 11:50:09 +03:00
2021-03-29 14:29:57 +03:00
template <typename E>
2021-03-29 10:48:23 +03:00
static std::vector<std::string_view>
2021-03-29 14:29:57 +03:00
read_response_file(Context<E> &ctx, std::string_view path) {
2021-02-28 05:32:04 +03:00
std::vector<std::string_view> vec;
2021-03-29 14:29:57 +03:00
MemoryMappedFile<E> *mb =
MemoryMappedFile<E>::must_open(ctx, std::string(path));
2021-03-29 10:48:23 +03:00
u8 *data = mb->data(ctx);
2021-02-28 05:32:04 +03:00
auto read_quoted = [&](i64 i, char quote) {
2021-04-06 12:18:45 +03:00
std::string buf;
2021-03-29 10:48:23 +03:00
while (i < mb->size() && data[i] != quote) {
if (data[i] == '\\') {
2021-04-06 12:18:45 +03:00
buf.append(1, data[i + 1]);
2021-02-28 05:32:04 +03:00
i += 2;
} else {
2021-04-06 12:18:45 +03:00
buf.append(1, data[i++]);
2021-02-28 05:32:04 +03:00
}
}
if (i >= mb->size())
2021-03-29 10:48:23 +03:00
Fatal(ctx) << path << ": premature end of input";
2021-04-06 12:18:45 +03:00
vec.push_back(save_string(ctx, buf));
2021-02-28 05:32:04 +03:00
return i + 1;
};
auto read_unquoted = [&](i64 i) {
2021-04-06 12:18:45 +03:00
std::string buf;
2021-03-29 10:48:23 +03:00
while (i < mb->size() && !isspace(data[i]))
2021-04-06 12:18:45 +03:00
buf.append(1, data[i++]);
vec.push_back(save_string(ctx, buf));
2021-02-28 05:32:04 +03:00
return i;
};
for (i64 i = 0; i < mb->size();) {
2021-03-29 10:48:23 +03:00
if (isspace(data[i]))
2021-02-28 05:32:04 +03:00
i++;
2021-03-29 10:48:23 +03:00
else if (data[i] == '\'')
2021-02-28 05:32:04 +03:00
i = read_quoted(i + 1, '\'');
2021-03-29 10:48:23 +03:00
else if (data[i] == '\"')
2021-02-28 05:32:04 +03:00
i = read_quoted(i + 1, '\"');
else
i = read_unquoted(i);
}
return vec;
}
2021-03-29 14:29:57 +03:00
template <typename E>
2021-03-29 10:48:23 +03:00
std::vector<std::string_view>
2021-03-29 14:29:57 +03:00
expand_response_files(Context<E> &ctx, char **argv) {
2021-02-28 05:32:04 +03:00
std::vector<std::string_view> vec;
for (i64 i = 0; argv[i]; i++) {
if (argv[i][0] == '@')
2021-03-29 10:48:23 +03:00
append(vec, read_response_file(ctx, argv[i] + 1));
2021-02-28 05:32:04 +03:00
else
vec.push_back(argv[i]);
}
return vec;
}
static std::vector<std::string> add_dashes(std::string name) {
2021-02-28 08:58:39 +03:00
// Multi-letter linker options can be preceded by either a single
// dash or double dashes except ones starting with "o", which must
// be preceded by double dashes. For example, "-omagic" is
// interpreted as "-o magic". If you really want to specify the
// "omagic" option, you have to pass "--omagic".
2021-02-28 05:36:11 +03:00
if (name[0] == 'o')
2021-05-10 13:12:12 +03:00
return {"--" + name};
2021-02-28 05:36:11 +03:00
return {"-" + name, "--" + name};
2021-02-28 05:32:04 +03:00
}
2021-03-29 14:29:57 +03:00
template <typename E>
bool read_arg(Context<E> &ctx, std::span<std::string_view> &args,
2021-03-29 10:48:23 +03:00
std::string_view &arg, std::string name) {
2021-02-28 05:32:04 +03:00
if (name.size() == 1) {
if (args[0] == "-" + name) {
if (args.size() == 1)
2021-03-29 10:48:23 +03:00
Fatal(ctx) << "option -" << name << ": argument missing";
2021-02-28 05:32:04 +03:00
arg = args[1];
args = args.subspan(2);
return true;
}
if (args[0].starts_with("-" + name)) {
arg = args[0].substr(name.size() + 1);
args = args.subspan(1);
return true;
}
return false;
}
for (std::string opt : add_dashes(name)) {
if (args[0] == opt) {
if (args.size() == 1)
Fatal(ctx) << "option -" << name << ": argument missing";
2021-02-28 05:32:04 +03:00
arg = args[1];
args = args.subspan(2);
return true;
}
if (args[0].starts_with(opt + "=")) {
arg = args[0].substr(opt.size() + 1);
args = args.subspan(1);
return true;
}
}
return false;
}
bool read_flag(std::span<std::string_view> &args, std::string name) {
for (std::string opt : add_dashes(name)) {
if (args[0] == opt) {
args = args.subspan(1);
return true;
}
}
return false;
}
static bool read_z_flag(std::span<std::string_view> &args, std::string name) {
if (args.size() >= 2 && args[0] == "-z" && args[1] == name) {
args = args.subspan(2);
return true;
}
if (!args.empty() && args[0] == "-z" + name) {
args = args.subspan(1);
return true;
}
return false;
}
2021-04-09 04:08:56 +03:00
template <typename E>
std::string create_response_file(Context<E> &ctx) {
std::string buf;
std::stringstream out;
2021-04-09 10:05:52 +03:00
std::string cwd = get_current_dir();
out << "-C " << cwd.substr(1) << "\n";
if (cwd != "/") {
out << "--chroot ..";
i64 depth = std::count(cwd.begin(), cwd.end(), '/');
for (i64 i = 1; i < depth; i++)
out << "/..";
out << "\n";
}
2021-05-08 11:50:09 +03:00
for (i64 i = 1; i < ctx.cmdline_args.size(); i++) {
2021-04-09 12:59:54 +03:00
std::string_view arg = ctx.cmdline_args[i];
2021-05-02 13:21:24 +03:00
if (arg == "-repro" || arg == "--repro") {
2021-04-09 12:59:54 +03:00
i++;
continue;
}
2021-04-09 04:08:56 +03:00
out << arg << "\n";
2021-04-09 12:59:54 +03:00
}
2021-04-09 10:05:52 +03:00
return out.str();
2021-04-09 04:08:56 +03:00
}
2021-03-29 14:29:57 +03:00
template <typename E>
static i64 parse_hex(Context<E> &ctx, std::string opt, std::string_view value) {
2021-02-28 05:32:04 +03:00
if (!value.starts_with("0x") && !value.starts_with("0X"))
2021-03-29 10:48:23 +03:00
Fatal(ctx) << "option -" << opt << ": not a hexadecimal number";
2021-02-28 05:32:04 +03:00
value = value.substr(2);
2021-03-29 14:29:57 +03:00
if (value.find_first_not_of("0123456789abcdefABCDEF") != value.npos)
2021-03-29 10:48:23 +03:00
Fatal(ctx) << "option -" << opt << ": not a hexadecimal number";
2021-02-28 05:32:04 +03:00
return std::stol(std::string(value), nullptr, 16);
}
2021-03-29 14:29:57 +03:00
template <typename E>
static i64 parse_number(Context<E> &ctx, std::string opt,
std::string_view value) {
2021-05-21 11:28:51 +03:00
size_t nread;
i64 ret = std::stol(std::string(value), &nread, 0);
if (value.size() != nread)
Fatal(ctx) << "option -" << opt << ": not a number: " << value;
return ret;
2021-03-08 14:48:21 +03:00
}
2021-03-29 14:29:57 +03:00
template <typename E>
2021-05-31 06:48:26 +03:00
static std::vector<u8> parse_hex_build_id(Context<E> &ctx,
std::string_view arg) {
2021-03-08 14:48:21 +03:00
assert(arg.starts_with("0x") || arg.starts_with("0X"));
if (arg.size() % 2)
2021-03-29 10:48:23 +03:00
Fatal(ctx) << "invalid build-id: " << arg;
2021-03-08 14:48:21 +03:00
if (arg.substr(2).find_first_not_of("0123456789abcdefABCDEF") != arg.npos)
2021-03-29 10:48:23 +03:00
Fatal(ctx) << "invalid build-id: " << arg;
2021-03-08 14:48:21 +03:00
arg = arg.substr(2);
auto fn = [](char c) {
if ('0' <= c && c <= '9')
return c - '0';
if ('a' <= c && c <= 'f')
return c - 'a' + 10;
assert('A' <= c && c <= 'F');
return c - 'A' + 10;
};
std::vector<u8> vec(arg.size() / 2);
for (i64 i = 0; i < vec.size(); i++)
vec[i] = (fn(arg[i * 2]) << 4) | fn(arg[i * 2 + 1]);
return vec;
2021-02-28 05:32:04 +03:00
}
2021-03-08 09:25:23 +03:00
static std::vector<std::string_view>
2021-04-11 07:16:11 +03:00
split_by_comma_or_colon(std::string_view str) {
2021-03-08 09:25:23 +03:00
std::vector<std::string_view> vec;
for (;;) {
2021-04-11 07:16:11 +03:00
i64 pos = str.find_first_of(",:");
2021-03-08 09:25:23 +03:00
if (pos == str.npos) {
vec.push_back(str);
break;
}
vec.push_back(str.substr(0, pos));
str = str.substr(pos);
}
return vec;
}
2021-03-23 15:29:26 +03:00
static i64 get_default_thread_count() {
2021-03-11 13:35:37 +03:00
// mold doesn't scale above 32 threads.
2021-03-23 15:29:26 +03:00
int n = tbb::global_control::active_value(
2021-03-11 13:35:37 +03:00
tbb::global_control::max_allowed_parallelism);
2021-03-23 15:29:26 +03:00
return std::min(n, 32);
}
2021-05-26 16:48:53 +03:00
static std::string_view trim(std::string_view str) {
size_t pos = str.find_first_not_of(" \t");
if (pos == str.npos)
return "";
str = str.substr(pos);
pos = str.find_last_not_of(" \t");
if (pos == str.npos)
return str;
return str.substr(0, pos + 1);
}
template <typename E>
static void read_retain_symbols_file(Context<E> &ctx, std::string_view path) {
MemoryMappedFile<E> *mb =
MemoryMappedFile<E>::must_open(ctx, std::string(path));
std::string_view data((char *)mb->data(ctx), mb->size());
ctx.arg.retain_symbols_file.reset(new std::unordered_set<std::string_view>);
while (!data.empty()) {
size_t pos = data.find('\n');
std::string_view name;
if (pos == data.npos) {
name = data;
data = "";
} else {
name = data.substr(0, pos);
data = data.substr(pos + 1);
}
name = trim(name);
if (!name.empty())
ctx.arg.retain_symbols_file->insert(name);
}
}
static bool is_file(std::string_view path) {
struct stat st;
return stat(std::string(path).c_str(), &st) == 0 &&
(st.st_mode & S_IFMT) != S_IFDIR;
}
2021-03-29 14:29:57 +03:00
template <typename E>
void parse_nonpositional_args(Context<E> &ctx,
2021-03-23 15:29:26 +03:00
std::vector<std::string_view> &remaining) {
2021-03-29 08:05:55 +03:00
std::span<std::string_view> args = ctx.cmdline_args;
2021-05-08 11:50:09 +03:00
args = args.subspan(1);
2021-03-29 07:20:51 +03:00
ctx.arg.thread_count = get_default_thread_count();
2021-05-23 12:22:20 +03:00
bool version_shown = false;
2021-02-28 05:32:04 +03:00
while (!args.empty()) {
std::string_view arg;
2021-05-08 11:50:09 +03:00
if (read_flag(args, "help")) {
SyncOut(ctx) << "Usage: " << ctx.cmdline_args[0]
2021-05-16 19:06:30 +03:00
<< " [options] file...\n" << helpmsg;
2021-05-08 11:50:09 +03:00
exit(0);
}
2021-05-16 09:22:26 +03:00
if (read_arg(ctx, args, arg, "o") || read_arg(ctx, args, arg, "output")) {
2021-03-29 07:20:51 +03:00
ctx.arg.output = arg;
2021-03-29 10:48:23 +03:00
} else if (read_arg(ctx, args, arg, "dynamic-linker") ||
read_arg(ctx, args, arg, "I")) {
2021-03-29 07:20:51 +03:00
ctx.arg.dynamic_linker = arg;
2021-03-29 10:48:23 +03:00
} else if (read_arg(ctx, args, arg, "no-dynamic-linker")) {
2021-03-29 07:20:51 +03:00
ctx.arg.dynamic_linker = "";
2021-05-23 12:22:20 +03:00
} else if (read_flag(args, "v") || read_flag(args, "version")) {
SyncOut(ctx) << get_version_string();
version_shown = true;
2021-05-22 07:46:38 +03:00
} else if (read_flag(args, "V")) {
SyncOut(ctx) << get_version_string()
<< "\n Supported emulations:\n elf_x86_64\n elf_i386";
2021-05-23 12:22:20 +03:00
version_shown = true;
2021-03-01 09:41:10 +03:00
} else if (read_flag(args, "export-dynamic") || read_flag(args, "E")) {
2021-03-29 07:20:51 +03:00
ctx.arg.export_dynamic = true;
2021-03-03 18:30:34 +03:00
} else if (read_flag(args, "no-export-dynamic")) {
2021-03-29 07:20:51 +03:00
ctx.arg.export_dynamic = false;
2021-03-02 15:47:19 +03:00
} else if (read_flag(args, "Bsymbolic")) {
2021-03-29 07:20:51 +03:00
ctx.arg.Bsymbolic = true;
2021-03-02 16:08:06 +03:00
} else if (read_flag(args, "Bsymbolic-functions")) {
2021-03-29 07:20:51 +03:00
ctx.arg.Bsymbolic_functions = true;
2021-04-11 07:16:11 +03:00
} else if (read_arg(ctx, args, arg, "exclude-libs")) {
append(ctx.arg.exclude_libs, split_by_comma_or_colon(arg));
2021-03-29 10:48:23 +03:00
} else if (read_arg(ctx, args, arg, "e") ||
read_arg(ctx, args, arg, "entry")) {
2021-03-29 07:20:51 +03:00
ctx.arg.entry = arg;
2021-03-29 10:48:23 +03:00
} else if (read_arg(ctx, args, arg, "Map")) {
2021-03-29 07:20:51 +03:00
ctx.arg.Map = arg;
ctx.arg.print_map = true;
2021-03-12 11:21:23 +03:00
} else if (read_flag(args, "print-map") || read_flag(args, "M")) {
2021-03-29 07:20:51 +03:00
ctx.arg.print_map = true;
2021-03-16 15:57:28 +03:00
} else if (read_flag(args, "static") || read_flag(args, "Bstatic")) {
2021-03-29 07:20:51 +03:00
ctx.arg.is_static = true;
2021-03-16 15:57:28 +03:00
remaining.push_back("-Bstatic");
} else if (read_flag(args, "Bdynamic")) {
2021-03-29 07:20:51 +03:00
ctx.arg.is_static = false;
2021-03-16 15:57:28 +03:00
remaining.push_back("-Bdynamic");
2021-02-28 05:32:04 +03:00
} else if (read_flag(args, "shared") || read_flag(args, "Bshareable")) {
2021-03-29 07:20:51 +03:00
ctx.arg.shared = true;
2021-04-11 09:43:23 +03:00
} else if (read_arg(ctx, args, arg, "spare-dynamic-tags")) {
ctx.arg.spare_dynamic_tags = parse_number(ctx, "spare-dynamic-tags", arg);
2021-02-28 05:32:04 +03:00
} else if (read_flag(args, "demangle")) {
2021-03-29 07:20:51 +03:00
ctx.arg.demangle = true;
2021-02-28 05:32:04 +03:00
} else if (read_flag(args, "no-demangle")) {
2021-03-29 07:20:51 +03:00
ctx.arg.demangle = false;
2021-03-29 10:48:23 +03:00
} else if (read_arg(ctx, args, arg, "y") ||
read_arg(ctx, args, arg, "trace-symbol")) {
2021-03-29 07:20:51 +03:00
ctx.arg.trace_symbol.push_back(arg);
2021-03-29 10:48:23 +03:00
} else if (read_arg(ctx, args, arg, "filler")) {
ctx.arg.filler = parse_hex(ctx, "filler", arg);
} else if (read_arg(ctx, args, arg, "L") ||
read_arg(ctx, args, arg, "library-path")) {
2021-03-29 07:20:51 +03:00
ctx.arg.library_paths.push_back(arg);
2021-03-29 10:48:23 +03:00
} else if (read_arg(ctx, args, arg, "sysroot")) {
2021-03-29 07:20:51 +03:00
ctx.arg.sysroot = arg;
2021-03-29 10:48:23 +03:00
} else if (read_arg(ctx, args, arg, "u") ||
read_arg(ctx, args, arg, "undefined")) {
2021-03-29 07:20:51 +03:00
ctx.arg.undefined.push_back(arg);
2021-03-29 10:48:23 +03:00
} else if (read_arg(ctx, args, arg, "init")) {
2021-03-29 07:20:51 +03:00
ctx.arg.init = arg;
2021-03-29 10:48:23 +03:00
} else if (read_arg(ctx, args, arg, "fini")) {
2021-03-29 07:20:51 +03:00
ctx.arg.fini = arg;
2021-03-29 10:48:23 +03:00
} else if (read_arg(ctx, args, arg, "hash-style")) {
2021-02-28 05:32:04 +03:00
if (arg == "sysv") {
2021-03-29 07:20:51 +03:00
ctx.arg.hash_style_sysv = true;
ctx.arg.hash_style_gnu = false;
2021-02-28 05:32:04 +03:00
} else if (arg == "gnu") {
2021-03-29 07:20:51 +03:00
ctx.arg.hash_style_sysv = false;
ctx.arg.hash_style_gnu = true;
2021-02-28 05:32:04 +03:00
} else if (arg == "both") {
2021-03-29 07:20:51 +03:00
ctx.arg.hash_style_sysv = true;
ctx.arg.hash_style_gnu = true;
2021-02-28 05:32:04 +03:00
} else {
2021-03-29 10:48:23 +03:00
Fatal(ctx) << "invalid --hash-style argument: " << arg;
2021-02-28 05:32:04 +03:00
}
2021-03-29 10:48:23 +03:00
} else if (read_arg(ctx, args, arg, "soname") ||
read_arg(ctx, args, arg, "h")) {
2021-03-29 07:20:51 +03:00
ctx.arg.soname = arg;
2021-02-28 05:32:04 +03:00
} else if (read_flag(args, "allow-multiple-definition")) {
2021-03-29 07:20:51 +03:00
ctx.arg.allow_multiple_definition = true;
2021-02-28 05:32:04 +03:00
} else if (read_flag(args, "trace")) {
2021-03-29 07:20:51 +03:00
ctx.arg.trace = true;
2021-02-28 05:32:04 +03:00
} else if (read_flag(args, "eh-frame-hdr")) {
2021-03-29 07:20:51 +03:00
ctx.arg.eh_frame_hdr = true;
2021-02-28 05:32:04 +03:00
} else if (read_flag(args, "no-eh-frame-hdr")) {
2021-03-29 07:20:51 +03:00
ctx.arg.eh_frame_hdr = false;
2021-02-28 05:32:04 +03:00
} else if (read_flag(args, "pie") || read_flag(args, "pic-executable")) {
2021-03-29 07:20:51 +03:00
ctx.arg.pic = true;
ctx.arg.pie = true;
2021-03-12 13:26:22 +03:00
} else if (read_flag(args, "no-pie") ||
read_flag(args, "no-pic-executable")) {
2021-03-29 07:20:51 +03:00
ctx.arg.pic = false;
ctx.arg.pie = false;
2021-02-28 05:32:04 +03:00
} else if (read_flag(args, "relax")) {
2021-03-29 07:20:51 +03:00
ctx.arg.relax = true;
2021-02-28 05:32:04 +03:00
} else if (read_flag(args, "no-relax")) {
2021-03-29 07:20:51 +03:00
ctx.arg.relax = false;
} else if (read_flag(args, "r") || read_flag(args, "relocatable")) {
ctx.arg.relocatable = true;
2021-03-13 15:55:27 +03:00
} else if (read_flag(args, "perf")) {
2021-03-29 07:20:51 +03:00
ctx.arg.perf = true;
2021-03-13 15:55:27 +03:00
} else if (read_flag(args, "stats")) {
2021-03-29 07:20:51 +03:00
ctx.arg.stats = true;
2021-03-13 14:28:08 +03:00
Counter::enabled = true;
2021-04-09 10:05:52 +03:00
} else if (read_arg(ctx, args, arg, "C") ||
read_arg(ctx, args, arg, "directory")) {
2021-04-09 04:08:56 +03:00
ctx.arg.directory = arg;
2021-04-09 10:05:52 +03:00
} else if (read_arg(ctx, args, arg, "chroot")) {
ctx.arg.chroot = arg;
2021-03-23 19:13:45 +03:00
} else if (read_flag(args, "warn-common")) {
2021-03-29 07:20:51 +03:00
ctx.arg.warn_common = true;
2021-03-23 19:13:45 +03:00
} else if (read_flag(args, "no-warn-common")) {
2021-03-29 07:20:51 +03:00
ctx.arg.warn_common = false;
2021-05-06 05:29:02 +03:00
} else if (read_arg(ctx, args, arg, "compress-debug-sections")) {
if (arg == "zlib" || arg == "zlib-gabi")
2021-06-03 16:22:29 +03:00
ctx.arg.compress_debug_sections = COMPRESS_GABI;
else if (arg == "zlib-gnu")
ctx.arg.compress_debug_sections = COMPRESS_GNU;
2021-05-06 05:29:02 +03:00
else if (arg == "none")
2021-06-03 16:22:29 +03:00
ctx.arg.compress_debug_sections = COMPRESS_NONE;
2021-05-06 05:29:02 +03:00
else
Fatal(ctx) << "invalid --compress-debug-sections argument: " << arg;
2021-05-21 19:12:24 +03:00
} else if (read_arg(ctx, args, arg, "wrap")) {
ctx.arg.wrap.insert(arg);
2021-05-10 13:12:12 +03:00
} else if (read_flag(args, "omagic") || read_flag(args, "N")) {
ctx.arg.omagic = true;
ctx.arg.is_static = true;
} else if (read_flag(args, "no-omagic")) {
ctx.arg.omagic = false;
2021-05-26 16:48:53 +03:00
} else if (read_arg(ctx, args, arg, "retain-symbols-file")) {
read_retain_symbols_file(ctx, arg);
2021-05-02 13:21:24 +03:00
} else if (read_flag(args, "repro")) {
ctx.arg.repro = true;
2021-02-28 05:32:04 +03:00
} else if (read_z_flag(args, "now")) {
2021-03-29 07:20:51 +03:00
ctx.arg.z_now = true;
2021-04-10 17:04:07 +03:00
} else if (read_z_flag(args, "lazy")) {
ctx.arg.z_now = false;
2021-03-12 12:09:15 +03:00
} else if (read_z_flag(args, "execstack")) {
2021-03-29 07:20:51 +03:00
ctx.arg.z_execstack = true;
2021-03-12 12:09:15 +03:00
} else if (read_z_flag(args, "noexecstack")) {
2021-03-29 07:20:51 +03:00
ctx.arg.z_execstack = false;
2021-03-12 13:57:34 +03:00
} else if (read_z_flag(args, "relro")) {
2021-03-29 07:20:51 +03:00
ctx.arg.z_relro = true;
2021-03-12 13:57:34 +03:00
} else if (read_z_flag(args, "norelro")) {
2021-03-29 07:20:51 +03:00
ctx.arg.z_relro = false;
2021-03-13 15:41:26 +03:00
} else if (read_z_flag(args, "defs")) {
2021-03-29 07:20:51 +03:00
ctx.arg.z_defs = true;
2021-03-13 15:41:26 +03:00
} else if (read_z_flag(args, "nodefs")) {
2021-03-29 07:20:51 +03:00
ctx.arg.z_defs = false;
2021-03-18 07:16:52 +03:00
} else if (read_z_flag(args, "nodlopen")) {
2021-03-29 07:20:51 +03:00
ctx.arg.z_dlopen = false;
2021-03-18 07:16:52 +03:00
} else if (read_z_flag(args, "nodelete")) {
2021-03-29 07:20:51 +03:00
ctx.arg.z_delete = false;
2021-03-18 13:54:56 +03:00
} else if (read_z_flag(args, "nocopyreloc")) {
2021-03-29 07:20:51 +03:00
ctx.arg.z_copyreloc = false;
2021-04-10 12:16:01 +03:00
} else if (read_z_flag(args, "initfirst")) {
ctx.arg.z_initfirst = true;
2021-04-10 12:18:56 +03:00
} else if (read_z_flag(args, "interpose")) {
ctx.arg.z_interpose = true;
} else if (read_z_flag(args, "muldefs")) {
ctx.arg.allow_multiple_definition = true;
2021-06-15 17:26:18 +03:00
} else if (read_z_flag(args, "keep-text-section-prefix")) {
ctx.arg.z_keep_text_section_prefix = true;
} else if (read_z_flag(args, "nokeep-text-section-prefix")) {
ctx.arg.z_keep_text_section_prefix = false;
2021-06-17 07:32:39 +03:00
} else if (read_z_flag(args, "text")) {
ctx.arg.z_text = true;
} else if (read_z_flag(args, "notext") || read_z_flag(args, "textoff")) {
ctx.arg.z_text = false;
2021-03-13 15:41:26 +03:00
} else if (read_flag(args, "no-undefined")) {
2021-03-29 07:20:51 +03:00
ctx.arg.z_defs = true;
2021-03-23 19:33:31 +03:00
} else if (read_flag(args, "fatal-warnings")) {
2021-03-29 07:20:51 +03:00
ctx.arg.fatal_warnings = true;
2021-03-23 19:33:31 +03:00
} else if (read_flag(args, "no-fatal-warnings")) {
2021-03-29 07:20:51 +03:00
ctx.arg.fatal_warnings = false;
2021-02-28 05:32:04 +03:00
} else if (read_flag(args, "fork")) {
2021-03-29 07:20:51 +03:00
ctx.arg.fork = true;
2021-02-28 05:32:04 +03:00
} else if (read_flag(args, "no-fork")) {
2021-03-29 07:20:51 +03:00
ctx.arg.fork = false;
2021-02-28 05:32:04 +03:00
} else if (read_flag(args, "gc-sections")) {
2021-03-29 07:20:51 +03:00
ctx.arg.gc_sections = true;
2021-02-28 05:32:04 +03:00
} else if (read_flag(args, "no-gc-sections")) {
2021-03-29 07:20:51 +03:00
ctx.arg.gc_sections = false;
2021-02-28 05:32:04 +03:00
} else if (read_flag(args, "print-gc-sections")) {
2021-03-29 07:20:51 +03:00
ctx.arg.print_gc_sections = true;
2021-02-28 05:32:04 +03:00
} else if (read_flag(args, "no-print-gc-sections")) {
2021-03-29 07:20:51 +03:00
ctx.arg.print_gc_sections = false;
} else if (read_arg(ctx, args, arg, "icf")) {
if (arg == "all")
ctx.arg.icf = true;
else if (arg == "none")
ctx.arg.icf = false;
else
Fatal(ctx) << "unknown --icf argument: " << arg;
2021-02-28 05:32:04 +03:00
} else if (read_flag(args, "no-icf")) {
2021-03-29 07:20:51 +03:00
ctx.arg.icf = false;
2021-05-21 11:28:51 +03:00
} else if (read_arg(ctx, args, arg, "image-base")) {
ctx.arg.image_base = parse_number(ctx, "image-base", arg);
2021-02-28 09:07:33 +03:00
} else if (read_flag(args, "quick-exit")) {
2021-03-29 07:20:51 +03:00
ctx.arg.quick_exit = true;
2021-02-28 09:07:33 +03:00
} else if (read_flag(args, "no-quick-exit")) {
2021-03-29 07:20:51 +03:00
ctx.arg.quick_exit = false;
2021-02-28 05:32:04 +03:00
} else if (read_flag(args, "print-icf-sections")) {
2021-03-29 07:20:51 +03:00
ctx.arg.print_icf_sections = true;
2021-02-28 05:32:04 +03:00
} else if (read_flag(args, "no-print-icf-sections")) {
2021-03-29 07:20:51 +03:00
ctx.arg.print_icf_sections = false;
2021-02-28 05:32:04 +03:00
} else if (read_flag(args, "quick-exit")) {
2021-03-29 07:20:51 +03:00
ctx.arg.quick_exit = true;
2021-02-28 05:32:04 +03:00
} else if (read_flag(args, "no-quick-exit")) {
2021-03-29 07:20:51 +03:00
ctx.arg.quick_exit = false;
2021-03-29 10:48:23 +03:00
} else if (read_arg(ctx, args, arg, "thread-count")) {
ctx.arg.thread_count = parse_number(ctx, "thread-count", arg);
2021-03-23 15:29:26 +03:00
} else if (read_flag(args, "threads")) {
2021-03-29 07:20:51 +03:00
ctx.arg.thread_count = get_default_thread_count();
2021-02-28 05:32:04 +03:00
} else if (read_flag(args, "no-threads")) {
2021-03-29 07:20:51 +03:00
ctx.arg.thread_count = 1;
2021-02-28 05:32:04 +03:00
} else if (read_flag(args, "discard-all") || read_flag(args, "x")) {
2021-03-29 07:20:51 +03:00
ctx.arg.discard_all = true;
2021-02-28 05:32:04 +03:00
} else if (read_flag(args, "discard-locals") || read_flag(args, "X")) {
2021-03-29 07:20:51 +03:00
ctx.arg.discard_locals = true;
2021-02-28 05:32:04 +03:00
} else if (read_flag(args, "strip-all") || read_flag(args, "s")) {
2021-03-29 07:20:51 +03:00
ctx.arg.strip_all = true;
2021-03-14 11:04:45 +03:00
} else if (read_flag(args, "strip-debug") || read_flag(args, "S")) {
ctx.arg.strip_all = true;
} else if (read_flag(args, "warn-unresolved-symbols")) {
ctx.arg.warn_unresolved_symbols = true;
} else if (read_flag(args, "error-unresolved-symbols")) {
ctx.arg.warn_unresolved_symbols = false;
2021-03-29 10:48:23 +03:00
} else if (read_arg(ctx, args, arg, "rpath")) {
if (!ctx.arg.rpaths.empty())
ctx.arg.rpaths += ":";
ctx.arg.rpaths += arg;
} else if (read_arg(ctx, args, arg, "R")) {
if (is_file(arg))
Fatal(ctx) << "-R" << arg
<< ": -R as an alias for --just-symbols is not supported";
2021-03-29 07:20:51 +03:00
if (!ctx.arg.rpaths.empty())
ctx.arg.rpaths += ":";
ctx.arg.rpaths += arg;
2021-02-28 05:32:04 +03:00
} else if (read_flag(args, "build-id")) {
2021-03-29 07:20:51 +03:00
ctx.arg.build_id.kind = BuildId::HASH;
ctx.arg.build_id.hash_size = 20;
2021-03-29 10:48:23 +03:00
} else if (read_arg(ctx, args, arg, "build-id")) {
2021-02-28 05:32:04 +03:00
if (arg == "none") {
2021-03-29 07:20:51 +03:00
ctx.arg.build_id.kind = BuildId::NONE;
2021-02-28 05:32:04 +03:00
} else if (arg == "uuid") {
2021-03-29 07:20:51 +03:00
ctx.arg.build_id.kind = BuildId::UUID;
2021-02-28 05:32:04 +03:00
} else if (arg == "md5") {
2021-03-29 07:20:51 +03:00
ctx.arg.build_id.kind = BuildId::HASH;
ctx.arg.build_id.hash_size = 16;
2021-02-28 05:32:04 +03:00
} else if (arg == "sha1") {
2021-03-29 07:20:51 +03:00
ctx.arg.build_id.kind = BuildId::HASH;
ctx.arg.build_id.hash_size = 20;
2021-02-28 05:32:04 +03:00
} else if (arg == "sha256") {
2021-03-29 07:20:51 +03:00
ctx.arg.build_id.kind = BuildId::HASH;
ctx.arg.build_id.hash_size = 32;
2021-03-08 14:48:21 +03:00
} else if (arg.starts_with("0x") || arg.starts_with("0X")) {
2021-03-29 07:20:51 +03:00
ctx.arg.build_id.kind = BuildId::HEX;
2021-03-29 10:48:23 +03:00
ctx.arg.build_id.value = parse_hex_build_id(ctx, arg);
2021-02-28 05:32:04 +03:00
} else {
2021-03-29 10:48:23 +03:00
Fatal(ctx) << "invalid --build-id argument: " << arg;
2021-02-28 05:32:04 +03:00
}
2021-03-07 16:28:49 +03:00
} else if (read_flag(args, "no-build-id")) {
2021-03-29 07:20:51 +03:00
ctx.arg.build_id.kind = BuildId::NONE;
2021-03-29 10:48:23 +03:00
} else if (read_arg(ctx, args, arg, "auxiliary") ||
read_arg(ctx, args, arg, "f")) {
2021-03-29 07:20:51 +03:00
ctx.arg.auxiliary.push_back(arg);
2021-03-29 10:48:23 +03:00
} else if (read_arg(ctx, args, arg, "filter") ||
read_arg(ctx, args, arg, "F")) {
2021-03-29 07:20:51 +03:00
ctx.arg.filter.push_back(arg);
2021-02-28 05:32:04 +03:00
} else if (read_flag(args, "preload")) {
2021-03-29 07:20:51 +03:00
ctx.arg.preload = true;
2021-03-29 10:48:23 +03:00
} else if (read_arg(ctx, args, arg, "O")) {
2021-03-01 12:21:10 +03:00
} else if (read_flag(args, "O0")) {
} else if (read_flag(args, "O1")) {
} else if (read_flag(args, "O2")) {
2021-06-17 06:14:42 +03:00
} else if (read_flag(args, "verbose")) {
2021-03-29 10:48:23 +03:00
} else if (read_arg(ctx, args, arg, "plugin")) {
} else if (read_arg(ctx, args, arg, "plugin-opt")) {
2021-03-15 13:23:08 +03:00
} else if (read_flag(args, "color-diagnostics")) {
2021-03-27 10:47:52 +03:00
} else if (read_flag(args, "gdb-index")) {
2021-03-29 10:48:23 +03:00
} else if (read_arg(ctx, args, arg, "m")) {
2021-02-28 05:32:04 +03:00
} else if (read_flag(args, "eh-frame-hdr")) {
} else if (read_flag(args, "start-group")) {
} else if (read_flag(args, "end-group")) {
2021-02-28 15:03:13 +03:00
} else if (read_flag(args, "(")) {
} else if (read_flag(args, ")")) {
2021-02-28 05:32:04 +03:00
} else if (read_flag(args, "fatal-warnings")) {
2021-03-27 10:59:57 +03:00
} else if (read_flag(args, "enable-new-dtags")) {
2021-02-28 05:32:04 +03:00
} else if (read_flag(args, "disable-new-dtags")) {
2021-05-26 11:18:26 +03:00
} else if (read_flag(args, "nostdlib")) {
2021-05-19 05:26:03 +03:00
} else if (read_flag(args, "allow-shlib-undefined")) {
} else if (read_flag(args, "no-allow-shlib-undefined")) {
2021-05-19 05:52:39 +03:00
} else if (read_flag(args, "no-copy-dt-needed-entries")) {
} else if (read_flag(args, "no-undefined-version")) {
2021-03-29 10:48:23 +03:00
} else if (read_arg(ctx, args, arg, "sort-section")) {
2021-03-25 10:03:23 +03:00
} else if (read_flag(args, "sort-common")) {
2021-05-10 13:23:32 +03:00
} else if (read_flag(args, "nodefaultlibs")) {
2021-03-29 10:48:23 +03:00
} else if (read_arg(ctx, args, arg, "rpath-link")) {
2021-04-09 12:50:24 +03:00
} else if (read_arg(ctx, args, arg, "version-script")) {
remaining.push_back("--version-script");
remaining.push_back(arg);
} else if (read_arg(ctx, args, arg, "dynamic-list")) {
remaining.push_back("--dynamic-list");
remaining.push_back(arg);
2021-02-28 05:32:04 +03:00
} else if (read_flag(args, "as-needed")) {
remaining.push_back("-as-needed");
} else if (read_flag(args, "no-as-needed")) {
remaining.push_back("-no-as-needed");
} else if (read_flag(args, "whole-archive")) {
remaining.push_back("-whole-archive");
} else if (read_flag(args, "no-whole-archive")) {
remaining.push_back("-no-whole-archive");
2021-03-29 10:48:23 +03:00
} else if (read_arg(ctx, args, arg, "l")) {
2021-02-28 05:32:04 +03:00
remaining.push_back("-l");
remaining.push_back(arg);
2021-03-29 10:48:23 +03:00
} else if (read_arg(ctx, args, arg, "script") ||
read_arg(ctx, args, arg, "T")) {
2021-02-28 09:24:36 +03:00
remaining.push_back(arg);
2021-03-12 11:37:39 +03:00
} else if (read_flag(args, "push-state")) {
remaining.push_back("-push-state");
} else if (read_flag(args, "pop-state")) {
remaining.push_back("-pop-state");
2021-02-28 05:32:04 +03:00
} else {
2021-06-07 14:53:35 +03:00
if (args[0] == "-z" && args.size() >= 2)
Fatal(ctx) << "mold: unknown command line option: -z " << args[1];
2021-02-28 05:32:04 +03:00
if (args[0][0] == '-')
2021-03-29 10:48:23 +03:00
Fatal(ctx) << "mold: unknown command line option: " << args[0];
2021-02-28 05:32:04 +03:00
remaining.push_back(args[0]);
args = args.subspan(1);
}
}
2021-03-29 07:20:51 +03:00
if (ctx.arg.shared) {
ctx.arg.pic = true;
ctx.arg.dynamic_linker = "";
2021-02-28 05:32:04 +03:00
}
2021-03-29 07:20:51 +03:00
if (ctx.arg.pic)
ctx.arg.image_base = 0;
2021-03-16 10:50:49 +03:00
2021-05-26 16:48:53 +03:00
if (ctx.arg.retain_symbols_file) {
ctx.arg.strip_all = false;
ctx.arg.discard_all = false;
}
2021-06-14 06:53:16 +03:00
if (ctx.arg.relocatable)
ctx.arg.is_static = true;
2021-03-29 07:20:51 +03:00
if (!ctx.arg.shared) {
if (!ctx.arg.filter.empty())
2021-03-29 10:48:23 +03:00
Fatal(ctx) << "-filter may not be used without -shared";
2021-03-29 07:20:51 +03:00
if (!ctx.arg.auxiliary.empty())
2021-03-29 10:48:23 +03:00
Fatal(ctx) << "-auxiliary may not be used without -shared";
2021-03-23 09:25:10 +03:00
}
if (char *env = getenv("MOLD_REPRO"); env && env[0])
ctx.arg.repro = true;
2021-03-29 07:20:51 +03:00
if (ctx.arg.output.empty())
ctx.arg.output = "a.out";
2021-05-23 12:22:20 +03:00
if (version_shown && remaining.empty())
exit(0);
2021-03-07 14:40:16 +03:00
}
2021-03-29 14:29:57 +03:00
2021-04-05 16:19:51 +03:00
#define INSTANTIATE(E) \
template \
std::vector<std::string_view> \
expand_response_files(Context<E> &ctx, char **argv); \
\
template \
bool read_arg(Context<E> &ctx, std::span<std::string_view> &args, \
std::string_view &arg, \
std::string name); \
\
2021-04-09 04:08:56 +03:00
template std::string create_response_file(Context<E> &ctx); \
\
2021-04-05 16:19:51 +03:00
template \
void parse_nonpositional_args(Context<E> &ctx, \
std::vector<std::string_view> &remaining)
INSTANTIATE(X86_64);
INSTANTIATE(I386);