Introduce native support for MacOS ARM64

There's a new program named ape/ape-m1.c which will be used to build an
embeddable binary that can load ape and elf executables. The support is
mostly working so far, but still chasing down ABI issues.
This commit is contained in:
Justine Tunney 2023-05-18 19:05:08 -07:00
parent b852650c08
commit 1422e96b4e
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
757 changed files with 2988 additions and 1321 deletions

298
ape/aarch64.lds Normal file
View file

@ -0,0 +1,298 @@
/*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│
│vi: set et sts=2 tw=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/zip.h"
ENTRY(_start)
OUTPUT_ARCH(aarch64)
OUTPUT_FORMAT("elf64-littleaarch64",
"elf64-bigaarch64",
"elf64-littleaarch64")
SECTIONS {
PROVIDE(__executable_start = SEGMENT_START("text-segment", IMAGE_BASE_VIRTUAL));
. = SEGMENT_START("text-segment", IMAGE_BASE_VIRTUAL) + SIZEOF_HEADERS;
.interp : { *(.interp) }
.note.gnu.build-id : { *(.note.gnu.build-id) }
.hash : { *(.hash) }
.gnu.hash : { *(.gnu.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.rela.init : { *(.rela.init) }
.rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
.rela.fini : { *(.rela.fini) }
.rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }
.rela.data.rel.ro : { *(.rela.data.rel.ro .rela.data.rel.ro.* .rela.gnu.linkonce.d.rel.ro.*) }
.rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }
.rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
.rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
.rela.ctors : { *(.rela.ctors) }
.rela.dtors : { *(.rela.dtors) }
.rela.got : { *(.rela.got) }
.rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
.rela.ifunc : { *(.rela.ifunc) }
.rela.plt : {
*(.rela.plt)
PROVIDE_HIDDEN(__rela_iplt_start = .);
*(.rela.iplt)
PROVIDE_HIDDEN(__rela_iplt_end = .);
}
.init : {
KEEP(*(.initprologue))
KEEP(*(SORT_NONE(.init)))
KEEP(*(.initepilogue))
} =0x1f2003d5
.plt : ALIGN(16) {
*(.plt)
*(.iplt)
}
.text : {
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
*(.text.antiquity .text.antiquity.*)
*(.text.exit .text.exit.*)
*(.text.startup .text.startup.*)
*(.text.hot .text.hot.*)
*(.text.modernity .text.modernity.*)
*(.text .stub .text.* .gnu.linkonce.t.*)
*(.gnu.warning)
} =0x1f2003d5
.fini : {
KEEP(*(SORT_NONE(.fini)))
} =0x1f2003d5
.privileged : {
PROVIDE_HIDDEN(__privileged_start = .);
*(.privileged*)
PROVIDE_HIDDEN(__privileged_end = .);
}
.rodata : {
KEEP(*(.rodata.pytab.0));
KEEP(*(.rodata.pytab.1));
KEEP(*(.rodata.pytab.2));
KEEP(*(SORT_BY_NAME(.sort.rodata.*)))
*(.rodata .rodata.* .gnu.linkonce.r.*)
*(.ubsan.types)
*(.ubsan.data)
}
.comment : {
KEEP(*(.commentprologue))
KEEP(*(.comment))
KEEP(*(.commentepilogue))
}
.eh_frame_hdr : {
*(.eh_frame_hdr)
*(.eh_frame_entry .eh_frame_entry.*)
}
.eh_frame : ONLY_IF_RO {
KEEP(*(.eh_frame))
*(.eh_frame.*)
}
.gcc_except_table : ONLY_IF_RO {
*(.gcc_except_table .gcc_except_table.*)
}
.gnu_extab : ONLY_IF_RO {
*(.gnu_extab*)
}
.exception_ranges : ONLY_IF_RO {
*(.exception_ranges*)
}
PROVIDE(__etext = .);
PROVIDE(_etext = .);
PROVIDE(etext = .);
. = ALIGN(0x4000);
. = DATA_SEGMENT_ALIGN(CONSTANT(MAXPAGESIZE), CONSTANT(COMMONPAGESIZE));
.eh_frame : ONLY_IF_RW {
KEEP(*(.eh_frame))
*(.eh_frame.*)
}
.gnu_extab : ONLY_IF_RW {
*(.gnu_extab)
}
.gcc_except_table : ONLY_IF_RW {
*(.gcc_except_table .gcc_except_table.*)
}
.exception_ranges : ONLY_IF_RW {
*(.exception_ranges*)
}
.tdata : ONLY_IF_RW {
PROVIDE_HIDDEN(_tdata_start = .);
PROVIDE_HIDDEN(__tdata_start = .);
*(.tdata .tdata.* .gnu.linkonce.td.*)
PROVIDE_HIDDEN(_tdata_end = .);
}
.tbss : {
PROVIDE_HIDDEN(_tbss_start = .);
*(.tbss .tbss.* .gnu.linkonce.tb.*)
*(.tcommon)
PROVIDE_HIDDEN(_tbss_end = .);
}
.init_array : {
PROVIDE_HIDDEN(__init_array_start = .);
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP(*(.init_array EXCLUDE_FILE(*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
PROVIDE_HIDDEN(__init_array_end = .);
}
.fini_array : {
PROVIDE_HIDDEN(__fini_array_start = .);
KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP(*(.fini_array EXCLUDE_FILE(*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
PROVIDE_HIDDEN(__fini_array_end = .);
}
.data.rel.ro : {
*(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*)
*(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*)
}
.dynamic : {
*(.dynamic)
}
.got : {
*(.got)
*(.igot)
}
. = DATA_SEGMENT_RELRO_END(24, .);
.got.plt : {
*(.got.plt)
*(.igot.plt)
}
.data : {
PROVIDE(__data_start = .);
*(.data .data.* .gnu.linkonce.d.*)
KEEP(*(SORT_BY_NAME(.sort.data.*)))
SORT(CONSTRUCTORS)
}
_edata = .;
PROVIDE(edata = .);
.data : {
KEEP(*(SORT_BY_NAME(.zip.*)))
HIDDEN(_ezip = .);
}
. = .;
__bss_start = .;
__bss_start__ = .;
.bss : {
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
KEEP(*(SORT_BY_NAME(.piro.bss.sort.*)))
*(COMMON)
}
_bss_end__ = .;
__bss_end__ = .;
. = ALIGN(64 / 8);
. = SEGMENT_START("ldata-segment", .);
. = ALIGN(64 / 8);
__end__ = .;
_end = .;
PROVIDE(end = .);
. = DATA_SEGMENT_END(.);
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
.debug_pubtypes 0 : { *(.debug_pubtypes) }
.debug_ranges 0 : { *(.debug_ranges) }
.debug_macro 0 : { *(.debug_macro) }
.debug_addr 0 : { *(.debug_addr) }
.ARM.attributes 0 : { KEEP(*(.ARM.attributes)) KEEP(*(.gnu.attributes)) }
.note.gnu.arm.ident 0 : { KEEP(*(.note.gnu.arm.ident)) }
/DISCARD/ : {
*(.GCC.command.line)
*(.note.GNU-stack)
*(.gnu_debuglink)
*(.text.windows)
*(.gnu.lto_*)
*(.idata.*)
*(.head)
}
}
PROVIDE(ape_stack_memsz = DEFINED(ape_stack_memsz) ? ape_stack_memsz : STACKSIZE);
PROVIDE_HIDDEN(_tls_size = _tbss_end - _tdata_start);
PROVIDE_HIDDEN(_tdata_size = _tdata_end - _tdata_start);
PROVIDE_HIDDEN(_tbss_size = _tbss_end - _tbss_start);
PROVIDE_HIDDEN(_tbss_offset = _tbss_start - _tdata_start);
PROVIDE_HIDDEN(_tls_content = (_tdata_end - _tdata_start) + (_tbss_end - _tbss_start));
PROVIDE_HIDDEN(__zip_start_rva = DEFINED(__zip_start) ? __zip_start - __executable_start : 0);
/* ZIP End of Central Directory header */
#define ZIPCONST(NAME, VAL) HIDDEN(NAME = DEFINED(__zip_start) ? VAL : 0);
ZIPCONST(v_zip_cdoffset, __zip_start - IMAGE_BASE_VIRTUAL);
ZIPCONST(v_zip_cdirsize, __zip_end - __zip_start);
ASSERT(v_zip_cdirsize % kZipCdirHdrLinkableSize == 0, "bad zip cdir");
ZIPCONST(v_zip_records, v_zip_cdirsize / kZipCdirHdrLinkableSize);
ZIPCONST(v_zip_commentsize, _ezip - __zip_end - kZipCdirHdrMinSize);

800
ape/ape-m1.c Normal file
View file

@ -0,0 +1,800 @@
/*-*- 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 2021 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 <time.h>
#include <fcntl.h>
#include <errno.h>
#include <stdarg.h>
#include <unistd.h>
#include <signal.h>
#include <limits.h>
#include <pthread.h>
#include <sys/uio.h>
#include <sys/mman.h>
#include <libkern/OSCacheControl.h>
#define SYSLIB_MAGIC ('s' | 'l' << 8 | 'i' << 16 | 'b' << 24)
#define SYSLIB_VERSION 0
struct Syslib {
int magic;
int version;
void (*exit)(int) __attribute__((__noreturn__));
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 (*close)(int);
long (*clock_gettime)(int, struct timespec *);
long (*nanosleep)(const struct timespec *, struct timespec *);
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);
void (*pthread_jit_write_protect_np)(int);
void (*sys_icache_invalidate)(void *, size_t);
pthread_t (*pthread_self)(void);
int (*pthread_create)(pthread_t *, const pthread_attr_t *, void *(*)(void *), void *);
int (*pthread_detach)(pthread_t);
int (*pthread_join)(pthread_t, void **);
void (*pthread_exit)(void *);
int (*pthread_kill)(pthread_t, int);
int (*pthread_sigmask)(int, const sigset_t *restrict, sigset_t *restrict);
int (*pthread_setname_np)(const char *);
int (*pthread_key_create)(pthread_key_t *, void (*)(void *));
int (*pthread_setspecific)(pthread_key_t, const void *);
void *(*pthread_getspecific)(pthread_key_t);
};
#define TROUBLESHOOT 0
#define ELFCLASS64 2
#define ELFDATA2LSB 1
#define EM_AARCH64 183
#define ET_EXEC 2
#define PT_LOAD 1
#define PT_DYNAMIC 2
#define EI_CLASS 4
#define EI_DATA 5
#define PF_X 1
#define PF_W 2
#define PF_R 4
#define AT_PHDR 3
#define AT_PHENT 4
#define AT_PHNUM 5
#define AT_PAGESZ 6
#define AT_BASE 7
#define AT_ENTRY 9
#define AT_UID 11
#define AT_EUID 12
#define AT_GID 13
#define AT_EGID 14
#define AT_HWCAP 16
#define AT_HWCAP2 16
#define AT_SECURE 23
#define AT_RANDOM 25
#define AT_EXECFN 31
#define STACK_ALIGN (sizeof(long) * 2)
#define AUXV_BYTES (sizeof(long) * 2 * 14)
// from the xnu codebase
#define _COMM_PAGE_START_ADDRESS 0x0000000FFFFFC000ul
#define _COMM_PAGE_APRR_SUPPORT (_COMM_PAGE_START_ADDRESS + 0x10C)
#define _COMM_PAGE_APRR_WRITE_ENABLE (_COMM_PAGE_START_ADDRESS + 0x110)
#define _COMM_PAGE_APRR_WRITE_DISABLE (_COMM_PAGE_START_ADDRESS + 0x118)
#define Min(X, Y) ((Y) > (X) ? (X) : (Y))
#define Roundup(X, K) (((X) + (K) - 1) & -(K))
#define Rounddown(X, K) ((X) & -(K))
#define Read32(S) \
((unsigned)(255 & (S)[3]) << 030 | \
(unsigned)(255 & (S)[2]) << 020 | \
(unsigned)(255 & (S)[1]) << 010 | \
(unsigned)(255 & (S)[0]) << 000)
#define Read64(S) \
((unsigned long)(255 & (S)[7]) << 070 | \
(unsigned long)(255 & (S)[6]) << 060 | \
(unsigned long)(255 & (S)[5]) << 050 | \
(unsigned long)(255 & (S)[4]) << 040 | \
(unsigned long)(255 & (S)[3]) << 030 | \
(unsigned long)(255 & (S)[2]) << 020 | \
(unsigned long)(255 & (S)[1]) << 010 | \
(unsigned long)(255 & (S)[0]) << 000)
struct PathSearcher {
unsigned long namelen;
const char *name;
const char *syspath;
char path[1024];
};
struct ElfEhdr {
unsigned char e_ident[16];
unsigned short e_type;
unsigned short e_machine;
unsigned e_version;
unsigned long e_entry;
unsigned long e_phoff;
unsigned long e_shoff;
unsigned e_flags;
unsigned short e_ehsize;
unsigned short e_phentsize;
unsigned short e_phnum;
unsigned short e_shentsize;
unsigned short e_shnum;
unsigned short e_shstrndx;
};
struct ElfPhdr {
unsigned p_type;
unsigned p_flags;
unsigned long p_offset;
unsigned long p_vaddr;
unsigned long p_paddr;
unsigned long p_filesz;
unsigned long p_memsz;
unsigned long p_align;
};
union ElfEhdrBuf {
struct ElfEhdr ehdr;
char buf[0x1000];
};
union ElfPhdrBuf {
struct ElfPhdr phdr;
char buf[0x1000];
};
static int ToLower(int c) {
return 'A' <= c && c <= 'Z' ? c + ('a' - 'A') : c;
}
static void *MemSet(void *a, int c, unsigned long n) {
char *d = a;
unsigned long i;
for (i = 0; i < n; ++i) {
d[i] = c;
}
return d;
}
static void *MemMove(void *a, const void *b, unsigned long n) {
char *d = a;
unsigned long i;
const char *s = b;
if (d > s) {
for (i = n; i--;) {
d[i] = s[i];
}
} else {
for (i = 0; i < n; ++i) {
d[i] = s[i];
}
}
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) {
for (; n; --n, ++s) {
if ((*s & 255) == c) {
return s;
}
}
return 0;
}
static char *GetEnv(char **p, const char *s) {
unsigned long i, j;
if (p) {
for (i = 0; p[i]; ++i) {
for (j = 0;; ++j) {
if (!s[j]) {
if (p[i][j] == '=') {
return p[i] + j + 1;
}
break;
}
if (s[j] != p[i][j]) {
break;
}
}
}
}
return 0;
}
static char *Utoa(char p[21], unsigned long x) {
char t;
unsigned long i, a, b;
i = 0;
do {
p[i++] = x % 10 + '0';
x = x / 10;
} while (x > 0);
p[i] = '\0';
if (i) {
for (a = 0, b = i - 1; a < b; ++a, --b) {
t = p[a];
p[a] = p[b];
p[b] = t;
}
}
return p + i;
}
static char *Itoa(char p[21], long x) {
if (x < 0) *p++ = '-', x = -(unsigned long)x;
return Utoa(p, x);
}
static void Emit(const char *s) {
write(2, s, StrLen(s));
}
static void Perror(const char *c, int failed, const char *s) {
char ibuf[21];
Emit("ape error: ");
Emit(c);
Emit(": ");
Emit(s);
if (failed) {
Emit(" failed errno=");
Itoa(ibuf, errno);
Emit(ibuf);
}
Emit("\n");
}
__attribute__((__noreturn__))
static void Pexit(const char *c, int failed, const char *s) {
Perror(c, failed, s);
_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) {
unsigned long i, m;
if (n >= (m = StrLen(s))) {
for (i = n - m; i < n; ++i) {
if (ToLower(p[i]) != *s++) {
return 0;
}
}
return 1;
} else {
return 0;
}
}
static char IsComPath(struct PathSearcher *ps) {
return EndsWithIgnoreCase(ps->name, ps->namelen, ".com") ||
EndsWithIgnoreCase(ps->name, ps->namelen, ".exe") ||
EndsWithIgnoreCase(ps->name, ps->namelen, ".com.dbg");
}
static char AccessCommand(struct PathSearcher *ps, const char *suffix,
unsigned long pathlen) {
unsigned long suffixlen;
suffixlen = StrLen(suffix);
if (pathlen + 1 + ps->namelen + suffixlen + 1 > sizeof(ps->path)) return 0;
if (pathlen && ps->path[pathlen - 1] != '/') ps->path[pathlen++] = '/';
MemMove(ps->path + pathlen, ps->name, ps->namelen);
MemMove(ps->path + pathlen + ps->namelen, suffix, suffixlen + 1);
return !access(ps->path, X_OK);
}
static char SearchPath(struct PathSearcher *ps, const char *suffix) {
const char *p;
unsigned long i;
for (p = ps->syspath;;) {
for (i = 0; p[i] && p[i] != ':'; ++i) {
if (i < sizeof(ps->path)) {
ps->path[i] = p[i];
}
}
if (AccessCommand(ps, suffix, i)) {
return 1;
} else if (p[i] == ':') {
p += i + 1;
} else {
return 0;
}
}
}
static char FindCommand(struct PathSearcher *ps, const char *suffix) {
if (MemChr(ps->name, '/', ps->namelen) ||
MemChr(ps->name, '\\', ps->namelen)) {
ps->path[0] = 0;
return AccessCommand(ps, suffix, 0);
} else {
if (AccessCommand(ps, suffix, 0)) return 1;
}
return SearchPath(ps, suffix);
}
static char *Commandv(struct PathSearcher *ps,
const char *name,
const char *syspath) {
ps->syspath = syspath ? syspath : "/bin:/usr/local/bin:/usr/bin";
if (!(ps->namelen = StrLen((ps->name = name)))) return 0;
if (ps->namelen + 1 > sizeof(ps->path)) return 0;
if (FindCommand(ps, "") || (!IsComPath(ps) && FindCommand(ps, ".com"))) {
return ps->path;
} else {
return 0;
}
}
static void pthread_jit_write_protect_np_workaround(int enabled) {
int count_start = 8192;
volatile int count = count_start;
unsigned long *addr, *other, val, val2, reread = -1;
addr = (unsigned long *)(!enabled ? _COMM_PAGE_APRR_WRITE_ENABLE
: _COMM_PAGE_APRR_WRITE_DISABLE);
other = (unsigned long *)(enabled ? _COMM_PAGE_APRR_WRITE_ENABLE
: _COMM_PAGE_APRR_WRITE_DISABLE);
switch (*(volatile unsigned char *)_COMM_PAGE_APRR_SUPPORT) {
case 1:
do {
val = *addr;
reread = -1;
asm volatile("msr\tS3_4_c15_c2_7,%0\n"
"isb\tsy\n"
: /* no outputs */
: "r"(val)
: "memory");
val2 = *addr;
asm volatile("mrs\t%0,S3_4_c15_c2_7\n"
: "=r"(reread)
: /* no inputs */
: "memory");
if (val2 == reread) {
return;
}
usleep(10);
} while (count-- > 0);
break;
case 3:
do {
val = *addr;
reread = -1;
asm volatile("msr\tS3_6_c15_c1_5,%0\n"
"isb\tsy\n"
: /* no outputs */
: "r"(val)
: "memory");
val2 = *addr;
asm volatile("mrs\t%0,S3_6_c15_c1_5\n"
: "=r"(reread)
: /* no inputs */
: "memory");
if (val2 == reread) {
return;
}
usleep(10);
} while (count-- > 0);
break;
default:
pthread_jit_write_protect_np(enabled);
return;
}
Pexit("ape-m1", 0, "failed to set jit write protection");
}
__attribute__((__noreturn__))
static void Spawn(const char *exe,
int fd, long *sp,
struct ElfEhdr *e,
struct ElfPhdr *p,
struct Syslib *lib) {
int prot, flags;
long code, codesize;
unsigned long a, b, i;
code = 0;
codesize = 0;
for (i = e->e_phnum; i--;) {
if (p[i].p_type == PT_DYNAMIC) {
Pexit(exe, 0, "not a real executable");
}
if (p[i].p_type != PT_LOAD) {
continue;
}
if (!p[i].p_memsz) {
continue;
}
if (p[i].p_vaddr & 0x3fff) {
Pexit(exe, 0, "APE phdr addr must be 16384-aligned");
}
if (p[i].p_offset & 0x3fff) {
Pexit(exe, 0, "APE phdr offset must be 16384-aligned");
}
if ((p[i].p_flags & (PF_W | PF_X)) == (PF_W | PF_X)) {
Pexit(exe, 0, "Apple Silicon doesn't allow RWX memory");
}
prot = 0;
flags = MAP_FIXED | MAP_PRIVATE;
if (p[i].p_flags & PF_R) {
prot |= PROT_READ;
}
if (p[i].p_flags & PF_W) {
prot |= PROT_WRITE;
}
if (p[i].p_flags & PF_X) {
prot |= PROT_EXEC;
code = p[i].p_vaddr;
codesize = p[i].p_filesz;
}
if (p[i].p_filesz) {
if (mmap((char *)p[i].p_vaddr, p[i].p_filesz, prot,
flags, fd, p[i].p_offset) == MAP_FAILED) {
Pexit(exe, -1, "image mmap()");
}
if ((a = Min(-p[i].p_filesz & 0x3fff, p[i].p_memsz - p[i].p_filesz))) {
MemSet((void *)(p[i].p_vaddr + p[i].p_filesz), 0, a);
}
}
if ((b = Roundup(p[i].p_memsz, 0x4000)) >
(a = Roundup(p[i].p_filesz, 0x4000))) {
if (mmap((char *)p[i].p_vaddr + a, b - a,
prot, flags | MAP_ANONYMOUS, -1, 0) == MAP_FAILED) {
Pexit(exe, -1, "bss mmap()");
}
}
}
if (!code) {
Pexit(exe, 0, "ELF needs PT_LOAD phdr w/ PF_X");
}
close(fd);
register long *x0 asm("x0") = sp;
register struct Syslib *x15 asm("x15") = lib;
register long x16 asm("x16") = e->e_entry;
asm volatile("mov\tx1,#0\n\t"
"mov\tx2,#0\n\t"
"mov\tx3,#0\n\t"
"mov\tx4,#0\n\t"
"mov\tx5,#0\n\t"
"mov\tx6,#0\n\t"
"mov\tx7,#0\n\t"
"mov\tx8,#0\n\t"
"mov\tx9,#0\n\t"
"mov\tx10,#0\n\t"
"mov\tx11,#0\n\t"
"mov\tx12,#0\n\t"
"mov\tx13,#0\n\t"
"mov\tx14,#0\n\t"
"mov\tx17,#0\n\t"
"mov\tx19,#0\n\t"
"mov\tx20,#0\n\t"
"mov\tx21,#0\n\t"
"mov\tx22,#0\n\t"
"mov\tx23,#0\n\t"
"mov\tx24,#0\n\t"
"mov\tx25,#0\n\t"
"mov\tx26,#0\n\t"
"mov\tx27,#0\n\t"
"mov\tx28,#0\n\t"
"mov\tx29,#0\n\t"
"mov\tx30,#0\n\t"
"mov\tsp,x0\n\t"
"mov\tx0,#0\n\t"
"br\tx16"
: /* no outputs */
: "r"(x0), "r"(x15), "r"(x16)
: "memory");
__builtin_unreachable();
}
static void TryElf(const char *exe, int fd, long *sp, long *bp, char *execfn,
union ElfEhdrBuf *ehdr, union ElfPhdrBuf *phdr, struct Syslib *lib) {
unsigned long n;
if (Read32(ehdr->buf) == Read32("\177ELF") &&
ehdr->ehdr.e_type == ET_EXEC &&
ehdr->ehdr.e_machine == EM_AARCH64 &&
ehdr->ehdr.e_ident[EI_CLASS] == ELFCLASS64 &&
ehdr->ehdr.e_ident[EI_DATA] == ELFDATA2LSB &&
(n = ehdr->ehdr.e_phnum * sizeof(phdr->phdr)) <= sizeof(phdr->buf) &&
pread(fd, phdr->buf, n, ehdr->ehdr.e_phoff) == n) {
long auxv[][2] = {
{AT_PHDR, (long)&phdr->phdr}, //
{AT_PHENT, ehdr->ehdr.e_phentsize}, //
{AT_PHNUM, ehdr->ehdr.e_phnum}, //
{AT_ENTRY, ehdr->ehdr.e_entry}, //
{AT_PAGESZ, 0x4000}, //
{AT_UID, getuid()}, //
{AT_EUID, geteuid()}, //
{AT_GID, getgid()}, //
{AT_EGID, getegid()}, //
{AT_HWCAP, 0xffb3ffffu}, //
{AT_HWCAP2, 0x181}, //
{AT_SECURE, issetugid()}, //
{AT_EXECFN, (long)execfn}, //
{0, 0}, //
};
_Static_assert(sizeof(auxv) == AUXV_BYTES,
"Please update the AUXV_BYTES constant");
MemMove(bp, auxv, sizeof(auxv));
Spawn(exe, fd, sp, &ehdr->ehdr, &phdr->phdr, lib);
}
}
__attribute__((__noinline__))
static long sysret(long rc) {
return rc == -1 ? -errno : rc;
}
static long sys_fork(void) {
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]) {
return sysret(pipe(pfds));
}
static long sys_close(int fd) {
return sysret(close(fd));
}
static long sys_clock_gettime(int clock, struct timespec *ts) {
return sysret(clock_gettime(clock, ts));
}
static long sys_nanosleep(const struct timespec *req, struct timespec *rem) {
return sysret(nanosleep(req, rem));
}
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));
}
static long sys_sigaction(int sig, const struct sigaction *restrict act,
struct sigaction *restrict oact) {
return sysret(sigaction(sig, act, oact));
}
int loader(int argc, char **argv, char **envp) {
long *sp, *bp, *ip;
int c, i, n, fd, rc;
char *p, *tp, *exe, *prog, *execfn;
struct {
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;
} M;
// expose some apple libraries
M.lib.magic = SYSLIB_MAGIC;
M.lib.version = SYSLIB_VERSION;
M.lib.exit = _exit;
M.lib.fork = sys_fork;
M.lib.read = sys_read;
M.lib.pread = sys_pread;
M.lib.readv = sys_readv;
M.lib.write = sys_write;
M.lib.pwrite = sys_pwrite;
M.lib.writev = sys_writev;
M.lib.openat = sys_openat;
M.lib.close = sys_close;
M.lib.clock_gettime = sys_clock_gettime;
M.lib.nanosleep = sys_nanosleep;
M.lib.mmap = sys_mmap;
M.lib.sigaction = sys_sigaction;
M.lib.pthread_jit_write_protect_supported_np =
pthread_jit_write_protect_supported_np;
M.lib.pthread_jit_write_protect_np =
pthread_jit_write_protect_np_workaround;
M.lib.pthread_self = pthread_self;
M.lib.pthread_create = pthread_create;
M.lib.pthread_join = pthread_join;
M.lib.pthread_exit = pthread_exit;
M.lib.pthread_kill = pthread_kill;
M.lib.pthread_sigmask = pthread_sigmask;
M.lib.pthread_setname_np = pthread_setname_np;
M.lib.pthread_key_create = pthread_key_create;
M.lib.pthread_getspecific = pthread_getspecific;
M.lib.pthread_setspecific = pthread_setspecific;
// copy system provided argument block
bp = M.numblock;
tp = M.argblock + sizeof(M.argblock);
*bp++ = argc;
for (i = 0; i < argc; ++i) {
tp -= (n = StrLen(argv[i]) + 1);
MemMove(tp, argv[i], n);
*bp++ = (long)tp;
}
*bp++ = 0;
for (i = 0; envp[i]; ++i) {
tp -= (n = StrLen(envp[i]) + 1);
MemMove(tp, envp[i], n);
*bp++ = (long)tp;
}
*bp++ = 0;
// get arguments that point into our block
sp = M.numblock;
argc = *sp;
argv = (char **)(sp + 1);
envp = (char **)(sp + 1 + argc + 1);
// xnu stores getauxval(at_execfn) in getenv("_")
execfn = argc > 0 ? argv[0] : 0;
for (i = 0; envp[i]; ++i) {
if (envp[i][0] == '_' && envp[i][1] == '=') {
execfn = envp[i] + 2;
break;
}
}
// interpret command line arguments
if (argc >= 3 && !StrCmp(argv[1], "-")) {
// if the first argument is a hyphen then we give the user the
// power to change argv[0] or omit it entirely. most operating
// systems don't permit the omission of argv[0] but we do, b/c
// it's specified by ANSI X3.159-1988.
prog = (char *)sp[3];
argc = sp[3] = sp[0] - 3;
argv = (char **)((sp += 3) + 1);
} else if (argc < 2) {
Emit("usage: ape-m1 PROG [ARGV1,ARGV2,...]\n"
" ape-m1 - PROG [ARGV0,ARGV1,...]\n"
"actually portable executable loader (apple arm)\n"
"copyright 2023 justine alexandra roberts tunney\n"
"https://justine.lol/ape.html\n");
_exit(1);
} else {
prog = (char *)sp[2];
argc = sp[1] = sp[0] - 1;
argv = (char **)((sp += 1) + 1);
}
// squeeze and align the argument block
ip = (long *)(((long)tp - AUXV_BYTES) & -sizeof(long));
ip -= (n = bp - sp);
ip = (long *)((long)ip & -STACK_ALIGN);
MemMove(ip, sp, n * sizeof(long));
bp = ip + n;
sp = ip;
// search for executable
if (!(exe = Commandv(&M.ps, prog, GetEnv(envp, "PATH")))) {
Pexit(prog, 0, "not found (maybe chmod +x)");
} else if ((fd = openat(AT_FDCWD, exe, O_RDONLY)) < 0) {
Pexit(exe, -1, "open");
} else if ((rc = read(fd, M.ehdr.buf, sizeof(M.ehdr.buf))) < 0) {
Pexit(exe, -1, "read");
} else if (rc != sizeof(M.ehdr.buf)) {
Pexit(exe, 0, "too small");
}
#if TROUBLESHOOT
for (i = 0; i < argc; ++i) {
Emit("argv = ");
Emit(argv[i]);
Emit("\n");
}
#endif
// ape intended behavior
// 1. if file is an elf executable, it'll be used as-is
// 2. if ape, will scan shell script for elf printf statements
// 3. shell script may have multiple lines producing elf headers
// 4. all elf printf lines must exist in the first 4096 bytes of file
// 5. elf program headers may appear anywhere in the binary
if (Read64(M.ehdr.buf) == Read64("MZqFpD='") ||
Read64(M.ehdr.buf) == Read64("jartsr='")) {
for (p = M.ehdr.buf; p < M.ehdr.buf + sizeof(M.ehdr.buf); ++p) {
if (Read64(p) != Read64("printf '")) {
continue;
}
for (i = 0, p += 8; p + 3 < M.ehdr.buf + sizeof(M.ehdr.buf) && (c = *p++) != '\'';) {
if (c == '\\') {
if ('0' <= *p && *p <= '7') {
c = *p++ - '0';
if ('0' <= *p && *p <= '7') {
c *= 8;
c += *p++ - '0';
if ('0' <= *p && *p <= '7') {
c *= 8;
c += *p++ - '0';
}
}
}
}
M.ehdr.buf[i++] = c;
}
if (i >= sizeof(M.ehdr.ehdr)) {
TryElf(exe, fd, sp, bp, execfn, &M.ehdr, &M.phdr, &M.lib);
}
}
}
TryElf(exe, fd, sp, bp, execfn, &M.ehdr, &M.phdr, &M.lib);
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

@ -199,9 +199,8 @@
#define SKEW 0 #define SKEW 0
#endif #endif
#ifdef __aarch64__ #if IMAGE_BASE_VIRTUAL > 0xffffffff
#undef PAGESIZE #error "please use 32-bit addresses for image data"
#define PAGESIZE 16384
#endif #endif
ENTRY(_start) ENTRY(_start)
@ -223,7 +222,7 @@ SECTIONS {
/*BEGIN: bsd addressability guarantee */ /*BEGIN: bsd addressability guarantee */
.head SEGMENT_START("text-segment", IMAGE_BASE_VIRTUAL) + SKEW : AT(IMAGE_BASE_REAL) { .head SEGMENT_START("text-segment", IMAGE_BASE_VIRTUAL) + SKEW : AT(IMAGE_BASE_REAL) {
HIDDEN(_base = .); HIDDEN(__executable_start = .);
/* Real Mode */ /* Real Mode */
KEEP(*(.head)) KEEP(*(.head))
@ -650,6 +649,7 @@ TSSDESCSTUB2(_tss, _tss, _tss_end ? _tss_end - _tss - 1 : 0);
/* ZIP End of Central Directory header */ /* ZIP End of Central Directory header */
#define ZIPCONST(NAME, VAL) HIDDEN(NAME = DEFINED(__zip_start) ? VAL : 0); #define ZIPCONST(NAME, VAL) HIDDEN(NAME = DEFINED(__zip_start) ? VAL : 0);
ZIPCONST(v_zip_cdoffset, __zip_start - IMAGE_BASE_VIRTUAL); ZIPCONST(v_zip_cdoffset, __zip_start - IMAGE_BASE_VIRTUAL);
ZIPCONST(v_zip_cdoffset, __zip_start - IMAGE_BASE_VIRTUAL);
ZIPCONST(v_zip_cdirsize, __zip_end - __zip_start); ZIPCONST(v_zip_cdirsize, __zip_end - __zip_start);
ASSERT(v_zip_cdirsize % kZipCdirHdrLinkableSize == 0, "bad zip cdir"); ASSERT(v_zip_cdirsize % kZipCdirHdrLinkableSize == 0, "bad zip cdir");
ZIPCONST(v_zip_records, v_zip_cdirsize / kZipCdirHdrLinkableSize); ZIPCONST(v_zip_records, v_zip_cdirsize / kZipCdirHdrLinkableSize);

View file

@ -19,8 +19,9 @@ APE_FILES := $(wildcard ape/*.*)
APE_HDRS = $(filter %.h,$(APE_FILES)) APE_HDRS = $(filter %.h,$(APE_FILES))
APE_INCS = $(filter %.inc,$(APE_FILES)) APE_INCS = $(filter %.inc,$(APE_FILES))
APE = o/$(MODE)/ape/ape.o \ ifeq ($(ARCH), aarch64)
o/$(MODE)/ape/ape.lds
APE = o/$(MODE)/ape/aarch64.lds
APELINK = \ APELINK = \
$(COMPILE) \ $(COMPILE) \
@ -29,8 +30,6 @@ APELINK = \
$(LINKARGS) \ $(LINKARGS) \
$(OUTPUT_OPTION) $(OUTPUT_OPTION)
ifeq ($(ARCH), aarch64)
APE_SRCS = ape/ape.S APE_SRCS = ape/ape.S
APE_OBJS = o/$(MODE)/ape/ape.o APE_OBJS = o/$(MODE)/ape/ape.o
APE_NO_MODIFY_SELF = $(APE) APE_NO_MODIFY_SELF = $(APE)
@ -39,8 +38,26 @@ APE_COPY_SELF = $(APE)
.PHONY: o/$(MODE)/ape .PHONY: o/$(MODE)/ape
o/$(MODE)/ape: $(APE) o/$(MODE)/ape: $(APE)
o/$(MODE)/ape/aarch64.lds: \
ape/aarch64.lds \
libc/zip.h \
libc/intrin/bits.h \
libc/calls/struct/timespec.h \
libc/macros.internal.h \
libc/str/str.h
else else
APE = o/$(MODE)/ape/ape.o \
o/$(MODE)/ape/ape.lds
APELINK = \
$(COMPILE) \
-ALINK.ape \
$(LINK) \
$(LINKARGS) \
$(OUTPUT_OPTION)
APE_NO_MODIFY_SELF = \ APE_NO_MODIFY_SELF = \
o/$(MODE)/ape/ape.lds \ o/$(MODE)/ape/ape.lds \
o/$(MODE)/ape/ape-no-modify-self.o o/$(MODE)/ape/ape-no-modify-self.o

View file

@ -180,10 +180,13 @@ struct ElfPhdr {
extern char ehdr[]; extern char ehdr[];
extern char _end[]; extern char _end[];
static void *syscall_; static void *syscall_;
static char relocated;
static struct PathSearcher ps; static struct PathSearcher ps;
extern char __syscall_loader[]; extern char __syscall_loader[];
#if SET_EXE_FILE
static char relocated;
#endif
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;
} }

View file

@ -3,31 +3,31 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0) #if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_ COSMOPOLITAN_C_START_
extern unsigned char _base[]; extern unsigned char __executable_start[] __attribute__((__weak__));
extern unsigned char _ehead[]; extern unsigned char _ehead[] __attribute__((__weak__));
extern unsigned char _etext[]; extern unsigned char _etext[] __attribute__((__weak__));
extern unsigned char _edata[]; extern unsigned char _edata[] __attribute__((__weak__));
extern unsigned char _ezip[]; extern unsigned char _ezip[] __attribute__((__weak__));
extern unsigned char _end[]; extern unsigned char _end[] __attribute__((__weak__));
extern unsigned char _ereal[]; extern unsigned char _ereal[] __attribute__((__weak__));
extern unsigned char _tdata_start[]; extern unsigned char _tdata_start[] __attribute__((__weak__));
extern unsigned char _tdata_end[]; extern unsigned char _tdata_end[] __attribute__((__weak__));
extern unsigned char _tbss_start[]; extern unsigned char _tbss_start[] __attribute__((__weak__));
extern unsigned char _tbss_end[]; extern unsigned char _tbss_end[] __attribute__((__weak__));
extern unsigned char __privileged_start[]; extern unsigned char __privileged_start[] __attribute__((__weak__));
extern unsigned char __privileged_addr[]; extern unsigned char __privileged_addr[] __attribute__((__weak__));
extern unsigned char __privileged_size[]; extern unsigned char __privileged_size[] __attribute__((__weak__));
extern unsigned char __privileged_end[]; extern unsigned char __privileged_end[] __attribute__((__weak__));
extern unsigned char __test_start[]; extern unsigned char __test_start[] __attribute__((__weak__));
extern unsigned char __ro[]; extern unsigned char __ro[] __attribute__((__weak__));
extern unsigned char *__relo_start[]; extern unsigned char *__relo_start[] __attribute__((__weak__));
extern unsigned char *__relo_end[]; extern unsigned char *__relo_end[] __attribute__((__weak__));
extern uint8_t __zip_start[]; extern uint8_t __zip_start[] __attribute__((__weak__));
extern uint8_t __zip_end[]; extern uint8_t __zip_end[] __attribute__((__weak__));
extern uint8_t __data_start[]; extern uint8_t __data_start[] __attribute__((__weak__));
extern uint8_t __data_end[]; extern uint8_t __data_end[] __attribute__((__weak__));
extern uint8_t __bss_start[]; extern uint8_t __bss_start[] __attribute__((__weak__));
extern uint8_t __bss_end[]; extern uint8_t __bss_end[] __attribute__((__weak__));
COSMOPOLITAN_C_END_ COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

Binary file not shown.

View file

@ -192,6 +192,7 @@ PYFLAGS += \
endif endif
ifeq ($(MODE), aarch64-tiny) ifeq ($(MODE), aarch64-tiny)
# TODO(jart): -mcmodel=tiny
CONFIG_CPPFLAGS += \ CONFIG_CPPFLAGS += \
-DTINY \ -DTINY \
-DNDEBUG \ -DNDEBUG \
@ -203,7 +204,7 @@ CONFIG_CCFLAGS += \
-fno-align-labels \ -fno-align-labels \
-fno-align-loops \ -fno-align-loops \
-fschedule-insns2 \ -fschedule-insns2 \
-fomit-frame-pointer \ -fno-omit-frame-pointer \
-momit-leaf-frame-pointer \ -momit-leaf-frame-pointer \
-foptimize-sibling-calls \ -foptimize-sibling-calls \
-DDWARFLESS -DDWARFLESS

View file

@ -68,7 +68,6 @@ COMPILE = build/bootstrap/compile.com -V9 -P4096 $(QUOTA)
COMMA := , COMMA := ,
PWD := $(shell build/bootstrap/pwd.com) PWD := $(shell build/bootstrap/pwd.com)
IMAGE_BASE_VIRTUAL ?= 0x400000
IGNORE := $(shell $(ECHO) -2 ♥cosmo) IGNORE := $(shell $(ECHO) -2 ♥cosmo)
IGNORE := $(shell $(MKDIR) o/tmp) IGNORE := $(shell $(MKDIR) o/tmp)
@ -126,6 +125,12 @@ ifneq ($(ARCH), aarch64)
MNO_FENTRY = -mno-fentry MNO_FENTRY = -mno-fentry
endif endif
ifeq ($(ARCH), aarch64)
IMAGE_BASE_VIRTUAL ?= 0x010000000000
else
IMAGE_BASE_VIRTUAL ?= 0x400000
endif
FTRACE = \ FTRACE = \
-pg -pg
@ -169,7 +174,6 @@ DEFAULT_OFLAGS = \
DEFAULT_COPTS = \ DEFAULT_COPTS = \
-fno-math-errno \ -fno-math-errno \
-fno-fp-int-builtin-inexact \
-fno-ident \ -fno-ident \
-fno-common \ -fno-common \
-fno-gnu-unique \ -fno-gnu-unique \
@ -177,12 +181,25 @@ DEFAULT_COPTS = \
-fstrict-overflow \ -fstrict-overflow \
-fno-semantic-interposition -fno-semantic-interposition
ifneq ($(ARCH), aarch64) ifeq ($(ARCH), x86_64)
DEFAULT_COPTS += \ DEFAULT_COPTS += \
-mno-red-zone \ -mno-red-zone \
-mno-tls-direct-seg-refs -mno-tls-direct-seg-refs
endif endif
ifeq ($(ARCH), aarch64)
#
# - Apple says in "Writing ARM64 code for Apple platforms" that we're
# not allowed to use the x18 register.
#
# - Cosmopolitan Libc uses x28 for thread-local storage because Apple
# forbids us from using tpidr_el0 too.
#
DEFAULT_COPTS += \
-ffixed-x18 \
-ffixed-x28
endif
MATHEMATICAL = \ MATHEMATICAL = \
-O3 \ -O3 \
-fwrapv -fwrapv
@ -217,8 +234,18 @@ DEFAULT_LDFLAGS = \
-nostdlib \ -nostdlib \
--gc-sections \ --gc-sections \
--build-id=none \ --build-id=none \
--no-dynamic-linker \ --no-dynamic-linker #--cref -Map=$@.map
-zmax-page-size=0x1000 #--cref -Map=$@.map
ifeq ($(ARCH), aarch64)
DEFAULT_LDFLAGS += \
-zmax-page-size=0x4000 \
-zcommon-page-size=0x4000 \
-znorelro
else
DEFAULT_LDFLAGS += \
-zmax-page-size=0x1000 \
-zcommon-page-size=0x1000
endif
ZIPOBJ_FLAGS = \ ZIPOBJ_FLAGS = \
-b$(IMAGE_BASE_VIRTUAL) -b$(IMAGE_BASE_VIRTUAL)

View file

@ -16,18 +16,21 @@
MAKEFLAGS += --no-builtin-rules MAKEFLAGS += --no-builtin-rules
ifneq ($(ARCH), aarch64)
MAKE_OBJCOPY = $(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -S -O binary $< $@
else
MAKE_OBJCOPY = $(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -S $< $@
endif
o/%.lds: %.lds ; @$(COMPILE) -APREPROCESS $(PREPROCESS.lds) $(OUTPUT_OPTION) $< o/%.lds: %.lds ; @$(COMPILE) -APREPROCESS $(PREPROCESS.lds) $(OUTPUT_OPTION) $<
o/%.inc: %.h ; @$(COMPILE) -APREPROCESS $(PREPROCESS) $(OUTPUT_OPTION) -D__ASSEMBLER__ -P $< o/%.inc: %.h ; @$(COMPILE) -APREPROCESS $(PREPROCESS) $(OUTPUT_OPTION) -D__ASSEMBLER__ -P $<
o/%.greg.o: %.greg.c ; @$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $< o/$(MODE)/%: o/$(MODE)/%.dbg ; @$(MAKE_OBJCOPY)
o/$(MODE)/%: o/$(MODE)/%.dbg ; @$(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -S -O binary $< $@
o/$(MODE)/%.o: %.f ; @$(COMPILE) -AOBJECTIFY.f $(OBJECTIFY.f) $(OUTPUT_OPTION) $< o/$(MODE)/%.o: %.f ; @$(COMPILE) -AOBJECTIFY.f $(OBJECTIFY.f) $(OUTPUT_OPTION) $<
o/$(MODE)/%.o: %.F ; @$(COMPILE) -AOBJECTIFY.F $(OBJECTIFY.F) $(OUTPUT_OPTION) $< o/$(MODE)/%.o: %.F ; @$(COMPILE) -AOBJECTIFY.F $(OBJECTIFY.F) $(OUTPUT_OPTION) $<
o/$(MODE)/%.h: %.c ; @$(COMPILE) -AAMALGAMATE $(PREPROCESS) $(OUTPUT_OPTION) -fdirectives-only -P $< o/$(MODE)/%.h: %.c ; @$(COMPILE) -AAMALGAMATE $(PREPROCESS) $(OUTPUT_OPTION) -fdirectives-only -P $<
o/$(MODE)/%.h: o/$(MODE)/%.c ; @$(COMPILE) -AAMALGAMATE $(PREPROCESS) $(OUTPUT_OPTION) -fdirectives-only -P $< o/$(MODE)/%.h: o/$(MODE)/%.c ; @$(COMPILE) -AAMALGAMATE $(PREPROCESS) $(OUTPUT_OPTION) -fdirectives-only -P $<
o/$(MODE)/%.o: %.cc ; @$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $< o/$(MODE)/%.o: %.cc ; @$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
o/$(MODE)/%.lds: %.lds ; @$(COMPILE) -APREPROCESS $(PREPROCESS.lds) $(OUTPUT_OPTION) $< o/$(MODE)/%.lds: %.lds ; @$(COMPILE) -APREPROCESS $(PREPROCESS.lds) $(OUTPUT_OPTION) $<
o/$(MODE)/%.o: %.greg.c ; @$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
o/$(MODE)/%.greg.o: %.greg.c ; @$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
o/$(MODE)/%.initabi.o: %.initabi.c ; @$(COMPILE) -AOBJECTIFY.init $(OBJECTIFY.initabi.c) $(OUTPUT_OPTION) $< o/$(MODE)/%.initabi.o: %.initabi.c ; @$(COMPILE) -AOBJECTIFY.init $(OBJECTIFY.initabi.c) $(OUTPUT_OPTION) $<
o/$(MODE)/%.ncabi.o: %.ncabi.c ; @$(COMPILE) -AOBJECTIFY.nc $(OBJECTIFY.ncabi.c) $(OUTPUT_OPTION) $< o/$(MODE)/%.ncabi.o: %.ncabi.c ; @$(COMPILE) -AOBJECTIFY.nc $(OBJECTIFY.ncabi.c) $(OUTPUT_OPTION) $<
o/$(MODE)/%.real.o: %.c ; @$(COMPILE) -AOBJECTIFY.real $(OBJECTIFY.real.c) $(OUTPUT_OPTION) $< o/$(MODE)/%.real.o: %.c ; @$(COMPILE) -AOBJECTIFY.real $(OBJECTIFY.real.c) $(OUTPUT_OPTION) $<
@ -76,6 +79,18 @@ o/$(MODE)/%.o: o/$(MODE)/%.cc
@$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $< @$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
@$(COMPILE) -AFIXUPOBJ -wT$@ $(FIXUPOBJ) $@ @$(COMPILE) -AFIXUPOBJ -wT$@ $(FIXUPOBJ) $@
o/%.greg.o: %.greg.c
@$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
@$(COMPILE) -AFIXUPOBJ -wT$@ $(FIXUPOBJ) $@
o/$(MODE)/%.o: %.greg.c
@$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
@$(COMPILE) -AFIXUPOBJ -wT$@ $(FIXUPOBJ) $@
o/$(MODE)/%.greg.o: %.greg.c
@$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
@$(COMPILE) -AFIXUPOBJ -wT$@ $(FIXUPOBJ) $@
o/%.a: o/%.a:
$(file >$(TMPDIR)/$(subst /,_,$@),$^) $(file >$(TMPDIR)/$(subst /,_,$@),$^)
@$(COMPILE) -AARCHIVE -wT$@ $(AR) $(ARFLAGS) $@ @$(TMPDIR)/$(subst /,_,$@) @$(COMPILE) -AARCHIVE -wT$@ $(AR) $(ARFLAGS) $@ @$(TMPDIR)/$(subst /,_,$@)
@ -199,10 +214,6 @@ o/$(MODE)/%.okk: %
################################################################################ ################################################################################
# EXECUTABLE HELPERS # EXECUTABLE HELPERS
MAKE_OBJCOPY = \
$(COMPILE) -AOBJCOPY -T$@ \
$(OBJCOPY) -S -O binary $< $@
MAKE_SYMTAB_CREATE = \ MAKE_SYMTAB_CREATE = \
$(COMPILE) -wASYMTAB \ $(COMPILE) -wASYMTAB \
$(VM) \ $(VM) \

View file

@ -77,8 +77,8 @@ uint64_t unixv7(void) {
uint64_t ape(void) { uint64_t ape(void) {
static int i; static int i;
if ((i += 8) > _end - _base) i = 8; if ((i += 8) > _end - __executable_start) i = 8;
return READ64LE(_base + i); return READ64LE(__executable_start + i);
} }
uint64_t moby(void) { uint64_t moby(void) {

View file

@ -20,7 +20,7 @@
*/ */
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
if (_base[0] == 'M' && _base[1] == 'Z') { if (__executable_start[0] == 'M' && __executable_start[1] == 'Z') {
printf("success: %s spawned without needing to modify its " printf("success: %s spawned without needing to modify its "
"executable header", "executable header",
argv[0]); argv[0]);

View file

@ -16,52 +16,18 @@ void __assert_fail(const char *, const char *, int) _Hide relegated;
#define static_assert _Static_assert #define static_assert _Static_assert
#endif #endif
#ifdef __GNUC__ #ifndef NDEBUG
#if !defined(TINY) && !defined(MODE_DBG) #define _unassert(x) __assert_macro(x, #x)
/** #define _npassert(x) __assert_macro(x, #x)
* Specifies expression can't possibly be false. #define __assert_macro(x, s) \
*
* This macro uses the `notpossible` keyword and is intended for things
* like systems integration, where we know for a fact that something is
* never going to happen, but there's no proof. So we don't want to add
* extra bloat for filenames and line numbers, since `ShowCrashReports`
* can print a backtrace if we just embed the UD2 instruction to crash.
* That's useful for systems code, for the following reason. Invariants
* make sense with _unassert() since they usually get placed at the top
* of functions. But if you used _unassert() to test a system call does
* not fail, then check happens at the end of your function usually and
* is therefore likely to result in a failure condition where execution
* falls through into a different function, which is shocking to debug.
*
* In `MODE=tiny` these assertions are redefined as undefined behavior.
*/
#define _npassert(x) \
({ \ ({ \
if (__builtin_expect(!(x), 0)) { \ if (__builtin_expect(!(x), 0)) { \
__assert_fail(s, __FILE__, __LINE__); \
notpossible; \ notpossible; \
} \ } \
(void)0; \ (void)0; \
}) })
#else #else
#define _npassert(x) _unassert(x)
#endif
#endif
#ifdef __GNUC__
/**
* Specifies expression being false is undefined behavior.
*
* This is a good way to tell the compiler about your invariants, which
* leads to smaller faster programs. The expression is never removed by
* the preprocessor so it's recommended that it be free of side-effects
* if you intend for it to be removed. At the same time, this guarantee
* makes this assertion useful for things like system calls, since they
* won't be removed by `NDEBUG` mode.
*
* If this assertion fails, the worst possible things can happen unless
* you've built your binary in `MODE=dbg` since UBSAN is the only thing
* that's capable of debugging this macro.
*/
#define _unassert(x) \ #define _unassert(x) \
({ \ ({ \
if (__builtin_expect(!(x), 0)) { \ if (__builtin_expect(!(x), 0)) { \
@ -69,6 +35,16 @@ void __assert_fail(const char *, const char *, int) _Hide relegated;
} \ } \
(void)0; \ (void)0; \
}) })
#define _npassert(x) \
({ \
if (__builtin_expect(!(x), 0)) { \
notpossible; \
} \
(void)0; \
})
#endif
#ifdef __GNUC__
#endif #endif
COSMOPOLITAN_C_END_ COSMOPOLITAN_C_END_

View file

@ -134,7 +134,7 @@ static bool __sig_deliver(bool restartable, int sig, int si_code,
} }
// handover control to user // handover control to user
((sigaction_f)(_base + rva))(sig, infop, ctx); ((sigaction_f)(__executable_start + rva))(sig, infop, ctx);
if ((~flags & SA_NODEFER) && (~flags & SA_RESETHAND)) { if ((~flags & SA_NODEFER) && (~flags & SA_RESETHAND)) {
// it's now safe to reenter the signal so we need to restore it. // it's now safe to reenter the signal so we need to restore it.

View file

@ -188,6 +188,10 @@ o/$(MODE)/libc/calls/unveil.o: private \
OVERRIDE_CFLAGS += \ OVERRIDE_CFLAGS += \
-DSTACK_FRAME_UNLIMITED -DSTACK_FRAME_UNLIMITED
ifeq ($(ARCH), aarch64)
o/$(MODE)/libc/calls/sigaction.o: private OVERRIDE_CFLAGS += -mcmodel=large
endif
# we want -Os because: # we want -Os because:
# it makes a big difference # it makes a big difference
# we need pic because: # we need pic because:

26
libc/calls/err.c Normal file
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 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/errno.h"
extern _Thread_local int hog;
int dog(void) {
return hog;
}

View file

@ -24,7 +24,6 @@
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h" #include "libc/intrin/asan.internal.h"
#include "libc/intrin/describeflags.internal.h" #include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/likely.h" #include "libc/intrin/likely.h"
#include "libc/intrin/promises.internal.h" #include "libc/intrin/promises.internal.h"
#include "libc/intrin/strace.internal.h" #include "libc/intrin/strace.internal.h"

View file

@ -63,7 +63,7 @@ textstartup noasan void InitializeMetalFile(void) {
* The zipos code will automatically arrange to do this. Alternatively, * The zipos code will automatically arrange to do this. Alternatively,
* user code can STATIC_YOINK this symbol. * user code can STATIC_YOINK this symbol.
*/ */
size_t size = ROUNDUP(_ezip - _base, 4096); size_t size = ROUNDUP(_ezip - __executable_start, 4096);
void *copied_base; void *copied_base;
struct DirectMap dm; struct DirectMap dm;
dm = sys_mmap_metal(NULL, size, PROT_READ | PROT_WRITE, dm = sys_mmap_metal(NULL, size, PROT_READ | PROT_WRITE,

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/struct/sigaction.h" #include "libc/calls/struct/sigaction.h"
#include "ape/sections.internal.h"
#include "libc/assert.h" #include "libc/assert.h"
#include "libc/calls/blocksigs.internal.h" #include "libc/calls/blocksigs.internal.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
@ -168,9 +169,11 @@ static int __sigaction(int sig, const struct sigaction *act,
rva = (int32_t)(intptr_t)SIG_DFL; rva = (int32_t)(intptr_t)SIG_DFL;
} else if ((intptr_t)act->sa_handler < kSigactionMinRva) { } else if ((intptr_t)act->sa_handler < kSigactionMinRva) {
rva = (int)(intptr_t)act->sa_handler; rva = (int)(intptr_t)act->sa_handler;
} else if ((intptr_t)act->sa_handler >= (intptr_t)&_base + kSigactionMinRva && } else if ((intptr_t)act->sa_handler >=
(intptr_t)act->sa_handler < (intptr_t)&_base + INT_MAX) { (intptr_t)&__executable_start + kSigactionMinRva &&
rva = (int)((uintptr_t)act->sa_handler - (uintptr_t)&_base); (intptr_t)act->sa_handler <
(intptr_t)&__executable_start + INT_MAX) {
rva = (int)((uintptr_t)act->sa_handler - (uintptr_t)&__executable_start);
} else { } else {
return efault(); return efault();
} }
@ -249,8 +252,9 @@ static int __sigaction(int sig, const struct sigaction *act,
if (oldact) { if (oldact) {
oldrva = __sighandrvas[sig]; oldrva = __sighandrvas[sig];
oldact->sa_sigaction = oldact->sa_sigaction =
(sigaction_f)(oldrva < kSigactionMinRva ? oldrva (sigaction_f)(oldrva < kSigactionMinRva
: (intptr_t)&_base + oldrva); ? oldrva
: (intptr_t)&__executable_start + oldrva);
} }
if (act) { if (act) {
__sighandrvas[sig] = rva; __sighandrvas[sig] = rva;

View file

@ -45,7 +45,7 @@ privileged void __sigenter_freebsd(int sig, struct siginfo_freebsd *freebsdinfo,
if (rva >= kSigactionMinRva) { if (rva >= kSigactionMinRva) {
flags = __sighandflags[sig & (NSIG - 1)]; flags = __sighandflags[sig & (NSIG - 1)];
if (~flags & SA_SIGINFO) { if (~flags & SA_SIGINFO) {
((sigaction_f)(_base + rva))(sig, 0, 0); ((sigaction_f)(__executable_start + rva))(sig, 0, 0);
} else { } else {
__repstosb(&g, 0, sizeof(g)); __repstosb(&g, 0, sizeof(g));
g.uc.uc_mcontext.fpregs = &g.uc.__fpustate; g.uc.uc_mcontext.fpregs = &g.uc.__fpustate;
@ -78,7 +78,7 @@ privileged void __sigenter_freebsd(int sig, struct siginfo_freebsd *freebsdinfo,
g.uc.uc_mcontext.trapno = ctx->uc_mcontext.mc_trapno; g.uc.uc_mcontext.trapno = ctx->uc_mcontext.mc_trapno;
__repmovsb(&g.uc.__fpustate, &ctx->uc_mcontext.mc_fpstate, 512); __repmovsb(&g.uc.__fpustate, &ctx->uc_mcontext.mc_fpstate, 512);
__siginfo2cosmo(&g.si, (void *)freebsdinfo); __siginfo2cosmo(&g.si, (void *)freebsdinfo);
((sigaction_f)(_base + rva))(sig, &g.si, &g.uc); ((sigaction_f)(__executable_start + rva))(sig, &g.si, &g.uc);
ctx->uc_stack.ss_sp = g.uc.uc_stack.ss_sp; ctx->uc_stack.ss_sp = g.uc.uc_stack.ss_sp;
ctx->uc_stack.ss_size = g.uc.uc_stack.ss_size; ctx->uc_stack.ss_size = g.uc.uc_stack.ss_size;
ctx->uc_stack.ss_flags = g.uc.uc_stack.ss_flags; ctx->uc_stack.ss_flags = g.uc.uc_stack.ss_flags;

View file

@ -44,7 +44,7 @@ privileged void __sigenter_wsl(int sig, struct siginfo *info, ucontext_t *ctx) {
memcpy(ctx->__fpustate.st + i, &nan, 16); memcpy(ctx->__fpustate.st + i, &nan, 16);
} }
} }
((sigaction_f)(_base + rva))(sig, info, ctx); ((sigaction_f)(__executable_start + rva))(sig, info, ctx);
} }
} }

View file

@ -43,7 +43,7 @@ privileged void __sigenter_netbsd(int sig, struct siginfo_netbsd *si,
if (rva >= kSigactionMinRva) { if (rva >= kSigactionMinRva) {
flags = __sighandflags[sig & (NSIG - 1)]; flags = __sighandflags[sig & (NSIG - 1)];
if (~flags & SA_SIGINFO) { if (~flags & SA_SIGINFO) {
((sigaction_f)(_base + rva))(sig, 0, 0); ((sigaction_f)(__executable_start + rva))(sig, 0, 0);
} else { } else {
__repstosb(&uc, 0, sizeof(uc)); __repstosb(&uc, 0, sizeof(uc));
__siginfo2cosmo(&si2, (void *)si); __siginfo2cosmo(&si2, (void *)si);
@ -75,7 +75,7 @@ privileged void __sigenter_netbsd(int sig, struct siginfo_netbsd *si,
uc.uc_mcontext.rip = ctx->uc_mcontext.rip; uc.uc_mcontext.rip = ctx->uc_mcontext.rip;
uc.uc_mcontext.rsp = ctx->uc_mcontext.rsp; uc.uc_mcontext.rsp = ctx->uc_mcontext.rsp;
*uc.uc_mcontext.fpregs = ctx->uc_mcontext.__fpregs; *uc.uc_mcontext.fpregs = ctx->uc_mcontext.__fpregs;
((sigaction_f)(_base + rva))(sig, &si2, &uc); ((sigaction_f)(__executable_start + rva))(sig, &si2, &uc);
ctx->uc_stack.ss_sp = uc.uc_stack.ss_sp; ctx->uc_stack.ss_sp = uc.uc_stack.ss_sp;
ctx->uc_stack.ss_size = uc.uc_stack.ss_size; ctx->uc_stack.ss_size = uc.uc_stack.ss_size;
ctx->uc_stack.ss_flags = uc.uc_stack.ss_flags; ctx->uc_stack.ss_flags = uc.uc_stack.ss_flags;

View file

@ -45,7 +45,7 @@ privileged void __sigenter_openbsd(int sig, struct siginfo_openbsd *openbsdinfo,
if (rva >= kSigactionMinRva) { if (rva >= kSigactionMinRva) {
flags = __sighandflags[sig & (NSIG - 1)]; flags = __sighandflags[sig & (NSIG - 1)];
if (~flags & SA_SIGINFO) { if (~flags & SA_SIGINFO) {
((sigaction_f)(_base + rva))(sig, 0, 0); ((sigaction_f)(__executable_start + rva))(sig, 0, 0);
} else { } else {
__repstosb(&g.uc, 0, sizeof(g.uc)); __repstosb(&g.uc, 0, sizeof(g.uc));
__siginfo2cosmo(&g.si, (void *)openbsdinfo); __siginfo2cosmo(&g.si, (void *)openbsdinfo);
@ -76,7 +76,7 @@ privileged void __sigenter_openbsd(int sig, struct siginfo_openbsd *openbsdinfo,
if (ctx->sc_fpstate) { if (ctx->sc_fpstate) {
*g.uc.uc_mcontext.fpregs = *ctx->sc_fpstate; *g.uc.uc_mcontext.fpregs = *ctx->sc_fpstate;
} }
((sigaction_f)(_base + rva))(sig, &g.si, &g.uc); ((sigaction_f)(__executable_start + rva))(sig, &g.si, &g.uc);
ctx->sc_mask = g.uc.uc_sigmask.__bits[0]; ctx->sc_mask = g.uc.uc_sigmask.__bits[0];
ctx->sc_rdi = g.uc.uc_mcontext.rdi; ctx->sc_rdi = g.uc.uc_mcontext.rdi;
ctx->sc_rsi = g.uc.uc_mcontext.rsi; ctx->sc_rsi = g.uc.uc_mcontext.rsi;

View file

@ -31,7 +31,6 @@
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "libc/sysv/consts/sa.h" #include "libc/sysv/consts/sa.h"
#ifdef __x86_64__
/** /**
* @fileoverview XNU kernel callback normalization. * @fileoverview XNU kernel callback normalization.
@ -345,10 +344,37 @@ struct __darwin_mcontext_avx512_64_full {
struct __darwin_x86_avx512_state64 __fs; struct __darwin_x86_avx512_state64 __fs;
}; };
struct __darwin_arm_exception_state64 {
uint64_t far;
uint32_t esr;
uint32_t exception;
};
struct __darwin_arm_thread_state64 {
uint64_t __x[29];
uint64_t __fp;
uint64_t __lr;
uint64_t __sp;
uint64_t __pc;
uint32_t __cpsr;
uint32_t __pad;
};
struct __darwin_arm_vfp_state {
uint32_t __r[64];
uint32_t __fpscr;
};
struct __darwin_mcontext64 { struct __darwin_mcontext64 {
#ifdef __x86_64__
struct __darwin_x86_exception_state64 __es; struct __darwin_x86_exception_state64 __es;
struct __darwin_x86_thread_state64 __ss; struct __darwin_x86_thread_state64 __ss;
struct __darwin_x86_float_state64 __fs; struct __darwin_x86_float_state64 __fs;
#elif defined(__aarch64__)
struct __darwin_arm_exception_state64 __es;
struct __darwin_arm_thread_state64 __ss;
struct __darwin_arm_vfp_state __fs;
#endif
}; };
struct __darwin_ucontext { struct __darwin_ucontext {
@ -360,6 +386,8 @@ struct __darwin_ucontext {
struct __darwin_mcontext64 *uc_mcontext; struct __darwin_mcontext64 *uc_mcontext;
}; };
#ifdef __x86_64__
static privileged void xnuexceptionstate2linux( static privileged void xnuexceptionstate2linux(
mcontext_t *mc, struct __darwin_x86_exception_state64 *xnues) { mcontext_t *mc, struct __darwin_x86_exception_state64 *xnues) {
mc->trapno = xnues->__trapno; mc->trapno = xnues->__trapno;
@ -455,6 +483,8 @@ static privileged void linuxssefpustate2xnu(
CopyFpXmmRegs(&xnufs->__fpu_stmm0, fs->st); CopyFpXmmRegs(&xnufs->__fpu_stmm0, fs->st);
} }
#endif /* __x86_64__ */
privileged void __sigenter_xnu(void *fn, int infostyle, int sig, privileged void __sigenter_xnu(void *fn, int infostyle, int sig,
struct siginfo_xnu *xnuinfo, struct siginfo_xnu *xnuinfo,
struct __darwin_ucontext *xnuctx) { struct __darwin_ucontext *xnuctx) {
@ -468,15 +498,17 @@ privileged void __sigenter_xnu(void *fn, int infostyle, int sig,
if (rva >= kSigactionMinRva) { if (rva >= kSigactionMinRva) {
flags = __sighandflags[sig & (NSIG - 1)]; flags = __sighandflags[sig & (NSIG - 1)];
if (~flags & SA_SIGINFO) { if (~flags & SA_SIGINFO) {
((sigaction_f)(_base + rva))(sig, 0, 0); ((sigaction_f)(__executable_start + rva))(sig, 0, 0);
} else { } else {
__repstosb(&g, 0, sizeof(g)); __repstosb(&g, 0, sizeof(g));
if (xnuctx) { if (xnuctx) {
g.uc.uc_sigmask.__bits[0] = xnuctx->uc_sigmask; g.uc.uc_sigmask.__bits[0] = xnuctx->uc_sigmask;
g.uc.uc_sigmask.__bits[1] = 0; g.uc.uc_sigmask.__bits[1] = 0;
g.uc.uc_stack.ss_sp = xnuctx->uc_stack.ss_sp; g.uc.uc_stack.ss_sp = xnuctx->uc_stack.ss_sp;
g.uc.uc_stack.ss_flags = xnuctx->uc_stack.ss_flags; g.uc.uc_stack.ss_flags = xnuctx->uc_stack.ss_flags;
g.uc.uc_stack.ss_size = xnuctx->uc_stack.ss_size; g.uc.uc_stack.ss_size = xnuctx->uc_stack.ss_size;
#ifdef __x86_64__
g.uc.uc_mcontext.fpregs = &g.uc.__fpustate; g.uc.uc_mcontext.fpregs = &g.uc.__fpustate;
if (xnuctx->uc_mcontext) { if (xnuctx->uc_mcontext) {
if (xnuctx->uc_mcsize >= if (xnuctx->uc_mcsize >=
@ -493,16 +525,24 @@ privileged void __sigenter_xnu(void *fn, int infostyle, int sig,
xnussefpustate2linux(&g.uc.__fpustate, &xnuctx->uc_mcontext->__fs); xnussefpustate2linux(&g.uc.__fpustate, &xnuctx->uc_mcontext->__fs);
} }
} }
#elif defined(__aarch64__)
if (xnuctx->uc_mcontext) {
memcpy(g.uc.uc_mcontext.regs, &xnuctx->uc_mcontext->__ss.__x, 33 * 8);
} }
#endif /* __x86_64__ */
}
if (xnuinfo) { if (xnuinfo) {
__siginfo2cosmo(&g.si, (void *)xnuinfo); __siginfo2cosmo(&g.si, (void *)xnuinfo);
} }
((sigaction_f)(_base + rva))(sig, &g.si, &g.uc); ((sigaction_f)(__executable_start + rva))(sig, &g.si, &g.uc);
if (xnuctx) { if (xnuctx) {
xnuctx->uc_stack.ss_sp = g.uc.uc_stack.ss_sp; xnuctx->uc_stack.ss_sp = g.uc.uc_stack.ss_sp;
xnuctx->uc_stack.ss_flags = g.uc.uc_stack.ss_flags; xnuctx->uc_stack.ss_flags = g.uc.uc_stack.ss_flags;
xnuctx->uc_stack.ss_size = g.uc.uc_stack.ss_size; xnuctx->uc_stack.ss_size = g.uc.uc_stack.ss_size;
xnuctx->uc_sigmask = g.uc.uc_sigmask.__bits[0]; xnuctx->uc_sigmask = g.uc.uc_sigmask.__bits[0];
#ifdef __x86_64__
if (xnuctx->uc_mcontext) { if (xnuctx->uc_mcontext) {
if (xnuctx->uc_mcsize >= if (xnuctx->uc_mcsize >=
sizeof(struct __darwin_x86_exception_state64)) { sizeof(struct __darwin_x86_exception_state64)) {
@ -519,14 +559,29 @@ privileged void __sigenter_xnu(void *fn, int infostyle, int sig,
linuxssefpustate2xnu(&xnuctx->uc_mcontext->__fs, &g.uc.__fpustate); linuxssefpustate2xnu(&xnuctx->uc_mcontext->__fs, &g.uc.__fpustate);
} }
} }
#elif defined(__aarch64__)
if (xnuctx->uc_mcontext) {
memcpy(&xnuctx->uc_mcontext->__ss.__x, g.uc.uc_mcontext.regs, 33 * 8);
}
#endif /* __x86_64__ */
} }
} }
} }
#ifdef __x86_64__
asm volatile("syscall" asm volatile("syscall"
: "=a"(ax) : "=a"(ax)
: "0"(0x20000b8 /* sigreturn */), "D"(xnuctx), "S"(infostyle) : "0"(0x20000b8 /* sigreturn */), "D"(xnuctx), "S"(infostyle)
: "rcx", "r11", "memory", "cc"); : "rcx", "r11", "memory", "cc");
#else
register long r0 asm("x0") = (long)xnuctx;
register long r1 asm("x1") = (long)infostyle;
asm volatile("mov\tx16,%0\n\t"
"svc\t0"
: /* no outputs */
: "i"(0x0b8 /* sigreturn */), "r"(r0), "r"(r1)
: "x16", "memory");
#endif /* __x86_64__ */
notpossible; notpossible;
} }
#endif

View file

@ -17,9 +17,27 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/calls.h" #include "libc/calls/calls.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"
#include "libc/sysv/consts/nr.h"
static inline unsigned sys_umask(unsigned newmask) {
#ifdef __x86_64__
unsigned res;
asm volatile("syscall"
: "=a"(res)
: "0"(__NR_umask), "D"(newmask)
: "memory", "cc");
#elif defined(__aarch64__)
// xnu m1 doesn't manage carry flag
register long r0 asm("x0") = newmask;
register long r8 asm("x8") = __NR_umask & 0x7ff;
register long r16 asm("x16") = __NR_umask & 0x7ff;
register unsigned res asm("x0");
asm volatile("svc\t0" : "=r"(res) : "r"(r0), "r"(r8), "r"(r16) : "memory");
#endif
return res;
}
/** /**
* Sets file mode creation mask. * Sets file mode creation mask.

View file

@ -43,7 +43,7 @@
#define nlink_t uint64_t #define nlink_t uint64_t
#elif defined(__aarch64__) #elif defined(__aarch64__)
#define blksize_t int32_t #define blksize_t int32_t
#define nlink_t uint32_t #define nlink_t uint32_t /* uint16_t on xnu */
#endif #endif
#define TIME_T_MAX __INT64_MAX__ #define TIME_T_MAX __INT64_MAX__

View file

@ -128,6 +128,11 @@ _start:
// setup backtraces // setup backtraces
mov x29,#0 mov x29,#0
// second arg shall be struct Syslib passed by ape-m1.c
// used to talk to apple's authoritarian libraries
// should be set to zero on other platforms
mov x1,x15
// switch to c code // switch to c code
bl cosmo bl cosmo
.unreachable .unreachable

View file

@ -12,7 +12,7 @@
*/ */
#define SUPPORT_VECTOR 255 #define SUPPORT_VECTOR 255
#else #else
#define SUPPORT_VECTOR _HOSTLINUX #define SUPPORT_VECTOR (_HOSTLINUX | _HOSTXNU)
#endif #endif
#endif #endif
@ -110,11 +110,11 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0) #if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_ COSMOPOLITAN_C_START_
#ifdef __x86_64__
extern const int __hostos; extern const int __hostos;
#ifdef __x86_64__
bool IsWsl1(void); bool IsWsl1(void);
#else #else
#define __hostos _HOSTLINUX
#define IsWsl1() false #define IsWsl1() false
#endif #endif

View file

@ -29,7 +29,7 @@
#define __memchr_aarch64 memchr #define __memchr_aarch64 memchr
.ident "\n\ .ident "\n\n\
Optimized Routines (MIT License)\n\ Optimized Routines (MIT License)\n\
Copyright 2022 ARM Limited\n" Copyright 2022 ARM Limited\n"
.include "libc/disclaimer.inc" .include "libc/disclaimer.inc"

View file

@ -29,7 +29,7 @@
#define __memcmp_aarch64 memcmp #define __memcmp_aarch64 memcmp
.ident "\n\ .ident "\n\n\
Optimized Routines (MIT License)\n\ Optimized Routines (MIT License)\n\
Copyright 2022 ARM Limited\n" Copyright 2022 ARM Limited\n"
.include "libc/disclaimer.inc" .include "libc/disclaimer.inc"

View file

@ -30,7 +30,7 @@
#define __memcpy_aarch64_simd memcpy #define __memcpy_aarch64_simd memcpy
#define __memmove_aarch64_simd memmove #define __memmove_aarch64_simd memmove
.ident "\n\ .ident "\n\n\
Optimized Routines (MIT License)\n\ Optimized Routines (MIT License)\n\
Copyright 2022 ARM Limited\n" Copyright 2022 ARM Limited\n"
.include "libc/disclaimer.inc" .include "libc/disclaimer.inc"

View file

@ -29,7 +29,7 @@
#define __memrchr_aarch64 memrchr #define __memrchr_aarch64 memrchr
.ident "\n\ .ident "\n\n\
Optimized Routines (MIT License)\n\ Optimized Routines (MIT License)\n\
Copyright 2022 ARM Limited\n" Copyright 2022 ARM Limited\n"
.include "libc/disclaimer.inc" .include "libc/disclaimer.inc"

View file

@ -29,7 +29,7 @@
#define __memset_aarch64 memset #define __memset_aarch64 memset
.ident "\n\ .ident "\n\n\
Optimized Routines (MIT License)\n\ Optimized Routines (MIT License)\n\
Copyright 2022 ARM Limited\n" Copyright 2022 ARM Limited\n"
.include "libc/disclaimer.inc" .include "libc/disclaimer.inc"

View file

@ -29,7 +29,7 @@
#define __stpcpy_aarch64 stpcpy #define __stpcpy_aarch64 stpcpy
.ident "\n\ .ident "\n\n\
Optimized Routines (MIT License)\n\ Optimized Routines (MIT License)\n\
Copyright 2022 ARM Limited\n" Copyright 2022 ARM Limited\n"
.include "libc/disclaimer.inc" .include "libc/disclaimer.inc"

View file

@ -29,7 +29,7 @@
#define __strchr_aarch64 strchr #define __strchr_aarch64 strchr
.ident "\n\ .ident "\n\n\
Optimized Routines (MIT License)\n\ Optimized Routines (MIT License)\n\
Copyright 2022 ARM Limited\n" Copyright 2022 ARM Limited\n"
.include "libc/disclaimer.inc" .include "libc/disclaimer.inc"

View file

@ -29,7 +29,7 @@
#define __strchrnul_aarch64 strchrnul #define __strchrnul_aarch64 strchrnul
.ident "\n\ .ident "\n\n\
Optimized Routines (MIT License)\n\ Optimized Routines (MIT License)\n\
Copyright 2022 ARM Limited\n" Copyright 2022 ARM Limited\n"
.include "libc/disclaimer.inc" .include "libc/disclaimer.inc"

View file

@ -29,7 +29,7 @@
#define __strcmp_aarch64 strcmp #define __strcmp_aarch64 strcmp
.ident "\n\ .ident "\n\n\
Optimized Routines (MIT License)\n\ Optimized Routines (MIT License)\n\
Copyright 2022 ARM Limited\n" Copyright 2022 ARM Limited\n"
.include "libc/disclaimer.inc" .include "libc/disclaimer.inc"

View file

@ -29,7 +29,7 @@
#define __strcpy_aarch64 strcpy #define __strcpy_aarch64 strcpy
.ident "\n\ .ident "\n\n\
Optimized Routines (MIT License)\n\ Optimized Routines (MIT License)\n\
Copyright 2022 ARM Limited\n" Copyright 2022 ARM Limited\n"
.include "libc/disclaimer.inc" .include "libc/disclaimer.inc"

View file

@ -29,7 +29,7 @@
#define __strlen_aarch64 strlen #define __strlen_aarch64 strlen
.ident "\n\ .ident "\n\n\
Optimized Routines (MIT License)\n\ Optimized Routines (MIT License)\n\
Copyright 2022 ARM Limited\n" Copyright 2022 ARM Limited\n"
.include "libc/disclaimer.inc" .include "libc/disclaimer.inc"

View file

@ -29,7 +29,7 @@
#define __strncmp_aarch64 strncmp #define __strncmp_aarch64 strncmp
.ident "\n\ .ident "\n\n\
Optimized Routines (MIT License)\n\ Optimized Routines (MIT License)\n\
Copyright 2022 ARM Limited\n" Copyright 2022 ARM Limited\n"
.include "libc/disclaimer.inc" .include "libc/disclaimer.inc"

View file

@ -29,7 +29,7 @@
#define __strnlen_aarch64 strnlen #define __strnlen_aarch64 strnlen
.ident "\n\ .ident "\n\n\
Optimized Routines (MIT License)\n\ Optimized Routines (MIT License)\n\
Copyright 2022 ARM Limited\n" Copyright 2022 ARM Limited\n"
.include "libc/disclaimer.inc" .include "libc/disclaimer.inc"

View file

@ -29,7 +29,7 @@
#define __strrchr_aarch64 strrchr #define __strrchr_aarch64 strrchr
.ident "\n\ .ident "\n\n\
Optimized Routines (MIT License)\n\ Optimized Routines (MIT License)\n\
Copyright 2022 ARM Limited\n" Copyright 2022 ARM Limited\n"
.include "libc/disclaimer.inc" .include "libc/disclaimer.inc"

View file

@ -412,7 +412,7 @@ static bool __asan_is_mapped(int x) {
} }
static bool __asan_is_image(const unsigned char *p) { static bool __asan_is_image(const unsigned char *p) {
return _base <= p && p < _end; return __executable_start <= p && p < _end;
} }
static bool __asan_exists(const void *x) { static bool __asan_exists(const void *x) {
@ -823,7 +823,7 @@ static void __asan_report_memory_origin(const unsigned char *addr, int size,
default: default:
break; break;
} }
if (_base <= addr && addr < _end) { if (__executable_start <= addr && addr < _end) {
__asan_report_memory_origin_image((intptr_t)addr, size); __asan_report_memory_origin_image((intptr_t)addr, size);
} else if (IsAutoFrame((intptr_t)addr >> 16)) { } else if (IsAutoFrame((intptr_t)addr >> 16)) {
__asan_report_memory_origin_heap(addr, size); __asan_report_memory_origin_heap(addr, size);
@ -898,7 +898,7 @@ dontdiscard static __asan_die_f *__asan_report(const void *addr, int size,
} }
*p++ = '\n'; *p++ = '\n';
} }
p = __asan_format_section(p, _base, _etext, ".text", addr); p = __asan_format_section(p, __executable_start, _etext, ".text", addr);
p = __asan_format_section(p, _etext, _edata, ".data", addr); p = __asan_format_section(p, _etext, _edata, ".data", addr);
p = __asan_format_section(p, _end, _edata, ".bss", addr); p = __asan_format_section(p, _end, _edata, ".bss", addr);
__mmi_lock(); __mmi_lock();
@ -1487,7 +1487,7 @@ void __asan_init(int argc, char **argv, char **envp, intptr_t *auxv) {
REQUIRE(dlmalloc_usable_size); REQUIRE(dlmalloc_usable_size);
} }
__asan_shadow_existing_mappings(); __asan_shadow_existing_mappings();
__asan_map_shadow((uintptr_t)_base, _end - _base); __asan_map_shadow((uintptr_t)__executable_start, _end - __executable_start);
__asan_map_shadow(0, 4096); __asan_map_shadow(0, 4096);
__asan_poison(0, GUARDSIZE, kAsanNullPage); __asan_poison(0, GUARDSIZE, kAsanNullPage);
if (!IsWindows()) { if (!IsWindows()) {

View file

@ -20,6 +20,7 @@
#include "libc/atomic.h" #include "libc/atomic.h"
#include "libc/calls/state.internal.h" #include "libc/calls/state.internal.h"
#include "libc/calls/syscall-sysv.internal.h" #include "libc/calls/syscall-sysv.internal.h"
#include "libc/errno.h"
#include "libc/intrin/atomic.h" #include "libc/intrin/atomic.h"
#include "libc/intrin/kprintf.h" #include "libc/intrin/kprintf.h"
#include "libc/intrin/weaken.h" #include "libc/intrin/weaken.h"
@ -38,7 +39,7 @@ relegated void __assert_fail(const char *expr, const char *file, int line) {
owner = 0; owner = 0;
me = sys_gettid(); me = sys_gettid();
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0);
kprintf("%s:%d: assert(%s) failed (tid %d)\n", file, line, expr, me); kprintf("%s:%d: assert(%s) failed (tid %d) %m\n", file, line, expr, me);
if (__vforked || if (__vforked ||
atomic_compare_exchange_strong_explicit( 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

@ -66,7 +66,7 @@ static const char *GetFrameName(int x) {
sizeof(struct WinArgs) - 1) >> sizeof(struct WinArgs) - 1) >>
16))) { 16))) {
return "winargs"; return "winargs";
} else if ((int)((intptr_t)_base >> 16) <= x && } else if ((int)((intptr_t)__executable_start >> 16) <= x &&
x <= (int)(((intptr_t)_end - 1) >> 16)) { x <= (int)(((intptr_t)_end - 1) >> 16)) {
return "image"; return "image";
} else { } else {

View file

@ -62,9 +62,11 @@ struct DirectMap sys_mmap(void *addr, size_t size, int prot, int flags, int fd,
register long res_x0 asm("x0"); register long res_x0 asm("x0");
long res; long res;
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_x0)
: "i"(222), "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5) : "i"(222), "i"(197), "r"(r0), "r"(r1), "r"(r2), "r"(r3),
"r"(r4), "r"(r5)
: "x8", "memory"); : "x8", "memory");
res = res_x0; res = res_x0;
if ((unsigned long)res >= (unsigned long)-4095) { if ((unsigned long)res >= (unsigned long)-4095) {

View file

@ -68,10 +68,11 @@ wontreturn void _Exit(int exitcode) {
#elif defined(__aarch64__) #elif defined(__aarch64__)
register long x0 asm("x0") = exitcode; register long x0 asm("x0") = exitcode;
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"(94), "r"(x0) : "i"(94), "i"(1), "r"(x0)
: "x8", "memory"); : "x8", "x16", "memory");
notpossible; notpossible;
#else #else
#error "arch unsupported" #error "arch unsupported"

View file

@ -76,9 +76,10 @@ privileged wontreturn void _Exit1(int rc) {
#elif defined(__aarch64__) #elif defined(__aarch64__)
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), "r"(r0) : "i"(93), "i"(0x169), "r"(r0)
: "x8", "memory"); : "x8", "memory");
notpossible; notpossible;
#else #else

View file

@ -130,11 +130,13 @@ privileged static inline bool kiskernelpointer(const void *p) {
} }
privileged static inline bool kistextpointer(const void *p) { privileged static inline bool kistextpointer(const void *p) {
return _base <= (const unsigned char *)p && (const unsigned char *)p < _etext; return __executable_start <= (const unsigned char *)p &&
(const unsigned char *)p < _etext;
} }
privileged static inline bool kisimagepointer(const void *p) { privileged static inline bool kisimagepointer(const void *p) {
return _base <= (const unsigned char *)p && (const unsigned char *)p < _end; return __executable_start <= (const unsigned char *)p &&
(const unsigned char *)p < _end;
} }
privileged static inline bool kischarmisaligned(const char *p, signed char t) { privileged static inline bool kischarmisaligned(const char *p, signed char t) {
@ -224,11 +226,12 @@ privileged static 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; register long r8 asm("x8") = (long)__NR_write & 0x7ff;
register long r16 asm("x16") = (long)__NR_write & 0x7ff;
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)
: "r"(r0), "r"(r1), "r"(r2), "r"(r8) : "r"(r0), "r"(r1), "r"(r2), "r"(r8), "r"(r16)
: "memory"); : "memory");
#else #else
#error "unsupported architecture" #error "unsupported architecture"

View file

@ -20,7 +20,7 @@
#define _NOPL_PROLOGUE(SECTION) \ #define _NOPL_PROLOGUE(SECTION) \
".section \".sort.rodata." SECTION ".1" \ ".section \".sort.rodata." SECTION ".1" \
"\",\"aG\",@progbits,\"" SECTION "\",comdat\n\t" \ "\",\"aG\",@progbits,\"" SECTION "\",comdat\n\t" \
".align\t4\n\t" \ ".balign\t4\n\t" \
".type\t\"" SECTION "_start\",@object\n\t" \ ".type\t\"" SECTION "_start\",@object\n\t" \
".globl\t\"" SECTION "_start\"\n\t" \ ".globl\t\"" SECTION "_start\"\n\t" \
".equ\t\"" SECTION "_start\",.\n\t" \ ".equ\t\"" SECTION "_start\",.\n\t" \
@ -29,7 +29,7 @@
#define _NOPL_EPILOGUE(SECTION) \ #define _NOPL_EPILOGUE(SECTION) \
".section \".sort.rodata." SECTION ".3" \ ".section \".sort.rodata." SECTION ".3" \
"\",\"aG\",@progbits,\"" SECTION "\",comdat\n\t" \ "\",\"aG\",@progbits,\"" SECTION "\",comdat\n\t" \
".align\t4\n\t" \ ".balign\t4\n\t" \
".type\"" SECTION "_end\",@object\n\t" \ ".type\"" SECTION "_end\",@object\n\t" \
".globl\t\"" SECTION "_end\"\n\t" \ ".globl\t\"" SECTION "_end\"\n\t" \
".equ\t\"" SECTION "_end\",.\n\t" \ ".equ\t\"" SECTION "_end\",.\n\t" \
@ -40,7 +40,7 @@
asm volatile(_NOPL_PROLOGUE(SECTION) /* */ \ asm volatile(_NOPL_PROLOGUE(SECTION) /* */ \
_NOPL_EPILOGUE(SECTION) /* */ \ _NOPL_EPILOGUE(SECTION) /* */ \
".section \".sort.rodata." SECTION ".2\",\"a\",@progbits\n\t" \ ".section \".sort.rodata." SECTION ".2\",\"a\",@progbits\n\t" \
".align\t4\n\t" \ ".balign\t4\n\t" \
".long\t353f-%a1\n\t" \ ".long\t353f-%a1\n\t" \
".previous\n353:\t" \ ".previous\n353:\t" \
"nopl\t%a0" \ "nopl\t%a0" \
@ -57,7 +57,7 @@
asm volatile(_NOPL_PROLOGUE(SECTION) /* */ \ asm volatile(_NOPL_PROLOGUE(SECTION) /* */ \
_NOPL_EPILOGUE(SECTION) /* */ \ _NOPL_EPILOGUE(SECTION) /* */ \
".section \".sort.rodata." SECTION ".2\",\"a\",@progbits\n\t" \ ".section \".sort.rodata." SECTION ".2\",\"a\",@progbits\n\t" \
".align\t4\n\t" \ ".balign\t4\n\t" \
".long\t353f-%a2\n\t" \ ".long\t353f-%a2\n\t" \
".previous\n353:\t" \ ".previous\n353:\t" \
"nopl\t%a1" \ "nopl\t%a1" \

View file

@ -19,6 +19,7 @@
#include "libc/intrin/kprintf.h" #include "libc/intrin/kprintf.h"
#include "libc/intrin/strace.internal.h" #include "libc/intrin/strace.internal.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/thread/tls.h"
#include "libc/thread/tls2.h" #include "libc/thread/tls2.h"
privileged void __stracef(const char *fmt, ...) { privileged void __stracef(const char *fmt, ...) {

View file

@ -65,9 +65,10 @@ privileged int sys_gettid(void) {
#elif defined(__aarch64__) #elif defined(__aarch64__)
register long res_x0 asm("x0"); register long res_x0 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_x0)
: "i"(178) : "i"(178), "i"(186)
: "x8", "memory"); : "x8", "memory");
return res_x0; return res_x0;
#else #else

View file

@ -12,7 +12,7 @@ COSMOPOLITAN_C_START_
bool Cond; \ bool Cond; \
struct countbranch *Info; \ struct countbranch *Info; \
asm(".section .rodata.str1.1,\"aMS\",@progbits,1\n\t" \ asm(".section .rodata.str1.1,\"aMS\",@progbits,1\n\t" \
".align\t1\n" \ ".balign\t1\n" \
"31338:\t" \ "31338:\t" \
".asciz\t" xs "\n" \ ".asciz\t" xs "\n" \
"31339:\t" \ "31339:\t" \
@ -24,7 +24,7 @@ COSMOPOLITAN_C_START_
"nopl\tcountbranch_data(%%rip)\n\t" \ "nopl\tcountbranch_data(%%rip)\n\t" \
".previous\n\t" \ ".previous\n\t" \
".section .sort.data.countbranch.2,\"a\",@progbits\n\t" \ ".section .sort.data.countbranch.2,\"a\",@progbits\n\t" \
".align\t8\n31337:\t" \ ".balign\t8\n31337:\t" \
".quad\t0\n\t" \ ".quad\t0\n\t" \
".quad\t0\n\t" \ ".quad\t0\n\t" \
".quad\t31338b\n\t" \ ".quad\t31338b\n\t" \

View file

@ -40,7 +40,7 @@ COSMOPOLITAN_C_START_
t2_ = stop(); \ t2_ = stop(); \
TiCkS = t2_ >= t1_ ? t2_ - t1_ : ~t1_ + t2_ + 1; \ TiCkS = t2_ >= t1_ ? t2_ - t1_ : ~t1_ + t2_ + 1; \
asm(".section .rodata.str1.1,\"aMS\",@progbits,1\n\t" \ asm(".section .rodata.str1.1,\"aMS\",@progbits,1\n\t" \
".align\t1\n" \ ".balign\t1\n" \
"31340:\t.asciz\t" file "\n\t" \ "31340:\t.asciz\t" file "\n\t" \
"31338:\t.asciz\t" code "\n" \ "31338:\t.asciz\t" code "\n" \
"31332:\t.asciz\t" macro "\n" \ "31332:\t.asciz\t" macro "\n" \
@ -49,7 +49,7 @@ COSMOPOLITAN_C_START_
"nopl\tcountexpr_data(%%rip)\n\t" \ "nopl\tcountexpr_data(%%rip)\n\t" \
".previous\n\t" \ ".previous\n\t" \
".section .sort.data.countexpr.2,\"a\",@progbits\n\t" \ ".section .sort.data.countexpr.2,\"a\",@progbits\n\t" \
".align\t8\n31337:\t" \ ".balign\t8\n31337:\t" \
".quad\t" #line "\n\t" \ ".quad\t" #line "\n\t" \
".quad\t31340b\n\t" \ ".quad\t31340b\n\t" \
".quad\t31338b\n\t" \ ".quad\t31338b\n\t" \

View file

@ -19,12 +19,13 @@ forceinline long __sysv_exit(long rc) {
: "memory", "cc"); : "memory", "cc");
#elif defined(__aarch64__) #elif defined(__aarch64__)
register long r0 asm("x0") = rc; register long r0 asm("x0") = rc;
register long r8 asm("x8") = __NR_exit_group; register long r8 asm("x8") = __NR_exit_group & 0x7ff;
register long r16 asm("x16") = __NR_exit_group & 0x7ff;
register long res_x0 asm("x0"); register long res_x0 asm("x0");
asm volatile("svc\t0" : "=r"(res_x0) : "r"(r0), "r"(r8) : "memory"); asm volatile("svc\t0" : "=r"(res_x0) : "r"(r0), "r"(r8), "r"(r16) : "memory");
ax = res_x0; ax = res_x0;
#else #else
ax = syscall(__NR_exit_group, rc); ax = syscall(__NR_exit_group & 0x7ff, rc);
#endif #endif
return ax; return ax;
} }
@ -38,16 +39,17 @@ forceinline int __sysv_close(long fd) {
: "rdx", "memory", "cc"); : "rdx", "memory", "cc");
#elif defined(__aarch64__) #elif defined(__aarch64__)
register long r0 asm("x0") = fd; register long r0 asm("x0") = fd;
register long r8 asm("x8") = __NR_close; register long r8 asm("x8") = __NR_close & 0x7ff;
register long r16 asm("x16") = __NR_close & 0x7ff;
register long res_x0 asm("x0"); register long res_x0 asm("x0");
asm volatile("mov\tx8,%1\n\t" asm volatile("mov\tx8,%1\n\t"
"svc\t0" "svc\t0"
: "=r"(res_x0) : "=r"(res_x0)
: "r"(r0), "r"(r8) : "r"(r0), "r"(r8), "r"(r16)
: "memory"); : "memory");
ax = res_x0; ax = res_x0;
#else #else
ax = syscall(__NR_close, fd); ax = syscall(__NR_close & 0x7ff, fd);
#endif #endif
return ax; return ax;
} }
@ -64,15 +66,16 @@ forceinline int __sysv_open(const char *path, long flags, long mode) {
register long r1 asm("x1") = (long)path; register long r1 asm("x1") = (long)path;
register long r2 asm("x2") = (long)flags; register long r2 asm("x2") = (long)flags;
register long r3 asm("x3") = (long)mode; register long r3 asm("x3") = (long)mode;
register long r8 asm("x8") = (long)__NR_open; register long r8 asm("x8") = (long)__NR_open & 0x7ff;
register long r16 asm("x16") = (long)__NR_open & 0x7ff;
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)
: "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r8) : "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r8), "r"(r16)
: "memory"); : "memory");
ax = res_x0; ax = res_x0;
#else #else
ax = syscall(__NR_open, path, flags, mode); ax = syscall(__NR_open & 0x7ff, path, flags, mode);
#endif #endif
return ax; return ax;
} }
@ -88,15 +91,16 @@ forceinline long __sysv_read(long fd, void *data, unsigned long size) {
register long r0 asm("x0") = (long)fd; register long r0 asm("x0") = (long)fd;
register long r1 asm("x1") = (long)data; register long r1 asm("x1") = (long)data;
register long r2 asm("x2") = (long)size; register long r2 asm("x2") = (long)size;
register long r8 asm("x8") = (long)__NR_read; register long r8 asm("x8") = (long)__NR_read & 0x7ff;
register long r16 asm("x16") = (long)__NR_read & 0x7ff;
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)
: "r"(r0), "r"(r1), "r"(r2), "r"(r8) : "r"(r0), "r"(r1), "r"(r2), "r"(r8), "r"(r16)
: "memory"); : "memory");
ax = res_x0; ax = res_x0;
#else #else
ax = syscall(__NR_read, fd, data, size); ax = syscall(__NR_read & 0x7ff, fd, data, size);
#endif #endif
return ax; return ax;
} }
@ -112,15 +116,16 @@ forceinline long __sysv_write(long fd, const void *data, unsigned long size) {
register long r0 asm("x0") = (long)fd; register long r0 asm("x0") = (long)fd;
register long r1 asm("x1") = (long)data; register long r1 asm("x1") = (long)data;
register long r2 asm("x2") = (long)size; register long r2 asm("x2") = (long)size;
register long r8 asm("x8") = (long)__NR_write; register long r8 asm("x8") = (long)__NR_write & 0x7ff;
register long r16 asm("x16") = (long)__NR_write & 0x7ff;
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)
: "i"(64), "r"(r0), "r"(r1), "r"(r2), "r"(r8) : "i"(64), "r"(r0), "r"(r1), "r"(r2), "r"(r8), "r"(r16)
: "memory"); : "memory");
ax = res_x0; ax = res_x0;
#else #else
ax = syscall(__NR_write, fd, data, size); ax = syscall(__NR_write & 0x7ff, fd, data, size);
#endif #endif
return ax; return ax;
} }
@ -136,15 +141,16 @@ forceinline long __sysv_mprotect(void *addr, size_t size, long prot) {
register long r0 asm("x0") = (long)addr; register long r0 asm("x0") = (long)addr;
register long r1 asm("x1") = (long)size; register long r1 asm("x1") = (long)size;
register long r2 asm("x2") = (long)prot; register long r2 asm("x2") = (long)prot;
register long r8 asm("x8") = (long)__NR_mprotect; register long r8 asm("x8") = (long)__NR_mprotect & 0x7ff;
register long r16 asm("x16") = (long)__NR_mprotect & 0x7ff;
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)
: "r"(r0), "r"(r1), "r"(r2), "r"(r8) : "r"(r0), "r"(r1), "r"(r2), "r"(r8), "r"(r16)
: "memory"); : "memory");
ax = res_x0; ax = res_x0;
#else #else
ax = syscall(__NR_mprotect, addr, size, prot); ax = syscall(__NR_mprotect & 0x7ff, addr, size, prot);
#endif #endif
return ax; return ax;
} }
@ -157,12 +163,13 @@ forceinline int __sysv_getpid(void) {
: "0"(__NR_getpid) : "0"(__NR_getpid)
: "rdx", "memory", "cc"); : "rdx", "memory", "cc");
#elif defined(__aarch64__) #elif defined(__aarch64__)
register long r8 asm("x8") = (long)__NR_getpid; register long r8 asm("x8") = (long)__NR_getpid & 0x7ff;
register long r16 asm("x16") = (long)__NR_getpid & 0x7ff;
register long res_x0 asm("x0"); register long res_x0 asm("x0");
asm volatile("svc\t0" : "=r"(res_x0) : "r"(r8) : "memory"); asm volatile("svc\t0" : "=r"(res_x0) : "r"(r8), "r"(r16) : "memory");
ax = res_x0; ax = res_x0;
#else #else
ax = syscall(__NR_getpid); ax = syscall(__NR_getpid & 0x7ff);
#endif #endif
return ax; return ax;
} }

View file

@ -317,7 +317,7 @@ relegated void __oncrash_amd64(int sig, struct siginfo *si, void *arg) {
// RestoreDefaultCrashSignalHandlers(); // RestoreDefaultCrashSignalHandlers();
gdbpid = AttachDebugger( gdbpid = AttachDebugger(
((sig == SIGTRAP || sig == SIGQUIT) && ((sig == SIGTRAP || sig == SIGQUIT) &&
(rip >= (intptr_t)&_base && rip < (intptr_t)&_etext)) (rip >= (intptr_t)&__executable_start && rip < (intptr_t)&_etext))
? rip ? rip
: 0); : 0);
} }

View file

@ -58,7 +58,7 @@ struct Buffer {
}; };
static bool IsCode(uintptr_t p) { static bool IsCode(uintptr_t p) {
return _base <= (uint8_t *)p && (uint8_t *)p < _etext; return __executable_start <= (uint8_t *)p && (uint8_t *)p < _etext;
} }
static void Append(struct Buffer *b, const char *fmt, ...) { static void Append(struct Buffer *b, const char *fmt, ...) {
@ -97,8 +97,9 @@ static const char *ColorRegister(int r) {
case 25: // saved case 25: // saved
case 26: // saved case 26: // saved
case 27: // saved case 27: // saved
case 28: // saved
return MAGENTA; return MAGENTA;
case 18: // platform register
case 28: // our tls register
case 29: // frame pointer case 29: // frame pointer
case 30: // return pointer case 30: // return pointer
case 31: // stack pointer case 31: // stack pointer

View file

@ -124,7 +124,7 @@
// @note therefore no section relative addressing // @note therefore no section relative addressing
.macro .rodata.str1.1 .macro .rodata.str1.1
.section .rodata.str1.1,"aMS",@progbits,1 .section .rodata.str1.1,"aMS",@progbits,1
.align 1 .balign 1
.endm .endm
// Locates unreferenced code invulnerable to --gc-sections. // Locates unreferenced code invulnerable to --gc-sections.
@ -150,6 +150,12 @@
.weak \canonical .weak \canonical
.endm .endm
#ifdef __aarch64__
.macro jmp dest:req
b \dest
.endm
#endif
// Pulls unrelated module into linkage. // Pulls unrelated module into linkage.
// //
// In order for this technique to work with --gc-sections, another // In order for this technique to work with --gc-sections, another
@ -195,31 +201,31 @@
// @note therefore no section relative addressing // @note therefore no section relative addressing
.macro .rodata.cst4 .macro .rodata.cst4
.section .rodata.cst4,"aM",@progbits,4 .section .rodata.cst4,"aM",@progbits,4
.align 4 .balign 4
.endm .endm
.macro .rodata.cst8 .macro .rodata.cst8
.section .rodata.cst8,"aM",@progbits,8 .section .rodata.cst8,"aM",@progbits,8
.align 8 .balign 8
.endm .endm
.macro .rodata.cst16 .macro .rodata.cst16
.section .rodata.cst16,"aM",@progbits,16 .section .rodata.cst16,"aM",@progbits,16
.align 16 .balign 16
.endm .endm
.macro .rodata.cst32 .macro .rodata.cst32
.section .rodata.cst32,"aM",@progbits,32 .section .rodata.cst32,"aM",@progbits,32
.align 32 .balign 32
.endm .endm
.macro .rodata.cst64 .macro .rodata.cst64
.section .rodata.cst64,"aM",@progbits,64 .section .rodata.cst64,"aM",@progbits,64
.align 64 .balign 64
.endm .endm
.macro .tdata .macro .tdata
.section .tdata,"awT",@progbits .section .tdata,"awT",@progbits
.align 4 .balign 4
.endm .endm
.macro .tbss .macro .tbss
.section .tdata,"awT",@nobits .section .tdata,"awT",@nobits
.align 4 .balign 4
.endm .endm
// Loads address of errno into %rcx // Loads address of errno into %rcx
@ -242,11 +248,11 @@
// @see libc/runtime/_init.S // @see libc/runtime/_init.S
.macro .initro number:req name:req .macro .initro number:req name:req
.section ".initro.\number\().\name","a",@progbits .section ".initro.\number\().\name","a",@progbits
.align 8 .balign 8
.endm .endm
.macro .initbss number:req name:req .macro .initbss number:req name:req
.section ".piro.bss.init.2.\number\().\name","aw",@nobits .section ".piro.bss.init.2.\number\().\name","aw",@nobits
.align 8 .balign 8
.endm .endm
.macro .init.start number:req name:req .macro .init.start number:req name:req
.section ".init.\number\().\name","ax",@progbits .section ".init.\number\().\name","ax",@progbits

View file

@ -66,7 +66,7 @@ kHalfCache3:
#else #else
.rodata .rodata
.align 8 .balign 8
kHalfCache3: kHalfCache3:
.quad 4 * 1024 * 1024 .quad 4 * 1024 * 1024
.endobj kHalfCache3,globl .endobj kHalfCache3,globl

View file

@ -23,6 +23,8 @@
*/ */
int __threaded; int __threaded;
#ifdef __x86_64__
bool __tls_enabled; bool __tls_enabled;
#endif
unsigned __tls_index; unsigned __tls_index;

View file

@ -38,7 +38,8 @@ __zip_end:
.short v_zip_records // number of records on disk .short v_zip_records // number of records on disk
.short v_zip_records // records .short v_zip_records // records
.long v_zip_cdirsize // size of central directory .long v_zip_cdirsize // size of central directory
.long RVA(__zip_start) // central directory offset .weak v_zip_cdoffset
.long v_zip_cdoffset // central directory offset
.short v_zip_commentsize // comment size .short v_zip_commentsize // comment size
.endobj __zip_end,globl,hidden .endobj __zip_end,globl,hidden
.weak v_zip_records .weak v_zip_records

View file

@ -48,8 +48,8 @@ kNtdllProcRvas:
0: lodsq 0: lodsq
test %rax,%rax test %rax,%rax
jz 1f jz 1f
.weak _base .weak __executable_start
lea _base(%rax),%rdx lea __executable_start(%rax),%rdx
mov %r12,%rcx mov %r12,%rcx
call *__imp_GetProcAddress(%rip) call *__imp_GetProcAddress(%rip)
test %rax,%rax test %rax,%rax

View file

@ -30,6 +30,7 @@
#include "libc/runtime/pc.internal.h" #include "libc/runtime/pc.internal.h"
#include "libc/sysv/consts/sig.h" #include "libc/sysv/consts/sig.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
#ifdef __x86_64__
#define rdmsr(msr) \ #define rdmsr(msr) \
({ \ ({ \
@ -238,3 +239,5 @@ int arch_prctl(int code, int64_t addr) {
#endif #endif
return rc; return rc;
} }
#endif /* __x86_64__ */

View file

@ -192,7 +192,7 @@ XnuThreadMain(void *pthread, // rdi
"syscall\n\t" // __bsdthread_terminate() "syscall\n\t" // __bsdthread_terminate()
"ud2" "ud2"
: "=m"(*wt->ztid) : "=m"(*wt->ztid)
: "a"(0x2000000 | 361), "D"(0), "S"(0), "d"(0) : "a"(0x2000000 | 361), "D"(0), "S"(0), "d"(0L)
: "rcx", "r10", "r11", "memory"); : "rcx", "r10", "r11", "memory");
notpossible; notpossible;
} }

View file

@ -18,13 +18,13 @@
*/ */
#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/kprintf.h"
#include "libc/intrin/strace.internal.h" #include "libc/intrin/strace.internal.h"
#include "libc/macros.internal.h" #include "libc/macros.internal.h"
#include "libc/nexgen32e/rdtsc.h" #include "libc/nexgen32e/rdtsc.h"
#include "libc/runtime/internal.h" #include "libc/runtime/internal.h"
#include "libc/runtime/memtrack.internal.h" #include "libc/runtime/memtrack.internal.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/runtime/syslib.internal.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__
@ -33,15 +33,27 @@ 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);
extern long syscon_start[];
extern long syscon_end[];
extern long syscon_linux[];
extern long syscon_xnu[];
extern long syscon_freebsd[];
extern long syscon_openbsd[];
extern long syscon_netbsd[];
extern long syscon_windows[];
extern init_f __strace_init; extern init_f __strace_init;
extern init_f *__preinit_array_start[] __attribute__((__weak__));
extern init_f *__preinit_array_end[] __attribute__((__weak__));
extern init_f *__init_array_start[] __attribute__((__weak__)); extern init_f *__init_array_start[] __attribute__((__weak__));
extern init_f *__init_array_end[] __attribute__((__weak__)); extern init_f *__init_array_end[] __attribute__((__weak__));
extern pthread_mutex_t __mmi_lock_obj; extern pthread_mutex_t __mmi_lock_obj;
extern int hostos asm("__hostos");
textstartup void cosmo(long *sp) { textstartup void cosmo(long *sp, struct Syslib *m1) {
int argc; int argc;
init_f **fp; init_f **fp;
uintptr_t *pp; uintptr_t *pp;
long *mp, *magnums;
char **argv, **envp; char **argv, **envp;
unsigned long *auxv; unsigned long *auxv;
@ -56,6 +68,20 @@ textstartup void cosmo(long *sp) {
auxv = (unsigned long *)(sp + 1 + argc + 1); auxv = (unsigned long *)(sp + 1 + argc + 1);
while (*auxv++) donothing; while (*auxv++) donothing;
// detect apple m1 environment
if ((__syslib = m1)) {
hostos = _HOSTXNU;
magnums = syscon_xnu;
} else {
hostos = _HOSTLINUX;
magnums = syscon_linux;
}
// setup system magic numbers
for (mp = syscon_start; mp < syscon_end; ++mp) {
*mp = *magnums++;
}
// needed by kisdangerous() // needed by kisdangerous()
__oldstack = (intptr_t)sp; __oldstack = (intptr_t)sp;
__pid = sys_getpid().ax; __pid = sys_getpid().ax;
@ -65,11 +91,6 @@ textstartup void cosmo(long *sp) {
_mmi.p = _mmi.s; _mmi.p = _mmi.s;
__mmi_lock_obj._type = PTHREAD_MUTEX_RECURSIVE; __mmi_lock_obj._type = PTHREAD_MUTEX_RECURSIVE;
#ifdef SYSDEBUG
// initialize --strace functionality
argc = __strace_init(argc, argv, envp, auxv);
#endif
#if 0 #if 0
#if IsAsan() #if IsAsan()
__asan_init(argc, argv, envp, auxv); __asan_init(argc, argv, envp, auxv);
@ -89,6 +110,9 @@ textstartup void cosmo(long *sp) {
// run initialization callbacks // run initialization callbacks
_init(); _init();
__enable_tls(); __enable_tls();
#ifdef SYSDEBUG
argc = __strace_init(argc, argv, envp, auxv);
#endif
for (fp = __init_array_end; fp-- > __init_array_start;) { for (fp = __init_array_end; fp-- > __init_array_start;) {
(*fp)(argc, argv, envp, auxv); (*fp)(argc, argv, envp, auxv);
} }

View file

@ -174,14 +174,15 @@ __msabi noasan EFI_STATUS EfiMain(EFI_HANDLE ImageHandle,
(0x7e000 - 0x79000 + sizeof(struct EfiArgs) + 4095) / 4096, &Address); (0x7e000 - 0x79000 + sizeof(struct EfiArgs) + 4095) / 4096, &Address);
Address = IMAGE_BASE_PHYSICAL; Address = IMAGE_BASE_PHYSICAL;
SystemTable->BootServices->AllocatePages( SystemTable->BootServices->AllocatePages(
AllocateAddress, EfiRuntimeServicesData, ((_end - _base) + 4095) / 4096, AllocateAddress, EfiRuntimeServicesData,
&Address); ((_end - __executable_start) + 4095) / 4096, &Address);
mm = (struct mman *)0x0500; mm = (struct mman *)0x0500;
SystemTable->BootServices->SetMem(mm, sizeof(*mm), 0); SystemTable->BootServices->SetMem(mm, sizeof(*mm), 0);
SystemTable->BootServices->SetMem( SystemTable->BootServices->SetMem(
(void *)0x79000, 0x7e000 - 0x79000 + sizeof(struct EfiArgs), 0); (void *)0x79000, 0x7e000 - 0x79000 + sizeof(struct EfiArgs), 0);
SystemTable->BootServices->CopyMem((void *)IMAGE_BASE_PHYSICAL, _base, SystemTable->BootServices->CopyMem((void *)IMAGE_BASE_PHYSICAL,
_end - _base); __executable_start,
_end - __executable_start);
/* /*
* Converts UEFI shell arguments to argv. * Converts UEFI shell arguments to argv.

View file

@ -41,28 +41,28 @@ _EfiPostboot:
mov %rdi,rMm mov %rdi,rMm
mov %rdx,rArgc mov %rdx,rArgc
lea (rBane,%rcx),rArgv lea (rBane,%rcx),rArgv
mov $PHYSICAL(.Ltmpstk),%rax # switch to temporary stack mov $PHYSICAL(.Ltmpstk),%rax // switch to temporary stack
and $-16,%al # in physical space and $-16,%al // in physical space
xchg %rax,%rsp xchg %rax,%rsp
mov $PHYSICAL(0f),%eax # resume execution in copied mov $PHYSICAL(0f),%eax // resume execution in copied
jmp *%rax # image jmp *%rax // image
0: mov $EFER,%ecx # enable syscall/sysret & nx 0: mov $EFER,%ecx // enable syscall/sysret & nx
rdmsr rdmsr
or $EFER_SCE|EFER_NXE,%eax or $EFER_SCE|EFER_NXE,%eax
wrmsr wrmsr
mov %rsi,%cr3 # load new page table mov %rsi,%cr3 // load new page table
add rBane,%rsp # we can now switch stack to add rBane,%rsp // we can now switch stack to
add rBane,rMm # negative address space add rBane,rMm // negative address space
mov $1024*1024,%edx # set up virtual memory mov $1024*1024,%edx // set up virtual memory
mov $1024*1024+_end,%ecx # mapping mov $1024*1024+_end,%ecx // mapping
sub $_base,%ecx sub $__executable_start,%ecx
call __map_phdrs call __map_phdrs
mov $1f,%eax # switch rip to virtual mov $1f,%eax // switch rip to virtual
jmp *%rax # address space jmp *%rax // address space
1: push $0x037f 1: push $0x037f
fldcw (%rsp) fldcw (%rsp)
.weak _gdtr .weak _gdtr
lgdt _gdtr # switch to our own GDT lgdt _gdtr // switch to our own GDT
mov $GDT_LONG_DATA,%ax mov $GDT_LONG_DATA,%ax
mov %ax,%ds mov %ax,%ds
mov %ax,%ss mov %ax,%ss
@ -71,34 +71,34 @@ _EfiPostboot:
mov %ax,%gs mov %ax,%gs
.weak ape_stack_vaddr .weak ape_stack_vaddr
.weak ape_stack_memsz .weak ape_stack_memsz
movabs $ape_stack_vaddr,%rsp # switch to final stack in movabs $ape_stack_vaddr,%rsp // switch to final stack in
add $ape_stack_memsz,%rsp # virtual address space add $ape_stack_memsz,%rsp // virtual address space
movl $0,0x7b000 # unmap null 2mb movl $0,0x7b000 // unmap null 2mb
mov rMm,%rdi mov rMm,%rdi
xor %esi,%esi # free up now-unused pages xor %esi,%esi // free up now-unused pages
xor %edx,%edx xor %edx,%edx
call __reclaim_boot_pages call __reclaim_boot_pages
push .Lenv0(%rip) # envp[0][0] push .Lenv0(%rip) // envp[0][0]
mov %rsp,%rbp mov %rsp,%rbp
push $0 # auxv[1][1] push $0 // auxv[1][1]
push $0 # auxv[1][0] push $0 // auxv[1][0]
mov (rArgv),%rax mov (rArgv),%rax
add rBane,%rax add rBane,%rax
push %rax # auxv[0][1] push %rax // auxv[0][1]
push $31 # auxv[0][0] AT_EXECFN push $31 // auxv[0][0] AT_EXECFN
push $0 # envp[1] push $0 // envp[1]
push %rbp # envp[0] push %rbp // envp[0]
push $0 # argv[argc] NULL push $0 // argv[argc] NULL
lea -8(rArgv,rArgc,8),%rsi # push rest of argv, & lea -8(rArgv,rArgc,8),%rsi // push rest of argv, &
mov rArgc,%rcx # adjust pointers to point to mov rArgc,%rcx // adjust pointers to point to
std # negative space std // negative space
2: lodsq 2: lodsq
add rBane,%rax add rBane,%rax
push %rax push %rax
loop 2b loop 2b
cld cld
push rArgc # argc push rArgc // argc
pushpop _HOSTMETAL,%rcx # sets __hostos in crt.S pushpop _HOSTMETAL,%rcx // sets __hostos in crt.S
xor %ebp,%ebp xor %ebp,%ebp
xor %eax,%eax xor %eax,%eax
xor %ebx,%ebx xor %ebx,%ebx
@ -124,3 +124,6 @@ _EfiPostboot:
.space 0x1000 .space 0x1000
.Ltmpstk: .Ltmpstk:
.previous .previous
.weak __executable_start
.weak _end

View file

@ -53,9 +53,9 @@ static privileged dontinline void FixupLockNops(void) {
* binary the offsets of all the instructions we need to change. * binary the offsets of all the instructions we need to change.
*/ */
for (int *p = __threadcalls_start; p < __threadcalls_end; ++p) { for (int *p = __threadcalls_start; p < __threadcalls_end; ++p) {
_base[*p + 0] = 0x67; __executable_start[*p + 0] = 0x67;
_base[*p + 1] = 0x67; __executable_start[*p + 1] = 0x67;
_base[*p + 2] = 0xe8; __executable_start[*p + 2] = 0xe8;
} }
__morph_end(&mask); __morph_end(&mask);
} }

View file

@ -58,6 +58,7 @@ _Alignas(TLS_ALIGNMENT) static char __static_tls[6016];
* *
* Here's the TLS memory layout on aarch64: * Here's the TLS memory layout on aarch64:
* *
* x28
* %tpidr_el0 * %tpidr_el0
* *
* _Thread_local * _Thread_local
@ -82,7 +83,7 @@ _Alignas(TLS_ALIGNMENT) static char __static_tls[6016];
* can disable it as follows: * can disable it as follows:
* *
* int main() { * int main() {
* __tls_enabled = false; * __tls_enabled_set(false);
* // do stuff * // do stuff
* } * }
* *
@ -98,15 +99,15 @@ textstartup void __enable_tls(void) {
// Here's the layout we're currently using: // Here's the layout we're currently using:
// //
// .align PAGESIZE // .balign PAGESIZE
// _tdata_start: // _tdata_start:
// .tdata // .tdata
// _tdata_size = . - _tdata_start // _tdata_size = . - _tdata_start
// .align PAGESIZE // .balign PAGESIZE
// _tbss_start: // _tbss_start:
// _tdata_start + _tbss_offset: // _tdata_start + _tbss_offset:
// .tbss // .tbss
// .align TLS_ALIGNMENT // .balign TLS_ALIGNMENT
// _tbss_size = . - _tbss_start // _tbss_size = . - _tbss_start
// _tbss_end: // _tbss_end:
// _tbss_start + _tbss_size: // _tbss_start + _tbss_size:
@ -219,5 +220,5 @@ textstartup void __enable_tls(void) {
#endif #endif
// we are now allowed to use tls // we are now allowed to use tls
__tls_enabled = true; __tls_enabled_set(true);
} }

View file

@ -97,7 +97,7 @@ static dontinline textwindows bool ForkIo2(int64_t h, void *buf, size_t n,
bool32 (*fn)(), const char *sf, bool32 (*fn)(), const char *sf,
bool ischild) { bool ischild) {
ssize_t rc = ForkIo(h, buf, n, fn); ssize_t rc = ForkIo(h, buf, n, fn);
if (ischild) __tls_enabled = false; // prevent tls crash in kprintf if (ischild) __tls_enabled_set(false); // prevent tls crash in kprintf
NTTRACE("%s(%ld, %p, %'zu) → %'zd% m", sf, h, buf, n, rc); NTTRACE("%s(%ld, %p, %'zu) → %'zd% m", sf, h, buf, n, rc);
return rc != -1; return rc != -1;
} }
@ -211,7 +211,7 @@ textwindows void WinMainForked(void) {
kStartTsc = savetsc; kStartTsc = savetsc;
__threaded = false; __threaded = false;
__tls_index = 0; __tls_index = 0;
__tls_enabled = false; __tls_enabled_set(false);
// apply fixups and reapply memory protections // apply fixups and reapply memory protections
_mmi.p = maps; _mmi.p = maps;
@ -352,7 +352,7 @@ textwindows int sys_fork_nt(uint32_t dwCreationFlags) {
if (tib && _weaken(__set_tls) && _weaken(__morph_tls)) { if (tib && _weaken(__set_tls) && _weaken(__morph_tls)) {
_weaken(__set_tls)(tib); _weaken(__set_tls)(tib);
_weaken(__morph_tls)(); _weaken(__morph_tls)();
__tls_enabled = true; __tls_enabled_set(true);
} }
if (threaded && !__threaded && _weaken(__enable_threads)) { if (threaded && !__threaded && _weaken(__enable_threads)) {
_weaken(__enable_threads)(); _weaken(__enable_threads)();

View file

@ -18,6 +18,7 @@
*/ */
#include "libc/calls/syscall-sysv.internal.h" #include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/runtime/syslib.internal.h"
#include "libc/sysv/consts/sig.h" #include "libc/sysv/consts/sig.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
@ -38,8 +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;
void *newtls = 0; void *newtls = 0;
@ -49,16 +49,22 @@ int sys_fork(void) {
register long r2 asm("x2") = (long)parent_tidptr; register long r2 asm("x2") = (long)parent_tidptr;
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 long res_x0 asm("x0"); register int res_x0 asm("x0");
asm volatile("mov\tx8,%1\n\t" register int res_x1 asm("x1");
asm volatile("mov\tx8,%2\n\t"
"mov\tx16,%3\n\t"
"svc\t0" "svc\t0"
: "=r"(res_x0) : "=r"(res_x0), "=r"(res_x1)
: "i"(220), "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4) : "i"(220), "i"(2), "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4)
: "x8", "memory"); : "x8", "x16", "memory");
return _sysret(res_x0); if (IsXnu() && res_x0 != -1) {
} else { res_x0 &= res_x1 - 1;
return enosys();
} }
return _sysret(res_x0);
#else
return enosys();
#endif #endif
} }

View file

@ -18,15 +18,15 @@ extern const char v_ntsubsystem[] __attribute__((__weak__));
extern const uintptr_t __fini_array_end[] __attribute__((__weak__)); extern const uintptr_t __fini_array_end[] __attribute__((__weak__));
extern const uintptr_t __fini_array_start[] __attribute__((__weak__)); extern const uintptr_t __fini_array_start[] __attribute__((__weak__));
extern unsigned char _tdata_start[]; extern unsigned char _tdata_start[] __attribute__((__weak__));
extern unsigned char _tdata_end[]; extern unsigned char _tdata_end[] __attribute__((__weak__));
extern unsigned char _tdata_size[]; extern unsigned char _tdata_size[] __attribute__((__weak__));
extern unsigned char _tbss_start[]; extern unsigned char _tbss_start[] __attribute__((__weak__));
extern unsigned char _tbss_end[]; extern unsigned char _tbss_end[] __attribute__((__weak__));
extern unsigned char _tbss_size[]; extern unsigned char _tbss_size[] __attribute__((__weak__));
extern unsigned char _tbss_offset[]; extern unsigned char _tbss_offset[] __attribute__((__weak__));
extern unsigned char _tls_size[]; extern unsigned char _tls_size[] __attribute__((__weak__));
extern unsigned char _tls_content[]; extern unsigned char _tls_content[] __attribute__((__weak__));
void _init(void) _Hide; void _init(void) _Hide;
void __morph_tls(void); void __morph_tls(void);
@ -44,8 +44,7 @@ int GetDosEnviron(const char16_t *, char *, size_t, char **, size_t);
bool __intercept_flag(int *, char *[], const char *); bool __intercept_flag(int *, char *[], const char *);
int sys_mprotect_nt(void *, size_t, int) _Hide; int sys_mprotect_nt(void *, size_t, int) _Hide;
int __inflate(void *, size_t, const void *, size_t); int __inflate(void *, size_t, const void *, size_t);
noasan void *_Mmap(void *addr, size_t size, int prot, int flags, int fd, noasan void *_Mmap(void *, size_t, int, int, int, int64_t) _Hide;
int64_t off) _Hide;
noasan int _Munmap(char *, size_t) _Hide; noasan int _Munmap(char *, size_t) _Hide;
void InitializeFileDescriptors(void); void InitializeFileDescriptors(void);
void __on_arithmetic_overflow(void); void __on_arithmetic_overflow(void);

View file

@ -126,18 +126,16 @@ forceinline pureconst bool IsOldStack(const void *x) {
/* openbsd uses 4mb stack by default */ /* openbsd uses 4mb stack by default */
/* freebsd uses 512mb stack by default */ /* freebsd uses 512mb stack by default */
/* most systems use 8mb stack by default */ /* most systems use 8mb stack by default */
size_t foss_stack_size = 4ul * 1024 * 1024; size_t foss_stack_size = 1ul * 1024 * 1024;
uintptr_t top = ROUNDUP(__oldstack, FRAMESIZE); uintptr_t top = ROUNDUP(__oldstack + 1, foss_stack_size);
uintptr_t bot = top - foss_stack_size; uintptr_t bot = ROUNDDOWN(__oldstack, foss_stack_size);
uintptr_t old = ROUNDDOWN(__oldstack, foss_stack_size);
return bot <= (uintptr_t)x && (uintptr_t)x < top; return bot <= (uintptr_t)x && (uintptr_t)x < top;
} }
forceinline pureconst bool IsOldStackFrame(int x) { forceinline pureconst bool IsOldStackFrame(int x) {
size_t foss_stack_size = 4ul * 1024 * 1024; size_t foss_stack_size = 1ul * 1024 * 1024;
uintptr_t top = ROUNDUP(__oldstack, FRAMESIZE); uintptr_t top = ROUNDUP(__oldstack + 1, foss_stack_size);
uintptr_t bot = top - foss_stack_size; uintptr_t bot = ROUNDDOWN(__oldstack, foss_stack_size);
uintptr_t old = ROUNDDOWN(__oldstack, foss_stack_size);
return (int)(bot >> 16) <= x && x <= (int)((top >> 16) - 1); return (int)(bot >> 16) <= x && x <= (int)((top >> 16) - 1);
} }
@ -151,7 +149,7 @@ forceinline pureconst bool OverlapsImageSpace(const void *p, size_t n) {
if (n) { if (n) {
BegA = p; BegA = p;
EndA = BegA + (n - 1); EndA = BegA + (n - 1);
BegB = _base; BegB = __executable_start;
EndB = _end - 1; EndB = _end - 1;
return MAX(BegA, BegB) < MIN(EndA, EndB); return MAX(BegA, BegB) < MIN(EndA, EndB);
} else { } else {

View file

@ -129,8 +129,8 @@ privileged void __morph_begin(sigset_t *save) {
#else #else
__morph_sigprocmask(SIG_BLOCK, &ss, save); __morph_sigprocmask(SIG_BLOCK, &ss, save);
#endif #endif
__morph_mprotect(_base, __privileged_addr - _base, PROT_READ | PROT_WRITE, __morph_mprotect(__executable_start, __privileged_addr - __executable_start,
kNtPageWritecopy); PROT_READ | PROT_WRITE, kNtPageWritecopy);
} }
/** /**
@ -140,8 +140,8 @@ privileged void __morph_end(sigset_t *save) {
int ax; int ax;
long dx; long dx;
bool cf; bool cf;
__morph_mprotect(_base, __privileged_addr - _base, PROT_READ | PROT_EXEC, __morph_mprotect(__executable_start, __privileged_addr - __executable_start,
kNtPageExecuteRead); PROT_READ | PROT_EXEC, kNtPageExecuteRead);
#ifdef __x86_64__ #ifdef __x86_64__
if (IsOpenbsd()) { if (IsOpenbsd()) {
asm volatile(CFLAG_ASM("syscall") asm volatile(CFLAG_ASM("syscall")
@ -153,7 +153,7 @@ privileged void __morph_end(sigset_t *save) {
asm volatile("mov\t$8,%%r10d\n\t" asm volatile("mov\t$8,%%r10d\n\t"
"syscall" "syscall"
: "=a"(ax), "=d"(dx) : "=a"(ax), "=d"(dx)
: "0"(__NR_sigprocmask), "D"(SIG_SETMASK), "S"(save), "1"(0) : "0"(__NR_sigprocmask), "D"(SIG_SETMASK), "S"(save), "1"(0L)
: "rcx", "r8", "r9", "r10", "r11", "memory", "cc"); : "rcx", "r8", "r9", "r10", "r11", "memory", "cc");
_npassert(!ax); _npassert(!ax);
} }

View file

@ -19,6 +19,7 @@
#include "ape/sections.internal.h" #include "ape/sections.internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/bits.h" #include "libc/intrin/bits.h"
#include "libc/intrin/kprintf.h"
#include "libc/runtime/internal.h" #include "libc/runtime/internal.h"
#include "libc/runtime/morph.h" #include "libc/runtime/morph.h"
#include "libc/thread/tls.h" #include "libc/thread/tls.h"
@ -44,7 +45,7 @@ privileged void __morph_tls(void) {
// We check `_tls_content` which is generated by the linker script // We check `_tls_content` which is generated by the linker script
// since it lets us determine ahead of time if _Thread_local vars // since it lets us determine ahead of time if _Thread_local vars
// have actually been linked into this program. // have actually been linked into this program.
if ((intptr_t)_tls_content && (IsWindows() || IsXnu())) { if (IsWindows() || IsXnu()) {
int n; int n;
uint64_t w; uint64_t w;
sigset_t mask; sigset_t mask;

View file

@ -22,7 +22,7 @@
// Loads all pages from program image into memory. // Loads all pages from program image into memory.
_peekall: _peekall:
.leafprologue .leafprologue
ezlea _base,si ezlea __executable_start,si
ezlea _etext,cx ezlea _etext,cx
add $0x1000,%rsi add $0x1000,%rsi
0: xor (%rsi),%eax 0: xor (%rsi),%eax
@ -39,3 +39,7 @@ _peekall:
jb 0b jb 0b
.leafepilogue .leafepilogue
.endfn _peekall,globl .endfn _peekall,globl
.weak __executable_start
.weak _etext
.weak _end

View file

@ -233,7 +233,7 @@ textstartup void __printargs(const char *prologue) {
"mov\t%%ebx,%1\n\t" "mov\t%%ebx,%1\n\t"
"pop\t%%rbx" "pop\t%%rbx"
: "=a"(eax), "=rm"(ebx), "=c"(ecx), "=d"(edx) : "=a"(eax), "=rm"(ebx), "=c"(ecx), "=d"(edx)
: "0"(0x40000000), "2"(0)); : "0"(0x40000000), "2"(0L));
PRINT(" Running inside %.4s%.4s%.4s (eax=%#x)", &ebx, &ecx, &edx, eax); PRINT(" Running inside %.4s%.4s%.4s (eax=%#x)", &ebx, &ecx, &edx, eax);
} }
CPUID4_ITERATE(i, { CPUID4_ITERATE(i, {
@ -272,9 +272,8 @@ textstartup void __printargs(const char *prologue) {
if (X86_HAVE(LA57)) kprintf(" LA57"); if (X86_HAVE(LA57)) kprintf(" LA57");
if (X86_HAVE(FSGSBASE)) kprintf(" FSGSBASE"); if (X86_HAVE(FSGSBASE)) kprintf(" FSGSBASE");
#elif defined(__aarch64__) #elif defined(__aarch64__)
PRINT(" AARCH64\n"); PRINT(" AARCH64");
#endif #endif
kprintf("\n");
PRINT(""); PRINT("");
PRINT("FILE DESCRIPTORS"); PRINT("FILE DESCRIPTORS");
@ -366,21 +365,33 @@ textstartup void __printargs(const char *prologue) {
PRINT(""); PRINT("");
PRINT("RESOURCE LIMITS"); PRINT("RESOURCE LIMITS");
for (i = 0; i < RLIM_NLIMITS; ++i) { for (gotsome = i = 0; i < RLIM_NLIMITS; ++i) {
if (!getrlimit(i, &rlim)) { if (!getrlimit(i, &rlim)) {
char buf[20]; char buf[20];
if (rlim.rlim_cur == RLIM_INFINITY) rlim.rlim_cur = -1; if (rlim.rlim_cur == RLIM_INFINITY) rlim.rlim_cur = -1;
if (rlim.rlim_max == RLIM_INFINITY) rlim.rlim_max = -1; if (rlim.rlim_max == RLIM_INFINITY) rlim.rlim_max = -1;
PRINT(" ☼ %-20s %,16ld %,16ld", (DescribeRlimitName)(buf, i), PRINT(" ☼ %-20s %,16ld %,16ld", (DescribeRlimitName)(buf, i),
rlim.rlim_cur, rlim.rlim_max); rlim.rlim_cur, rlim.rlim_max);
gotsome = true;
} }
} }
if (!gotsome) {
PRINT(" ☼ %s", "none");
}
PRINT("");
PRINT("STACK");
size_t foss_stack_size = 4ul * 1024 * 1024;
PRINT(" ☼ %p __oldstack top", ROUNDUP(__oldstack + 1, foss_stack_size));
PRINT(" ☼ %p __oldstack ptr", __oldstack);
PRINT(" ☼ %p __oldstack bot", ROUNDDOWN(__oldstack, foss_stack_size));
PRINT(" ☼ %p __builtin_frame_address(0)", __builtin_frame_address(0));
PRINT(""); PRINT("");
PRINT("ARGUMENTS (%p)", __argv); PRINT("ARGUMENTS (%p)", __argv);
if (*__argv) { if (*__argv) {
for (i = 0; i < __argc; ++i) { for (i = 0; i < __argc; ++i) {
PRINT(" ☼ %s", __argv[i]); PRINT(" %p %s", __argv[i], __argv[i]);
} }
} else { } else {
PRINT(" none"); PRINT(" none");
@ -390,7 +401,7 @@ textstartup void __printargs(const char *prologue) {
PRINT("ENVIRONMENT (%p)", __envp); PRINT("ENVIRONMENT (%p)", __envp);
if (*__envp) { if (*__envp) {
for (env = __envp; *env; ++env) { for (env = __envp; *env; ++env) {
PRINT(" %s", *env); PRINT(" %p %s", *env, *env);
} }
} else { } else {
PRINT(" none"); PRINT(" none");
@ -403,9 +414,9 @@ textstartup void __printargs(const char *prologue) {
for (auxp = __auxv; *auxp; auxp += 2) { for (auxp = __auxv; *auxp; auxp += 2) {
if ((auxinfo = DescribeAuxv(auxp[0]))) { if ((auxinfo = DescribeAuxv(auxp[0]))) {
ksnprintf(u.path, sizeof(u.path), auxinfo->fmt, auxp[1]); ksnprintf(u.path, sizeof(u.path), auxinfo->fmt, auxp[1]);
PRINT(" %16s[%4ld] = %s", auxinfo->name, auxp[0], u.path); PRINT(" %p %16s[%4ld] = %s", auxp, auxinfo->name, auxp[0], u.path);
} else { } else {
PRINT(" %16s[%4ld] = %014p", "unknown", auxp[0], auxp[1]); PRINT(" %p %16s[%4ld] = %014p", auxp, "unknown", auxp[0], auxp[1]);
} }
} }
} }

View file

@ -64,6 +64,9 @@ $(LIBC_RUNTIME_A).pkg: \
# asan and ubsan can be function traced # asan and ubsan can be function traced
# we can't use function tracing because: # we can't use function tracing because:
# this is the function tracing runtime # this is the function tracing runtime
o/$(MODE)/libc/runtime/cosmo2.o: private \
OVERRIDE_CFLAGS += -O0
o/$(MODE)/libc/runtime/ftracer.o: private \ o/$(MODE)/libc/runtime/ftracer.o: private \
OVERRIDE_CFLAGS += \ OVERRIDE_CFLAGS += \
-x-no-pg \ -x-no-pg \
@ -114,6 +117,13 @@ o//libc/runtime/opensymboltable.greg.o: private \
OVERRIDE_CFLAGS += \ OVERRIDE_CFLAGS += \
-Os -Os
ifeq ($(ARCH), aarch64)
o/$(MODE)/libc/runtime/mmap.o \
o/$(MODE)/libc/runtime/enable_tls.o: private \
OVERRIDE_CFLAGS += \
-mcmodel=large
endif
# these assembly files are safe to build on aarch64 # these assembly files are safe to build on aarch64
o/$(MODE)/libc/runtime/init.o: libc/runtime/init.S o/$(MODE)/libc/runtime/init.o: libc/runtime/init.S
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $< @$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<

View file

@ -18,11 +18,13 @@
*/ */
#include "libc/assert.h" #include "libc/assert.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/nexgen32e/msr.internal.h" #include "libc/nexgen32e/msr.internal.h"
#include "libc/nt/thread.h" #include "libc/nt/thread.h"
#include "libc/thread/tls.h" #include "libc/thread/tls.h"
#include "libc/thread/tls2.h"
int sys_set_tls(); int sys_set_tls();
@ -59,6 +61,9 @@ textstartup void __set_tls(struct CosmoTib *tib) {
"d"((uint32_t)(val >> 32))); "d"((uint32_t)(val >> 32)));
} }
#else #else
asm volatile("mov\tx28,%0" : /* no outputs */ : "r"(tib));
if (!IsXnu()) {
asm volatile("msr\ttpidr_el0,%0" : /* no outputs */ : "r"(tib)); asm volatile("msr\ttpidr_el0,%0" : /* no outputs */ : "r"(tib));
}
#endif #endif
} }

View file

@ -0,0 +1,54 @@
#ifndef 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/sigset.h"
#include "libc/calls/struct/timespec.h"
#include "libc/thread/thread.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define SYSLIB_MAGIC ('s' | 'l' << 8 | 'i' << 16 | 'b' << 24)
#define SYSLIB_VERSION 0
struct Syslib {
int magic;
int version;
void (*exit)(int) wontreturn;
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 (*close)(int);
long (*clock_gettime)(int, struct timespec *);
long (*nanosleep)(const struct timespec *, struct timespec *);
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);
void (*pthread_jit_write_protect_np)(int);
void (*sys_icache_invalidate)(void *, size_t);
pthread_t (*pthread_self)(void);
int (*pthread_create)(pthread_t *, const pthread_attr_t *, void *(*)(void *),
void *);
int (*pthread_detach)(pthread_t);
int (*pthread_join)(pthread_t, void **);
void (*pthread_exit)(void *);
int (*pthread_kill)(pthread_t, int);
int (*pthread_sigmask)(int, const sigset_t *restrict, sigset_t *restrict);
int (*pthread_setname_np)(const char *);
int (*pthread_key_create)(pthread_key_t *, void (*)(void *));
int (*pthread_setspecific)(pthread_key_t, const void *);
void *(*pthread_getspecific)(pthread_key_t);
};
extern struct Syslib *__syslib;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_RUNTIME_SYSLIB_H_ */

View file

@ -57,6 +57,10 @@ $(LIBC_SOCK_A).pkg: \
$(LIBC_SOCK_A_OBJS) \ $(LIBC_SOCK_A_OBJS) \
$(foreach x,$(LIBC_SOCK_A_DIRECTDEPS),$($(x)_A).pkg) $(foreach x,$(LIBC_SOCK_A_DIRECTDEPS),$($(x)_A).pkg)
# these assembly files are safe to build on aarch64
o/$(MODE)/libc/sock/sys_sendfile_xnu.o: libc/sock/sys_sendfile_xnu.S
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
LIBC_SOCK_LIBS = $(foreach x,$(LIBC_SOCK_ARTIFACTS),$($(x))) LIBC_SOCK_LIBS = $(foreach x,$(LIBC_SOCK_ARTIFACTS),$($(x)))
LIBC_SOCK_SRCS = $(foreach x,$(LIBC_SOCK_ARTIFACTS),$($(x)_SRCS)) LIBC_SOCK_SRCS = $(foreach x,$(LIBC_SOCK_ARTIFACTS),$($(x)_SRCS))
LIBC_SOCK_HDRS = $(foreach x,$(LIBC_SOCK_ARTIFACTS),$($(x)_HDRS)) LIBC_SOCK_HDRS = $(foreach x,$(LIBC_SOCK_ARTIFACTS),$($(x)_HDRS))

View file

@ -21,7 +21,7 @@
// $OpenBSD: strlcat.c,v 1.19 2019/01/25 00:19:25 millert Exp $ // $OpenBSD: strlcat.c,v 1.19 2019/01/25 00:19:25 millert Exp $
asm(".ident\t\"\\n\\n\ asm(".ident\t\"\\n\\n\
strlcat (ISC)\\n\ OpenBSD Strings (ISC)\\n\
Copyright (c) 1998, 2015 Todd C. Miller <millert@openbsd.org>\""); Copyright (c) 1998, 2015 Todd C. Miller <millert@openbsd.org>\"");
asm(".include \"libc/disclaimer.inc\""); asm(".include \"libc/disclaimer.inc\"");

View file

@ -1,7 +1,7 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ /*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi vi: set et ft=c ts=8 tw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney Copyright (c) 1998, 2015 Todd C. Miller <millert@openbsd.org>
Permission to use, copy, modify, and/or distribute this software for Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the any purpose with or without fee is hereby granted, provided that the
@ -16,27 +16,43 @@
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/intrin/safemacros.internal.h"
#include "libc/macros.internal.h"
#include "libc/str/str.h" #include "libc/str/str.h"
// clang-format off
// $OpenBSD: strlcpy.c,v 1.16 2019/01/25 00:19:25 millert Exp $
asm(".ident\t\"\\n\\n\
OpenBSD Strings (ISC)\\n\
Copyright (c) 1998, 2015 Todd C. Miller <millert@openbsd.org>\"");
asm(".include \"libc/disclaimer.inc\"");
/** /**
* Copies string, the BSD way. * Copies string, the BSD way.
* *
* @param d is buffer which needn't be initialized * Copy string src to buffer `dst` of size `dsize`. At most `dsize-1`
* @param s is a NUL-terminated string * chars will be copied. Always NUL terminates (unless `dsize == 0`).
* @param n is byte capacity of d * Returns `strlen(src)`; if `retval >= dsize`, truncation occurred.
* @return strlen(s)
* @note d and s can't overlap
* @note we prefer memccpy()
*/ */
size_t strlcpy(char *d, const char *s, size_t n) { size_t
size_t slen, actual; strlcpy(char *dst, const char *src, size_t dsize)
slen = strlen(s); {
if (n) { const char *osrc = src;
actual = MIN(n - 1, slen); size_t nleft = dsize;
memcpy(d, s, actual);
d[actual] = '\0'; /* Copy as many bytes as will fit. */
if (nleft != 0) {
while (--nleft != 0) {
if ((*dst++ = *src++) == '\0')
break;
} }
return slen; }
/* Not enough room in dst, add NUL and traverse rest of src. */
if (nleft == 0) {
if (dsize != 0)
*dst = '\0'; /* NUL-terminate dst */
while (*src++)
;
}
return(src - osrc - 1); /* count does not include NUL */
} }

View file

@ -1,117 +0,0 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 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.
*/
// Traditional executable boundaries defined by linker.
// @see man etext
_etext = 0
_edata = 0
_end = 0
// Cosmopolitan executable boundaries defined by linker script.
// @see libc/elf/elf.lds
// @see ape/ape.lds
_base = 0
ape_xlm = 0
_ehead = 0
_ezip = 0
_ereal = 0
__privileged_start = 0
__privileged_end = 0
__privileged_addr = 0
__privileged_size = 0
__test_start = 0
__ro = 0
__relo_start = 0
__relo_end = 0
__data_start = 0
__data_end = 0
__bss_start = 0
__bss_end = 0
// Thread local boundaries defined by linker script
// @see ape/ape.lds
_tdata_start = 0
_tdata_end = 0
_tdata_size = 0
_tbss_start = 0
_tbss_end = 0
_tbss_offset = 0
_tbss_size = 0
_tls_size = 0
_tls_content = 0
.globl _base
.globl ape_xlm
.globl __relo_start
.globl __relo_end
.globl __privileged_size
.globl __privileged_addr
.globl __privileged_start
.globl __privileged_end
.globl __ro
.globl __test_start
.globl _edata
.globl _ehead
.globl _end
.globl _ezip
.globl _ereal
.globl _etext
.globl _tdata_start
.globl _tdata_end
.globl _tdata_size
.globl _tbss_start
.globl _tbss_end
.globl _tbss_size
.globl _tbss_offset
.globl _tls_size
.globl _tls_content
.globl __data_start
.globl __data_end
.globl __bss_start
.globl __bss_end
.weak _base
.weak ape_xlm
.weak __relo_start
.weak __relo_end
.weak __privileged_size
.weak __privileged_addr
.weak __privileged_start
.weak __privileged_end
.weak __ro
.weak __test_start
.weak _edata
.weak _ehead
.weak _end
.weak _ezip
.weak _ereal
.weak _etext
.weak _tdata_start
.weak _tdata_end
.weak _tdata_size
.weak _tbss_start
.weak _tbss_end
.weak _tbss_size
.weak _tls_size
.weak _tls_content
.weak _tbss_offset
.weak __data_start
.weak __data_end
.weak __bss_start
.weak __bss_end

View file

@ -43,8 +43,6 @@ $(LIBC_STUBS_A).pkg: \
$(foreach x,$(LIBC_STUBS_A_DIRECTDEPS),$($(x)_A).pkg) $(foreach x,$(LIBC_STUBS_A_DIRECTDEPS),$($(x)_A).pkg)
# these assembly files are safe to build on aarch64 # these assembly files are safe to build on aarch64
o/$(MODE)/libc/stubs/ld.o: libc/stubs/ld.S
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
o/$(MODE)/libc/stubs/abort.o: libc/stubs/abort.S o/$(MODE)/libc/stubs/abort.o: libc/stubs/abort.S
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $< @$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<

View file

@ -1,2 +1,2 @@
#include "libc/sysv/macros.internal.h" #include "libc/sysv/macros.internal.h"
.scall __bsd_setegid,0xfff0b60b620b6fff,0xfff,globl,hidden .scall __bsd_setegid,0xfff0b60b620b6fff,4095,182,globl,hidden

View file

@ -1,2 +1,2 @@
#include "libc/sysv/macros.internal.h" #include "libc/sysv/macros.internal.h"
.scall __bsd_seteuid,0xfff0b70b720b7fff,0xfff,globl,hidden .scall __bsd_seteuid,0xfff0b70b720b7fff,4095,183,globl,hidden

View file

@ -1,2 +1,2 @@
#include "libc/sysv/macros.internal.h" #include "libc/sysv/macros.internal.h"
.scall __sys_accept,0x81e81ea1d281e82b,0x0ca,globl,hidden .scall __sys_accept,0x81e81ea1d281e82b,202,30,globl,hidden

View file

@ -1,2 +1,2 @@
#include "libc/sysv/macros.internal.h" #include "libc/sysv/macros.internal.h"
.scall __sys_accept4,0xfff85da1dffff920,0x0f2,globl,hidden .scall __sys_accept4,0xfff85da1dffff920,242,4095,globl,hidden

View file

@ -1,2 +1,2 @@
#include "libc/sysv/macros.internal.h" #include "libc/sysv/macros.internal.h"
.scall __sys_bind,0x0680680682068031,0x0c8,globl,hidden .scall __sys_bind,0x0680680682068031,200,104,globl,hidden

View file

@ -1,2 +1,2 @@
#include "libc/sysv/macros.internal.h" #include "libc/sysv/macros.internal.h"
.scall __sys_clock_nanosleep,0x9ddfff8f4ffff8e6,0x073,globl,hidden .scall __sys_clock_nanosleep,0x9ddfff8f4ffff8e6,115,4095,globl,hidden

View file

@ -1,2 +1,2 @@
#include "libc/sysv/macros.internal.h" #include "libc/sysv/macros.internal.h"
.scall __sys_connect,0x862862862286282a,0x0cb,globl,hidden .scall __sys_connect,0x862862862286282a,203,98,globl,hidden

View file

@ -1,2 +1,2 @@
#include "libc/sysv/macros.internal.h" #include "libc/sysv/macros.internal.h"
.scall __sys_dup3,0x1c6066fffffff124,0x018,globl,hidden .scall __sys_dup3,0x1c6066fffffff124,24,4095,globl,hidden

View file

@ -1,2 +1,2 @@
#include "libc/sysv/macros.internal.h" #include "libc/sysv/macros.internal.h"
.scall __sys_execve,0x03b03b03b203b03b,0x0dd,globl,hidden .scall __sys_execve,0x03b03b03b203b03b,221,59,globl,hidden

View file

@ -1,2 +1,2 @@
#include "libc/sysv/macros.internal.h" #include "libc/sysv/macros.internal.h"
.scall __sys_fcntl,0x05c05c05c205c048,0x019,globl,hidden .scall __sys_fcntl,0x05c05c05c205c048,25,92,globl,hidden

View file

@ -1,2 +1,2 @@
#include "libc/sysv/macros.internal.h" #include "libc/sysv/macros.internal.h"
.scall __sys_fcntl_cp,0x85c85c85c285c848,0x019,globl,hidden .scall __sys_fcntl_cp,0x85c85c85c285c848,25,92,globl,hidden

View file

@ -1,2 +1,2 @@
#include "libc/sysv/macros.internal.h" #include "libc/sysv/macros.internal.h"
.scall __sys_fork,0x0020020022002039,0xfff,globl,hidden .scall __sys_fork,0x0020020022002039,4095,2,globl,hidden

View file

@ -1,2 +1,2 @@
#include "libc/sysv/macros.internal.h" #include "libc/sysv/macros.internal.h"
.scall __sys_fstat,0x1b80352272153005,0x050,globl,hidden .scall __sys_fstat,0x1b80352272153005,80,339,globl,hidden

View file

@ -1,2 +1,2 @@
#include "libc/sysv/macros.internal.h" #include "libc/sysv/macros.internal.h"
.scall __sys_fstatat,0x1d202a22821d6106,0x04f,globl,hidden .scall __sys_fstatat,0x1d202a22821d6106,79,470,globl,hidden

View file

@ -1,2 +1,2 @@
#include "libc/sysv/macros.internal.h" #include "libc/sysv/macros.internal.h"
.scall __sys_getpeername,0x01f01f08d201f034,0x0cd,globl,hidden .scall __sys_getpeername,0x01f01f08d201f034,205,31,globl,hidden

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