Support thread local storage

This commit is contained in:
Justine Tunney 2022-05-16 13:20:08 -07:00
parent 91ee2b19d4
commit 55de4ca6b5
197 changed files with 1483 additions and 874 deletions

View file

@ -65,10 +65,21 @@ $(LIBC_CALLS_A).pkg: \
$(LIBC_CALLS_A_OBJS) \
$(foreach x,$(LIBC_CALLS_A_DIRECTDEPS),$($(x)_A).pkg)
o/$(MODE)/libc/calls/sigenter-freebsd.o \
o/$(MODE)/libc/calls/sigenter-netbsd.o \
o/$(MODE)/libc/calls/sigenter-openbsd.o \
o/$(MODE)/libc/calls/sigenter-xnu.o: \
OVERRIDE_COPTS += \
-mno-fentry \
-fno-stack-protector \
-fno-sanitize=all
o/$(MODE)/libc/calls/sys_mprotect.greg.o \
o/$(MODE)/libc/calls/vdsofunc.greg.o \
o/$(MODE)/libc/calls/directmap.o \
o/$(MODE)/libc/calls/directmap-nt.o \
o/$(MODE)/libc/calls/mapstack.greg.o \
o/$(MODE)/libc/calls/execve-nt.greg.o \
o/$(MODE)/libc/calls/getcwd.greg.o \
o/$(MODE)/libc/calls/getcwd-xnu.greg.o \
o/$(MODE)/libc/calls/getprogramexecutablename.greg.o \
@ -114,7 +125,7 @@ o/$(MODE)/libc/calls/execl.o \
o/$(MODE)/libc/calls/execle.o \
o/$(MODE)/libc/calls/execlp.o \
o/$(MODE)/libc/calls/copyfile.o \
o/$(MODE)/libc/calls/execve-nt.o \
o/$(MODE)/libc/calls/execve-nt.greg.o \
o/$(MODE)/libc/calls/linkat-nt.o \
o/$(MODE)/libc/calls/renameat-nt.o \
o/$(MODE)/libc/calls/execve-sysv.o \

View file

@ -16,44 +16,95 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#define ShouldUseMsabiAttribute() 1
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/ntspawn.h"
#include "libc/calls/strace.internal.h"
#include "libc/mem/alloca.h"
#include "libc/nt/accounting.h"
#include "libc/nt/console.h"
#include "libc/nt/enum/startf.h"
#include "libc/nt/enum/status.h"
#include "libc/nt/memory.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/processinformation.h"
#include "libc/nt/struct/startupinfo.h"
#include "libc/nt/synchronization.h"
#include "libc/nt/thunk/msabi.h"
#include "libc/runtime/memtrack.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/at.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/ok.h"
#include "libc/sysv/errfuns.h"
__msabi extern typeof(CloseHandle) *const __imp_CloseHandle;
__msabi extern typeof(WaitForSingleObject) *const __imp_WaitForSingleObject;
__msabi extern typeof(GetExitCodeProcess) *const __imp_GetExitCodeProcess;
__msabi extern typeof(UnmapViewOfFile) *const __imp_UnmapViewOfFile;
static noinstrument __msabi bool32
BlockExecveConsoleEvent(uint32_t dwCtrlType) {
// block SIGINT and SIGQUIT in execve() parent process
return true;
}
textwindows int sys_execve_nt(const char *program, char *const argv[],
char *const envp[]) {
int rc;
size_t i;
uint32_t dwExitCode;
struct MemoryIntervals *mm;
struct NtStartupInfo startinfo;
struct NtProcessInformation procinfo;
// this is a non-recoverable operation, so do some manual validation
if (sys_faccessat_nt(AT_FDCWD, program, X_OK, 0) == -1) {
return eacces();
}
//////////////////////////////////////////////////////////////////////////////
// execve operation is unrecoverable from this point
// close cloexec handles
for (i = 3; i < g_fds.n; ++i) {
if (g_fds.p[i].kind != kFdEmpty && (g_fds.p[i].flags & O_CLOEXEC)) {
__imp_CloseHandle(g_fds.p[i].handle);
}
}
bzero(&startinfo, sizeof(startinfo));
startinfo.cb = sizeof(struct NtStartupInfo);
startinfo.dwFlags = kNtStartfUsestdhandles;
startinfo.hStdInput = __getfdhandleactual(0);
startinfo.hStdOutput = __getfdhandleactual(1);
startinfo.hStdError = __getfdhandleactual(2);
// spawn the process
rc = ntspawn(program, argv, envp, 0, 0, 0, 1, 0, 0, &startinfo, &procinfo);
if (rc == -1) return -1;
CloseHandle(g_fds.p[0].handle);
CloseHandle(g_fds.p[1].handle);
CloseHandle(procinfo.hThread);
if (rc == -1) {
STRACE("panic: unrecoverable ntspawn(%#s) error: %m", program);
__imp_ExitProcess(6543);
}
//////////////////////////////////////////////////////////////////////////////
// zombie shell process remains, to wait for child and propagate its exit
// code
__imp_CloseHandle(g_fds.p[0].handle);
__imp_CloseHandle(g_fds.p[1].handle);
__imp_CloseHandle(procinfo.hThread);
__imp_SetConsoleCtrlHandler((void *)BlockExecveConsoleEvent, 1);
do {
WaitForSingleObject(procinfo.hProcess, -1);
__imp_WaitForSingleObject(procinfo.hProcess, -1);
dwExitCode = kNtStillActive;
GetExitCodeProcess(procinfo.hProcess, &dwExitCode);
__imp_GetExitCodeProcess(procinfo.hProcess, &dwExitCode);
} while (dwExitCode == kNtStillActive);
CloseHandle(procinfo.hProcess);
_Exit(dwExitCode);
__imp_CloseHandle(procinfo.hProcess);
__imp_ExitProcess(dwExitCode);
unreachable;
}

View file

@ -63,11 +63,6 @@ int execve(const char *prog, char *const argv[], char *const envp[]) {
kprintf("})\n");
}
#endif
for (i = 3; i < g_fds.n; ++i) {
if (g_fds.p[i].kind != kFdEmpty && (g_fds.p[i].flags & O_CLOEXEC)) {
close(i);
}
}
if (!IsWindows()) {
rc = sys_execve(prog, argv, envp);
} else {

View file

@ -134,6 +134,7 @@ i32 __sys_pipe2(i32[hasatleast 2], u32) hidden;
i32 __sys_sigprocmask(i32, const sigset *, sigset *, u64) hidden;
i32 __sys_utimensat(i32, const char *, const struct timespec *, i32) hidden;
i32 __sys_wait4(i32, i32 *, i32, struct rusage *) hidden;
i32 sys_arch_prctl(i32, i64) hidden;
i32 sys_chdir(const char *) hidden;
i32 sys_chroot(const char *) hidden;
i32 sys_clock_gettime(i32, struct timespec *) hidden;

View file

@ -18,10 +18,11 @@
*/
#include "libc/calls/internal.h"
#include "libc/calls/ucontext.h"
#include "libc/log/libfatal.internal.h"
#include "libc/nt/struct/context.h"
#include "libc/str/str.h"
textwindows void _ntcontext2linux(ucontext_t *ctx, const struct NtContext *cr) {
privileged void _ntcontext2linux(ucontext_t *ctx, const struct NtContext *cr) {
if (!cr) return;
ctx->uc_flags = cr->EFlags;
ctx->uc_mcontext.eflags = cr->EFlags;
@ -46,10 +47,10 @@ textwindows void _ntcontext2linux(ucontext_t *ctx, const struct NtContext *cr) {
ctx->uc_mcontext.gs = cr->SegGs;
ctx->uc_mcontext.fs = cr->SegFs;
ctx->uc_mcontext.fpregs = &ctx->__fpustate;
memcpy(&ctx->__fpustate, &cr->FltSave, sizeof(ctx->__fpustate));
__repmovsb(&ctx->__fpustate, &cr->FltSave, sizeof(ctx->__fpustate));
}
textwindows void _ntlinux2context(struct NtContext *cr, const ucontext_t *ctx) {
privileged void _ntlinux2context(struct NtContext *cr, const ucontext_t *ctx) {
if (!cr) return;
cr->EFlags = ctx->uc_flags;
cr->EFlags = ctx->uc_mcontext.eflags;
@ -73,5 +74,5 @@ textwindows void _ntlinux2context(struct NtContext *cr, const ucontext_t *ctx) {
cr->SegCs = ctx->uc_mcontext.cs;
cr->SegGs = ctx->uc_mcontext.gs;
cr->SegFs = ctx->uc_mcontext.fs;
memcpy(&cr->FltSave, &ctx->__fpustate, sizeof(ctx->__fpustate));
__repmovsb(&cr->FltSave, &ctx->__fpustate, sizeof(ctx->__fpustate));
}

View file

@ -22,6 +22,7 @@
#include "libc/calls/strace.internal.h"
#include "libc/intrin/cmpxchg.h"
#include "libc/intrin/spinlock.h"
#include "libc/log/libfatal.internal.h"
#include "libc/macros.internal.h"
#include "libc/runtime/internal.h"
#include "libc/runtime/runtime.h"
@ -90,8 +91,8 @@ static textwindows struct Signal *__sig_remove(void) {
* @note called from main thread
* @return true if EINTR should be returned by caller
*/
static textwindows bool __sig_deliver(bool restartable, int sig, int si_code,
ucontext_t *ctx) {
static privileged bool __sig_deliver(bool restartable, int sig, int si_code,
ucontext_t *ctx) {
unsigned rva, flags;
siginfo_t info, *infop;
STRACE("delivering %G", sig);
@ -113,7 +114,7 @@ static textwindows bool __sig_deliver(bool restartable, int sig, int si_code,
// setup the somewhat expensive information args
// only if they're requested by the user in sigaction()
if (flags & SA_SIGINFO) {
bzero(&info, sizeof(info));
__repstosb(&info, 0, sizeof(info));
info.si_signo = sig;
info.si_code = si_code;
infop = &info;
@ -162,8 +163,8 @@ static textwindows bool __sig_isfatal(int sig) {
* @param restartable can be used to suppress true return if SA_RESTART
* @return true if signal was delivered
*/
textwindows bool __sig_handle(bool restartable, int sig, int si_code,
ucontext_t *ctx) {
privileged bool __sig_handle(bool restartable, int sig, int si_code,
ucontext_t *ctx) {
bool delivered;
switch (__sighandrvas[sig]) {
case (intptr_t)SIG_DFL:

View file

@ -25,13 +25,13 @@
#include "libc/calls/typedef/sigaction_f.h"
#include "libc/calls/ucontext.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/repstosb.h"
#include "libc/log/libfatal.internal.h"
#include "libc/macros.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/sa.h"
void __sigenter_freebsd(int sig, struct siginfo_freebsd *freebsdinfo,
struct ucontext_freebsd *ctx) {
privileged void __sigenter_freebsd(int sig, struct siginfo_freebsd *freebsdinfo,
struct ucontext_freebsd *ctx) {
int rva, flags;
struct Goodies {
ucontext_t uc;
@ -43,14 +43,14 @@ void __sigenter_freebsd(int sig, struct siginfo_freebsd *freebsdinfo,
if (~flags & SA_SIGINFO) {
((sigaction_f)(_base + rva))(sig, 0, 0);
} else {
repstosb(&g, 0, sizeof(g));
__repstosb(&g, 0, sizeof(g));
g.uc.uc_mcontext.fpregs = &g.uc.__fpustate;
g.uc.uc_stack.ss_sp = ctx->uc_stack.ss_sp;
g.uc.uc_stack.ss_size = ctx->uc_stack.ss_size;
g.uc.uc_stack.ss_flags = ctx->uc_stack.ss_flags;
g.uc.uc_flags = ctx->uc_flags;
memcpy(&g.uc.uc_sigmask, &ctx->uc_sigmask,
MIN(sizeof(g.uc.uc_sigmask), sizeof(ctx->uc_sigmask)));
__repmovsb(&g.uc.uc_sigmask, &ctx->uc_sigmask,
MIN(sizeof(g.uc.uc_sigmask), sizeof(ctx->uc_sigmask)));
g.uc.uc_mcontext.r8 = ctx->uc_mcontext.mc_r8;
g.uc.uc_mcontext.r9 = ctx->uc_mcontext.mc_r9;
g.uc.uc_mcontext.r10 = ctx->uc_mcontext.mc_r10;
@ -73,7 +73,7 @@ void __sigenter_freebsd(int sig, struct siginfo_freebsd *freebsdinfo,
g.uc.uc_mcontext.gs = ctx->uc_mcontext.mc_gs;
g.uc.uc_mcontext.err = ctx->uc_mcontext.mc_err;
g.uc.uc_mcontext.trapno = ctx->uc_mcontext.mc_trapno;
memcpy(&g.uc.__fpustate, &ctx->uc_mcontext.mc_fpstate, 512);
__repmovsb(&g.uc.__fpustate, &ctx->uc_mcontext.mc_fpstate, 512);
g.si.si_signo = freebsdinfo->si_signo;
g.si.si_errno = freebsdinfo->si_errno;
g.si.si_code = freebsdinfo->si_code;
@ -89,8 +89,8 @@ void __sigenter_freebsd(int sig, struct siginfo_freebsd *freebsdinfo,
ctx->uc_stack.ss_size = g.uc.uc_stack.ss_size;
ctx->uc_stack.ss_flags = g.uc.uc_stack.ss_flags;
ctx->uc_flags = g.uc.uc_flags;
memcpy(&ctx->uc_sigmask, &g.uc.uc_sigmask,
MIN(sizeof(g.uc.uc_sigmask), sizeof(ctx->uc_sigmask)));
__repmovsb(&ctx->uc_sigmask, &g.uc.uc_sigmask,
MIN(sizeof(g.uc.uc_sigmask), sizeof(ctx->uc_sigmask)));
ctx->uc_mcontext.mc_rdi = g.uc.uc_mcontext.rdi;
ctx->uc_mcontext.mc_rsi = g.uc.uc_mcontext.rsi;
ctx->uc_mcontext.mc_rdx = g.uc.uc_mcontext.rdx;
@ -113,7 +113,7 @@ void __sigenter_freebsd(int sig, struct siginfo_freebsd *freebsdinfo,
ctx->uc_mcontext.mc_err = g.uc.uc_mcontext.err;
ctx->uc_mcontext.mc_rip = g.uc.uc_mcontext.rip;
ctx->uc_mcontext.mc_rsp = g.uc.uc_mcontext.rsp;
memcpy(&ctx->uc_mcontext.mc_fpstate, &g.uc.__fpustate, 512);
__repmovsb(&ctx->uc_mcontext.mc_fpstate, &g.uc.__fpustate, 512);
}
}
/*

View file

@ -24,12 +24,13 @@
#include "libc/calls/struct/ucontext-netbsd.internal.h"
#include "libc/calls/typedef/sigaction_f.h"
#include "libc/calls/ucontext.h"
#include "libc/log/libfatal.internal.h"
#include "libc/macros.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/sa.h"
void __sigenter_netbsd(int sig, struct siginfo_netbsd *si,
struct ucontext_netbsd *ctx) {
privileged void __sigenter_netbsd(int sig, struct siginfo_netbsd *si,
struct ucontext_netbsd *ctx) {
int rva, flags;
ucontext_t uc;
struct siginfo si2;
@ -39,8 +40,8 @@ void __sigenter_netbsd(int sig, struct siginfo_netbsd *si,
if (~flags & SA_SIGINFO) {
((sigaction_f)(_base + rva))(sig, 0, 0);
} else {
bzero(&uc, sizeof(uc));
bzero(&si2, sizeof(si2));
__repstosb(&uc, 0, sizeof(uc));
__repstosb(&si2, 0, sizeof(si2));
si2.si_signo = si->si_signo;
si2.si_code = si->si_code;
si2.si_errno = si->si_errno;
@ -52,8 +53,8 @@ void __sigenter_netbsd(int sig, struct siginfo_netbsd *si,
uc.uc_stack.ss_sp = ctx->uc_stack.ss_sp;
uc.uc_stack.ss_size = ctx->uc_stack.ss_size;
uc.uc_stack.ss_flags = ctx->uc_stack.ss_flags;
memcpy(&uc.uc_sigmask, &ctx->uc_sigmask,
MIN(sizeof(uc.uc_sigmask), sizeof(ctx->uc_sigmask)));
__repmovsb(&uc.uc_sigmask, &ctx->uc_sigmask,
MIN(sizeof(uc.uc_sigmask), sizeof(ctx->uc_sigmask)));
uc.uc_mcontext.rdi = ctx->uc_mcontext.rdi;
uc.uc_mcontext.rsi = ctx->uc_mcontext.rsi;
uc.uc_mcontext.rdx = ctx->uc_mcontext.rdx;

View file

@ -24,13 +24,13 @@
#include "libc/calls/struct/ucontext-openbsd.internal.h"
#include "libc/calls/typedef/sigaction_f.h"
#include "libc/calls/ucontext.h"
#include "libc/intrin/repstosb.h"
#include "libc/log/libfatal.internal.h"
#include "libc/macros.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/sa.h"
void __sigenter_openbsd(int sig, struct siginfo_openbsd *openbsdinfo,
struct ucontext_openbsd *ctx) {
privileged void __sigenter_openbsd(int sig, struct siginfo_openbsd *openbsdinfo,
struct ucontext_openbsd *ctx) {
int rva, flags;
struct Goodies {
ucontext_t uc;
@ -42,7 +42,7 @@ void __sigenter_openbsd(int sig, struct siginfo_openbsd *openbsdinfo,
if (~flags & SA_SIGINFO) {
((sigaction_f)(_base + rva))(sig, 0, 0);
} else {
repstosb(&g, 0, sizeof(g));
__repstosb(&g, 0, sizeof(g));
g.si.si_signo = openbsdinfo->si_signo;
g.si.si_code = openbsdinfo->si_code;
g.si.si_errno = openbsdinfo->si_errno;
@ -54,8 +54,8 @@ void __sigenter_openbsd(int sig, struct siginfo_openbsd *openbsdinfo,
}
g.si.si_value = openbsdinfo->si_value;
g.uc.uc_mcontext.fpregs = &g.uc.__fpustate;
memcpy(&g.uc.uc_sigmask, &ctx->sc_mask,
MIN(sizeof(g.uc.uc_sigmask), sizeof(ctx->sc_mask)));
__repmovsb(&g.uc.uc_sigmask, &ctx->sc_mask,
MIN(sizeof(g.uc.uc_sigmask), sizeof(ctx->sc_mask)));
g.uc.uc_mcontext.rdi = ctx->sc_rdi;
g.uc.uc_mcontext.rsi = ctx->sc_rsi;
g.uc.uc_mcontext.rdx = ctx->sc_rdx;

View file

@ -25,6 +25,7 @@
#include "libc/calls/ucontext.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/repstosb.h"
#include "libc/log/libfatal.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/sa.h"
@ -355,19 +356,19 @@ struct __darwin_ucontext {
struct __darwin_mcontext64 *uc_mcontext;
};
noasan static void xnuexceptionstate2linux(
static privileged void xnuexceptionstate2linux(
mcontext_t *mc, struct __darwin_x86_exception_state64 *xnues) {
mc->trapno = xnues->__trapno;
mc->err = xnues->__err;
}
noasan static void linuxexceptionstate2xnu(
static privileged void linuxexceptionstate2xnu(
struct __darwin_x86_exception_state64 *xnues, mcontext_t *mc) {
xnues->__trapno = mc->trapno;
xnues->__err = mc->err;
}
noasan static void xnuthreadstate2linux(
static privileged void xnuthreadstate2linux(
mcontext_t *mc, struct __darwin_x86_thread_state64 *xnuss) {
mc->rdi = xnuss->__rdi;
mc->rsi = xnuss->__rsi;
@ -392,7 +393,7 @@ noasan static void xnuthreadstate2linux(
mc->r15 = xnuss->__r15;
}
noasan static void linuxthreadstate2xnu(
static privileged void linuxthreadstate2xnu(
struct __darwin_x86_thread_state64 *xnuss, ucontext_t *uc, mcontext_t *mc) {
xnuss->__rdi = mc->rdi;
xnuss->__rsi = mc->rsi;
@ -417,14 +418,14 @@ noasan static void linuxthreadstate2xnu(
xnuss->__r15 = mc->r15;
}
noasan static void CopyFpXmmRegs(void *d, const void *s) {
static privileged void CopyFpXmmRegs(void *d, const void *s) {
size_t i;
for (i = 0; i < (8 + 16) * 16; i += 16) {
__builtin_memcpy((char *)d + i, (const char *)s + i, 16);
}
}
noasan static void xnussefpustate2linux(
static privileged void xnussefpustate2linux(
struct FpuState *fs, struct __darwin_x86_float_state64 *xnufs) {
fs->cwd = xnufs->__fpu_fcw;
fs->swd = xnufs->__fpu_fsw;
@ -437,7 +438,7 @@ noasan static void xnussefpustate2linux(
CopyFpXmmRegs(fs->st, &xnufs->__fpu_stmm0);
}
noasan static void linuxssefpustate2xnu(
static privileged void linuxssefpustate2xnu(
struct __darwin_x86_float_state64 *xnufs, struct FpuState *fs) {
xnufs->__fpu_fcw = fs->cwd;
xnufs->__fpu_fsw = fs->swd;
@ -450,9 +451,9 @@ noasan static void linuxssefpustate2xnu(
CopyFpXmmRegs(&xnufs->__fpu_stmm0, fs->st);
}
noasan void __sigenter_xnu(void *fn, int infostyle, int sig,
struct siginfo_xnu *xnuinfo,
struct __darwin_ucontext *xnuctx) {
privileged void __sigenter_xnu(void *fn, int infostyle, int sig,
struct siginfo_xnu *xnuinfo,
struct __darwin_ucontext *xnuctx) {
intptr_t ax;
int rva, flags;
struct Goodies {
@ -465,7 +466,7 @@ noasan void __sigenter_xnu(void *fn, int infostyle, int sig,
if (~flags & SA_SIGINFO) {
((sigaction_f)(_base + rva))(sig, 0, 0);
} else {
repstosb(&g, 0, sizeof(g));
__repstosb(&g, 0, sizeof(g));
if (xnuctx) {
g.uc.uc_flags = xnuctx->uc_onstack ? SA_ONSTACK : 0;
g.uc.uc_sigmask.__bits[0] = xnuctx->uc_sigmask;

View file

@ -30,7 +30,7 @@
#include "libc/sysv/consts/sicode.h"
#include "libc/sysv/consts/sig.h"
textwindows unsigned __wincrash(struct NtExceptionPointers *ep) {
privileged unsigned __wincrash(struct NtExceptionPointers *ep) {
int64_t rip;
int sig, code;
ucontext_t ctx;