mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-22 21:32:31 +00:00
Improve AARCH64 execution
This change fixes bugs in the APE loader. The execve() unit tests are now enabled for MODE=aarch64. See the README for how you need to have binfmt_misc configured with Qemu to run them. Apple Silicon bugs have been fixed too, e.g. tkill() now works.
This commit is contained in:
parent
1965d7488e
commit
77a7873057
31 changed files with 599 additions and 195 deletions
|
@ -59,6 +59,7 @@
|
|||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/thread/posixthread.internal.h"
|
||||
#include "libc/thread/thread.h"
|
||||
#ifdef __x86_64__
|
||||
|
||||
#define keywords textwindows dontasan dontubsan dontinstrument
|
||||
|
||||
|
@ -275,3 +276,5 @@ static keywords void sys_execve_nt_relay(intptr_t h, long b, long c, long d) {
|
|||
__imp_ExitProcess(dwExitCode);
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
#endif /* __x86_64__ */
|
||||
|
|
|
@ -17,15 +17,21 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/ape.h"
|
||||
#include "libc/atomic.h"
|
||||
#include "libc/calls/blockcancel.internal.h"
|
||||
#include "libc/calls/blocksigs.internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/execve-sysv.internal.h"
|
||||
#include "libc/calls/cp.internal.h"
|
||||
#include "libc/calls/execve.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/cosmo.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/magnumstrs.internal.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/mem/alloca.h"
|
||||
#include "libc/paths.h"
|
||||
|
@ -36,77 +42,100 @@
|
|||
#include "libc/sysv/consts/ok.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static bool CanExecute(const char *path) {
|
||||
return !sys_faccessat(AT_FDCWD, path, X_OK, 0);
|
||||
}
|
||||
#define ELIBBAD_LINUX 80
|
||||
#define EBADEXEC_XNU 85
|
||||
#define EBADARCH_XNU 86
|
||||
|
||||
bool IsAPEMagic(char buf[8]) {
|
||||
return READ64LE(buf) == READ64LE("MZqFpD='") ||
|
||||
READ64LE(buf) == READ64LE("JTqFpD='");
|
||||
}
|
||||
static struct {
|
||||
atomic_uint once;
|
||||
const char *home;
|
||||
const char *tmpdir;
|
||||
} g_execve;
|
||||
|
||||
static bool IsApeBinary(const char *path) {
|
||||
int fd;
|
||||
char buf[8];
|
||||
bool res = false;
|
||||
// TODO(jart): Should we block signals too?
|
||||
BLOCK_CANCELLATIONS;
|
||||
if ((fd = sys_openat(AT_FDCWD, path, O_RDONLY, 0)) != -1) {
|
||||
res = sys_read(fd, buf, 8) == 8 && IsAPEMagic(buf);
|
||||
sys_close(fd);
|
||||
static bool IsApeFile(const char *path) {
|
||||
if (!endswith(path, ".com")) {
|
||||
return true;
|
||||
} else {
|
||||
bool res = false;
|
||||
BLOCK_CANCELLATIONS;
|
||||
BEGIN_CANCELLATION_POINT;
|
||||
int fd;
|
||||
char buf[8];
|
||||
int flags = O_RDONLY | O_NOCTTY | O_NONBLOCK | O_CLOEXEC;
|
||||
if ((fd = sys_openat(AT_FDCWD, path, flags, 0)) != -1) {
|
||||
res = sys_pread(fd, buf, 8, 0, 0) == 8 && IsApeLoadable(buf);
|
||||
sys_close(fd);
|
||||
}
|
||||
END_CANCELLATION_POINT;
|
||||
ALLOW_CANCELLATIONS;
|
||||
return res;
|
||||
}
|
||||
ALLOW_CANCELLATIONS;
|
||||
return res;
|
||||
}
|
||||
|
||||
static const char *Join(const char *a, const char *b, char buf[PATH_MAX]) {
|
||||
size_t n, m;
|
||||
n = strlen(a);
|
||||
m = strlen(b);
|
||||
if (n + 1 + m + 1 < PATH_MAX) {
|
||||
stpcpy(stpcpy(stpcpy(buf, a), "/"), b);
|
||||
return buf;
|
||||
} else {
|
||||
return "";
|
||||
if (a && *a) {
|
||||
n = strlen(a);
|
||||
m = strlen(b);
|
||||
if (n + m + 1 < PATH_MAX) {
|
||||
stpcpy(stpcpy(buf, a), b);
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void RetryExecve(const char *prog, char **argv, char *const *envp) {
|
||||
if ((argv[0] = (char *)prog)) {
|
||||
STRACE("execve(%#s, %s) due to %s", prog, DescribeStringList(argv),
|
||||
_strerrno(errno));
|
||||
__sys_execve(prog, argv, envp);
|
||||
}
|
||||
}
|
||||
|
||||
int sys_execve(const char *prog, char *const argv[], char *const envp[]) {
|
||||
size_t i;
|
||||
int e, rc;
|
||||
char *buf;
|
||||
char **shargs;
|
||||
const char *ape;
|
||||
e = errno;
|
||||
__sys_execve(prog, argv, envp);
|
||||
if (errno == ENOEXEC) {
|
||||
for (i = 0; argv[i];) ++i;
|
||||
buf = alloca(PATH_MAX);
|
||||
shargs = alloca((i + 4) * sizeof(char *));
|
||||
if (IsApeBinary(prog) &&
|
||||
(CanExecute((ape = "/usr/bin/ape")) ||
|
||||
CanExecute((ape = Join(firstnonnull(getenv("TMPDIR"),
|
||||
firstnonnull(getenv("HOME"), ".")),
|
||||
".ape-" APE_VERSION_STR, buf))) ||
|
||||
CanExecute((ape = Join(firstnonnull(getenv("HOME"), "."),
|
||||
".ape-" APE_VERSION_STR, buf))))) {
|
||||
shargs[0] = (char *)ape;
|
||||
shargs[1] = (char *)"-";
|
||||
shargs[2] = (char *)prog;
|
||||
memcpy(shargs + 3, argv, (i + 1) * sizeof(char *));
|
||||
errno = e;
|
||||
rc = __sys_execve(shargs[0], shargs, envp);
|
||||
} else if (CanExecute(prog)) {
|
||||
shargs[0] = _PATH_BSHELL;
|
||||
shargs[1] = (char *)prog;
|
||||
memcpy(shargs + 2, argv + 1, i * sizeof(char *));
|
||||
errno = e;
|
||||
rc = __sys_execve(shargs[0], shargs, envp);
|
||||
} else {
|
||||
rc = enoexec();
|
||||
}
|
||||
} else {
|
||||
rc = -1;
|
||||
}
|
||||
return rc;
|
||||
static void SetupExecve(void) {
|
||||
g_execve.home = getenv("HOME");
|
||||
g_execve.tmpdir = getenv("TMPDIR");
|
||||
}
|
||||
|
||||
__attribute__((__constructor__)) static void InitExecve(void) {
|
||||
cosmo_once(&g_execve.once, SetupExecve);
|
||||
}
|
||||
|
||||
int sys_execve(const char *prog, char *const argv[], char *const envp[]) {
|
||||
|
||||
// try kernel
|
||||
// this also checks execute bit
|
||||
__sys_execve(prog, argv, envp);
|
||||
if (!(errno == ENOEXEC || (IsLinux() && errno == ELIBBAD_LINUX))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// allocate memory
|
||||
int argc;
|
||||
for (argc = 0; argv[argc];) ++argc;
|
||||
char **shargs = alloca((argc + 4) * sizeof(char *));
|
||||
|
||||
// try ape loader
|
||||
if (IsApeFile(prog)) {
|
||||
shargs[1] = (char *)"-";
|
||||
shargs[2] = (char *)prog;
|
||||
memcpy(shargs + 3, argv, (argc + 1) * sizeof(char *));
|
||||
RetryExecve("/usr/bin/ape", shargs, envp);
|
||||
char *buf = alloca(PATH_MAX);
|
||||
const char *name = "/.ape-" APE_VERSION_STR;
|
||||
InitExecve();
|
||||
RetryExecve(Join(g_execve.tmpdir, name, buf), shargs, envp);
|
||||
RetryExecve(Join(g_execve.home, name, buf), shargs, envp);
|
||||
RetryExecve(Join(".", name, buf), shargs, envp);
|
||||
}
|
||||
|
||||
// try bourne shell
|
||||
shargs[0] = _PATH_BSHELL;
|
||||
shargs[1] = (char *)prog;
|
||||
memcpy(shargs + 2, argv + 1, argc * sizeof(char *));
|
||||
RetryExecve(shargs[0], shargs, envp);
|
||||
|
||||
enoexec();
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ int execve(const char *prog, char *const argv[], char *const envp[]) {
|
|||
!__asan_is_valid_strlist(envp)))) {
|
||||
rc = efault();
|
||||
} else {
|
||||
STRACE("execve(%#s, %s, %s) → ...", prog, DescribeStringList(argv),
|
||||
STRACE("execve(%#s, %s, %s)", prog, DescribeStringList(argv),
|
||||
DescribeStringList(envp));
|
||||
rc = 0;
|
||||
if (IsLinux() && __execpromises && _weaken(sys_pledge_linux)) {
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
bool IsAPEMagic(char[8]);
|
||||
void __execve_lock(void);
|
||||
void __execve_unlock(void);
|
||||
bool IsApeLoadable(char[8]);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
|
@ -21,7 +21,7 @@
|
|||
#include "libc/calls/blocksigs.internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/cp.internal.h"
|
||||
#include "libc/calls/execve-sysv.internal.h"
|
||||
#include "libc/calls/execve.internal.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/stat.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
|
@ -30,6 +30,7 @@
|
|||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
|
@ -46,7 +47,7 @@
|
|||
|
||||
static bool IsAPEFd(const int fd) {
|
||||
char buf[8];
|
||||
return (sys_pread(fd, buf, 8, 0, 0) == 8) && IsAPEMagic(buf);
|
||||
return (sys_pread(fd, buf, 8, 0, 0) == 8) && IsApeLoadable(buf);
|
||||
}
|
||||
|
||||
static int fexecve_impl(const int fd, char *const argv[], char *const envp[]) {
|
||||
|
@ -141,7 +142,7 @@ static int fd_to_mem_fd(const int infd, char *path) {
|
|||
ssize_t readRc;
|
||||
readRc = pread(infd, space, st.st_size, 0);
|
||||
bool success = readRc != -1;
|
||||
if (success && (st.st_size > 8) && IsAPEMagic(space)) {
|
||||
if (success && (st.st_size > 8) && IsApeLoadable(space)) {
|
||||
int flags = fcntl(fd, F_GETFD);
|
||||
if ((success = (flags != -1) &&
|
||||
(fcntl(fd, F_SETFD, flags & (~FD_CLOEXEC)) != -1) &&
|
||||
|
|
|
@ -93,9 +93,9 @@ static inline void GetProgramExecutableNameImpl(char *p, char *e) {
|
|||
|
||||
// if argv[0] exists then turn it into an absolute path. we also try
|
||||
// adding a .com suffix since the ape auto-appends it when resolving
|
||||
if (((q = __argv[0]) && !sys_faccessat(AT_FDCWD, q, F_OK, 0)) ||
|
||||
((q = StrCat(u.path, __argv[0], ".com")) &&
|
||||
!sys_faccessat(AT_FDCWD, q, F_OK, 0))) {
|
||||
if ((q = __argv[0]) && ((!sys_faccessat(AT_FDCWD, q, F_OK, 0)) ||
|
||||
((q = StrCat(u.path, __argv[0], ".com")) &&
|
||||
!sys_faccessat(AT_FDCWD, q, F_OK, 0)))) {
|
||||
if (*q != '/') {
|
||||
if (q[0] == '.' && q[1] == '/') {
|
||||
q += 2;
|
||||
|
|
29
libc/calls/isapemagic.c
Normal file
29
libc/calls/isapemagic.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
|
||||
/**
|
||||
* Returns true if executable image is supported by APE Loader.
|
||||
*/
|
||||
bool IsApeLoadable(char buf[8]) {
|
||||
return READ32LE(buf) == READ32LE("\177ELF") ||
|
||||
READ64LE(buf) == READ64LE("MZqFpD='") ||
|
||||
READ64LE(buf) == READ64LE("JTqFpD='");
|
||||
}
|
|
@ -34,6 +34,7 @@
|
|||
#include "libc/nt/struct/securityattributes.h"
|
||||
#include "libc/nt/struct/startupinfo.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#ifdef __x86_64__
|
||||
|
||||
struct SpawnBlock {
|
||||
union {
|
||||
|
@ -108,3 +109,5 @@ textwindows int ntspawn(
|
|||
if (handle) CloseHandle(handle);
|
||||
return __fix_enotdir(rc, prog16);
|
||||
}
|
||||
|
||||
#endif /* __x86_64__ */
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/struct/context.h"
|
||||
#include "libc/nt/thread.h"
|
||||
#include "libc/runtime/syslib.internal.h"
|
||||
#include "libc/sysv/consts/sicode.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
@ -97,10 +98,17 @@ static dontinline textwindows int __tkill_nt(int tid, int sig,
|
|||
}
|
||||
}
|
||||
|
||||
static int __tkill_m1(int tid, int sig, struct CosmoTib *tib) {
|
||||
struct PosixThread *pt = (struct PosixThread *)__get_tls()->tib_pthread;
|
||||
return __syslib->pthread_kill(pt->next, sig);
|
||||
}
|
||||
|
||||
// OpenBSD has an optional `tib` parameter for extra safety.
|
||||
int __tkill(int tid, int sig, void *tib) {
|
||||
int rc;
|
||||
if (IsLinux() || IsXnu() || IsFreebsd() || IsOpenbsd() || IsNetbsd()) {
|
||||
if (IsXnuSilicon()) {
|
||||
return __tkill_m1(tid, sig, tib);
|
||||
} else if (IsLinux() || IsXnu() || IsFreebsd() || IsOpenbsd() || IsNetbsd()) {
|
||||
rc = sys_tkill(tid, sig, tib);
|
||||
} else if (IsWindows()) {
|
||||
rc = __tkill_nt(tid, sig, tib);
|
||||
|
|
|
@ -406,11 +406,9 @@ static bool __asan_is_mapped(int x) {
|
|||
// xxx: we can't lock because no reentrant locks yet
|
||||
int i;
|
||||
bool res;
|
||||
struct MemoryIntervals *m;
|
||||
__mmi_lock();
|
||||
m = _weaken(_mmi);
|
||||
i = __find_memory(m, x);
|
||||
res = i < m->i && x >= m->p[i].x;
|
||||
i = __find_memory(&_mmi, x);
|
||||
res = i < _mmi.i && x >= _mmi.p[i].x;
|
||||
__mmi_unlock();
|
||||
return res;
|
||||
}
|
||||
|
@ -902,7 +900,7 @@ static __wur __asan_die_f *__asan_report(const void *addr, int size,
|
|||
p = __asan_format_section(p, _etext, _edata, ".data", addr);
|
||||
p = __asan_format_section(p, _end, _edata, ".bss", addr);
|
||||
__mmi_lock();
|
||||
for (m = _weaken(_mmi), i = 0; i < m->i; ++i) {
|
||||
for (m = &_mmi, i = 0; i < m->i; ++i) {
|
||||
x = m->p[i].x;
|
||||
y = m->p[i].y;
|
||||
p = __asan_format_interval(p, x << 16, (y << 16) + (FRAMESIZE - 1));
|
||||
|
@ -1396,7 +1394,7 @@ void __asan_map_shadow(uintptr_t p, size_t n) {
|
|||
kprintf("error: %p size %'zu overlaps shadow space\n", p, n);
|
||||
_Exit(1);
|
||||
}
|
||||
m = _weaken(_mmi);
|
||||
m = &_mmi;
|
||||
a = (0x7fff8000 + (p >> 3)) >> 16;
|
||||
b = (0x7fff8000 + (p >> 3) + (n >> 3) + 0xffff) >> 16;
|
||||
for (; a <= b; a += i) {
|
||||
|
@ -1413,12 +1411,11 @@ void __asan_map_shadow(uintptr_t p, size_t n) {
|
|||
addr = (void *)ADDR_32_TO_48(a);
|
||||
prot = PROT_READ | PROT_WRITE;
|
||||
flag = MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS;
|
||||
sm = _weaken(sys_mmap)(addr, size, prot, flag, -1, 0);
|
||||
sm = sys_mmap(addr, size, prot, flag, -1, 0);
|
||||
if (sm.addr == MAP_FAILED ||
|
||||
_weaken(__track_memory)(m, a, a + i - 1, sm.maphandle,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, false,
|
||||
false, 0, size) == -1) {
|
||||
__track_memory(m, a, a + i - 1, sm.maphandle, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, false, false, 0,
|
||||
size) == -1) {
|
||||
kprintf("error: could not map asan shadow memory\n");
|
||||
__asan_die()();
|
||||
__asan_unreachable();
|
||||
|
@ -1539,9 +1536,6 @@ void __asan_init(int argc, char **argv, char **envp, unsigned long *auxv) {
|
|||
__write_str("error: asan binaries require windows10\r\n");
|
||||
_Exit(0); /* So `make MODE=dbg test` passes w/ Windows7 */
|
||||
}
|
||||
REQUIRE(_mmi);
|
||||
REQUIRE(sys_mmap);
|
||||
REQUIRE(__track_memory);
|
||||
if (_weaken(hook_malloc) || _weaken(hook_calloc) || _weaken(hook_realloc) ||
|
||||
_weaken(hook_realloc_in_place) || _weaken(hook_free) ||
|
||||
_weaken(hook_malloc_usable_size)) {
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
|
||||
// TODO(jart): Fork this function into ASAN and non-ASAN versions.
|
||||
const char *DescribeFlags(char *p, size_t n, const struct DescribeFlags *d,
|
||||
size_t m, const char *prefix, unsigned x) {
|
||||
bool t;
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
|
||||
dontasan unsigned __find_memory(const struct MemoryIntervals *mm, int x) {
|
||||
|
@ -31,6 +30,5 @@ dontasan unsigned __find_memory(const struct MemoryIntervals *mm, int x) {
|
|||
r = m;
|
||||
}
|
||||
}
|
||||
unassert(l == mm->i || x <= mm->p[l].y);
|
||||
return l;
|
||||
}
|
||||
|
|
|
@ -487,6 +487,10 @@ static errno_t CloneSilicon(int (*fn)(void *, int), char *stk, size_t stksz,
|
|||
if (!(res = __syslib->pthread_create(&th, 0, SiliconThreadMain, wt)) &&
|
||||
(flags & CLONE_PARENT_SETTID)) {
|
||||
*ptid = tid;
|
||||
if (flags & CLONE_SETTLS) {
|
||||
struct CosmoTib *tib = tls;
|
||||
tib[-1].tib_pthread = th;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ COSMOPOLITAN_C_START_
|
|||
*/
|
||||
|
||||
#define SYSLIB_MAGIC ('s' | 'l' << 8 | 'i' << 16 | 'b' << 24)
|
||||
#define SYSLIB_VERSION 1
|
||||
#define SYSLIB_VERSION 2
|
||||
|
||||
typedef uint64_t dispatch_time_t;
|
||||
typedef uint64_t dispatch_semaphore_t;
|
||||
|
@ -42,6 +42,8 @@ struct Syslib {
|
|||
long (*dispatch_semaphore_signal)(dispatch_semaphore_t);
|
||||
long (*dispatch_semaphore_wait)(dispatch_semaphore_t, dispatch_time_t);
|
||||
dispatch_time_t (*dispatch_walltime)(const struct timespec *, int64_t);
|
||||
/* v2 (2023-09-10) */
|
||||
long (*pthread_self)(void);
|
||||
};
|
||||
|
||||
extern struct Syslib *__syslib;
|
||||
|
|
|
@ -89,6 +89,8 @@ dos kNtErrorUnexpNetErr ECONNABORTED
|
|||
dos kNtErrorWorkingSetQuota ENOMEM
|
||||
dos kNtErrorWriteProtect EACCES
|
||||
dos kNtErrorWrongDisk EACCES
|
||||
dos kNtErrorExeMarkedInvalid ENOEXEC
|
||||
dos kNtErrorExeMachineTypeMismatch ENOEXEC
|
||||
dos WSAEACCES EACCES
|
||||
dos WSAEDISCON EPIPE
|
||||
dos WSAEFAULT EFAULT
|
||||
|
|
15
libc/sysv/dos2errno/ENOEXEC.S
Normal file
15
libc/sysv/dos2errno/ENOEXEC.S
Normal file
|
@ -0,0 +1,15 @@
|
|||
// generated by libc/sysv/dos2errno.sh
|
||||
#include "libc/nt/errors.h"
|
||||
#ifndef __x86_64__
|
||||
.end
|
||||
#endif
|
||||
.macro .e doscode systemv
|
||||
.short \doscode
|
||||
.long \systemv
|
||||
.endm
|
||||
.section .sort.rodata.dos2errno.2,"a",@progbits
|
||||
.globl kDos2Errno.ENOEXEC
|
||||
.type kDos2Errno.ENOEXEC,@object
|
||||
kDos2Errno.ENOEXEC:
|
||||
.e kNtErrorExeMarkedInvalid,ENOEXEC
|
||||
.e kNtErrorExeMachineTypeMismatch,ENOEXEC
|
|
@ -17,6 +17,8 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
|
@ -31,9 +33,24 @@ __static_yoink("zipos");
|
|||
*/
|
||||
void testlib_extract(const char *zip, const char *to, int mode) {
|
||||
int fdin, fdout;
|
||||
ASSERT_NE(-1, (fdin = open(zip, O_RDONLY)));
|
||||
ASSERT_NE(-1, (fdout = creat(to, mode)));
|
||||
ASSERT_NE(-1, copyfd(fdin, fdout, -1));
|
||||
ASSERT_NE(-1, close(fdout));
|
||||
ASSERT_NE(-1, close(fdin));
|
||||
if ((fdin = open(zip, O_RDONLY)) == -1) {
|
||||
perror(zip);
|
||||
exit(1);
|
||||
}
|
||||
if ((fdout = creat(to, mode)) == -1) {
|
||||
perror(to);
|
||||
exit(1);
|
||||
}
|
||||
if (copyfd(fdin, fdout, -1) == -1) {
|
||||
perror(zip);
|
||||
exit(1);
|
||||
}
|
||||
if (close(fdout)) {
|
||||
perror(to);
|
||||
exit(1);
|
||||
}
|
||||
if (close(fdin)) {
|
||||
perror(zip);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,6 +79,7 @@ struct PosixThread {
|
|||
char *tls; // bottom of tls allocation
|
||||
struct CosmoTib *tib; // middle of tls allocation
|
||||
struct Dll list; // list of threads
|
||||
pthread_t next; // for xnu silicon
|
||||
jmp_buf exiter; // for pthread_exit
|
||||
pthread_attr_t attr;
|
||||
struct _pthread_cleanup_buffer *cleanup;
|
||||
|
|
|
@ -78,6 +78,7 @@ static int PosixThread(void *arg, int tid) {
|
|||
}
|
||||
// set long jump handler so pthread_exit can bring control back here
|
||||
if (!setjmp(pt->exiter)) {
|
||||
pt->next = __get_tls()->tib_pthread;
|
||||
__get_tls()->tib_pthread = (pthread_t)pt;
|
||||
unassert(!sigprocmask(SIG_SETMASK, (sigset_t *)pt->attr.__sigmask, 0));
|
||||
rc = pt->start(pt->arg);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue