Get threads working well on MacOS Arm64

- Now using 10x better GCD semaphores
- We now generate Linux-like thread ids
- We now use fast system clock / sleep libraries
- The APE M1 loader now generates Linux-like stacks
This commit is contained in:
Justine Tunney 2023-06-04 01:57:10 -07:00
parent b5eab2b0b7
commit bcf9af94bf
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
2037 changed files with 4664 additions and 4451 deletions

View file

@ -16,53 +16,45 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <time.h> #include <dispatch/dispatch.h>
#include <fcntl.h>
#include <errno.h> #include <errno.h>
#include <stdarg.h> #include <fcntl.h>
#include <unistd.h> #include <libkern/OSCacheControl.h>
#include <signal.h>
#include <limits.h> #include <limits.h>
#include <pthread.h> #include <pthread.h>
#include <sys/uio.h> #include <signal.h>
#include <stdarg.h>
#include <stdint.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <libkern/OSCacheControl.h> #include <sys/random.h>
#include <sys/uio.h>
#include <time.h>
#include <unistd.h>
#define SYSLIB_MAGIC ('s' | 'l' << 8 | 'i' << 16 | 'b' << 24) #define SYSLIB_MAGIC ('s' | 'l' << 8 | 'i' << 16 | 'b' << 24)
#define SYSLIB_VERSION 0 #define SYSLIB_VERSION 1
struct Syslib { struct Syslib {
int magic; int magic;
int version; int version;
void (*exit)(int) __attribute__((__noreturn__));
long (*fork)(void); long (*fork)(void);
long (*read)(int, void *, size_t);
long (*pread)(int, void *, size_t, off_t);
long (*readv)(int, const struct iovec *, int);
long (*write)(int, const void *, size_t);
long (*pwrite)(int, const void *, size_t, off_t);
long (*writev)(int, const struct iovec *, int);
long (*openat)(int, const char *, int, ...);
long (*pipe)(int[2]); long (*pipe)(int[2]);
long (*close)(int);
long (*clock_gettime)(int, struct timespec *); long (*clock_gettime)(int, struct timespec *);
long (*nanosleep)(const struct timespec *, struct timespec *); long (*nanosleep)(const struct timespec *, struct timespec *);
long (*mmap)(void *, size_t, int, int, int, off_t); long (*mmap)(void *, size_t, int, int, int, off_t);
long (*sigaction)(int, const struct sigaction *restrict, struct sigaction *restrict);
int (*pthread_jit_write_protect_supported_np)(void); int (*pthread_jit_write_protect_supported_np)(void);
void (*pthread_jit_write_protect_np)(int); void (*pthread_jit_write_protect_np)(int);
void (*sys_icache_invalidate)(void *, size_t); void (*sys_icache_invalidate)(void *, size_t);
pthread_t (*pthread_self)(void); int (*pthread_create)(pthread_t *, const pthread_attr_t *, void *(*)(void *),
int (*pthread_create)(pthread_t *, const pthread_attr_t *, void *(*)(void *), void *); void *);
int (*pthread_detach)(pthread_t);
int (*pthread_join)(pthread_t, void **);
void (*pthread_exit)(void *); void (*pthread_exit)(void *);
int (*pthread_kill)(pthread_t, int); int (*pthread_kill)(pthread_t, int);
int (*pthread_sigmask)(int, const sigset_t *restrict, sigset_t *restrict); int (*pthread_sigmask)(int, const sigset_t *restrict, sigset_t *restrict);
int (*pthread_setname_np)(const char *); int (*pthread_setname_np)(const char *);
int (*pthread_key_create)(pthread_key_t *, void (*)(void *)); dispatch_semaphore_t (*dispatch_semaphore_create)(long);
int (*pthread_setspecific)(pthread_key_t, const void *); long (*dispatch_semaphore_signal)(dispatch_semaphore_t);
void *(*pthread_getspecific)(pthread_key_t); long (*dispatch_semaphore_wait)(dispatch_semaphore_t, dispatch_time_t);
dispatch_time_t (*dispatch_walltime)(const struct timespec *, int64_t);
}; };
#define TROUBLESHOOT 0 #define TROUBLESHOOT 0
@ -94,8 +86,9 @@ struct Syslib {
#define AT_RANDOM 25 #define AT_RANDOM 25
#define AT_EXECFN 31 #define AT_EXECFN 31
#define STACK_SIZE (8ul * 1024 * 1024)
#define STACK_ALIGN (sizeof(long) * 2) #define STACK_ALIGN (sizeof(long) * 2)
#define AUXV_BYTES (sizeof(long) * 2 * 14) #define AUXV_BYTES (sizeof(long) * 2 * 15)
// from the xnu codebase // from the xnu codebase
#define _COMM_PAGE_START_ADDRESS 0x0000000FFFFFC000ul #define _COMM_PAGE_START_ADDRESS 0x0000000FFFFFC000ul
@ -104,14 +97,12 @@ struct Syslib {
#define _COMM_PAGE_APRR_WRITE_DISABLE (_COMM_PAGE_START_ADDRESS + 0x118) #define _COMM_PAGE_APRR_WRITE_DISABLE (_COMM_PAGE_START_ADDRESS + 0x118)
#define Min(X, Y) ((Y) > (X) ? (X) : (Y)) #define Min(X, Y) ((Y) > (X) ? (X) : (Y))
#define Roundup(X, K) (((X) + (K) - 1) & -(K)) #define Roundup(X, K) (((X) + (K)-1) & -(K))
#define Rounddown(X, K) ((X) & -(K)) #define Rounddown(X, K) ((X) & -(K))
#define Read32(S) \ #define Read32(S) \
((unsigned)(255 & (S)[3]) << 030 | \ ((unsigned)(255 & (S)[3]) << 030 | (unsigned)(255 & (S)[2]) << 020 | \
(unsigned)(255 & (S)[2]) << 020 | \ (unsigned)(255 & (S)[1]) << 010 | (unsigned)(255 & (S)[0]) << 000)
(unsigned)(255 & (S)[1]) << 010 | \
(unsigned)(255 & (S)[0]) << 000)
#define Read64(S) \ #define Read64(S) \
((unsigned long)(255 & (S)[7]) << 070 | \ ((unsigned long)(255 & (S)[7]) << 070 | \
@ -123,13 +114,6 @@ struct Syslib {
(unsigned long)(255 & (S)[1]) << 010 | \ (unsigned long)(255 & (S)[1]) << 010 | \
(unsigned long)(255 & (S)[0]) << 000) (unsigned long)(255 & (S)[0]) << 000)
struct PathSearcher {
unsigned long namelen;
const char *name;
const char *syspath;
char path[1024];
};
struct ElfEhdr { struct ElfEhdr {
unsigned char e_ident[16]; unsigned char e_ident[16];
unsigned short e_type; unsigned short e_type;
@ -168,10 +152,44 @@ union ElfPhdrBuf {
char buf[0x1000]; char buf[0x1000];
}; };
struct PathSearcher {
unsigned long namelen;
const char *name;
const char *syspath;
char path[1024];
};
struct ApeLoader {
union ElfEhdrBuf ehdr;
struct PathSearcher ps;
// this memory shall be discarded by the guest
//////////////////////////////////////////////
// this memory shall be known to guest program
union {
char argblock[ARG_MAX];
long numblock[ARG_MAX / sizeof(long)];
};
union ElfPhdrBuf phdr;
struct Syslib lib;
char rando[16];
};
static int ToLower(int c) { static int ToLower(int c) {
return 'A' <= c && c <= 'Z' ? c + ('a' - 'A') : c; return 'A' <= c && c <= 'Z' ? c + ('a' - 'A') : c;
} }
static unsigned long StrLen(const char *s) {
unsigned long n = 0;
while (*s++) ++n;
return n;
}
static int StrCmp(const char *l, const char *r) {
unsigned long i = 0;
while (l[i] == r[i] && r[i]) ++i;
return (l[i] & 255) - (r[i] & 255);
}
static void *MemSet(void *a, int c, unsigned long n) { static void *MemSet(void *a, int c, unsigned long n) {
char *d = a; char *d = a;
unsigned long i; unsigned long i;
@ -197,12 +215,6 @@ static void *MemMove(void *a, const void *b, unsigned long n) {
return d; return d;
} }
static unsigned long StrLen(const char *s) {
unsigned long n = 0;
while (*s++) ++n;
return n;
}
static const char *MemChr(const char *s, unsigned char c, unsigned long n) { static const char *MemChr(const char *s, unsigned char c, unsigned long n) {
for (; n; --n, ++s) { for (; n; --n, ++s) {
if ((*s & 255) == c) { if ((*s & 255) == c) {
@ -267,6 +279,7 @@ static void Perror(const char *c, int failed, const char *s) {
Emit(": "); Emit(": ");
Emit(s); Emit(s);
if (failed) { if (failed) {
#include <sys/random.h>
Emit(" failed errno="); Emit(" failed errno=");
Itoa(ibuf, errno); Itoa(ibuf, errno);
Emit(ibuf); Emit(ibuf);
@ -274,18 +287,12 @@ static void Perror(const char *c, int failed, const char *s) {
Emit("\n"); Emit("\n");
} }
__attribute__((__noreturn__)) __attribute__((__noreturn__)) static void Pexit(const char *c, int failed,
static void Pexit(const char *c, int failed, const char *s) { const char *s) {
Perror(c, failed, s); Perror(c, failed, s);
_exit(127); _exit(127);
} }
static int StrCmp(const char *l, const char *r) {
unsigned long i = 0;
while (l[i] == r[i] && r[i]) ++i;
return (l[i] & 255) - (r[i] & 255);
}
static char EndsWithIgnoreCase(const char *p, unsigned long n, const char *s) { static char EndsWithIgnoreCase(const char *p, unsigned long n, const char *s) {
unsigned long i, m; unsigned long i, m;
if (n >= (m = StrLen(s))) { if (n >= (m = StrLen(s))) {
@ -347,8 +354,7 @@ static char FindCommand(struct PathSearcher *ps, const char *suffix) {
return SearchPath(ps, suffix); return SearchPath(ps, suffix);
} }
static char *Commandv(struct PathSearcher *ps, static char *Commandv(struct PathSearcher *ps, const char *name,
const char *name,
const char *syspath) { const char *syspath) {
ps->syspath = syspath ? syspath : "/bin:/usr/local/bin:/usr/bin"; ps->syspath = syspath ? syspath : "/bin:/usr/local/bin:/usr/bin";
if (!(ps->namelen = StrLen((ps->name = name)))) return 0; if (!(ps->namelen = StrLen((ps->name = name)))) return 0;
@ -416,15 +422,14 @@ static void pthread_jit_write_protect_np_workaround(int enabled) {
Pexit("ape-m1", 0, "failed to set jit write protection"); Pexit("ape-m1", 0, "failed to set jit write protection");
} }
__attribute__((__noreturn__)) __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
static void Spawn(const char *exe, long *sp, struct ElfEhdr *e,
int fd, long *sp,
struct ElfEhdr *e,
struct ElfPhdr *p, struct ElfPhdr *p,
struct Syslib *lib) { struct Syslib *lib) {
int prot, flags; int prot, flags;
long code, codesize; long code, codesize;
unsigned long a, b, i; unsigned long a, b, i;
code = 0; code = 0;
codesize = 0; codesize = 0;
for (i = e->e_phnum; i--;) { for (i = e->e_phnum; i--;) {
@ -460,8 +465,8 @@ static void Spawn(const char *exe,
codesize = p[i].p_filesz; codesize = p[i].p_filesz;
} }
if (p[i].p_filesz) { if (p[i].p_filesz) {
if (mmap((char *)p[i].p_vaddr, p[i].p_filesz, prot, if (mmap((char *)p[i].p_vaddr, p[i].p_filesz, prot, flags, fd,
flags, fd, p[i].p_offset) == MAP_FAILED) { p[i].p_offset) == MAP_FAILED) {
Pexit(exe, -1, "image mmap()"); Pexit(exe, -1, "image mmap()");
} }
if ((a = Min(-p[i].p_filesz & 0x3fff, p[i].p_memsz - p[i].p_filesz))) { if ((a = Min(-p[i].p_filesz & 0x3fff, p[i].p_memsz - p[i].p_filesz))) {
@ -470,8 +475,8 @@ static void Spawn(const char *exe,
} }
if ((b = Roundup(p[i].p_memsz, 0x4000)) > if ((b = Roundup(p[i].p_memsz, 0x4000)) >
(a = Roundup(p[i].p_filesz, 0x4000))) { (a = Roundup(p[i].p_filesz, 0x4000))) {
if (mmap((char *)p[i].p_vaddr + a, b - a, if (mmap((char *)p[i].p_vaddr + a, b - a, prot, flags | MAP_ANONYMOUS, -1,
prot, flags | MAP_ANONYMOUS, -1, 0) == MAP_FAILED) { 0) == MAP_FAILED) {
Pexit(exe, -1, "bss mmap()"); Pexit(exe, -1, "bss mmap()");
} }
} }
@ -521,21 +526,21 @@ static void Spawn(const char *exe,
__builtin_unreachable(); __builtin_unreachable();
} }
static void TryElf(const char *exe, int fd, long *sp, long *bp, char *execfn, static void TryElf(struct ApeLoader *M, const char *exe, int fd, long *sp,
union ElfEhdrBuf *ehdr, union ElfPhdrBuf *phdr, struct Syslib *lib) { long *bp, char *execfn) {
unsigned long n; unsigned long n;
if (Read32(ehdr->buf) == Read32("\177ELF") && if (Read32(M->ehdr.buf) == Read32("\177ELF") &&
ehdr->ehdr.e_type == ET_EXEC && M->ehdr.ehdr.e_type == ET_EXEC && M->ehdr.ehdr.e_machine == EM_AARCH64 &&
ehdr->ehdr.e_machine == EM_AARCH64 && M->ehdr.ehdr.e_ident[EI_CLASS] == ELFCLASS64 &&
ehdr->ehdr.e_ident[EI_CLASS] == ELFCLASS64 && M->ehdr.ehdr.e_ident[EI_DATA] == ELFDATA2LSB &&
ehdr->ehdr.e_ident[EI_DATA] == ELFDATA2LSB && (n = M->ehdr.ehdr.e_phnum * sizeof(M->phdr.phdr)) <=
(n = ehdr->ehdr.e_phnum * sizeof(phdr->phdr)) <= sizeof(phdr->buf) && sizeof(M->phdr.buf) &&
pread(fd, phdr->buf, n, ehdr->ehdr.e_phoff) == n) { pread(fd, M->phdr.buf, n, M->ehdr.ehdr.e_phoff) == n) {
long auxv[][2] = { long auxv[][2] = {
{AT_PHDR, (long)&phdr->phdr}, // {AT_PHDR, (long)&M->phdr.phdr}, //
{AT_PHENT, ehdr->ehdr.e_phentsize}, // {AT_PHENT, M->ehdr.ehdr.e_phentsize}, //
{AT_PHNUM, ehdr->ehdr.e_phnum}, // {AT_PHNUM, M->ehdr.ehdr.e_phnum}, //
{AT_ENTRY, ehdr->ehdr.e_entry}, // {AT_ENTRY, M->ehdr.ehdr.e_entry}, //
{AT_PAGESZ, 0x4000}, // {AT_PAGESZ, 0x4000}, //
{AT_UID, getuid()}, // {AT_UID, getuid()}, //
{AT_EUID, geteuid()}, // {AT_EUID, geteuid()}, //
@ -544,18 +549,18 @@ static void TryElf(const char *exe, int fd, long *sp, long *bp, char *execfn,
{AT_HWCAP, 0xffb3ffffu}, // {AT_HWCAP, 0xffb3ffffu}, //
{AT_HWCAP2, 0x181}, // {AT_HWCAP2, 0x181}, //
{AT_SECURE, issetugid()}, // {AT_SECURE, issetugid()}, //
{AT_RANDOM, (long)M->rando}, //
{AT_EXECFN, (long)execfn}, // {AT_EXECFN, (long)execfn}, //
{0, 0}, // {0, 0}, //
}; };
_Static_assert(sizeof(auxv) == AUXV_BYTES, _Static_assert(sizeof(auxv) == AUXV_BYTES,
"Please update the AUXV_BYTES constant"); "Please update the AUXV_BYTES constant");
MemMove(bp, auxv, sizeof(auxv)); MemMove(bp, auxv, sizeof(auxv));
Spawn(exe, fd, sp, &ehdr->ehdr, &phdr->phdr, lib); Spawn(exe, fd, sp, &M->ehdr.ehdr, &M->phdr.phdr, &M->lib);
} }
} }
__attribute__((__noinline__)) __attribute__((__noinline__)) static long sysret(long rc) {
static long sysret(long rc) {
return rc == -1 ? -errno : rc; return rc == -1 ? -errno : rc;
} }
@ -563,47 +568,10 @@ static long sys_fork(void) {
return sysret(fork()); return sysret(fork());
} }
static long sys_read(int fd, void *p, size_t n) {
return sysret(read(fd, p, n));
}
static long sys_pread(int fd, void *p, size_t n, off_t o) {
return sysret(pread(fd, p, n, o));
}
static long sys_readv(int fd, const struct iovec *p, int n) {
return sysret(readv(fd, p, n));
}
static long sys_write(int fd, const void *p, size_t n) {
return sysret(write(fd, p, n));
}
static long sys_pwrite(int fd, const void *p, size_t n, off_t o) {
return sysret(pwrite(fd, p, n, o));
}
static long sys_writev(int fd, const struct iovec *p, int n) {
return sysret(writev(fd, p, n));
}
static long sys_openat(int dirfd, const char *path, int oflag, ...) {
va_list va;
unsigned mode;
va_start(va, oflag);
mode = va_arg(va, unsigned);
va_end(va);
return sysret(openat(dirfd, path, oflag, mode));
}
static long sys_pipe(int pfds[2]) { static long sys_pipe(int pfds[2]) {
return sysret(pipe(pfds)); return sysret(pipe(pfds));
} }
static long sys_close(int fd) {
return sysret(close(fd));
}
static long sys_clock_gettime(int clock, struct timespec *ts) { static long sys_clock_gettime(int clock, struct timespec *ts) {
return sysret(clock_gettime(clock, ts)); return sysret(clock_gettime(clock, ts));
} }
@ -612,69 +580,62 @@ static long sys_nanosleep(const struct timespec *req, struct timespec *rem) {
return sysret(nanosleep(req, rem)); return sysret(nanosleep(req, rem));
} }
static long sys_mmap(void *addr, size_t size, int prot, int flags, int fd, off_t off) { static long sys_mmap(void *addr, size_t size, int prot, int flags, int fd,
off_t off) {
return sysret((long)mmap(addr, size, prot, flags, fd, off)); return sysret((long)mmap(addr, size, prot, flags, fd, off));
} }
static long sys_sigaction(int sig, const struct sigaction *restrict act, int main(int argc, char **argv, char **envp) {
struct sigaction *restrict oact) { long z;
return sysret(sigaction(sig, act, oact)); void *map;
}
int loader(int argc, char **argv, char **envp) {
long *sp, *bp, *ip; long *sp, *bp, *ip;
int c, i, n, fd, rc; int c, i, n, fd, rc;
struct ApeLoader *M;
unsigned char rando[24];
char *p, *tp, *exe, *prog, *execfn; char *p, *tp, *exe, *prog, *execfn;
struct { // generate some hard random data
union ElfEhdrBuf ehdr; if (getentropy(rando, sizeof(rando))) {
struct PathSearcher ps; Pexit(argv[0], -1, "getentropy");
// this memory shall be discarded by the guest }
//////////////////////////////////////////////
// this memory shall be known to guest program
union {
char argblock[ARG_MAX];
long numblock[ARG_MAX / sizeof(long)];
};
union ElfPhdrBuf phdr;
struct Syslib lib;
} M;
// expose some apple libraries // make the stack look like a linux one
M.lib.magic = SYSLIB_MAGIC; map = mmap((void *)(0x7f0000000000 | (long)rando[23] << 32), STACK_SIZE,
M.lib.version = SYSLIB_VERSION; PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
M.lib.exit = _exit; if (map == MAP_FAILED) {
M.lib.fork = sys_fork; Pexit(argv[0], -1, "stack mmap");
M.lib.read = sys_read; }
M.lib.pread = sys_pread;
M.lib.readv = sys_readv; // put argument block at top of allocated stack
M.lib.write = sys_write; z = (long)map;
M.lib.pwrite = sys_pwrite; z += STACK_SIZE - sizeof(struct ApeLoader);
M.lib.writev = sys_writev; z &= -_Alignof(struct ApeLoader);
M.lib.openat = sys_openat; M = (struct ApeLoader *)z;
M.lib.close = sys_close;
M.lib.clock_gettime = sys_clock_gettime; // expose screwy apple libs
M.lib.nanosleep = sys_nanosleep; M->lib.magic = SYSLIB_MAGIC;
M.lib.mmap = sys_mmap; M->lib.version = SYSLIB_VERSION;
M.lib.sigaction = sys_sigaction; M->lib.fork = sys_fork;
M.lib.pthread_jit_write_protect_supported_np = M->lib.pipe = sys_pipe;
M->lib.clock_gettime = sys_clock_gettime;
M->lib.nanosleep = sys_nanosleep;
M->lib.mmap = sys_mmap;
M->lib.pthread_jit_write_protect_supported_np =
pthread_jit_write_protect_supported_np; pthread_jit_write_protect_supported_np;
M.lib.pthread_jit_write_protect_np = M->lib.pthread_jit_write_protect_np = pthread_jit_write_protect_np_workaround;
pthread_jit_write_protect_np_workaround; M->lib.pthread_create = pthread_create;
M.lib.pthread_self = pthread_self; M->lib.pthread_exit = pthread_exit;
M.lib.pthread_create = pthread_create; M->lib.pthread_kill = pthread_kill;
M.lib.pthread_join = pthread_join; M->lib.pthread_sigmask = pthread_sigmask;
M.lib.pthread_exit = pthread_exit; M->lib.pthread_setname_np = pthread_setname_np;
M.lib.pthread_kill = pthread_kill; M->lib.dispatch_semaphore_create = dispatch_semaphore_create;
M.lib.pthread_sigmask = pthread_sigmask; M->lib.dispatch_semaphore_signal = dispatch_semaphore_signal;
M.lib.pthread_setname_np = pthread_setname_np; M->lib.dispatch_semaphore_wait = dispatch_semaphore_wait;
M.lib.pthread_key_create = pthread_key_create; M->lib.dispatch_walltime = dispatch_walltime;
M.lib.pthread_getspecific = pthread_getspecific;
M.lib.pthread_setspecific = pthread_setspecific;
// copy system provided argument block // copy system provided argument block
bp = M.numblock; bp = M->numblock;
tp = M.argblock + sizeof(M.argblock); tp = M->argblock + sizeof(M->argblock);
*bp++ = argc; *bp++ = argc;
for (i = 0; i < argc; ++i) { for (i = 0; i < argc; ++i) {
tp -= (n = StrLen(argv[i]) + 1); tp -= (n = StrLen(argv[i]) + 1);
@ -690,7 +651,7 @@ int loader(int argc, char **argv, char **envp) {
*bp++ = 0; *bp++ = 0;
// get arguments that point into our block // get arguments that point into our block
sp = M.numblock; sp = M->numblock;
argc = *sp; argc = *sp;
argv = (char **)(sp + 1); argv = (char **)(sp + 1);
envp = (char **)(sp + 1 + argc + 1); envp = (char **)(sp + 1 + argc + 1);
@ -734,14 +695,18 @@ int loader(int argc, char **argv, char **envp) {
bp = ip + n; bp = ip + n;
sp = ip; sp = ip;
// relocate the guest's random numbers
MemMove(M->rando, rando, sizeof(M->rando));
MemSet(rando, 0, sizeof(rando));
// search for executable // search for executable
if (!(exe = Commandv(&M.ps, prog, GetEnv(envp, "PATH")))) { if (!(exe = Commandv(&M->ps, prog, GetEnv(envp, "PATH")))) {
Pexit(prog, 0, "not found (maybe chmod +x)"); Pexit(prog, 0, "not found (maybe chmod +x)");
} else if ((fd = openat(AT_FDCWD, exe, O_RDONLY)) < 0) { } else if ((fd = openat(AT_FDCWD, exe, O_RDONLY)) < 0) {
Pexit(exe, -1, "open"); Pexit(exe, -1, "open");
} else if ((rc = read(fd, M.ehdr.buf, sizeof(M.ehdr.buf))) < 0) { } else if ((rc = read(fd, M->ehdr.buf, sizeof(M->ehdr.buf))) < 0) {
Pexit(exe, -1, "read"); Pexit(exe, -1, "read");
} else if (rc != sizeof(M.ehdr.buf)) { } else if (rc != sizeof(M->ehdr.buf)) {
Pexit(exe, 0, "too small"); Pexit(exe, 0, "too small");
} }
@ -759,13 +724,14 @@ int loader(int argc, char **argv, char **envp) {
// 3. shell script may have multiple lines producing elf headers // 3. shell script may have multiple lines producing elf headers
// 4. all elf printf lines must exist in the first 4096 bytes of file // 4. all elf printf lines must exist in the first 4096 bytes of file
// 5. elf program headers may appear anywhere in the binary // 5. elf program headers may appear anywhere in the binary
if (Read64(M.ehdr.buf) == Read64("MZqFpD='") || if (Read64(M->ehdr.buf) == Read64("MZqFpD='") ||
Read64(M.ehdr.buf) == Read64("jartsr='")) { Read64(M->ehdr.buf) == Read64("jartsr='")) {
for (p = M.ehdr.buf; p < M.ehdr.buf + sizeof(M.ehdr.buf); ++p) { for (p = M->ehdr.buf; p < M->ehdr.buf + sizeof(M->ehdr.buf); ++p) {
if (Read64(p) != Read64("printf '")) { if (Read64(p) != Read64("printf '")) {
continue; continue;
} }
for (i = 0, p += 8; p + 3 < M.ehdr.buf + sizeof(M.ehdr.buf) && (c = *p++) != '\'';) { for (i = 0, p += 8;
p + 3 < M->ehdr.buf + sizeof(M->ehdr.buf) && (c = *p++) != '\'';) {
if (c == '\\') { if (c == '\\') {
if ('0' <= *p && *p <= '7') { if ('0' <= *p && *p <= '7') {
c = *p++ - '0'; c = *p++ - '0';
@ -779,22 +745,13 @@ int loader(int argc, char **argv, char **envp) {
} }
} }
} }
M.ehdr.buf[i++] = c; M->ehdr.buf[i++] = c;
} }
if (i >= sizeof(M.ehdr.ehdr)) { if (i >= sizeof(M->ehdr.ehdr)) {
TryElf(exe, fd, sp, bp, execfn, &M.ehdr, &M.phdr, &M.lib); TryElf(M, exe, fd, sp, bp, execfn);
} }
} }
} }
TryElf(exe, fd, sp, bp, execfn, &M.ehdr, &M.phdr, &M.lib); TryElf(M, exe, fd, sp, bp, execfn);
Pexit(exe, 0, "Not an acceptable APE/ELF executable for AARCH64"); Pexit(exe, 0, "Not an acceptable APE/ELF executable for AARCH64");
} }
asm(".globl\t_main\n_main:\t"
"stp\tx29,x30,[sp,#-16]!\n\t"
"mov\tx29,sp\n\t"
"mov\tx9,sp\n\t"
"and\tsp,x9,#-(2*1024*1024)\n\t"
"bl\t_loader\n\t"
"ldp\tx29,x30,[sp],#16\n\t"
"ret");

View file

@ -0,0 +1,26 @@
/*-*- 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 2022 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/struct/timespec.h"
#include "libc/calls/struct/timespec.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/runtime/syslib.internal.h"
int sys_clock_gettime_m1(int clock, struct timespec *ts) {
return _sysret(__syslib->clock_gettime(clock, ts));
}

View file

@ -110,8 +110,15 @@ clock_gettime_f *__clock_gettime_get(bool *opt_out_isfast) {
if (IsLinux() && (res = CGT_VDSO)) { if (IsLinux() && (res = CGT_VDSO)) {
isfast = true; isfast = true;
} else if (IsXnu()) { } else if (IsXnu()) {
isfast = false; #ifdef __x86_64__
res = sys_clock_gettime_xnu; res = sys_clock_gettime_xnu;
isfast = false;
#elif defined(__aarch64__)
res = sys_clock_gettime_m1;
isfast = true;
#else
#error "unsupported architecture"
#endif
} else if (IsWindows()) { } else if (IsWindows()) {
isfast = true; isfast = true;
res = sys_clock_gettime_nt; res = sys_clock_gettime_nt;

View file

@ -16,10 +16,13 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/struct/timespec.h"
#include "libc/calls/struct/timespec.internal.h" #include "libc/calls/struct/timespec.internal.h"
#include "libc/calls/struct/timeval.h" #include "libc/calls/struct/timeval.h"
#include "libc/calls/struct/timeval.internal.h" #include "libc/calls/struct/timeval.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/fmt/conv.h" #include "libc/fmt/conv.h"
#include "libc/runtime/syslib.internal.h"
#include "libc/sock/internal.h" #include "libc/sock/internal.h"
#include "libc/sysv/consts/clock.h" #include "libc/sysv/consts/clock.h"
#include "libc/sysv/consts/timer.h" #include "libc/sysv/consts/timer.h"
@ -27,23 +30,38 @@
int sys_clock_nanosleep_xnu(int clock, int flags, const struct timespec *req, int sys_clock_nanosleep_xnu(int clock, int flags, const struct timespec *req,
struct timespec *rem) { struct timespec *rem) {
int res; #ifdef __x86_64__
struct timeval now, abs, rel; struct timeval abs, now, rel;
if (clock == CLOCK_REALTIME) { if (clock == CLOCK_REALTIME) {
if (flags & TIMER_ABSTIME) { if (flags & TIMER_ABSTIME) {
abs = timespec_totimeval(*req); abs = timespec_totimeval(*req);
sys_gettimeofday_xnu(&now, 0, 0); sys_gettimeofday_xnu(&now, 0, 0);
if (timeval_cmp(abs, now) > 0) { if (timeval_cmp(abs, now) > 0) {
rel = timeval_sub(abs, now); rel = timeval_sub(abs, now);
res = sys_select(0, 0, 0, 0, &rel); return sys_select(0, 0, 0, 0, &rel);
} else { } else {
res = 0; return 0;
} }
} else { } else {
res = sys_nanosleep_xnu(req, rem); return sys_nanosleep_xnu(req, rem);
} }
} else { } else {
res = enotsup(); return enotsup();
} }
return res; #else
long res;
struct timespec abs, now, rel;
if (flags & TIMER_ABSTIME) {
abs = *req;
if (!(res = __syslib->clock_gettime(clock, &now))) {
if (timespec_cmp(abs, now) > 0) {
rel = timespec_sub(abs, now);
res = __syslib->nanosleep(&rel, 0);
}
}
} else {
res = __syslib->nanosleep(req, rem);
}
return _sysret(res);
#endif
} }

View file

@ -0,0 +1,35 @@
/*-*- 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 2020 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/struct/timespec.h"
#include "libc/calls/struct/timeval.h"
#include "libc/calls/struct/timeval.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/runtime/syslib.internal.h"
#include "libc/sysv/consts/clock.h"
axdx_t sys_gettimeofday_m1(struct timeval *tv, struct timezone *tz, void *wut) {
axdx_t ad;
struct timespec ts;
ad.ax = _sysret(__syslib->clock_gettime(CLOCK_REALTIME, &ts));
ad.dx = 0;
if (!ad.ax && tv) {
*tv = timespec_totimeval(ts);
}
return ad;
}

View file

@ -82,8 +82,15 @@ gettimeofday_f *__gettimeofday_get(bool *opt_out_isfast) {
isfast = true; isfast = true;
res = sys_gettimeofday_nt; res = sys_gettimeofday_nt;
} else if (IsXnu()) { } else if (IsXnu()) {
isfast = false; #ifdef __x86_64__
res = sys_gettimeofday_xnu; res = sys_gettimeofday_xnu;
isfast = false;
#elif defined(__aarch64__)
res = sys_gettimeofday_m1;
isfast = true;
#else
#error "unsupported architecture"
#endif
} else if (IsMetal()) { } else if (IsMetal()) {
isfast = false; isfast = false;
res = sys_gettimeofday_metal; res = sys_gettimeofday_metal;

View file

@ -20,24 +20,21 @@
#include "libc/calls/struct/timespec.internal.h" #include "libc/calls/struct/timespec.internal.h"
#include "libc/calls/struct/timeval.h" #include "libc/calls/struct/timeval.h"
#include "libc/calls/struct/timeval.internal.h" #include "libc/calls/struct/timeval.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/runtime/syslib.internal.h"
#include "libc/sock/internal.h" #include "libc/sock/internal.h"
// nanosleep() on xnu: a bloodbath of a polyfill // nanosleep() on xnu: a bloodbath of a polyfill
// consider using clock_nanosleep(TIMER_ABSTIME) // consider using clock_nanosleep(TIMER_ABSTIME)
int sys_nanosleep_xnu(const struct timespec *req, struct timespec *rem) { int sys_nanosleep_xnu(const struct timespec *req, struct timespec *rem) {
#ifdef __x86_64__
int rc; int rc;
struct timeval wt, t1, t2, td; struct timeval wt, t1, t2, td;
if (rem) sys_gettimeofday_xnu(&t1, 0, 0); if (rem) sys_gettimeofday_xnu(&t1, 0, 0);
wt = timespec_totimeval(*req); // rounds up wt = timespec_totimeval(*req); // rounds up
rc = sys_select(0, 0, 0, 0, &wt); rc = sys_select(0, 0, 0, 0, &wt);
if (rem) { if (rem && rc == -1 && errno == EINTR) {
if (!rc) {
rem->tv_sec = 0;
rem->tv_nsec = 0;
} else if (rc == -1 && errno == EINTR) {
// xnu select() doesn't modify timeout
// so we need, yet another system call
sys_gettimeofday_xnu(&t2, 0, 0); sys_gettimeofday_xnu(&t2, 0, 0);
td = timeval_sub(t2, t1); td = timeval_sub(t2, t1);
if (timeval_cmp(td, wt) >= 0) { if (timeval_cmp(td, wt) >= 0) {
@ -47,6 +44,8 @@ int sys_nanosleep_xnu(const struct timespec *req, struct timespec *rem) {
*rem = timeval_totimespec(timeval_sub(wt, td)); *rem = timeval_totimespec(timeval_sub(wt, td));
} }
} }
}
return rc; return rc;
#else
return _sysret(__syslib->nanosleep(req, rem));
#endif
} }

View file

@ -12,6 +12,7 @@ int __utimens(int, const char *, const struct timespec[2], int) _Hide;
int sys_clock_getres(int, struct timespec *) _Hide; int sys_clock_getres(int, struct timespec *) _Hide;
int sys_clock_gettime(int, struct timespec *) _Hide; int sys_clock_gettime(int, struct timespec *) _Hide;
int sys_clock_gettime_nt(int, struct timespec *) _Hide; int sys_clock_gettime_nt(int, struct timespec *) _Hide;
int sys_clock_gettime_m1(int, struct timespec *) _Hide;
int sys_clock_gettime_xnu(int, struct timespec *) _Hide; int sys_clock_gettime_xnu(int, struct timespec *) _Hide;
int sys_clock_nanosleep_nt(int, int, const struct timespec *, struct timespec *) _Hide; int sys_clock_nanosleep_nt(int, int, const struct timespec *, struct timespec *) _Hide;
int sys_clock_nanosleep_openbsd(int, int, const struct timespec *, struct timespec *) _Hide; int sys_clock_nanosleep_openbsd(int, int, const struct timespec *, struct timespec *) _Hide;

View file

@ -9,6 +9,7 @@ axdx_t sys_gettimeofday(struct timeval *, struct timezone *, void *) _Hide;
int sys_futimes(int, const struct timeval *) _Hide; int sys_futimes(int, const struct timeval *) _Hide;
int sys_lutimes(const char *, const struct timeval *) _Hide; int sys_lutimes(const char *, const struct timeval *) _Hide;
int sys_utimes(const char *, const struct timeval *) _Hide; int sys_utimes(const char *, const struct timeval *) _Hide;
axdx_t sys_gettimeofday_m1(struct timeval *, struct timezone *, void *) _Hide;
axdx_t sys_gettimeofday_xnu(struct timeval *, struct timezone *, void *) _Hide; axdx_t sys_gettimeofday_xnu(struct timeval *, struct timezone *, void *) _Hide;
axdx_t sys_gettimeofday_nt(struct timeval *, struct timezone *, void *) _Hide; axdx_t sys_gettimeofday_nt(struct timeval *, struct timezone *, void *) _Hide;
int sys_utimes_nt(const char *, const struct timeval[2]) _Hide; int sys_utimes_nt(const char *, const struct timeval[2]) _Hide;

View file

@ -66,6 +66,12 @@
#define IsAsan() 0 #define IsAsan() 0
#endif #endif
#ifdef __aarch64__
#define IsXnuSilicon() IsXnu()
#else
#define IsXnuSilicon() 0
#endif
#if defined(__PIE__) || defined(__PIC__) #if defined(__PIE__) || defined(__PIC__)
#define IsPositionIndependent() 1 #define IsPositionIndependent() 1
#else #else

View file

@ -29,6 +29,7 @@
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/runtime/symbols.internal.h" #include "libc/runtime/symbols.internal.h"
#include "libc/thread/thread.h" #include "libc/thread/thread.h"
#include "libc/thread/tls.h"
relegated void __assert_fail(const char *expr, const char *file, int line) { relegated void __assert_fail(const char *expr, const char *file, int line) {
int me, owner; int me, owner;
@ -37,7 +38,7 @@ relegated void __assert_fail(const char *expr, const char *file, int line) {
strace_enabled(-1); strace_enabled(-1);
ftrace_enabled(-1); ftrace_enabled(-1);
owner = 0; owner = 0;
me = sys_gettid(); me = __tls_enabled ? __get_tls()->tib_tid : sys_gettid();
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0);
kprintf("%s:%d: assert(%s) failed (tid %d) %m\n", file, line, expr, me); kprintf("%s:%d: assert(%s) failed (tid %d) %m\n", file, line, expr, me);
if (__vforked || if (__vforked ||

View file

@ -20,6 +20,7 @@
#include "libc/intrin/asmflag.h" #include "libc/intrin/asmflag.h"
#include "libc/nt/thread.h" #include "libc/nt/thread.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/runtime/syslib.internal.h"
#include "libc/sysv/consts/nr.h" #include "libc/sysv/consts/nr.h"
#include "libc/thread/tls.h" #include "libc/thread/tls.h"
@ -74,13 +75,16 @@ privileged wontreturn void _Exit1(int rc) {
} }
notpossible; notpossible;
#elif defined(__aarch64__) #elif defined(__aarch64__)
if (IsLinux()) {
register long r0 asm("x0") = rc; register long r0 asm("x0") = rc;
asm volatile("mov\tx8,%0\n\t" asm volatile("mov\tx8,%0\n\t"
"mov\tx16,%1\n\t"
"svc\t0" "svc\t0"
: /* no outputs */ : /* no outputs */
: "i"(93), "i"(0x169), "r"(r0) : "i"(93), "r"(r0)
: "x8", "memory"); : "x8", "memory");
} else if (IsXnu()) {
__syslib->pthread_exit(0);
}
notpossible; notpossible;
#else #else
#error "arch unsupported" #error "arch unsupported"

View file

@ -227,8 +227,8 @@ privileged dontinline void klog(const char *b, size_t n) {
register long r0 asm("x0") = (long)2; register long r0 asm("x0") = (long)2;
register long r1 asm("x1") = (long)b; register long r1 asm("x1") = (long)b;
register long r2 asm("x2") = (long)n; register long r2 asm("x2") = (long)n;
register long r8 asm("x8") = (long)__NR_write & 0x7ff; register long r8 asm("x8") = (long)__NR_write;
register long r16 asm("x16") = (long)__NR_write & 0x7ff; register long r16 asm("x16") = (long)__NR_write;
register long res_x0 asm("x0"); register long res_x0 asm("x0");
asm volatile("svc\t0" asm volatile("svc\t0"
: "=r"(res_x0) : "=r"(res_x0)

View file

@ -90,13 +90,18 @@ sched_yield:
#elif defined(__aarch64__) #elif defined(__aarch64__)
mov x0,#0 stp x29,x30,[sp,-32]!
mov x1,#0 mov x29,sp
mov x2,#0 mov x3,0
mov x3,#0 mov x2,0
mov x8,#0x7c // sched_yield() for linux add x4,sp,16
mov x16,#0x85d // select(0,0,0,0) for xnu mov x1,0
mov w0,0
stp xzr,xzr,[sp,16]
mov x8,#0x7c // sched_yield() for gnu/systemd
mov x16,#0x5d // select(0,0,0,0,&blah) for xnu
svc 0 svc 0
ldp x29,x30,[sp],32
ret ret
#else #else

View file

@ -63,14 +63,15 @@ privileged int sys_gettid(void) {
} }
return tid; return tid;
#elif defined(__aarch64__) #elif defined(__aarch64__)
register long res_x0 asm("x0"); // this can't be used on xnu
if (!IsLinux()) notpossible;
register long res asm("x0");
asm volatile("mov\tx8,%1\n\t" asm volatile("mov\tx8,%1\n\t"
"mov\tx16,%2\n\t"
"svc\t0" "svc\t0"
: "=r"(res_x0) : "=r"(res)
: "i"(178), "i"(186) : "i"(178)
: "x8", "memory"); : "x8", "memory");
return res_x0; return res;
#else #else
#error "arch unsupported" #error "arch unsupported"
#endif #endif

View file

@ -45,7 +45,7 @@ relegated wontreturn void __die(void) {
int me, owner; int me, owner;
static atomic_int once; static atomic_int once;
owner = 0; owner = 0;
me = sys_gettid(); me = __tls_enabled ? __get_tls()->tib_tid : sys_gettid();
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0);
if (__vforked || if (__vforked ||
atomic_compare_exchange_strong_explicit( atomic_compare_exchange_strong_explicit(

View file

@ -270,7 +270,7 @@ static wontreturn relegated noinstrument void __minicrash(int sig,
"\n", "\n",
kind, sig, __argv[0], ctx ? ctx->uc_mcontext.rip : 0, kind, sig, __argv[0], ctx ? ctx->uc_mcontext.rip : 0,
ctx ? ctx->uc_mcontext.rsp : 0, ctx ? ctx->uc_mcontext.rbp : 0, __pid, ctx ? ctx->uc_mcontext.rsp : 0, ctx ? ctx->uc_mcontext.rbp : 0, __pid,
sys_gettid()); __tls_enabled ? __get_tls()->tib_tid : sys_gettid());
_Exitr(119); _Exitr(119);
} }
@ -302,7 +302,7 @@ relegated void __oncrash_amd64(int sig, struct siginfo *si, void *arg) {
ftrace_enabled(-1); ftrace_enabled(-1);
strace_enabled(-1); strace_enabled(-1);
owner = 0; owner = 0;
me = sys_gettid(); me = __tls_enabled ? __get_tls()->tib_tid : sys_gettid();
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0);
if (atomic_compare_exchange_strong_explicit( if (atomic_compare_exchange_strong_explicit(
&once, &owner, me, memory_order_relaxed, memory_order_relaxed)) { &once, &owner, me, memory_order_relaxed, memory_order_relaxed)) {

View file

@ -27,7 +27,6 @@
#include "libc/intrin/asan.internal.h" #include "libc/intrin/asan.internal.h"
#include "libc/intrin/atomic.h" #include "libc/intrin/atomic.h"
#include "libc/intrin/describeflags.internal.h" #include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/strace.internal.h" #include "libc/intrin/strace.internal.h"
#include "libc/limits.h" #include "libc/limits.h"
#include "libc/macros.internal.h" #include "libc/macros.internal.h"
@ -53,6 +52,9 @@
#include "libc/thread/tls2.h" #include "libc/thread/tls2.h"
#include "libc/thread/xnu.internal.h" #include "libc/thread/xnu.internal.h"
#define kMaxThreadIds 32768
#define kMinThreadId 262144
#define __NR_thr_new 455 #define __NR_thr_new 455
#define __NR_clone_linux 56 #define __NR_clone_linux 56
#define __NR__lwp_create 309 #define __NR__lwp_create 309
@ -64,8 +66,11 @@
#define LWP_SUSPENDED 0x00000080 #define LWP_SUSPENDED 0x00000080
struct CloneArgs { struct CloneArgs {
union { _Alignas(16) union {
struct {
int tid; int tid;
int this;
};
uint32_t utid; uint32_t utid;
int64_t tid64; int64_t tid64;
}; };
@ -77,6 +82,12 @@ struct CloneArgs {
void *arg; void *arg;
}; };
static struct CloneArgs *AllocateCloneArgs(char *stk, size_t stksz) {
return (struct CloneArgs *)(((uintptr_t)(stk + stksz) -
sizeof(struct CloneArgs)) &
-16);
}
#ifdef __x86_64__ #ifdef __x86_64__
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -108,7 +119,7 @@ WinThreadEntry(int rdi, // rcx
int rc; int rc;
if (wt->tls) __set_tls_win32(wt->tls); if (wt->tls) __set_tls_win32(wt->tls);
*wt->ctid = wt->tid; *wt->ctid = wt->tid;
rc = WinThreadLaunch(wt->arg, wt->tid, wt->func, (intptr_t)wt & -16); rc = WinThreadLaunch(wt->arg, wt->tid, wt->func, (intptr_t)wt);
// we can now clear ctid directly since we're no longer using our own // we can now clear ctid directly since we're no longer using our own
// stack memory, which can now be safely free'd by the parent thread. // stack memory, which can now be safely free'd by the parent thread.
*wt->ztid = 0; *wt->ztid = 0;
@ -124,9 +135,7 @@ static textwindows errno_t CloneWindows(int (*func)(void *, int), char *stk,
void *tls, int *ptid, int *ctid) { void *tls, int *ptid, int *ctid) {
int64_t h; int64_t h;
struct CloneArgs *wt; struct CloneArgs *wt;
wt = (struct CloneArgs *)(((intptr_t)(stk + stksz) - wt = AllocateCloneArgs(stk, stksz);
sizeof(struct CloneArgs)) &
-alignof(struct CloneArgs));
wt->ctid = flags & CLONE_CHILD_SETTID ? ctid : &wt->tid; wt->ctid = flags & CLONE_CHILD_SETTID ? ctid : &wt->tid;
wt->ztid = flags & CLONE_CHILD_CLEARTID ? ctid : &wt->tid; wt->ztid = flags & CLONE_CHILD_CLEARTID ? ctid : &wt->tid;
wt->func = func; wt->func = func;
@ -155,7 +164,6 @@ void XnuThreadThunk(void *pthread, // rdi x0
asm("XnuThreadThunk:\n\t" asm("XnuThreadThunk:\n\t"
"xor\t%ebp,%ebp\n\t" "xor\t%ebp,%ebp\n\t"
"mov\t%r8,%rsp\n\t" "mov\t%r8,%rsp\n\t"
"and\t$-16,%rsp\n\t"
"push\t%rax\n\t" "push\t%rax\n\t"
"jmp\tXnuThreadMain\n\t" "jmp\tXnuThreadMain\n\t"
".size\tXnuThreadThunk,.-XnuThreadThunk"); ".size\tXnuThreadThunk,.-XnuThreadThunk");
@ -209,9 +217,7 @@ static errno_t CloneXnu(int (*fn)(void *), char *stk, size_t stksz, int flags,
_npassert(sys_bsdthread_register(XnuThreadThunk, 0, 0, 0, 0, 0, 0) != -1); _npassert(sys_bsdthread_register(XnuThreadThunk, 0, 0, 0, 0, 0, 0) != -1);
once = true; once = true;
} }
wt = (struct CloneArgs *)(((intptr_t)(stk + stksz) - wt = AllocateCloneArgs(stk, stksz);
sizeof(struct CloneArgs)) &
-alignof(struct CloneArgs));
wt->ptid = flags & CLONE_PARENT_SETTID ? ptid : &wt->tid; wt->ptid = flags & CLONE_PARENT_SETTID ? ptid : &wt->tid;
wt->ctid = flags & CLONE_CHILD_SETTID ? ctid : &wt->tid; wt->ctid = flags & CLONE_CHILD_SETTID ? ctid : &wt->tid;
wt->ztid = flags & CLONE_CHILD_CLEARTID ? ctid : &wt->tid; wt->ztid = flags & CLONE_CHILD_CLEARTID ? ctid : &wt->tid;
@ -248,9 +254,7 @@ static errno_t CloneFreebsd(int (*func)(void *, int), char *stk, size_t stksz,
bool failed; bool failed;
int64_t tid; int64_t tid;
struct CloneArgs *wt; struct CloneArgs *wt;
wt = (struct CloneArgs *)(((intptr_t)(stk + stksz) - wt = AllocateCloneArgs(stk, stksz);
sizeof(struct CloneArgs)) &
-alignof(struct CloneArgs));
wt->ctid = flags & CLONE_CHILD_SETTID ? ctid : &wt->tid; wt->ctid = flags & CLONE_CHILD_SETTID ? ctid : &wt->tid;
wt->ztid = flags & CLONE_CHILD_CLEARTID ? ctid : &wt->tid; wt->ztid = flags & CLONE_CHILD_CLEARTID ? ctid : &wt->tid;
wt->tls = tls; wt->tls = tls;
@ -260,7 +264,7 @@ static errno_t CloneFreebsd(int (*func)(void *, int), char *stk, size_t stksz,
.start_func = FreebsdThreadMain, .start_func = FreebsdThreadMain,
.arg = wt, .arg = wt,
.stack_base = stk, .stack_base = stk,
.stack_size = (((intptr_t)wt - (intptr_t)stk) & -16) - 8, .stack_size = (uintptr_t)wt - (uintptr_t)stk,
.tls_base = flags & CLONE_SETTLS ? tls : 0, .tls_base = flags & CLONE_SETTLS ? tls : 0,
.tls_size = 64, .tls_size = 64,
.child_tid = &wt->tid64, .child_tid = &wt->tid64,
@ -346,8 +350,7 @@ static wontreturn void NetbsdThreadMain(void *arg, // rdi
// we no longer use the stack after this point // we no longer use the stack after this point
// %eax = int __lwp_exit(void); // %eax = int __lwp_exit(void);
asm volatile("movl\t$0,%2\n\t" // *wt->ztid = 0 asm volatile("movl\t$0,%2\n\t" // *wt->ztid = 0
"syscall\n\t" // __lwp_exit() "syscall" // __lwp_exit()
"ud2"
: "=a"(ax), "=d"(dx), "=m"(*ztid) : "=a"(ax), "=d"(dx), "=m"(*ztid)
: "0"(310) : "0"(310)
: "rcx", "r11", "memory"); : "rcx", "r11", "memory");
@ -440,20 +443,18 @@ static int CloneNetbsd(int (*func)(void *, int), char *stk, size_t stksz,
static void *SiliconThreadMain(void *arg) { static void *SiliconThreadMain(void *arg) {
register struct CloneArgs *wt asm("x21") = arg; register struct CloneArgs *wt asm("x21") = arg;
asm volatile("ldr\tx28,%0" : /* no outputs */ : "m"(wt->tls)); asm volatile("ldr\tx28,%0" : /* no outputs */ : "m"(wt->tls));
int tid = sys_gettid(); *wt->ctid = wt->this;
*wt->ctid = tid;
*wt->ptid = tid;
register long x0 asm("x0") = (long)wt->arg; register long x0 asm("x0") = (long)wt->arg;
register long x1 asm("x1") = (long)tid; register long x1 asm("x1") = (long)wt->tid;
asm volatile("mov\tx19,x29\n\t" // save frame pointer asm volatile("mov\tx19,x29\n\t" // save frame pointer
"mov\tx20,sp\n\t" // save stack pointer "mov\tx20,sp\n\t" // save stack pointer
"mov\tx29,#0\n\t" // reset backtrace "mov\tx29,#0\n\t" // reset backtrace
"mov\tsp,x21\n\t" // switch stack "mov\tsp,%3\n\t" // switch stack
"blr\t%2\n\t" // wt->func(wt->arg, tid) "blr\t%2\n\t" // wt->func(wt->arg, tid)
"mov\tx29,x19\n\t" // restore frame pointer "mov\tx29,x19\n\t" // restore frame pointer
"mov\tsp,x20" // restore stack pointer "mov\tsp,x20" // restore stack pointer
: "+r"(x0) : "+r"(x0)
: "r"(x1), "r"(wt->func) : "r"(x1), "r"(wt->func), "r"(wt)
: "x19", "x20", "memory"); : "x19", "x20", "memory");
*wt->ztid = 0; *wt->ztid = 0;
return 0; return 0;
@ -462,18 +463,24 @@ static void *SiliconThreadMain(void *arg) {
static errno_t CloneSilicon(int (*fn)(void *, int), char *stk, size_t stksz, static errno_t CloneSilicon(int (*fn)(void *, int), char *stk, size_t stksz,
int flags, void *arg, void *tls, int *ptid, int flags, void *arg, void *tls, int *ptid,
int *ctid) { int *ctid) {
errno_t res;
unsigned tid;
pthread_t th; pthread_t th;
struct CloneArgs *wt; struct CloneArgs *wt;
wt = (struct CloneArgs *)(((intptr_t)(stk + stksz) - static atomic_uint tids;
sizeof(struct CloneArgs)) & wt = AllocateCloneArgs(stk, stksz);
-MAX(16, alignof(struct CloneArgs))); tid = atomic_fetch_add_explicit(&tids, 1, memory_order_acq_rel);
wt->this = tid = (tid & (kMaxThreadIds - 1)) + kMinThreadId;
wt->ctid = flags & CLONE_CHILD_SETTID ? ctid : &wt->tid; wt->ctid = flags & CLONE_CHILD_SETTID ? ctid : &wt->tid;
wt->ptid = flags & CLONE_PARENT_SETTID ? ptid : &wt->tid;
wt->ztid = flags & CLONE_CHILD_CLEARTID ? ctid : &wt->tid; wt->ztid = flags & CLONE_CHILD_CLEARTID ? ctid : &wt->tid;
wt->tls = flags & CLONE_SETTLS ? tls : 0; wt->tls = flags & CLONE_SETTLS ? tls : 0;
wt->func = fn; wt->func = fn;
wt->arg = arg; wt->arg = arg;
return __syslib->pthread_create(&th, 0, SiliconThreadMain, wt); if (!(res = __syslib->pthread_create(&th, 0, SiliconThreadMain, wt)) &&
(flags & CLONE_PARENT_SETTID)) {
*ptid = tid;
}
return res;
} }
#endif /* __aarch64__ */ #endif /* __aarch64__ */

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/calls.h"
#include "libc/calls/syscall-sysv.internal.h" #include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/strace.internal.h" #include "libc/intrin/strace.internal.h"
@ -27,11 +28,16 @@
#include "libc/runtime/stack.h" #include "libc/runtime/stack.h"
#include "libc/runtime/syslib.internal.h" #include "libc/runtime/syslib.internal.h"
#include "libc/sysv/consts/prot.h" #include "libc/sysv/consts/prot.h"
#include "libc/sysv/consts/sig.h"
#include "libc/thread/thread.h" #include "libc/thread/thread.h"
#include "libc/thread/tls.h" #include "libc/thread/tls.h"
#ifndef __x86_64__ #ifndef __x86_64__
void __wipe(uintptr_t); /**
* @fileoverview Cosmopolitan C Runtime, Second Edition
*/
void __wipe(uintptr_t) _Hide;
int main(int, char **, char **) __attribute__((__weak__)); int main(int, char **, char **) __attribute__((__weak__));
typedef int init_f(int argc, char **argv, char **envp, unsigned long *auxv); typedef int init_f(int argc, char **argv, char **envp, unsigned long *auxv);
@ -75,12 +81,14 @@ textstartup void cosmo(long *sp, struct Syslib *m1) {
while (*auxv++) donothing; while (*auxv++) donothing;
// detect apple m1 environment // detect apple m1 environment
if ((__syslib = m1)) { if (SupportsXnu() && (__syslib = m1)) {
hostos = _HOSTXNU; hostos = _HOSTXNU;
magnums = syscon_xnu; magnums = syscon_xnu;
} else { } else if (SupportsLinux()) {
hostos = _HOSTLINUX; hostos = _HOSTLINUX;
magnums = syscon_linux; magnums = syscon_linux;
} else {
notpossible;
} }
// setup system magic numbers // setup system magic numbers
@ -88,6 +96,18 @@ textstartup void cosmo(long *sp, struct Syslib *m1) {
*mp = *magnums++; *mp = *magnums++;
} }
// check system call abi compatibility
if (SupportsXnu() && __syslib && __syslib->version < SYSLIB_VERSION) {
sys_write(2, "need newer ape loader\n", 22);
_Exit(127);
}
// disable enosys trapping
if (IsBsd()) {
void *act[6] = {SIG_IGN};
sys_sigaction(SIGSYS, act, 0, 8, 0);
}
// needed by kisdangerous() // needed by kisdangerous()
__oldstack = (intptr_t)sp; __oldstack = (intptr_t)sp;
__pid = sys_getpid().ax; __pid = sys_getpid().ax;
@ -97,7 +117,7 @@ textstartup void cosmo(long *sp, struct Syslib *m1) {
_mmi.p = _mmi.s; _mmi.p = _mmi.s;
__mmi_lock_obj._type = PTHREAD_MUTEX_RECURSIVE; __mmi_lock_obj._type = PTHREAD_MUTEX_RECURSIVE;
// record system-provided stack to memory manager // record provided stack to memory manager
_mmi.i = 1; _mmi.i = 1;
_mmi.p->x = (uintptr_t)GetStackAddr() >> 16; _mmi.p->x = (uintptr_t)GetStackAddr() >> 16;
_mmi.p->y = (uintptr_t)(GetStackAddr() + (GetStackSize() - FRAMESIZE)) >> 16; _mmi.p->y = (uintptr_t)(GetStackAddr() + (GetStackSize() - FRAMESIZE)) >> 16;
@ -106,6 +126,7 @@ textstartup void cosmo(long *sp, struct Syslib *m1) {
#if 0 #if 0
#if IsAsan() #if IsAsan()
// TODO(jart): Figure out ASAN data model on AARCH64.
__asan_init(argc, argv, envp, auxv); __asan_init(argc, argv, envp, auxv);
#endif #endif
#endif #endif

View file

@ -66,5 +66,5 @@ void __enable_threads(void) {
STRACE("__enable_threads()"); STRACE("__enable_threads()");
FixupLockNops(); FixupLockNops();
#endif #endif
__threaded = sys_gettid(); __threaded = __tls_enabled ? __get_tls()->tib_tid : sys_gettid();
} }

View file

@ -190,7 +190,7 @@ textstartup void __enable_tls(void) {
tib->tib_strace = __strace; tib->tib_strace = __strace;
tib->tib_ftrace = __ftrace; tib->tib_ftrace = __ftrace;
tib->tib_pthread = (pthread_t)&_pthread_main; tib->tib_pthread = (pthread_t)&_pthread_main;
if (IsLinux()) { if (IsLinux() || IsXnuSilicon()) {
// gnu/systemd guarantees pid==tid for the main thread so we can // gnu/systemd guarantees pid==tid for the main thread so we can
// avoid issuing a superfluous system call at startup in program // avoid issuing a superfluous system call at startup in program
tid = __pid; tid = __pid;

View file

@ -39,6 +39,7 @@ int sys_fork(void) {
#elif defined(__aarch64__) #elif defined(__aarch64__)
if (IsLinux()) {
int flags = 17; // SIGCHLD int flags = 17; // SIGCHLD
void *child_stack = 0; void *child_stack = 0;
void *parent_tidptr = 0; void *parent_tidptr = 0;
@ -50,17 +51,17 @@ int sys_fork(void) {
register long r3 asm("x3") = (long)newtls; register long r3 asm("x3") = (long)newtls;
register long r4 asm("x4") = (long)child_tidptr; register long r4 asm("x4") = (long)child_tidptr;
register int res_x0 asm("x0"); register int res_x0 asm("x0");
register int res_x1 asm("x1"); asm volatile("mov\tx8,%1\n\t"
asm volatile("mov\tx8,%2\n\t"
"mov\tx16,%3\n\t"
"svc\t0" "svc\t0"
: "=r"(res_x0), "=r"(res_x1) : "=r"(res_x0)
: "i"(220), "i"(2), "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4) : "i"(220), "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4)
: "x8", "x16", "memory"); : "x8", "x16", "memory");
if (IsXnu() && res_x0 != -1) {
res_x0 &= res_x1 - 1;
}
return _sysret(res_x0); return _sysret(res_x0);
} else if (__syslib) {
return _sysret(__syslib->fork());
} else {
return enosys();
}
#else #else

View file

@ -56,7 +56,7 @@ int _fork(uint32_t dwCreationFlags) {
__pid = dx; __pid = dx;
if (__tls_enabled) { if (__tls_enabled) {
tib = __get_tls(); tib = __get_tls();
tid = IsLinux() ? dx : sys_gettid(); tid = IsLinux() || IsXnuSilicon() ? dx : sys_gettid();
atomic_store_explicit(&tib->tib_tid, tid, memory_order_relaxed); atomic_store_explicit(&tib->tib_tid, tid, memory_order_relaxed);
if ((pt = (struct PosixThread *)tib->tib_pthread)) { if ((pt = (struct PosixThread *)tib->tib_pthread)) {
atomic_store_explicit(&pt->ptid, tid, memory_order_relaxed); atomic_store_explicit(&pt->ptid, tid, memory_order_relaxed);

View file

@ -1,6 +1,5 @@
#ifndef COSMOPOLITAN_LIBC_RUNTIME_SYSLIB_H_ #ifndef COSMOPOLITAN_LIBC_RUNTIME_SYSLIB_H_
#define COSMOPOLITAN_LIBC_RUNTIME_SYSLIB_H_ #define COSMOPOLITAN_LIBC_RUNTIME_SYSLIB_H_
#include "libc/calls/struct/iovec.h"
#include "libc/calls/struct/sigaction.h" #include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/sigset.h" #include "libc/calls/struct/sigset.h"
#include "libc/calls/struct/timespec.h" #include "libc/calls/struct/timespec.h"
@ -8,43 +7,41 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0) #if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_ COSMOPOLITAN_C_START_
/**
* @fileoverview System DSO interfaces provided by APE loader.
*
* These functions are owned by the platform C library. Regardless of
* platform, POSIX APIs returning `long` will follow the Linux Kernel
* `-errno` convention, and hence should be wrapped with `_sysret()`.
*/
#define SYSLIB_MAGIC ('s' | 'l' << 8 | 'i' << 16 | 'b' << 24) #define SYSLIB_MAGIC ('s' | 'l' << 8 | 'i' << 16 | 'b' << 24)
#define SYSLIB_VERSION 0 #define SYSLIB_VERSION 1
typedef uint64_t dispatch_time_t;
typedef uint64_t dispatch_semaphore_t;
struct Syslib { struct Syslib {
int magic; int magic;
int version; int version;
void (*exit)(int) wontreturn;
long (*fork)(void); long (*fork)(void);
long (*read)(int, void *, size_t);
long (*pread)(int, void *, size_t, int64_t);
long (*readv)(int, const struct iovec *, int);
long (*write)(int, const void *, size_t);
long (*pwrite)(int, const void *, size_t, int64_t);
long (*writev)(int, const struct iovec *, int);
long (*openat)(int, const char *, int, ...);
long (*pipe)(int[2]); long (*pipe)(int[2]);
long (*close)(int);
long (*clock_gettime)(int, struct timespec *); long (*clock_gettime)(int, struct timespec *);
long (*nanosleep)(const struct timespec *, struct timespec *); long (*nanosleep)(const struct timespec *, struct timespec *);
long (*mmap)(void *, size_t, int, int, int, int64_t); long (*mmap)(void *, size_t, int, int, int, int64_t);
long (*sigaction)(int, const struct sigaction *restrict,
struct sigaction *restrict);
int (*pthread_jit_write_protect_supported_np)(void); int (*pthread_jit_write_protect_supported_np)(void);
void (*pthread_jit_write_protect_np)(int); void (*pthread_jit_write_protect_np)(int);
void (*sys_icache_invalidate)(void *, size_t); void (*sys_icache_invalidate)(void *, size_t);
pthread_t (*pthread_self)(void);
int (*pthread_create)(pthread_t *, const pthread_attr_t *, void *(*)(void *), int (*pthread_create)(pthread_t *, const pthread_attr_t *, void *(*)(void *),
void *); void *);
int (*pthread_detach)(pthread_t);
int (*pthread_join)(pthread_t, void **);
void (*pthread_exit)(void *); void (*pthread_exit)(void *);
int (*pthread_kill)(pthread_t, int); int (*pthread_kill)(pthread_t, int);
int (*pthread_sigmask)(int, const sigset_t *restrict, sigset_t *restrict); int (*pthread_sigmask)(int, const sigset_t *restrict, sigset_t *restrict);
int (*pthread_setname_np)(const char *); int (*pthread_setname_np)(const char *);
int (*pthread_key_create)(pthread_key_t *, void (*)(void *)); dispatch_semaphore_t (*dispatch_semaphore_create)(long);
int (*pthread_setspecific)(pthread_key_t, const void *); long (*dispatch_semaphore_signal)(dispatch_semaphore_t);
void *(*pthread_getspecific)(pthread_key_t); long (*dispatch_semaphore_wait)(dispatch_semaphore_t, dispatch_time_t);
dispatch_time_t (*dispatch_walltime)(const struct timespec *, int64_t);
}; };
extern struct Syslib *__syslib; extern struct Syslib *__syslib;

File diff suppressed because it is too large Load diff

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon misc,ABORTED_COMMAND,11,11,0,0,0,0,0 .syscon misc,ABORTED_COMMAND,11,11,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon misc,ACCT_BYTEORDER,0,0,0,0,0,0,0 .syscon misc,ACCT_BYTEORDER,0,0,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon misc,ACCT_COMM,0x10,0x10,0,0,0,0,0 .syscon misc,ACCT_COMM,0x10,0x10,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon misc,ACK,4,4,4,4,4,4,0 .syscon misc,ACK,4,4,4,4,4,4,4,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon misc,ACORE,0,0,8,8,8,8,0 .syscon misc,ACORE,0,0,8,8,8,8,8,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon misc,AFORK,0,0,1,1,1,1,0 .syscon misc,AFORK,0,0,1,1,1,1,1,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_ALG,38,38,0,0,0,0,0 .syscon af,AF_ALG,38,38,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_APPLETALK,5,5,0x10,0x10,0x10,0x10,0x10 .syscon af,AF_APPLETALK,5,5,0x10,0x10,0x10,0x10,0x10,0x10

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_ASH,18,18,0,0,0,0,0 .syscon af,AF_ASH,18,18,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_ATMPVC,8,8,0,0,0,0,0 .syscon af,AF_ATMPVC,8,8,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_ATMSVC,20,20,0,0,0,0,0 .syscon af,AF_ATMSVC,20,20,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_AX25,3,3,0,0,0,0,0 .syscon af,AF_AX25,3,3,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_BLUETOOTH,31,31,0,36,0x20,31,0 .syscon af,AF_BLUETOOTH,31,31,0,0,36,0x20,31,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_BRIDGE,7,7,0,0,0,0,0 .syscon af,AF_BRIDGE,7,7,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_CAIF,37,37,0,0,0,0,0 .syscon af,AF_CAIF,37,37,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_CAN,29,29,0,0,0,35,0 .syscon af,AF_CAN,29,29,0,0,0,0,35,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_ECONET,19,19,0,0,0,0,0 .syscon af,AF_ECONET,19,19,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_FILE,1,1,0,0,0,0,0 .syscon af,AF_FILE,1,1,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_IB,27,27,0,0,0,0,0 .syscon af,AF_IB,27,27,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_IEEE802154,36,36,0,0,0,0,0 .syscon af,AF_IEEE802154,36,36,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_INET,2,2,2,2,2,2,2 .syscon af,AF_INET,2,2,2,2,2,2,2,2

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_INET6,10,10,30,28,24,24,23 .syscon af,AF_INET6,10,10,30,30,28,24,24,23

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_IPX,4,4,23,23,23,23,6 .syscon af,AF_IPX,4,4,23,23,23,23,23,6

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_IRDA,23,23,0,0,0,0,0 .syscon af,AF_IRDA,23,23,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_ISDN,34,34,28,26,26,26,0 .syscon af,AF_ISDN,34,34,28,28,26,26,26,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_IUCV,0x20,0x20,0,0,0,0,0 .syscon af,AF_IUCV,0x20,0x20,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_KCM,41,41,0,0,0,0,0 .syscon af,AF_KCM,41,41,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_KEY,15,15,0,0,30,0,0 .syscon af,AF_KEY,15,15,0,0,0,30,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_LINK,0,0,18,18,18,18,0 .syscon af,AF_LINK,0,0,18,18,18,18,18,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_LLC,26,26,0,0,0,0,0 .syscon af,AF_LLC,26,26,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_LOCAL,1,1,1,1,1,1,1 .syscon af,AF_LOCAL,1,1,1,1,1,1,1,1

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_MAX,42,42,40,42,36,37,35 .syscon af,AF_MAX,42,42,40,40,42,36,37,35

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_MPLS,28,28,0,0,33,33,0 .syscon af,AF_MPLS,28,28,0,0,0,33,33,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_NETBEUI,13,13,0,0,0,0,0 .syscon af,AF_NETBEUI,13,13,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_NETLINK,16,16,0,0,0,0,0 .syscon af,AF_NETLINK,16,16,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_NETROM,6,6,0,0,0,0,0 .syscon af,AF_NETROM,6,6,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_NFC,39,39,0,0,0,0,0 .syscon af,AF_NFC,39,39,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_PACKET,17,17,0,0,0,0,0 .syscon af,AF_PACKET,17,17,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_PHONET,35,35,0,0,0,0,0 .syscon af,AF_PHONET,35,35,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_PPPOX,24,24,0,0,0,0,0 .syscon af,AF_PPPOX,24,24,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_RDS,21,21,0,0,0,0,0 .syscon af,AF_RDS,21,21,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_ROSE,11,11,0,0,0,0,0 .syscon af,AF_ROSE,11,11,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_ROUTE,16,16,17,17,17,34,0 .syscon af,AF_ROUTE,16,16,17,17,17,17,34,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_RXRPC,33,33,0,0,0,0,0 .syscon af,AF_RXRPC,33,33,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_SECURITY,14,14,0,0,0,0,0 .syscon af,AF_SECURITY,14,14,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_SNA,22,22,11,11,11,11,11 .syscon af,AF_SNA,22,22,11,11,11,11,11,11

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_TIPC,30,30,0,0,0,0,0 .syscon af,AF_TIPC,30,30,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_UNIX,1,1,1,1,1,1,1 .syscon af,AF_UNIX,1,1,1,1,1,1,1,1

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_UNSPEC,0,0,0,0,0,0,0 .syscon af,AF_UNSPEC,0,0,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_VSOCK,40,40,0,0,0,0,0 .syscon af,AF_VSOCK,40,40,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_WANPIPE,25,25,0,0,0,0,0 .syscon af,AF_WANPIPE,25,25,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon af,AF_X25,9,9,0,0,0,0,0 .syscon af,AF_X25,9,9,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon misc,AIO_ALLDONE,2,2,1,3,0,0,0 .syscon misc,AIO_ALLDONE,2,2,1,1,3,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon misc,AIO_CANCELED,0,0,2,1,0,0,0 .syscon misc,AIO_CANCELED,0,0,2,2,1,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon misc,AIO_NOTCANCELED,1,1,4,2,0,0,0 .syscon misc,AIO_NOTCANCELED,1,1,4,4,2,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon alg,ALG_SET_AEAD_ASSOCLEN,4,4,0,0,0,0,0 .syscon alg,ALG_SET_AEAD_ASSOCLEN,4,4,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon alg,ALG_SET_AEAD_AUTHSIZE,5,5,0,0,0,0,0 .syscon alg,ALG_SET_AEAD_AUTHSIZE,5,5,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon alg,ALG_SET_DRBG_ENTROPY,6,6,0,0,0,0,0 .syscon alg,ALG_SET_DRBG_ENTROPY,6,6,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon alg,ALG_SET_IV,2,2,0,0,0,0,0 .syscon alg,ALG_SET_IV,2,2,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon alg,ALG_SET_KEY,1,1,0,0,0,0,0 .syscon alg,ALG_SET_KEY,1,1,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon alg,ALG_SET_OP,3,3,0,0,0,0,0 .syscon alg,ALG_SET_OP,3,3,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon misc,AREGTYPE,0,0,0,0,0,0,0 .syscon misc,AREGTYPE,0,0,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon auxv,AT_BASE,7,7,7,7,0,7,0 .syscon auxv,AT_BASE,7,7,7,7,7,0,7,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon auxv,AT_BASE_PLATFORM,24,24,0,0,0,0,0 .syscon auxv,AT_BASE_PLATFORM,24,24,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon auxv,AT_CANARY,0,0,0,16,0,0,0 .syscon auxv,AT_CANARY,0,0,0,0,16,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon auxv,AT_CANARYLEN,0,0,0,17,0,0,0 .syscon auxv,AT_CANARYLEN,0,0,0,0,17,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon auxv,AT_CLKTCK,17,17,0,0,0,0,0 .syscon auxv,AT_CLKTCK,17,17,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon auxv,AT_DCACHEBSIZE,19,19,0,0,0,0,0 .syscon auxv,AT_DCACHEBSIZE,19,19,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon at,AT_EACCESS,0x0200,0x0200,0x10,0x0100,1,0x100,0 .syscon at,AT_EACCESS,0x0200,0x0200,0x10,0x10,0x0100,1,0x100,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon auxv,AT_EGID,14,14,14,0,0,2002,0 .syscon auxv,AT_EGID,14,14,14,14,0,0,2002,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon auxv,AT_EHDRFLAGS,0,0,0,24,0,0,0 .syscon auxv,AT_EHDRFLAGS,0,0,0,0,24,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon at,AT_EMPTY_PATH,0x1000,0x1000,0,0,0,0,0 .syscon at,AT_EMPTY_PATH,0x1000,0x1000,0,0,0,0,0,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon auxv,AT_ENTRY,9,9,9,9,0,9,0 .syscon auxv,AT_ENTRY,9,9,9,9,9,0,9,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon auxv,AT_EUID,12,12,12,0,0,2000,0 .syscon auxv,AT_EUID,12,12,12,12,0,0,2000,0

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h" #include "libc/sysv/consts/syscon.internal.h"
.syscon auxv,AT_EXECFD,2,2,0,2,0,2,0 .syscon auxv,AT_EXECFD,2,2,0,0,2,0,2,0

Some files were not shown because too many files have changed in this diff Show more