Skip to content

Commit

Permalink
[ELF] Remove --preload
Browse files Browse the repository at this point in the history
  • Loading branch information
rui314 committed Apr 30, 2022
1 parent d3130f3 commit a85b1f5
Show file tree
Hide file tree
Showing 4 changed files with 12 additions and 233 deletions.
8 changes: 0 additions & 8 deletions elf/cmdline.cc
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,6 @@ static const char helpmsg[] = R"(
--pie, --pic-executable Create a position independent executable
--no-pie, --no-pic-executable
--pop-state Pop state of flags governing input file handling
--preload
--no-preload
--print-gc-sections Print removed unreferenced sections
--no-print-gc-sections
--print-icf-sections Print folded identical sections
Expand Down Expand Up @@ -948,12 +946,6 @@ void parse_nonpositional_args(Context<E> &ctx,
} else if (read_arg(ctx, args, arg, "filter") ||
read_arg(ctx, args, arg, "F")) {
ctx.arg.filter.push_back(arg);
} else if (read_flag(args, "preload")) {
Warn(ctx) << "--preload is deprecated and will be removed in a"
<< " future version";
ctx.arg.preload = true;
} else if (read_flag(args, "no-preload")) {
ctx.arg.preload = false;
} else if (read_flag(args, "apply-dynamic-relocs")) {
} else if (read_arg(ctx, args, arg, "O")) {
} else if (read_flag(args, "O0")) {
Expand Down
40 changes: 12 additions & 28 deletions elf/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,7 @@ static int elf_main(int argc, char **argv) {

// Parse non-positional command line options
ctx.cmdline_args = expand_response_files(ctx, argv);

std::vector<std::string_view> file_args;
parse_nonpositional_args(ctx, file_args);

Expand All @@ -400,27 +401,29 @@ static int elf_main(int argc, char **argv) {

Timer t_all(ctx, "all");

install_signal_handler();

if (!ctx.arg.directory.empty())
if (chdir(ctx.arg.directory.c_str()) == -1)
Fatal(ctx) << "chdir failed: " << ctx.arg.directory
<< ": " << errno_string();

if (ctx.arg.relocatable) {
combine_objects(ctx, file_args);
return 0;
}

if (!ctx.arg.preload)
try_resume_daemon(ctx);
// Fork a subprocess unless --no-fork is given.
std::function<void()> on_complete;
if (ctx.arg.fork)
on_complete = fork_child();

i64 thread_count = ctx.arg.thread_count;
if (thread_count == 0)
thread_count = get_default_thread_count();
tbb::global_control tbb_cont(tbb::global_control::max_allowed_parallelism,
thread_count);

install_signal_handler();

if (!ctx.arg.directory.empty())
if (chdir(ctx.arg.directory.c_str()) == -1)
Fatal(ctx) << "chdir failed: " << ctx.arg.directory
<< ": " << errno_string();

// Handle --wrap options if any.
for (std::string_view name : ctx.arg.wrap)
get_symbol(ctx, name)->wrap = true;
Expand All @@ -430,31 +433,12 @@ static int elf_main(int argc, char **argv) {
for (std::string_view name : *ctx.arg.retain_symbols_file)
get_symbol(ctx, name)->write_to_symtab = true;

// Preload input files
std::function<void()> on_complete;
std::function<void()> wait_for_client;

if (ctx.arg.preload)
daemonize(ctx, &wait_for_client, &on_complete);
else if (ctx.arg.fork)
on_complete = fork_child();

for (std::string_view arg : ctx.arg.trace_symbol)
get_symbol(ctx, arg)->traced = true;

// Parse input files
read_input_files(ctx, file_args);

if (ctx.arg.preload) {
wait_for_client();
if (!reload_input_files(ctx)) {
std::vector<char *> args(argv, argv + argc);
args.push_back((char *)"--no-preload");
args.push_back(nullptr);
return elf_main<E>(argc + 1, args.data());
}
}

// Uniquify shared object files by soname
{
std::unordered_set<std::string_view> seen;
Expand Down
8 changes: 0 additions & 8 deletions elf/mold.h
Original file line number Diff line number Diff line change
Expand Up @@ -1340,13 +1340,6 @@ void print_map(Context<E> &ctx);

std::function<void()> fork_child();

template <typename E>
void try_resume_daemon(Context<E> &ctx);

template <typename E>
void daemonize(Context<E> &ctx, std::function<void()> *wait_for_client,
std::function<void()> *on_complete);

template <typename E>
[[noreturn]]
void process_run_subcommand(Context<E> &ctx, int argc, char **argv);
Expand Down Expand Up @@ -1603,7 +1596,6 @@ struct Context {
bool perf = false;
bool pic = false;
bool pie = false;
bool preload = false;
bool print_gc_sections = false;
bool print_icf_sections = false;
bool print_map = false;
Expand Down
189 changes: 0 additions & 189 deletions elf/subprocess.cc
Original file line number Diff line number Diff line change
Expand Up @@ -60,192 +60,6 @@ std::function<void()> fork_child() {
};
}

static std::string base64(u8 *data, u64 size) {
static const char chars[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_";

std::ostringstream out;

auto encode = [&](u32 x) {
out << chars[x & 0b111111]
<< chars[(x >> 6) & 0b111111]
<< chars[(x >> 12) & 0b111111]
<< chars[(x >> 18) & 0b111111];
};

i64 i = 0;
for (; i < size - 3; i += 3)
encode((data[i + 2] << 16) | (data[i + 1] << 8) | data[i]);

if (i == size - 1)
encode(data[i]);
else if (i == size - 2)
encode((data[i + 1] << 8) | data[i]);
return out.str();
}

static std::string compute_sha256(std::span<std::string_view> argv) {
SHA256_CTX sha;
SHA256_Init(&sha);

for (std::string_view arg : argv) {
if (arg != "-preload" && arg != "--preload") {
SHA256_Update(&sha, arg.data(), arg.size());
char buf[] = {0};
SHA256_Update(&sha, buf, 1);
}
}

u8 digest[SHA256_SIZE];
SHA256_Final(digest, &sha);
return base64(digest, SHA256_SIZE);
}

template <typename E>
static void send_fd(Context<E> &ctx, i64 conn, i64 fd) {
struct iovec iov;
char dummy = '1';
iov.iov_base = &dummy;
iov.iov_len = 1;

struct msghdr msg = {};
msg.msg_iov = &iov;
msg.msg_iovlen = 1;

char buf[CMSG_SPACE(sizeof(int))];
msg.msg_control = buf;
msg.msg_controllen = CMSG_LEN(sizeof(int));

struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
*(int *)CMSG_DATA(cmsg) = fd;

if (sendmsg(conn, &msg, 0) == -1)
Fatal(ctx) << "sendmsg failed: " << errno_string();
}

template <typename E>
static i64 recv_fd(Context<E> &ctx, i64 conn) {
struct iovec iov;
char buf[1];
iov.iov_base = buf;
iov.iov_len = sizeof(buf);

struct msghdr msg = {};
msg.msg_iov = &iov;
msg.msg_iovlen = 1;

char cmsgbuf[CMSG_SPACE(sizeof(int))];
msg.msg_control = (caddr_t)cmsgbuf;
msg.msg_controllen = sizeof(cmsgbuf);

i64 len = recvmsg(conn, &msg, 0);
if (len <= 0)
Fatal(ctx) << "recvmsg failed: " << errno_string();

struct cmsghdr *cmsg;
cmsg = CMSG_FIRSTHDR(&msg);
return *(int *)CMSG_DATA(cmsg);
}

template <typename E>
void try_resume_daemon(Context<E> &ctx) {
i64 conn = socket(AF_UNIX, SOCK_STREAM, 0);
if (conn == -1)
Fatal(ctx) << "socket failed: " << errno_string();

std::string path = "/tmp/mold-" + compute_sha256(ctx.cmdline_args);

struct sockaddr_un name = {};
name.sun_family = AF_UNIX;
memcpy(name.sun_path, path.data(), path.size());

if (connect(conn, (struct sockaddr *)&name, sizeof(name)) != 0) {
close(conn);
return;
}

send_fd(ctx, conn, STDOUT_FILENO);
send_fd(ctx, conn, STDERR_FILENO);

char buf[1];
i64 r = read(conn, buf, 1);
close(conn);
if (r == 1)
exit(0);
}

template <typename E>
void daemonize(Context<E> &ctx, std::function<void()> *wait_for_client,
std::function<void()> *on_complete) {
if (daemon(1, 0) == -1)
Fatal(ctx) << "daemon failed: " << errno_string();

i64 sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock == -1)
Fatal(ctx) << "socket failed: " << errno_string();

socket_tmpfile =
strdup(("/tmp/mold-" + compute_sha256(ctx.cmdline_args)).c_str());

struct sockaddr_un name = {};
name.sun_family = AF_UNIX;
strcpy(name.sun_path, socket_tmpfile);

u32 orig_mask = umask(0177);

if (bind(sock, (struct sockaddr *)&name, sizeof(name)) == -1) {
if (errno != EADDRINUSE)
Fatal(ctx) << "bind failed: " << errno_string();

unlink(socket_tmpfile);
if (bind(sock, (struct sockaddr *)&name, sizeof(name)) == -1)
Fatal(ctx) << "bind failed: " << errno_string();
}

umask(orig_mask);

if (listen(sock, 0) == -1)
Fatal(ctx) << "listen failed: " << errno_string();

static i64 conn = -1;

*wait_for_client = [=, &ctx] {
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(sock, &rfds);

struct timeval tv;
tv.tv_sec = DAEMON_TIMEOUT;
tv.tv_usec = 0;

i64 res = select(sock + 1, &rfds, NULL, NULL, &tv);
if (res == -1)
Fatal(ctx) << "select failed: " << errno_string();

if (res == 0) {
std::cout << "timeout\n";
exit(0);
}

conn = accept(sock, NULL, NULL);
if (conn == -1)
Fatal(ctx) << "accept failed: " << errno_string();
unlink(socket_tmpfile);

dup2(recv_fd(ctx, conn), STDOUT_FILENO);
dup2(recv_fd(ctx, conn), STDERR_FILENO);
};

*on_complete = [=] {
char buf[] = {1};
int n = write(conn, buf, 1);
assert(n == 1);
};
}

static std::string get_self_path() {
return std::filesystem::read_symlink("/proc/self/exe");
}
Expand Down Expand Up @@ -307,9 +121,6 @@ void process_run_subcommand(Context<E> &ctx, int argc, char **argv) {
}

#define INSTANTIATE(E) \
template void try_resume_daemon(Context<E> &); \
template void daemonize(Context<E> &, std::function<void()> *, \
std::function<void()> *); \
template void process_run_subcommand(Context<E> &, int, char **)

INSTANTIATE_ALL;
Expand Down

0 comments on commit a85b1f5

Please sign in to comment.