Skip to content

Commit

Permalink
Revert "Use %gs as TLS register when dlopen() is linked"
Browse files Browse the repository at this point in the history
This reverts commit d71da7f.
  • Loading branch information
jart committed Nov 8, 2023
1 parent d71da7f commit 956e68b
Show file tree
Hide file tree
Showing 13 changed files with 40 additions and 71 deletions.
3 changes: 1 addition & 2 deletions libc/calls/close-nt.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,14 @@
#include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h"

void sys_fcntl_nt_lock_cleanup(int);

textwindows int sys_close_nt(int fd, int fildes) {
if (fd + 0u >= g_fds.n) return ebadf();
struct Fd *f = g_fds.p + fd;
switch (f->kind) {
case kFdEmpty:
return ebadf();
case kFdFile:
void sys_fcntl_nt_lock_cleanup(int);
if (_weaken(sys_fcntl_nt_lock_cleanup)) {
_weaken(sys_fcntl_nt_lock_cleanup)(fildes);
}
Expand Down
5 changes: 2 additions & 3 deletions libc/calls/getprogramexecutablename.greg.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,10 @@ static inline void InitProgramExecutableNameImpl(void) {
}

// give up and just copy argv[0] into it
char *p, *e;
if ((q = __argv[0])) {
CopyString:
p = g_prog.u.buf;
e = p + sizeof(g_prog.u.buf);
char *p = g_prog.u.buf;
char *e = p + sizeof(g_prog.u.buf);
while ((c = *q++)) {
if (p + 1 < e) {
*p++ = c;
Expand Down
3 changes: 1 addition & 2 deletions libc/calls/park.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,14 @@ static textwindows int _park_thread(uint32_t msdelay, sigset_t waitmask,
if ((sig = __sig_get(waitmask))) goto HandleSignal;
int expect = 0;
atomic_int futex = 0;
int handler_was_called;
struct PosixThread *pt = _pthread_self();
pt->pt_blkmask = waitmask;
atomic_store_explicit(&pt->pt_blocker, &futex, memory_order_release);
bool32 ok = WaitOnAddress(&futex, &expect, sizeof(int), msdelay);
atomic_store_explicit(&pt->pt_blocker, 0, memory_order_release);
if (ok && (sig = __sig_get(waitmask))) {
HandleSignal:
handler_was_called = __sig_relay(sig, SI_KERNEL, waitmask);
int handler_was_called = __sig_relay(sig, SI_KERNEL, waitmask);
if (_check_cancel() == -1) return -1;
if (!restartable || (handler_was_called & SIG_HANDLED_NO_RESTART)) {
return eintr();
Expand Down
3 changes: 1 addition & 2 deletions libc/calls/read-nt.c
Original file line number Diff line number Diff line change
Expand Up @@ -723,7 +723,6 @@ static textwindows int WaitForConsole(struct Fd *f, sigset_t waitmask) {
int sig;
int64_t sem;
uint32_t wi, ms = -1;
int handler_was_called;
if (!__ttyconf.vmin) {
if (!__ttyconf.vtime) {
return 0; // non-blocking w/o raising eagain
Expand All @@ -746,7 +745,7 @@ static textwindows int WaitForConsole(struct Fd *f, sigset_t waitmask) {
if (wi != 1) return __winerr(); // wait failed
if (!(sig = __sig_get(waitmask))) return eintr();
DeliverSignal:
handler_was_called = __sig_relay(sig, SI_KERNEL, waitmask);
int handler_was_called = __sig_relay(sig, SI_KERNEL, waitmask);
if (_check_cancel() == -1) return -1;
if (!(handler_was_called & SIG_HANDLED_NO_RESTART)) return -2;
return eintr();
Expand Down
6 changes: 2 additions & 4 deletions libc/calls/readwrite-nt.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,7 @@ sys_readwrite_nt(int fd, void *data, size_t size, ssize_t offset,
bool32 ReadOrWriteFile(int64_t, void *, uint32_t, uint32_t *,
struct NtOverlapped *)) {
int sig;
bool eagained;
uint32_t exchanged;
int handler_was_called;
struct Fd *f = g_fds.p + fd;

// win32 i/o apis generally take 32-bit values thus we implicitly
Expand Down Expand Up @@ -81,7 +79,7 @@ sys_readwrite_nt(int fd, void *data, size_t size, ssize_t offset,
}

RestartOperation:
eagained = false;
bool eagained = false;
// check for signals and cancelation
if (_check_cancel() == -1) return -1; // ECANCELED
if ((sig = __sig_get(waitmask))) goto HandleInterrupt;
Expand Down Expand Up @@ -134,7 +132,7 @@ sys_readwrite_nt(int fd, void *data, size_t size, ssize_t offset,
// otherwise it must be due to a kill() via __sig_cancel()
if ((sig = __sig_get(waitmask))) {
HandleInterrupt:
handler_was_called = __sig_relay(sig, SI_KERNEL, waitmask);
int handler_was_called = __sig_relay(sig, SI_KERNEL, waitmask);
if (_check_cancel() == -1) return -1; // possible if we SIGTHR'd
// read() is @restartable unless non-SA_RESTART hands were called
if (!(handler_was_called & SIG_HANDLED_NO_RESTART)) {
Expand Down
45 changes: 26 additions & 19 deletions libc/dlopen/dlopen.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
#include "libc/nt/errors.h"
#include "libc/nt/memory.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/internal.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/syslib.internal.h"
#include "libc/stdio/stdio.h"
Expand Down Expand Up @@ -76,6 +75,17 @@ __static_yoink(".dlopen.aarch64.glibc.elf");
#define XNU_RTLD_LOCAL 4
#define XNU_RTLD_GLOBAL 8

#define BEGIN_FOREIGN \
{ \
struct CosmoTib *cosmo_tib = __get_tls(); \
pthread_mutex_lock(&foreign.lock); \
__set_tls(foreign.tib)

#define END_FOREIGN \
__set_tls(cosmo_tib); \
pthread_mutex_unlock(&foreign.lock); \
}

struct loaded {
char *base;
char *entry;
Expand All @@ -86,6 +96,8 @@ struct loaded {
static struct {
atomic_uint once;
bool is_supported;
struct CosmoTib *tib;
pthread_mutex_t lock;
void *(*dlopen)(const char *, int);
void *(*dlsym)(void *, const char *);
int (*dlclose)(void *);
Expand Down Expand Up @@ -300,6 +312,7 @@ static void foreign_setup(void) {
if (!dlopen_helper) {
return; // this platform isn't supported yet
}
struct CosmoTib *cosmo_tib = __get_tls();
if (!setjmp(foreign.jb)) {
elf_exec(dlopen_helper, interp, 2,
(char *[]){
Expand All @@ -310,6 +323,8 @@ static void foreign_setup(void) {
environ);
return; // if it returns then it failed
}
foreign.tib = __get_tls();
__set_tls(cosmo_tib);
foreign.is_supported = true;
}

Expand Down Expand Up @@ -376,17 +391,15 @@ static char *dlsym_nt_alloc_rwx_block(void) {
static void *dlsym_nt_alloc_rwx(size_t n) {
void *res;
static char *block;
static pthread_spinlock_t lock;
pthread_spin_lock(&lock);
pthread_mutex_lock(&foreign.lock);
if (!block || READ32LE(block) + n > 65536) {
if (!(block = dlsym_nt_alloc_rwx_block())) {
pthread_spin_unlock(&lock);
return 0;
}
}
res = block + READ32LE(block);
WRITE32LE(block, READ32LE(block) + n);
pthread_spin_unlock(&lock);
pthread_mutex_unlock(&foreign.lock);
return res;
}

Expand Down Expand Up @@ -482,7 +495,9 @@ void *dlopen(const char *path, int mode) {
last_dlerror = "dlopen() isn't supported on x86-64 MacOS";
res = 0;
} else if (foreign_init()) {
BEGIN_FOREIGN;
res = foreign.dlopen(path, mode);
END_FOREIGN;
} else {
res = 0;
}
Expand All @@ -509,7 +524,9 @@ void *dlsym(void *handle, const char *name) {
last_dlerror = "dlopen() isn't supported on x86-64 MacOS";
res = 0;
} else if (foreign_init()) {
BEGIN_FOREIGN;
res = foreign.dlsym(handle, name);
END_FOREIGN;
} else {
res = 0;
}
Expand All @@ -533,7 +550,9 @@ int dlclose(void *handle) {
last_dlerror = "dlopen() isn't supported on x86-64 MacOS";
res = -1;
} else if (foreign_init()) {
BEGIN_FOREIGN;
res = foreign.dlclose(handle);
END_FOREIGN;
} else {
res = -1;
}
Expand All @@ -551,24 +570,12 @@ char *dlerror(void) {
} else if (IsWindows() || IsXnu()) {
res = (char *)last_dlerror;
} else if (foreign_init()) {
BEGIN_FOREIGN;
res = foreign.dlerror();
END_FOREIGN;
} else {
res = (char *)last_dlerror;
}
STRACE("dlerror() → %#s", res);
return res;
}

#ifdef __x86_64__
static textstartup void dlopen_init() {
if (IsLinux() || IsFreebsd() || IsNetbsd()) {
// switch from %fs to %gs for tls
struct CosmoTib *tib = __get_tls();
__morph_tls();
__set_tls(tib);
}
}
const void *const dlopen_ctor[] initarray = {
dlopen_init,
};
#endif
21 changes: 0 additions & 21 deletions libc/intrin/tlsmorphed.c

This file was deleted.

4 changes: 2 additions & 2 deletions libc/proc/wait4-nt.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ static textwindows int __proc_wait(int pid, int *wstatus, int options,
for (;;) {

// check for signals and cancelation
int rc, sig, handler_was_called;
int sig, handler_was_called;
if (_check_cancel() == -1) {
return -1;
}
Expand All @@ -89,7 +89,7 @@ static textwindows int __proc_wait(int pid, int *wstatus, int options,
// check for zombie to harvest
__proc_lock();
CheckForZombies:
rc = __proc_check(pid, wstatus, rusage);
int rc = __proc_check(pid, wstatus, rusage);
if (rc || (options & WNOHANG)) {
__proc_unlock();
return rc;
Expand Down
5 changes: 1 addition & 4 deletions libc/runtime/morph_tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,11 @@ privileged void __morph_tls(void) {
// address 0x30 was promised to us, according to Go team
// https://github.com/golang/go/issues/23617
dis = 0x30;
} else if (IsWindows()) {
} else {
// MSVC __declspec(thread) generates binary code for this
// %gs:0x1480 abi. So long as TlsAlloc() isn't called >64
// times we should be good.
dis = 0x1480 + __tls_index * 8;
} else {
dis = 0;
}

// iterate over modifiable code looking for 9 byte instruction
Expand Down Expand Up @@ -114,7 +112,6 @@ privileged void __morph_tls(void) {
}
}

__tls_morphed = true;
__morph_end();
#endif
}
7 changes: 2 additions & 5 deletions libc/runtime/set_tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,6 @@
#include "libc/thread/tls.h"
#include "libc/thread/tls2.internal.h"

#define AMD64_SET_FSBASE 129
#define AMD64_SET_GSBASE 131

int sys_set_tls();

textstartup void __set_tls(struct CosmoTib *tib) {
Expand All @@ -39,9 +36,9 @@ textstartup void __set_tls(struct CosmoTib *tib) {
npassert(0 <= __tls_index && __tls_index < 64);
asm("mov\t%1,%%gs:%0" : "=m"(*((long *)0x1480 + __tls_index)) : "r"(tib));
} else if (IsFreebsd()) {
sys_set_tls(__tls_morphed ? AMD64_SET_GSBASE : AMD64_SET_FSBASE, tib);
sys_set_tls(129 /*AMD64_SET_FSBASE*/, tib);
} else if (IsLinux()) {
sys_set_tls(__tls_morphed ? ARCH_SET_GS : ARCH_SET_FS, tib);
sys_set_tls(ARCH_SET_FS, tib);
} else if (IsNetbsd()) {
// netbsd has sysarch(X86_SET_FSBASE) but we can't use that because
// signal handlers will cause it to be reset due to not setting the
Expand Down
2 changes: 1 addition & 1 deletion libc/stdio/fmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,7 @@ static int __fmt_bround(struct FPBits *b, int prec, int prec1) {
return prec;
}

static int __fmt_noop(const char *x, void *y, size_t z) {
static int __fmt_noop(const char *, void *, size_t) {
return 0;
}

Expand Down
1 change: 0 additions & 1 deletion libc/thread/tls.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ struct CosmoTib {
};

extern int __threaded;
extern bool __tls_morphed;
extern unsigned __tls_index;

char *_mktls(struct CosmoTib **);
Expand Down
6 changes: 1 addition & 5 deletions libc/thread/tls2.internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,7 @@ COSMOPOLITAN_C_START_
__funline struct CosmoTib *__get_tls_privileged(void) {
char *tib, *lin = (char *)0x30;
if (IsLinux() || IsFreebsd() || IsNetbsd() || IsOpenbsd() || IsMetal()) {
if (!__tls_morphed) {
asm("mov\t%%fs:(%1),%0" : "=a"(tib) : "r"(lin) : "memory");
} else {
asm("mov\t%%gs:(%1),%0" : "=a"(tib) : "r"(lin) : "memory");
}
asm("mov\t%%fs:(%1),%0" : "=a"(tib) : "r"(lin) : "memory");
} else {
asm("mov\t%%gs:(%1),%0" : "=a"(tib) : "r"(lin) : "memory");
if (IsWindows()) {
Expand Down

0 comments on commit 956e68b

Please sign in to comment.