1
1
mirror of https://github.com/rui314/mold.git synced 2024-08-16 08:20:23 +03:00
This commit is contained in:
Rui Ueyama 2024-03-21 10:56:14 +09:00
parent b10f818106
commit 7a65ed9082
4 changed files with 133 additions and 128 deletions

View File

@ -381,11 +381,13 @@ if(WIN32)
target_sources(mold PRIVATE
common/jobs-win32.cc
common/mapped-file-win32.cc
common/signal-win32.cc
)
else()
target_sources(mold PRIVATE
common/jobs-unix.cc
common/mapped-file-unix.cc
common/signal-unix.cc
)
endif()

View File

@ -1,11 +1,7 @@
#include "common.h"
#include "config.h"
#include <cstring>
#include <filesystem>
#include <signal.h>
#include <tbb/global_control.h>
#include <tbb/version.h>
#ifdef USE_SYSTEM_MIMALLOC
#include <mimalloc-new-delete.h>
@ -22,21 +18,12 @@
#ifdef _WIN32
# define unlink _unlink
# define write _write
#endif
namespace mold {
std::string mold_version_string = MOLD_VERSION;
namespace elf {
int main(int argc, char **argv);
}
namespace macho {
int main(int argc, char **argv);
}
static std::string get_mold_version() {
if (mold_git_hash.empty())
return "mold "s + MOLD_VERSION + " (compatible with GNU ld)";
@ -49,31 +36,6 @@ void cleanup() {
unlink(output_tmpfile);
}
#ifdef _WIN32
std::string errno_string() {
LPVOID buf;
DWORD dw = GetLastError();
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr, dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&buf, 0, nullptr);
std::string ret = (char *)buf;
LocalFree(buf);
return ret;
}
#else
std::string errno_string() {
// strerror is not thread-safe, so guard it with a lock.
static std::mutex mu;
std::scoped_lock lock(mu);
return strerror(errno);
}
#endif
// Returns the path of the mold executable itself
std::string get_self_path() {
#if __APPLE__
@ -105,96 +67,6 @@ std::string get_self_path() {
#endif
}
// mold mmap's an output file, and the mmap succeeds even if there's
// no enough space left on the filesystem. The actual disk blocks are
// not allocated on the mmap call but when the program writes to it
// for the first time.
//
// If a disk becomes full as a result of a write to an mmap'ed memory
// region, the failure of the write is reported as a SIGBUS or structured
// exeption with code EXCEPTION_IN_PAGE_ERROR on Windows. This
// signal handler catches that signal and prints out a user-friendly
// error message. Without this, it is very hard to realize that the
// disk might be full.
#ifdef _WIN32
static LONG WINAPI vectored_handler(_EXCEPTION_POINTERS *exception_info) {
static std::mutex mu;
std::scoped_lock lock{mu};
PEXCEPTION_RECORD exception_record = exception_info->ExceptionRecord;
ULONG_PTR *exception_information = exception_record->ExceptionInformation;
if (exception_record->ExceptionCode == EXCEPTION_IN_PAGE_ERROR &&
(ULONG_PTR)output_buffer_start <= exception_information[1] &&
exception_information[1] < (ULONG_PTR)output_buffer_end) {
const char msg[] = "mold: failed to write to an output file. Disk full?\n";
(void)!write(_fileno(stderr), msg, sizeof(msg) - 1);
}
cleanup();
_exit(1);
}
void install_signal_handler() {
AddVectoredExceptionHandler(0, vectored_handler);
}
#else
static std::string sigabrt_msg;
static void sighandler(int signo, siginfo_t *info, void *ucontext) {
static std::mutex mu;
std::scoped_lock lock{mu};
// Handle disk full error
switch (signo) {
case SIGSEGV:
case SIGBUS:
if (output_buffer_start <= info->si_addr &&
info->si_addr < output_buffer_end) {
const char msg[] = "mold: failed to write to an output file. Disk full?\n";
(void)!write(STDERR_FILENO, msg, sizeof(msg) - 1);
}
break;
case SIGABRT: {
(void)!write(STDERR_FILENO, &sigabrt_msg[0], sigabrt_msg.size());
break;
}
}
// Re-throw the signal
signal(SIGSEGV, SIG_DFL);
signal(SIGBUS, SIG_DFL);
signal(SIGABRT, SIG_DFL);
raise(signo);
}
void install_signal_handler() {
struct sigaction action;
action.sa_sigaction = sighandler;
sigemptyset(&action.sa_mask);
action.sa_flags = SA_SIGINFO;
sigaction(SIGSEGV, &action, NULL);
sigaction(SIGBUS, &action, NULL);
// OneTBB 2021.9.0 has the interface version 12090.
if (TBB_runtime_interface_version() < 12090) {
sigabrt_msg = "mold: aborted\n"
"mold: mold with libtbb version 2021.9.0 or older is known to be unstable "
"under heavy load. Your libtbb version is " +
std::string(TBB_runtime_version()) +
". Please upgrade your libtbb library and try again.\n";
sigaction(SIGABRT, &action, NULL);
}
}
#endif
i64 get_default_thread_count() {
// mold doesn't scale well above 32 threads.
int n = tbb::global_control::active_value(
@ -204,6 +76,14 @@ i64 get_default_thread_count() {
} // namespace mold
namespace mold::elf {
int main(int argc, char **argv);
}
namespace mold::macho {
int main(int argc, char **argv);
}
int main(int argc, char **argv) {
mold::mold_version = mold::get_mold_version();
return mold::elf::main(argc, argv);

77
common/signal-unix.cc Normal file
View File

@ -0,0 +1,77 @@
#include "common.h"
#include <signal.h>
#include <tbb/version.h>
namespace mold {
std::string errno_string() {
// strerror is not thread-safe, so guard it with a lock.
static std::mutex mu;
std::scoped_lock lock(mu);
return strerror(errno);
}
// mold mmap's an output file, and the mmap succeeds even if there's
// no enough space left on the filesystem. The actual disk blocks are
// not allocated on the mmap call but when the program writes to it
// for the first time.
//
// If a disk becomes full as a result of a write to an mmap'ed memory
// region, the failure of the write is reported as a SIGBUS or structured
// exeption with code EXCEPTION_IN_PAGE_ERROR on Windows. This
// signal handler catches that signal and prints out a user-friendly
// error message. Without this, it is very hard to realize that the
// disk might be full.
static std::string sigabrt_msg;
static void sighandler(int signo, siginfo_t *info, void *ucontext) {
static std::mutex mu;
std::scoped_lock lock{mu};
// Handle disk full error
switch (signo) {
case SIGSEGV:
case SIGBUS:
if (output_buffer_start <= info->si_addr &&
info->si_addr < output_buffer_end) {
const char msg[] = "mold: failed to write to an output file. Disk full?\n";
(void)!write(STDERR_FILENO, msg, sizeof(msg) - 1);
}
break;
case SIGABRT: {
(void)!write(STDERR_FILENO, &sigabrt_msg[0], sigabrt_msg.size());
break;
}
}
// Re-throw the signal
signal(SIGSEGV, SIG_DFL);
signal(SIGBUS, SIG_DFL);
signal(SIGABRT, SIG_DFL);
raise(signo);
}
void install_signal_handler() {
struct sigaction action;
action.sa_sigaction = sighandler;
sigemptyset(&action.sa_mask);
action.sa_flags = SA_SIGINFO;
sigaction(SIGSEGV, &action, NULL);
sigaction(SIGBUS, &action, NULL);
// OneTBB 2021.9.0 has the interface version 12090.
if (TBB_runtime_interface_version() < 12090) {
sigabrt_msg = "mold: aborted\n"
"mold: mold with libtbb version 2021.9.0 or older is known to be unstable "
"under heavy load. Your libtbb version is " +
std::string(TBB_runtime_version()) +
". Please upgrade your libtbb library and try again.\n";
sigaction(SIGABRT, &action, NULL);
}
}
} // namespace mold

46
common/signal-win32.cc Normal file
View File

@ -0,0 +1,46 @@
#include "common.h"
#include <windows.h>
namespace mold {
std::string errno_string() {
LPVOID buf;
DWORD dw = GetLastError();
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr, dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&buf, 0, nullptr);
std::string ret = (char *)buf;
LocalFree(buf);
return ret;
}
static LONG WINAPI vectored_handler(_EXCEPTION_POINTERS *exception_info) {
static std::mutex mu;
std::scoped_lock lock{mu};
PEXCEPTION_RECORD rec = exception_info->ExceptionRecord;
ULONG_PTR *p = rec->ExceptionInformation;
if (rec->ExceptionCode == EXCEPTION_IN_PAGE_ERROR &&
(ULONG_PTR)output_buffer_start <= p[1] &&
p[1] < (ULONG_PTR)output_buffer_end) {
static const char msg[] =
"mold: failed to write to an output file. Disk full?\n";
(void)!_write(_fileno(stderr), msg, sizeof(msg) - 1);
}
cleanup();
_exit(1);
}
void install_signal_handler() {
AddVectoredExceptionHandler(0, vectored_handler);
}
} // namespace mold