mirror of
https://github.com/rui314/mold.git
synced 2024-12-26 18:02:30 +03:00
temporary
This commit is contained in:
parent
95ce383b97
commit
4f46edac0c
2
Makefile
2
Makefile
@ -8,7 +8,7 @@ CPPFLAGS=-g -IoneTBB/include -pthread -std=c++20 -Wno-deprecated-volatile -Wno-s
|
||||
LDFLAGS=-L$(TBB_LIBDIR) -Wl,-rpath=$(TBB_LIBDIR) -fuse-ld=lld -pthread
|
||||
LIBS=-ltbb -ltbbmalloc -ltbbmalloc_proxy
|
||||
OBJS=main.o object_file.o input_sections.o output_chunks.o mapfile.o perf.o \
|
||||
linker_script.o archive_file.o sha1.o output_file.o
|
||||
linker_script.o archive_file.o sha1.o output_file.o subprocess.o
|
||||
|
||||
mold: $(OBJS)
|
||||
$(CXX) $(CFLAGS) $(OBJS) -o $@ $(LDFLAGS) $(LIBS)
|
||||
|
187
main.cc
187
main.cc
@ -13,11 +13,8 @@
|
||||
#include <unistd.h>
|
||||
#include <unordered_set>
|
||||
|
||||
#define DAEMON_TIMEOUT 30
|
||||
|
||||
static tbb::task_group parser_tg;
|
||||
static bool preloading;
|
||||
static char *socket_tmpfile;
|
||||
|
||||
static bool is_text_file(MemoryMappedFile *mb) {
|
||||
return mb->size() >= 4 &&
|
||||
@ -792,190 +789,6 @@ static u64 parse_number(std::string opt, std::string_view value) {
|
||||
return std::stol(std::string(value));
|
||||
}
|
||||
|
||||
// Exiting from a program with large memory usage is slow --
|
||||
// it may take a few hundred milliseconds. To hide the latency,
|
||||
// we fork a child and let it do the actual linking work.
|
||||
static std::function<void()> fork_child() {
|
||||
int pipefd[2];
|
||||
if (pipe(pipefd) == -1) {
|
||||
perror("pipe");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pid_t pid = fork();
|
||||
if (pid == -1) {
|
||||
perror("fork");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (pid > 0) {
|
||||
// Parent
|
||||
close(pipefd[1]);
|
||||
int r = read(pipefd[0], (char[1]){}, 1);
|
||||
_exit(r != 1);
|
||||
}
|
||||
|
||||
// Child
|
||||
close(pipefd[0]);
|
||||
return [=]() { write(pipefd[1], (char []){1}, 1); };
|
||||
}
|
||||
|
||||
static std::string compute_sha1(char **argv) {
|
||||
SHA1 sha1;
|
||||
|
||||
for (int i = 0; argv[i]; i++)
|
||||
if (!strcmp(argv[i], "-preload") && !strcmp(argv[i], "--preload"))
|
||||
sha1.update((u8 *)argv[i], strlen(argv[i]) + 1);
|
||||
|
||||
u8 digest[21];
|
||||
memset(digest, 0, sizeof(digest));
|
||||
sha1.get_result(digest);
|
||||
|
||||
static char chars[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
std::string res;
|
||||
for (int i = 0; i < sizeof(digest); i += 3) {
|
||||
u32 x = (digest[i + 2] << 16) | (digest[i + 1] << 8) | digest[i];
|
||||
res += chars[x & 0b111111];
|
||||
res += chars[(x >> 6) & 0b111111];
|
||||
res += chars[(x >> 12) & 0b111111];
|
||||
res += chars[(x >> 18) & 0b111111];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static void send_fd(int conn, int fd) {
|
||||
struct iovec iov;
|
||||
char dummy = '1';
|
||||
iov.iov_base = &dummy;
|
||||
iov.iov_len = 1;
|
||||
|
||||
struct msghdr msg;
|
||||
memset(&msg, 0, sizeof(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)
|
||||
Error() << "sendmsg failed: " << strerror(errno);
|
||||
}
|
||||
|
||||
static int recv_fd(int conn) {
|
||||
struct iovec iov;
|
||||
char buf[1];
|
||||
iov.iov_base = buf;
|
||||
iov.iov_len = sizeof(buf);
|
||||
|
||||
struct msghdr msg;
|
||||
memset(&msg, 0, sizeof(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);
|
||||
|
||||
int len = recvmsg(conn, &msg, 0);
|
||||
if (len <= 0)
|
||||
Error() << "recvmsg failed: " << strerror(errno);
|
||||
|
||||
struct cmsghdr *cmsg;
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
return *(int *)CMSG_DATA(cmsg);
|
||||
}
|
||||
|
||||
static bool resume_daemon(char **argv, int *code) {
|
||||
int conn = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (conn == -1)
|
||||
Error() << "socket failed: " << strerror(errno);
|
||||
|
||||
std::string path = "/tmp/mold-" + compute_sha1(argv);
|
||||
|
||||
struct sockaddr_un name;
|
||||
memset(&name, 0, sizeof(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 false;
|
||||
}
|
||||
|
||||
send_fd(conn, STDOUT_FILENO);
|
||||
send_fd(conn, STDERR_FILENO);
|
||||
int r = read(conn, (char[1]){}, 1);
|
||||
*code = (r != 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void daemonize(char **argv, std::function<void()> *wait_for_client,
|
||||
std::function<void()> *on_complete) {
|
||||
compute_sha1(argv);
|
||||
|
||||
if (daemon(1, 0) == -1)
|
||||
Error() << "daemon failed: " << strerror(errno);
|
||||
|
||||
int sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (sock == -1)
|
||||
Error() << "socket failed: " << strerror(errno);
|
||||
|
||||
socket_tmpfile = strdup(("/tmp/mold-" + compute_sha1(argv)).c_str());
|
||||
|
||||
struct sockaddr_un name;
|
||||
memset(&name, 0, sizeof(name));
|
||||
name.sun_family = AF_UNIX;
|
||||
strcpy(name.sun_path, socket_tmpfile);
|
||||
|
||||
if (bind(sock, (struct sockaddr *)&name, sizeof(name)) == -1) {
|
||||
if (errno != EADDRINUSE)
|
||||
Error() << "bind failed: " << strerror(errno);
|
||||
|
||||
unlink(socket_tmpfile);
|
||||
if (bind(sock, (struct sockaddr *)&name, sizeof(name)) == -1)
|
||||
Error() << "bind failed: " << strerror(errno);
|
||||
}
|
||||
|
||||
if (listen(sock, 0) == -1)
|
||||
Error() << "listen failed: " << strerror(errno);
|
||||
|
||||
static int conn = -1;
|
||||
|
||||
*wait_for_client = [=]() {
|
||||
fd_set rfds;
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(sock, &rfds);
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec = DAEMON_TIMEOUT;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
int res = select(sock + 1, &rfds, NULL, NULL, &tv);
|
||||
if (res == -1)
|
||||
Error() << "select failed: " << strerror(errno);
|
||||
|
||||
if (res == 0) {
|
||||
std::cout << "timeout\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
conn = accept(sock, NULL, NULL);
|
||||
if (conn == -1)
|
||||
Error() << "accept failed: " << strerror(errno);
|
||||
};
|
||||
|
||||
*on_complete = [=]() { write(conn, (char []){1}, 1); };
|
||||
}
|
||||
|
||||
static std::vector<std::string_view> read_response_file(std::string_view path) {
|
||||
std::vector<std::string_view> vec;
|
||||
MemoryMappedFile *mb = MemoryMappedFile::must_open(std::string(path));
|
||||
|
11
mold.h
11
mold.h
@ -924,6 +924,17 @@ private:
|
||||
|
||||
void print_map();
|
||||
|
||||
//
|
||||
// subprocess.cc
|
||||
//
|
||||
|
||||
extern char *socket_tmpfile;
|
||||
|
||||
std::function<void()> fork_child();
|
||||
bool resume_daemon(char **argv, int *code);
|
||||
void daemonize(char **argv, std::function<void()> *wait_for_client,
|
||||
std::function<void()> *on_complete);
|
||||
|
||||
//
|
||||
// main.cc
|
||||
//
|
||||
|
194
subprocess.cc
Normal file
194
subprocess.cc
Normal file
@ -0,0 +1,194 @@
|
||||
#include "mold.h"
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define DAEMON_TIMEOUT 30
|
||||
|
||||
char *socket_tmpfile;
|
||||
|
||||
// Exiting from a program with large memory usage is slow --
|
||||
// it may take a few hundred milliseconds. To hide the latency,
|
||||
// we fork a child and let it do the actual linking work.
|
||||
std::function<void()> fork_child() {
|
||||
int pipefd[2];
|
||||
if (pipe(pipefd) == -1) {
|
||||
perror("pipe");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pid_t pid = fork();
|
||||
if (pid == -1) {
|
||||
perror("fork");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (pid > 0) {
|
||||
// Parent
|
||||
close(pipefd[1]);
|
||||
int r = read(pipefd[0], (char[1]){}, 1);
|
||||
_exit(r != 1);
|
||||
}
|
||||
|
||||
// Child
|
||||
close(pipefd[0]);
|
||||
return [=]() { write(pipefd[1], (char []){1}, 1); };
|
||||
}
|
||||
|
||||
static std::string compute_sha1(char **argv) {
|
||||
SHA1 sha1;
|
||||
|
||||
for (int i = 0; argv[i]; i++)
|
||||
if (!strcmp(argv[i], "-preload") && !strcmp(argv[i], "--preload"))
|
||||
sha1.update((u8 *)argv[i], strlen(argv[i]) + 1);
|
||||
|
||||
u8 digest[21];
|
||||
memset(digest, 0, sizeof(digest));
|
||||
sha1.get_result(digest);
|
||||
|
||||
static char chars[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
std::string res;
|
||||
for (int i = 0; i < sizeof(digest); i += 3) {
|
||||
u32 x = (digest[i + 2] << 16) | (digest[i + 1] << 8) | digest[i];
|
||||
res += chars[x & 0b111111];
|
||||
res += chars[(x >> 6) & 0b111111];
|
||||
res += chars[(x >> 12) & 0b111111];
|
||||
res += chars[(x >> 18) & 0b111111];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static void send_fd(int conn, int fd) {
|
||||
struct iovec iov;
|
||||
char dummy = '1';
|
||||
iov.iov_base = &dummy;
|
||||
iov.iov_len = 1;
|
||||
|
||||
struct msghdr msg;
|
||||
memset(&msg, 0, sizeof(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)
|
||||
Error() << "sendmsg failed: " << strerror(errno);
|
||||
}
|
||||
|
||||
static int recv_fd(int conn) {
|
||||
struct iovec iov;
|
||||
char buf[1];
|
||||
iov.iov_base = buf;
|
||||
iov.iov_len = sizeof(buf);
|
||||
|
||||
struct msghdr msg;
|
||||
memset(&msg, 0, sizeof(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);
|
||||
|
||||
int len = recvmsg(conn, &msg, 0);
|
||||
if (len <= 0)
|
||||
Error() << "recvmsg failed: " << strerror(errno);
|
||||
|
||||
struct cmsghdr *cmsg;
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
return *(int *)CMSG_DATA(cmsg);
|
||||
}
|
||||
|
||||
bool resume_daemon(char **argv, int *code) {
|
||||
int conn = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (conn == -1)
|
||||
Error() << "socket failed: " << strerror(errno);
|
||||
|
||||
std::string path = "/tmp/mold-" + compute_sha1(argv);
|
||||
|
||||
struct sockaddr_un name;
|
||||
memset(&name, 0, sizeof(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 false;
|
||||
}
|
||||
|
||||
send_fd(conn, STDOUT_FILENO);
|
||||
send_fd(conn, STDERR_FILENO);
|
||||
int r = read(conn, (char[1]){}, 1);
|
||||
*code = (r != 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
void daemonize(char **argv, std::function<void()> *wait_for_client,
|
||||
std::function<void()> *on_complete) {
|
||||
compute_sha1(argv);
|
||||
|
||||
if (daemon(1, 0) == -1)
|
||||
Error() << "daemon failed: " << strerror(errno);
|
||||
|
||||
int sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (sock == -1)
|
||||
Error() << "socket failed: " << strerror(errno);
|
||||
|
||||
socket_tmpfile = strdup(("/tmp/mold-" + compute_sha1(argv)).c_str());
|
||||
|
||||
struct sockaddr_un name;
|
||||
memset(&name, 0, sizeof(name));
|
||||
name.sun_family = AF_UNIX;
|
||||
strcpy(name.sun_path, socket_tmpfile);
|
||||
|
||||
if (bind(sock, (struct sockaddr *)&name, sizeof(name)) == -1) {
|
||||
if (errno != EADDRINUSE)
|
||||
Error() << "bind failed: " << strerror(errno);
|
||||
|
||||
unlink(socket_tmpfile);
|
||||
if (bind(sock, (struct sockaddr *)&name, sizeof(name)) == -1)
|
||||
Error() << "bind failed: " << strerror(errno);
|
||||
}
|
||||
|
||||
if (listen(sock, 0) == -1)
|
||||
Error() << "listen failed: " << strerror(errno);
|
||||
|
||||
static int conn = -1;
|
||||
|
||||
*wait_for_client = [=]() {
|
||||
fd_set rfds;
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(sock, &rfds);
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec = DAEMON_TIMEOUT;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
int res = select(sock + 1, &rfds, NULL, NULL, &tv);
|
||||
if (res == -1)
|
||||
Error() << "select failed: " << strerror(errno);
|
||||
|
||||
if (res == 0) {
|
||||
std::cout << "timeout\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
conn = accept(sock, NULL, NULL);
|
||||
if (conn == -1)
|
||||
Error() << "accept failed: " << strerror(errno);
|
||||
unlink(socket_tmpfile);
|
||||
};
|
||||
|
||||
*on_complete = [=]() { write(conn, (char []){1}, 1); };
|
||||
}
|
Loading…
Reference in New Issue
Block a user