diff --git a/commandline.cc b/commandline.cc index 18506bb7..6f878c02 100644 --- a/commandline.cc +++ b/commandline.cc @@ -379,6 +379,10 @@ void parse_nonpositional_args(std::span args, remaining.push_back(arg); } else if (read_arg(args, arg, "script") || read_arg(args, arg, "T")) { remaining.push_back(arg); + } else if (read_flag(args, "push-state")) { + remaining.push_back("-push-state"); + } else if (read_flag(args, "pop-state")) { + remaining.push_back("-pop-state"); } else { if (args[0][0] == '-') Fatal() << "mold: unknown command line option: " << args[0]; diff --git a/main.cc b/main.cc index 162bf97a..8dd81071 100644 --- a/main.cc +++ b/main.cc @@ -934,6 +934,8 @@ MemoryMappedFile *find_library(std::string name, static void read_input_files(std::span args, ReadContext &ctx) { + std::vector> state; + while (!args.empty()) { std::string_view arg; @@ -945,6 +947,13 @@ static void read_input_files(std::span args, ctx.whole_archive = true; } else if (read_flag(args, "no-whole-archive")) { ctx.whole_archive = false; + } else if (read_flag(args, "push-state")) { + state.push_back({ctx.as_needed, ctx.whole_archive}); + } else if (read_flag(args, "pop-state")) { + if (state.empty()) + Fatal() << "no state pushed before popping"; + std::tie(ctx.as_needed, ctx.whole_archive) = state.back(); + state.pop_back(); } else if (read_arg(args, arg, "l")) { read_file(find_library(std::string(arg), config.library_paths), ctx); } else { diff --git a/test/push-pop-state.sh b/test/push-pop-state.sh new file mode 100755 index 00000000..630109e5 --- /dev/null +++ b/test/push-pop-state.sh @@ -0,0 +1,27 @@ +#!/bin/bash +set -e +cd $(dirname $0) +echo -n "Testing $(basename -s .sh $0) ... " +t=$(pwd)/tmp/$(basename -s .sh $0) +mkdir -p $t + +cat < $t/log +fgrep -q a.so $t/log +! fgrep -q b.so $t/log + +echo OK