mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-21 09:49:14 +00:00
Bug 1892493 - Support reading a response file when that's the only thing on the command line. r=sergesanspaille
Differential Revision: https://phabricator.services.mozilla.com/D208284
This commit is contained in:
parent
4856fd3c1e
commit
e41b7821eb
@ -12,6 +12,7 @@
|
||||
|
||||
#include "relrhack.h"
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
@ -26,6 +27,8 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "mozilla/ScopeExit.h"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
class CantSwapSections : public std::runtime_error {
|
||||
@ -420,10 +423,40 @@ uint16_t get_elf_machine(std::istream& in) {
|
||||
return ehdr.e_machine;
|
||||
}
|
||||
|
||||
int run_command(std::vector<const char*>& args) {
|
||||
int run_command(std::vector<const char*>& args, bool use_response_file) {
|
||||
std::string at_file;
|
||||
const char** argv = args.data();
|
||||
std::array<const char*, 3> args_with_atfile{};
|
||||
if (use_response_file) {
|
||||
const char* tmpdir = getenv("TMPDIR");
|
||||
if (!tmpdir) {
|
||||
tmpdir = "/tmp";
|
||||
}
|
||||
std::string tmpfile = tmpdir;
|
||||
tmpfile += "/relrhackXXXXXX";
|
||||
int fd = mkstemp(tmpfile.data());
|
||||
if (fd < 0) {
|
||||
std::cerr << "Failed to create temporary file." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
close(fd);
|
||||
std::ofstream f{tmpfile, f.binary};
|
||||
for (auto arg = std::next(args.begin()); arg != args.end(); ++arg) {
|
||||
f << *arg << "\n";
|
||||
}
|
||||
at_file = "@";
|
||||
at_file += tmpfile;
|
||||
args_with_atfile = {args.front(), at_file.c_str(), nullptr};
|
||||
argv = args_with_atfile.data();
|
||||
}
|
||||
auto guard = mozilla::MakeScopeExit([&] {
|
||||
if (!at_file.empty()) {
|
||||
unlink(at_file.c_str() + 1);
|
||||
}
|
||||
});
|
||||
pid_t child_pid;
|
||||
if (posix_spawn(&child_pid, args[0], nullptr, nullptr,
|
||||
const_cast<char* const*>(args.data()), environ) != 0) {
|
||||
const_cast<char* const*>(argv), environ) != 0) {
|
||||
throw std::runtime_error("posix_spawn failed");
|
||||
}
|
||||
|
||||
@ -442,6 +475,9 @@ int main(int argc, char* argv[]) {
|
||||
std::optional<fs::path> real_linker = std::nullopt;
|
||||
bool shared = false;
|
||||
bool is_android = false;
|
||||
bool use_response_file = false;
|
||||
std::vector<char> response_file;
|
||||
std::vector<const char*> response_file_args;
|
||||
uint16_t elf_machine = EM_NONE;
|
||||
// Scan argv in order to prepare the following:
|
||||
// - get the output file. That's the file we may need to adjust.
|
||||
@ -458,6 +494,33 @@ int main(int argc, char* argv[]) {
|
||||
//
|
||||
// At the same time, we also construct a new list of arguments, with
|
||||
// --real-linker filtered out. We'll later inject arguments in that list.
|
||||
if (argc == 2 && argv[1] && argv[1][0] == '@') {
|
||||
// When GCC is given a response file, it wraps all arguments into a
|
||||
// new response file with all arguments, even if originally there were
|
||||
// arguments and a response file.
|
||||
// In that case, we can't scan for arguments, so we need to read the
|
||||
// response file. And as we change the arguments, we'll need to write
|
||||
// a new one.
|
||||
std::ifstream f{argv[1] + 1, f.binary | f.ate};
|
||||
if (!f) {
|
||||
std::cerr << "Failed to read " << argv[1] + 1 << std::endl;
|
||||
return 1;
|
||||
}
|
||||
size_t len = f.tellg();
|
||||
response_file = read_vector_at<char>(f, 0, len);
|
||||
std::replace(response_file.begin(), response_file.end(), '\n', '\0');
|
||||
if (len && response_file[len - 1] != '\0') {
|
||||
response_file.push_back('\0');
|
||||
}
|
||||
response_file_args.push_back(argv[0]);
|
||||
for (const char* a = response_file.data();
|
||||
a < response_file.data() + response_file.size(); a += strlen(a) + 1) {
|
||||
response_file_args.push_back(a);
|
||||
}
|
||||
argv = const_cast<char**>(response_file_args.data());
|
||||
argc = response_file_args.size();
|
||||
use_response_file = true;
|
||||
}
|
||||
for (i = 1, argv++; i < argc && *argv; argv++, i++) {
|
||||
std::string_view arg{*argv};
|
||||
if (arg == "-shared") {
|
||||
@ -538,7 +601,7 @@ int main(int argc, char* argv[]) {
|
||||
hacked_args.insert(hacked_args.begin() + crti + 1, inject.c_str());
|
||||
hacked_args.insert(hacked_args.end() - 1, {"-z", "pack-relative-relocs",
|
||||
"-init=_relrhack_wrap_init"});
|
||||
int status = run_command(hacked_args);
|
||||
int status = run_command(hacked_args, use_response_file);
|
||||
if (status) {
|
||||
return status;
|
||||
}
|
||||
@ -563,5 +626,5 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
return run_command(args);
|
||||
return run_command(args, use_response_file);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user