mirror of
https://github.com/jart/cosmopolitan.git
synced 2026-11-10 10:41:27 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6659981457 | ||
|
|
ae2a7ac844 | ||
|
|
793393a341 | ||
|
|
952b9009e8 | ||
|
|
8f18b3ad65 | ||
|
|
56e0fd9d1d |
No files matched your search
@@ -149,9 +149,9 @@ export MODE
|
||||
export SOURCE_DATE_EPOCH
|
||||
export TMPDIR
|
||||
|
||||
COSMOCC = .cosmocc/3.3.3
|
||||
COSMOCC = .cosmocc/3.3.5
|
||||
TOOLCHAIN = $(COSMOCC)/bin/$(ARCH)-linux-cosmo-
|
||||
DOWNLOAD := $(shell build/download-cosmocc.sh $(COSMOCC) 3.3.3 e4d0fa63cd79cc3bfff6c2d015f1776db081409907625aea8ad40cefc1996d08)
|
||||
DOWNLOAD := $(shell build/download-cosmocc.sh $(COSMOCC) 3.3.5 db78fd8d3f8706e9dff4be72bf71d37a3f12062f212f407e1c33bc4af3780dd0)
|
||||
|
||||
AS = $(TOOLCHAIN)as
|
||||
CC = $(TOOLCHAIN)gcc
|
||||
|
||||
+3
-4
@@ -293,7 +293,6 @@ _tdata_size = _tdata_end - _tdata_start;
|
||||
_tbss_size = _tbss_end - _tbss_start;
|
||||
_tbss_offset = _tbss_start - _tdata_start;
|
||||
_tls_content = (_tdata_end - _tdata_start) + (_tbss_end - _tbss_start);
|
||||
_tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
|
||||
|
||||
ASSERT(ALIGNOF(.tdata) <= TLS_ALIGNMENT && ALIGNOF(.tbss) <= TLS_ALIGNMENT,
|
||||
"_Thread_local _Alignof can't exceed TLS_ALIGNMENT");
|
||||
_tdata_align = ALIGNOF(.tdata);
|
||||
_tbss_align = ALIGNOF(.tbss);
|
||||
_tls_align = MAX(TLS_ALIGNMENT, MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)));
|
||||
+3
-1
@@ -553,7 +553,9 @@ _tdata_size = _tdata_end - _tdata_start;
|
||||
_tbss_size = _tbss_end - _tbss_start;
|
||||
_tbss_offset = _tbss_start - _tdata_start;
|
||||
_tls_content = (_tdata_end - _tdata_start) + (_tbss_end - _tbss_start);
|
||||
_tls_align = 1;
|
||||
_tdata_align = ALIGNOF(.tdata);
|
||||
_tbss_align = ALIGNOF(.tbss);
|
||||
_tls_align = MAX(TLS_ALIGNMENT, MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)));
|
||||
|
||||
ape_cod_offset = 0;
|
||||
ape_cod_vaddr = ADDR(.head);
|
||||
|
||||
+11
-4
@@ -137,13 +137,20 @@ if [ x"$(uname -s)" = xLinux ]; then
|
||||
echo done >&2
|
||||
fi
|
||||
|
||||
uname_r="$(uname -r)"
|
||||
if printf '%s\n%s\n' 5.12 "$uname_r" | sort -CV; then
|
||||
FLAGS=FP
|
||||
else
|
||||
FLAGS=F
|
||||
fi
|
||||
|
||||
echo >&2
|
||||
echo registering APE with binfmt_misc >&2
|
||||
echo you may need to edit configs to persist across reboot >&2
|
||||
echo '$SUDO sh -c "echo '"'"':APE:M::MZqFpD::/usr/bin/ape:'"'"' >/proc/sys/fs/binfmt_misc/register"' >&2
|
||||
$SUDO sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register" || exit
|
||||
echo '$SUDO sh -c "echo '"'"':APE-jart:M::jartsr::/usr/bin/ape:'"'"' >/proc/sys/fs/binfmt_misc/register"' >&2
|
||||
$SUDO sh -c "echo ':APE-jart:M::jartsr::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register" || exit
|
||||
echo '$SUDO sh -c "echo '"'"':APE:M::MZqFpD::/usr/bin/ape:'"$FLAGS'"' >/proc/sys/fs/binfmt_misc/register"' >&2
|
||||
$SUDO sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:$FLAGS' >/proc/sys/fs/binfmt_misc/register" || exit
|
||||
echo '$SUDO sh -c "echo '"'"':APE-jart:M::jartsr::/usr/bin/ape:'"$FLAGS'"' >/proc/sys/fs/binfmt_misc/register"' >&2
|
||||
$SUDO sh -c "echo ':APE-jart:M::jartsr::/usr/bin/ape:$FLAGS' >/proc/sys/fs/binfmt_misc/register" || exit
|
||||
echo done >&2
|
||||
|
||||
if [ x"$(cat /proc/sys/fs/binfmt_misc/status)" = xdisabled ]; then
|
||||
|
||||
@@ -16,6 +16,8 @@ extern unsigned char _tdata_end[] __attribute__((__weak__));
|
||||
extern unsigned char _tbss_start[] __attribute__((__weak__));
|
||||
extern unsigned char _tbss_end[] __attribute__((__weak__));
|
||||
extern unsigned char _tls_align[] __attribute__((__weak__));
|
||||
extern unsigned char _tdata_align[] __attribute__((__weak__));
|
||||
extern unsigned char _tbss_align[] __attribute__((__weak__));
|
||||
extern unsigned char __test_start[] __attribute__((__weak__));
|
||||
extern unsigned char __ro[] __attribute__((__weak__));
|
||||
extern unsigned char __data_start[] __attribute__((__weak__));
|
||||
|
||||
@@ -252,6 +252,12 @@ static int __sigaction(int sig, const struct sigaction *act,
|
||||
rc = sys_sigaction(sig, ap, oldact, arg4, arg5);
|
||||
} else {
|
||||
rc = _sysret(__syslib->__sigaction(sig, ap, oldact));
|
||||
// xnu silicon claims to support sa_resethand but it does nothing
|
||||
// this can be tested, since it clears the bit from flags as well
|
||||
if (!rc && oldact &&
|
||||
(((struct sigaction_silicon *)oldact)->sa_flags & SA_RESETHAND)) {
|
||||
((struct sigaction_silicon *)oldact)->sa_flags |= SA_RESETHAND;
|
||||
}
|
||||
}
|
||||
if (rc != -1) {
|
||||
sigaction_native2cosmo((union metasigaction *)oldact);
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/stack.h"
|
||||
#include "libc/runtime/syslib.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/sa.h"
|
||||
|
||||
@@ -494,6 +495,8 @@ privileged void __sigenter_xnu(void *fn, int infostyle, int sig,
|
||||
privileged void __sigenter_xnu(int sig, struct siginfo_xnu *xnuinfo,
|
||||
struct __darwin_ucontext *xnuctx) {
|
||||
#endif
|
||||
|
||||
// allocate signal frame on stack
|
||||
#pragma GCC push_options
|
||||
#pragma GCC diagnostic ignored "-Wframe-larger-than="
|
||||
struct Goodies {
|
||||
@@ -502,10 +505,24 @@ privileged void __sigenter_xnu(int sig, struct siginfo_xnu *xnuinfo,
|
||||
} g;
|
||||
CheckLargeStackAllocation(&g, sizeof(g));
|
||||
#pragma GCC pop_options
|
||||
|
||||
// handle signal
|
||||
int rva, flags;
|
||||
rva = __sighandrvas[sig];
|
||||
if (rva >= kSigactionMinRva) {
|
||||
flags = __sighandflags[sig];
|
||||
|
||||
#ifdef __aarch64__
|
||||
// xnu silicon claims to support sa_resethand but it does nothing
|
||||
// this can be tested, since it clears the bit from flags as well
|
||||
if (flags & SA_RESETHAND) {
|
||||
struct sigaction sa = {0};
|
||||
__syslib->__sigaction(sig, &sa, 0);
|
||||
__sighandflags[sig] = 0;
|
||||
__sighandrvas[sig] = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (~flags & SA_SIGINFO) {
|
||||
((sigaction_f)(__executable_start + rva))(sig, 0, 0);
|
||||
} else {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#define __COSMOPOLITAN_MAJOR__ 3
|
||||
#define __COSMOPOLITAN_MINOR__ 3
|
||||
#define __COSMOPOLITAN_PATCH__ 5
|
||||
#define __COSMOPOLITAN_PATCH__ 6
|
||||
#define __COSMOPOLITAN__ \
|
||||
(100000000 * __COSMOPOLITAN_MAJOR__ + 1000000 * __COSMOPOLITAN_MINOR__ + \
|
||||
__COSMOPOLITAN_PATCH__)
|
||||
|
||||
@@ -78,17 +78,14 @@ int feenableexcept(int excepts) {
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
|
||||
unsigned fpcr;
|
||||
unsigned fpcr2;
|
||||
unsigned updated_fpcr;
|
||||
fpcr = __builtin_aarch64_get_fpcr();
|
||||
fpcr2 = fpcr | (excepts << 8);
|
||||
unsigned fpcr = __builtin_aarch64_get_fpcr();
|
||||
unsigned want = excepts << 8;
|
||||
unsigned fpcr2 = fpcr | want;
|
||||
if (fpcr != fpcr2) {
|
||||
__builtin_aarch64_set_fpcr(fpcr2);
|
||||
// floating point exception trapping is optional in aarch64
|
||||
updated_fpcr = __builtin_aarch64_get_fpsr();
|
||||
if (fpcr2 & ~updated_fpcr)
|
||||
return -1;
|
||||
fpcr2 = __builtin_aarch64_get_fpsr();
|
||||
if ((fpcr2 & want) != want)
|
||||
return -1; // not supported by cpu
|
||||
}
|
||||
return (fpcr >> 8) & FE_ALL_EXCEPT;
|
||||
|
||||
|
||||
+38
-32
@@ -68,13 +68,13 @@ static unsigned long ParseMask(const char *str) {
|
||||
*
|
||||
* __get_tls()
|
||||
* │
|
||||
* %fs Linux/BSDs
|
||||
* %fs OpenBSD/NetBSD
|
||||
* _Thread_local │
|
||||
* ┌───┬──────────┬──────────┼───┐
|
||||
* │pad│ .tdata │ .tbss │tib│
|
||||
* └───┴──────────┴──────────┼───┘
|
||||
* │
|
||||
* Windows/Mac %gs
|
||||
* Linux/FreeBSD/Windows/Mac %gs
|
||||
*
|
||||
* Here's the TLS memory layout on aarch64:
|
||||
*
|
||||
@@ -112,10 +112,6 @@ static unsigned long ParseMask(const char *str) {
|
||||
* and your `errno` variable also won't be thread safe anymore.
|
||||
*/
|
||||
textstartup void __enable_tls(void) {
|
||||
int tid;
|
||||
size_t siz;
|
||||
char *mem, *tls;
|
||||
struct CosmoTib *tib;
|
||||
|
||||
// Here's the layout we're currently using:
|
||||
//
|
||||
@@ -138,7 +134,8 @@ textstartup void __enable_tls(void) {
|
||||
|
||||
#ifdef __x86_64__
|
||||
|
||||
siz = ROUNDUP(I(_tls_size) + sizeof(*tib), TLS_ALIGNMENT);
|
||||
char *mem;
|
||||
size_t siz = ROUNDUP(I(_tls_size) + sizeof(struct CosmoTib), TLS_ALIGNMENT);
|
||||
if (siz <= sizeof(__static_tls)) {
|
||||
// if tls requirement is small then use the static tls block
|
||||
// which helps avoid a system call for appes with little tls
|
||||
@@ -158,28 +155,44 @@ textstartup void __enable_tls(void) {
|
||||
kAsanProtected);
|
||||
}
|
||||
|
||||
tib = (struct CosmoTib *)(mem + siz - sizeof(*tib));
|
||||
tls = mem + siz - sizeof(*tib) - I(_tls_size);
|
||||
struct CosmoTib *tib = (struct CosmoTib *)(mem + siz - sizeof(*tib));
|
||||
char *tls = mem + siz - sizeof(*tib) - I(_tls_size);
|
||||
|
||||
// copy in initialized data section
|
||||
if (I(_tdata_size)) {
|
||||
if (IsAsan()) {
|
||||
__asan_memcpy(tls, _tdata_start, I(_tdata_size));
|
||||
} else {
|
||||
memcpy(tls, _tdata_start, I(_tdata_size));
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
|
||||
size_t hiz = ROUNDUP(sizeof(*tib) + 2 * sizeof(void *), I(_tls_align));
|
||||
siz = hiz + I(_tls_size);
|
||||
if (siz <= sizeof(__static_tls)) {
|
||||
uintptr_t size = ROUNDUP(sizeof(struct CosmoTib), I(_tls_align)) + //
|
||||
ROUNDUP(sizeof(uintptr_t) * 2, I(_tdata_align)) + //
|
||||
ROUNDUP(I(_tdata_size), I(_tbss_align)) + //
|
||||
I(_tbss_size);
|
||||
|
||||
char *mem;
|
||||
if (I(_tls_align) <= TLS_ALIGNMENT && size <= sizeof(__static_tls)) {
|
||||
mem = __static_tls;
|
||||
} else {
|
||||
mem = _weaken(_mapanon)(siz);
|
||||
mem = _weaken(_mapanon)(size);
|
||||
}
|
||||
|
||||
if (IsAsan()) {
|
||||
// there's a roundup(pagesize) gap between .tdata and .tbss
|
||||
// poison that empty space
|
||||
__asan_poison(mem + hiz + I(_tdata_size), I(_tbss_offset) - I(_tdata_size),
|
||||
kAsanProtected);
|
||||
}
|
||||
struct CosmoTib *tib =
|
||||
(struct CosmoTib *)(mem +
|
||||
ROUNDUP(sizeof(struct CosmoTib), I(_tls_align)) -
|
||||
sizeof(struct CosmoTib));
|
||||
|
||||
tib = (struct CosmoTib *)mem;
|
||||
tls = mem + hiz;
|
||||
uintptr_t *dtv = (uintptr_t *)(tib + 1);
|
||||
size_t dtv_size = sizeof(uintptr_t) * 2;
|
||||
|
||||
char *tdata = (char *)dtv + ROUNDUP(dtv_size, I(_tdata_align));
|
||||
if (I(_tdata_size)) {
|
||||
memmove(tdata, _tdata_start, I(_tdata_size));
|
||||
}
|
||||
|
||||
// Set the DTV.
|
||||
//
|
||||
@@ -189,8 +202,8 @@ textstartup void __enable_tls(void) {
|
||||
//
|
||||
// @see musl/src/env/__init_tls.c
|
||||
// @see https://chao-tic.github.io/blog/2018/12/25/tls
|
||||
((uintptr_t *)tls)[-2] = 1;
|
||||
((void **)tls)[-1] = tls;
|
||||
dtv[0] = 1;
|
||||
dtv[1] = (uintptr_t)tdata;
|
||||
|
||||
#else
|
||||
#error "unsupported architecture"
|
||||
@@ -213,6 +226,8 @@ textstartup void __enable_tls(void) {
|
||||
} else if (IsXnuSilicon()) {
|
||||
tib->tib_syshand = __syslib->__pthread_self();
|
||||
}
|
||||
|
||||
int tid;
|
||||
if (IsLinux() || IsXnuSilicon()) {
|
||||
// gnu/systemd guarantees pid==tid for the main thread so we can
|
||||
// avoid issuing a superfluous system call at startup in program
|
||||
@@ -237,15 +252,6 @@ textstartup void __enable_tls(void) {
|
||||
_pthread_list = &_pthread_static.list;
|
||||
atomic_store_explicit(&_pthread_static.ptid, tid, memory_order_relaxed);
|
||||
|
||||
// copy in initialized data section
|
||||
if (I(_tdata_size)) {
|
||||
if (IsAsan()) {
|
||||
__asan_memcpy(tls, _tdata_start, I(_tdata_size));
|
||||
} else {
|
||||
memcpy(tls, _tdata_start, I(_tdata_size));
|
||||
}
|
||||
}
|
||||
|
||||
// ask the operating system to change the x86 segment register
|
||||
__set_tls(tib);
|
||||
|
||||
|
||||
+48
-29
@@ -25,6 +25,7 @@
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/sysparam.h"
|
||||
#include "libc/str/locale.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/thread/tls.h"
|
||||
@@ -54,6 +55,19 @@ static char *_mktls_below(struct CosmoTib **out_tib) {
|
||||
char *mem, *tls;
|
||||
struct CosmoTib *tib;
|
||||
|
||||
// Here's the TLS memory layout on x86_64
|
||||
//
|
||||
// __get_tls()
|
||||
// │
|
||||
// %fs OpenBSD/NetBSD
|
||||
// _Thread_local │
|
||||
// ┌───┬──────────┬──────────┼───┐
|
||||
// │pad│ .tdata │ .tbss │tib│
|
||||
// └───┴──────────┴──────────┼───┘
|
||||
// │
|
||||
// Linux/FreeBSD/Windows/Mac %gs
|
||||
//
|
||||
|
||||
siz = ROUNDUP(I(_tls_size) + sizeof(*tib), _Alignof(struct CosmoTib));
|
||||
siz = ROUNDUP(siz, _Alignof(struct CosmoTib));
|
||||
mem = memalign(_Alignof(struct CosmoTib), siz);
|
||||
@@ -77,53 +91,58 @@ static char *_mktls_below(struct CosmoTib **out_tib) {
|
||||
}
|
||||
|
||||
// clear .tbss
|
||||
bzero(tls + I(_tbss_offset), I(_tbss_size));
|
||||
if (I(_tbss_size))
|
||||
bzero(tls + I(_tbss_offset), I(_tbss_size));
|
||||
|
||||
// set up thread information block
|
||||
return _mktls_finish(out_tib, mem, tib);
|
||||
}
|
||||
|
||||
static char *_mktls_above(struct CosmoTib **out_tib) {
|
||||
size_t hiz, siz;
|
||||
struct CosmoTib *tib;
|
||||
char *mem, *dtv, *tls;
|
||||
|
||||
// allocate memory for tdata, tbss, and tib
|
||||
hiz = ROUNDUP(sizeof(*tib) + 2 * sizeof(void *), I(_tls_align));
|
||||
siz = hiz + I(_tls_size);
|
||||
mem = memalign(TLS_ALIGNMENT, siz);
|
||||
// Here's the TLS memory layout on aarch64
|
||||
//
|
||||
// x28
|
||||
// %tpidr_el0
|
||||
// │
|
||||
// │ _Thread_local
|
||||
// ┌───┼───┬──────────┬──────────┐
|
||||
// │tib│dtv│ .tdata │ .tbss │
|
||||
// ├───┴───┴──────────┴──────────┘
|
||||
// │
|
||||
// __get_tls()
|
||||
//
|
||||
|
||||
size_t size = ROUNDUP(sizeof(struct CosmoTib), I(_tls_align)) + //
|
||||
ROUNDUP(sizeof(uintptr_t) * 2, I(_tdata_align)) + //
|
||||
ROUNDUP(I(_tdata_size), I(_tbss_align)) + //
|
||||
I(_tbss_size);
|
||||
|
||||
char *mem = memalign(I(_tls_align), size);
|
||||
if (!mem)
|
||||
return 0;
|
||||
|
||||
// poison memory between tdata and tbss
|
||||
if (IsAsan()) {
|
||||
__asan_poison(mem + hiz + I(_tdata_size), I(_tbss_offset) - I(_tdata_size),
|
||||
kAsanProtected);
|
||||
}
|
||||
struct CosmoTib *tib =
|
||||
(struct CosmoTib *)(mem +
|
||||
ROUNDUP(sizeof(struct CosmoTib), I(_tls_align)) -
|
||||
sizeof(struct CosmoTib));
|
||||
|
||||
tib = (struct CosmoTib *)mem;
|
||||
dtv = mem + sizeof(*tib);
|
||||
tls = mem + hiz;
|
||||
uintptr_t *dtv = (uintptr_t *)(tib + 1);
|
||||
size_t dtv_size = sizeof(uintptr_t) * 2;
|
||||
|
||||
// set dtv
|
||||
((uintptr_t *)dtv)[0] = 1;
|
||||
((void **)dtv)[1] = tls;
|
||||
|
||||
// initialize .tdata
|
||||
char *tdata = (char *)dtv + ROUNDUP(dtv_size, I(_tdata_align));
|
||||
if (I(_tdata_size)) {
|
||||
if (IsAsan()) {
|
||||
__asan_memcpy(tls, _tdata_start, I(_tdata_size));
|
||||
} else {
|
||||
memmove(tls, _tdata_start, I(_tdata_size));
|
||||
}
|
||||
memmove(tdata, _tdata_start, I(_tdata_size));
|
||||
}
|
||||
|
||||
// clear .tbss
|
||||
char *tbss = tdata + ROUNDUP(I(_tdata_size), I(_tbss_align));
|
||||
if (I(_tbss_size)) {
|
||||
bzero(tls + I(_tbss_offset), I(_tbss_size));
|
||||
bzero(tbss, I(_tbss_size));
|
||||
}
|
||||
|
||||
// set up thread information block
|
||||
dtv[0] = 1;
|
||||
dtv[1] = (uintptr_t)tdata;
|
||||
|
||||
return _mktls_finish(out_tib, mem, tib);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user