mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-08 02:40:28 +00:00
Merge remote-tracking branch 'upstream/master' into patch-3.1
# Conflicts: # libc/time/localtime.c # test/libc/stdio/dirstream_test.c
This commit is contained in:
commit
0303463d7b
510 changed files with 1790 additions and 1489 deletions
4
.vscode/c_cpp_properties.json
vendored
4
.vscode/c_cpp_properties.json
vendored
|
@ -41,8 +41,8 @@
|
|||
"interruptfn=",
|
||||
"optimizespeed=",
|
||||
"forcealignargpointer=",
|
||||
"noasan=",
|
||||
"noubsan=",
|
||||
"dontasan=",
|
||||
"dontubsan=",
|
||||
"donothing=",
|
||||
"nosideeffect=",
|
||||
"unreachable=",,
|
||||
|
|
|
@ -143,8 +143,8 @@ machine](https://github.com/jart/blink) by adding the following to the
|
|||
top of your main.c file:
|
||||
|
||||
```c
|
||||
STATIC_YOINK("blink_linux_aarch64"); // for raspberry pi
|
||||
STATIC_YOINK("blink_xnu_aarch64"); // is apple silicon
|
||||
__static_yoink("blink_linux_aarch64"); // for raspberry pi
|
||||
__static_yoink("blink_xnu_aarch64"); // is apple silicon
|
||||
```
|
||||
|
||||
The benefit is you'll have single file executables that'll run on both
|
||||
|
|
|
@ -72,7 +72,9 @@ SECTIONS {
|
|||
KEEP(*(SORT_NONE(.fini)))
|
||||
} =0x1f2003d5
|
||||
|
||||
.privileged ALIGN(CONSTANT(COMMONPAGESIZE)) : {
|
||||
. += CONSTANT(COMMONPAGESIZE);
|
||||
|
||||
.privileged : {
|
||||
__privileged_start = .;
|
||||
*(.privileged*)
|
||||
} =0x1f2003d6
|
||||
|
@ -119,7 +121,7 @@ SECTIONS {
|
|||
_etext = .;
|
||||
PROVIDE(etext = .);
|
||||
|
||||
. = ALIGN(CONSTANT(COMMONPAGESIZE));
|
||||
. += CONSTANT(COMMONPAGESIZE);
|
||||
. = DATA_SEGMENT_ALIGN(CONSTANT(COMMONPAGESIZE), CONSTANT(COMMONPAGESIZE));
|
||||
|
||||
.eh_frame : ONLY_IF_RW {
|
||||
|
|
18
ape/ape-m1.c
18
ape/ape-m1.c
|
@ -190,6 +190,19 @@ static int StrCmp(const char *l, const char *r) {
|
|||
return (l[i] & 255) - (r[i] & 255);
|
||||
}
|
||||
|
||||
static const char *BaseName(const char *s) {
|
||||
int c;
|
||||
const char *b = "";
|
||||
if (s) {
|
||||
while ((c = *s++)) {
|
||||
if (c == '/') {
|
||||
b = s;
|
||||
}
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
static void Bzero(void *a, unsigned long n) {
|
||||
long z;
|
||||
char *p, *e;
|
||||
|
@ -848,7 +861,7 @@ int main(int argc, char **argv, char **envp) {
|
|||
} else if (argc < 2) {
|
||||
Emit("usage: ape PROG [ARGV1,ARGV2,...]\n"
|
||||
" ape - PROG [ARGV0,ARGV1,...]\n"
|
||||
"actually portable executable loader silicon 1.4\n"
|
||||
"actually portable executable loader silicon 1.5\n"
|
||||
"copyright 2023 justine alexandra roberts tunney\n"
|
||||
"https://justine.lol/ape.html\n");
|
||||
_exit(1);
|
||||
|
@ -871,7 +884,8 @@ int main(int argc, char **argv, char **envp) {
|
|||
pe = M->ehdr.buf + rc;
|
||||
|
||||
// resolve argv[0] to reflect path search
|
||||
if (argc > 0 && *prog != '/' && *exe == '/' && !StrCmp(prog, argv[0])) {
|
||||
if ((argc > 0 && *prog != '/' && *exe == '/' && !StrCmp(prog, argv[0])) ||
|
||||
!StrCmp(BaseName(prog), argv[0])) {
|
||||
tp -= (n = StrLen(exe) + 1);
|
||||
MemMove(tp, exe, n);
|
||||
argv[0] = tp;
|
||||
|
|
|
@ -610,7 +610,7 @@ apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang
|
|||
// extract the loader into a temp folder, and use it to
|
||||
// load the APE without modifying it.
|
||||
.ascii "[ x\"$1\" != x--assimilate ] && {\n"
|
||||
.ascii "t=\"${TMPDIR:-${HOME:-.}}/.ape-1.4\"\n"
|
||||
.ascii "t=\"${TMPDIR:-${HOME:-.}}/.ape-1.5\"\n"
|
||||
.ascii "[ -x \"$t\" ] || {\n"
|
||||
.ascii "mkdir -p \"${t%/*}\" &&\n"
|
||||
.ascii "dd if=\"$o\" of=\"$t.$$\" skip="
|
||||
|
@ -717,8 +717,8 @@ emush: .ascii "\n@\n#'\"\n"
|
|||
.previous
|
||||
// ...
|
||||
// decentralized section (.emush)
|
||||
// - STATIC_YOINK("blink_linux_aarch64"); // for raspberry pi
|
||||
// - STATIC_YOINK("blink_xnu_aarch64"); // is apple silicon
|
||||
// - __static_yoink("blink_linux_aarch64"); // for raspberry pi
|
||||
// - __static_yoink("blink_xnu_aarch64"); // is apple silicon
|
||||
// ...
|
||||
.section .emushepilogue,"a",@progbits
|
||||
.ascii "echo \"$0: this ape binary lacks $m support\" >&2\n"
|
||||
|
@ -818,7 +818,7 @@ ape.ident:
|
|||
.long 1
|
||||
1: .asciz "APE"
|
||||
2: .balign 4
|
||||
3: .long 104000000
|
||||
3: .long 105000000
|
||||
4: .size ape.ident,.-ape.ident
|
||||
.type ape.ident,@object
|
||||
.previous
|
||||
|
|
|
@ -432,6 +432,7 @@ SECTIONS {
|
|||
KEEP(*(SORT_BY_NAME(.piro.data.sort.*)))
|
||||
KEEP(*(.piro.pad.data))
|
||||
KEEP(*(.dataepilogue))
|
||||
. = ALIGN(512);
|
||||
/*END: NT FORK COPYING */
|
||||
_edata = .;
|
||||
PROVIDE(edata = .);
|
||||
|
|
50
ape/ape.mk
50
ape/ape.mk
|
@ -35,7 +35,7 @@ APELINK = \
|
|||
$(FIXUPOBJ) \
|
||||
$@
|
||||
|
||||
APE_SRCS = ape/ape.S
|
||||
APE_SRCS = ape/ape.S ape/start.S ape/launch.S ape/systemcall.S
|
||||
APE_OBJS = o/$(MODE)/ape/ape.o
|
||||
APE_NO_MODIFY_SELF = $(APE)
|
||||
APE_COPY_SELF = $(APE)
|
||||
|
@ -52,6 +52,54 @@ o/$(MODE)/ape/aarch64.lds: \
|
|||
libc/macros.internal.h \
|
||||
libc/str/str.h
|
||||
|
||||
APE_LOADER_LDFLAGS = \
|
||||
-pie \
|
||||
-static \
|
||||
-nostdlib \
|
||||
--no-dynamic-linker \
|
||||
-z norelro \
|
||||
-z common-page-size=0x4000 \
|
||||
-z max-page-size=0x4000
|
||||
|
||||
APE_LOADER_FLAGS = \
|
||||
-DNDEBUG \
|
||||
-iquote. \
|
||||
-Wall \
|
||||
-Wextra \
|
||||
-fpie \
|
||||
-Os \
|
||||
-ffreestanding \
|
||||
-mgeneral-regs-only \
|
||||
-fno-asynchronous-unwind-tables \
|
||||
-fno-stack-protector \
|
||||
-fno-ident \
|
||||
-fno-gnu-unique \
|
||||
-c \
|
||||
$(OUTPUT_OPTION) \
|
||||
$<
|
||||
|
||||
o/$(MODE)/ape/ape.elf: o/$(MODE)/ape/ape.elf.dbg
|
||||
$(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -g $< $@
|
||||
|
||||
o/$(MODE)/ape/ape.elf.dbg: \
|
||||
o/$(MODE)/ape/start.o \
|
||||
o/$(MODE)/ape/loader.o \
|
||||
o/$(MODE)/ape/launch.o \
|
||||
o/$(MODE)/ape/systemcall.o
|
||||
@$(COMPILE) -ALINK.elf $(LD) $(APE_LOADER_LDFLAGS) -o $@ $(patsubst %.lds,-T %.lds,$^)
|
||||
|
||||
o/$(MODE)/ape/loader.o: ape/loader.c
|
||||
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=1 -g $(APE_LOADER_FLAGS)
|
||||
o/$(MODE)/ape/start.o: ape/start.S
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||
o/$(MODE)/ape/launch.o: ape/launch.S
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||
o/$(MODE)/ape/systemcall.o: ape/systemcall.S
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||
|
||||
.PHONY: o/$(MODE)/ape
|
||||
o/$(MODE)/ape: o/$(MODE)/ape/ape.elf
|
||||
|
||||
else
|
||||
|
||||
APE = o/$(MODE)/ape/ape.o \
|
||||
|
|
|
@ -37,6 +37,7 @@ for x in .ape \
|
|||
.ape-1.1 \
|
||||
.ape-1.3 \
|
||||
.ape-1.4 \
|
||||
.ape-1.5 \
|
||||
.ape-blink-0.9.2 \
|
||||
.ape-blink-1.0.0; do
|
||||
rm -f \
|
||||
|
|
41
ape/launch.S
41
ape/launch.S
|
@ -34,7 +34,44 @@
|
|||
// @param rdx is stack pointer (becomes zero)
|
||||
// @param rcx is passed through as-is
|
||||
// @noreturn
|
||||
Launch: xor %r8d,%r8d
|
||||
Launch:
|
||||
#ifdef __aarch64__
|
||||
|
||||
mov x16,x1
|
||||
mov sp,x2
|
||||
mov x1,0
|
||||
mov x2,0
|
||||
mov x3,0
|
||||
mov x4,0
|
||||
mov x5,0
|
||||
mov x6,0
|
||||
mov x7,0
|
||||
mov x8,0
|
||||
mov x9,0
|
||||
mov x10,0
|
||||
mov x11,0
|
||||
mov x12,0
|
||||
mov x13,0
|
||||
mov x14,0
|
||||
mov x15,0
|
||||
mov x17,0
|
||||
mov x19,0
|
||||
mov x20,0
|
||||
mov x21,0
|
||||
mov x22,0
|
||||
mov x23,0
|
||||
mov x24,0
|
||||
mov x25,0
|
||||
mov x26,0
|
||||
mov x27,0
|
||||
mov x28,0
|
||||
mov x29,0
|
||||
mov x30,0
|
||||
br x16
|
||||
|
||||
#else
|
||||
|
||||
xor %r8d,%r8d
|
||||
xor %r9d,%r9d
|
||||
xor %r10d,%r10d
|
||||
xor %r11d,%r11d
|
||||
|
@ -50,4 +87,6 @@ Launch: xor %r8d,%r8d
|
|||
xor %ebx,%ebx
|
||||
xor %eax,%eax
|
||||
ret
|
||||
|
||||
#endif
|
||||
.endfn Launch,globl
|
||||
|
|
160
ape/loader.c
160
ape/loader.c
|
@ -98,6 +98,12 @@
|
|||
#define IsOpenbsd() (SupportsOpenbsd() && os == OPENBSD)
|
||||
#define IsNetbsd() (SupportsNetbsd() && os == NETBSD)
|
||||
|
||||
#ifdef __aarch64__
|
||||
#define IsAarch64() 1
|
||||
#else
|
||||
#define IsAarch64() 0
|
||||
#endif
|
||||
|
||||
#define O_RDONLY 0
|
||||
#define PROT_NONE 0
|
||||
#define PROT_READ 1
|
||||
|
@ -111,6 +117,7 @@
|
|||
#define ELFCLASS32 1
|
||||
#define ELFDATA2LSB 1
|
||||
#define EM_NEXGEN32E 62
|
||||
#define EM_AARCH64 183
|
||||
#define ET_EXEC 2
|
||||
#define ET_DYN 3
|
||||
#define PT_LOAD 1
|
||||
|
@ -229,6 +236,19 @@ static int StrCmp(const char *l, const char *r) {
|
|||
return (l[i] & 255) - (r[i] & 255);
|
||||
}
|
||||
|
||||
static const char *BaseName(const char *s) {
|
||||
int c;
|
||||
const char *b = "";
|
||||
if (s) {
|
||||
while ((c = *s++)) {
|
||||
if (c == '/') {
|
||||
b = s;
|
||||
}
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
static void Bzero(void *a, unsigned long n) {
|
||||
long z;
|
||||
char *p, *e;
|
||||
|
@ -354,43 +374,87 @@ __attribute__((__noinline__)) static long CallSystem(long arg1, long arg2,
|
|||
}
|
||||
|
||||
__attribute__((__noreturn__)) static void Exit(long rc, int os) {
|
||||
CallSystem(rc, 0, 0, 0, 0, 0, 0, IsLinux() ? 60 : 1, os);
|
||||
int numba;
|
||||
if (IsLinux()) {
|
||||
if (IsAarch64()) {
|
||||
numba = 94;
|
||||
} else {
|
||||
numba = 60;
|
||||
}
|
||||
} else {
|
||||
numba = 1;
|
||||
}
|
||||
CallSystem(rc, 0, 0, 0, 0, 0, 0, numba, os);
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
static int Close(int fd, int os) {
|
||||
return CallSystem(fd, 0, 0, 0, 0, 0, 0, IsLinux() ? 3 : 6, os);
|
||||
int numba;
|
||||
if (IsLinux()) {
|
||||
if (IsAarch64()) {
|
||||
numba = 57;
|
||||
} else {
|
||||
numba = 3;
|
||||
}
|
||||
} else {
|
||||
numba = 6;
|
||||
}
|
||||
return CallSystem(fd, 0, 0, 0, 0, 0, 0, numba, os);
|
||||
}
|
||||
|
||||
static long Pread(int fd, void *data, unsigned long size, long off, int os) {
|
||||
long magi;
|
||||
long numba;
|
||||
if (IsLinux()) {
|
||||
magi = 0x011;
|
||||
if (IsAarch64()) {
|
||||
numba = 0x043;
|
||||
} else {
|
||||
numba = 0x011;
|
||||
}
|
||||
} else if (IsXnu()) {
|
||||
magi = 0x2000099;
|
||||
numba = 0x2000099;
|
||||
} else if (IsFreebsd()) {
|
||||
magi = 0x1db;
|
||||
numba = 0x1db;
|
||||
} else if (IsOpenbsd()) {
|
||||
magi = 0x0a9; /* OpenBSD v7.3+ */
|
||||
numba = 0x0a9; /* OpenBSD v7.3+ */
|
||||
} else if (IsNetbsd()) {
|
||||
magi = 0x0ad;
|
||||
numba = 0x0ad;
|
||||
} else {
|
||||
__builtin_unreachable();
|
||||
}
|
||||
return SystemCall(fd, (long)data, size, off, off, 0, 0, magi);
|
||||
return SystemCall(fd, (long)data, size, off, off, 0, 0, numba);
|
||||
}
|
||||
|
||||
static long Write(int fd, const void *data, unsigned long size, int os) {
|
||||
return CallSystem(fd, (long)data, size, 0, 0, 0, 0, IsLinux() ? 1 : 4, os);
|
||||
int numba;
|
||||
if (IsLinux()) {
|
||||
if (IsAarch64()) {
|
||||
numba = 64;
|
||||
} else {
|
||||
numba = 1;
|
||||
}
|
||||
} else {
|
||||
numba = 4;
|
||||
}
|
||||
return CallSystem(fd, (long)data, size, 0, 0, 0, 0, numba, os);
|
||||
}
|
||||
|
||||
static int Execve(const char *prog, char **argv, char **envp, int os) {
|
||||
return CallSystem((long)prog, (long)argv, (long)envp, 0, 0, 0, 0, 59, os);
|
||||
int numba;
|
||||
if (IsLinux() && IsAarch64()) {
|
||||
numba = 221;
|
||||
} else {
|
||||
numba = 59;
|
||||
}
|
||||
return CallSystem((long)prog, (long)argv, (long)envp, 0, 0, 0, 0, numba, os);
|
||||
}
|
||||
|
||||
static int Access(const char *path, int mode, int os) {
|
||||
if (IsLinux() && IsAarch64()) {
|
||||
return SystemCall(-100, (long)path, mode, 0, 0, 0, 0, 48);
|
||||
} else {
|
||||
return CallSystem((long)path, mode, 0, 0, 0, 0, 0, IsLinux() ? 21 : 33, os);
|
||||
}
|
||||
}
|
||||
|
||||
static int Msyscall(long p, unsigned long n, int os) {
|
||||
if (IsOpenbsd()) {
|
||||
|
@ -401,31 +465,49 @@ static int Msyscall(long p, unsigned long n, int os) {
|
|||
}
|
||||
|
||||
static int Open(const char *path, int flags, int mode, int os) {
|
||||
return CallSystem((long)path, flags, mode, 0, 0, 0, 0, IsLinux() ? 2 : 5, os);
|
||||
if (IsLinux() && IsAarch64()) {
|
||||
return SystemCall(-100, (long)path, flags, mode, 0, 0, 0, 56);
|
||||
} else {
|
||||
return CallSystem((long)path, flags, mode, 0, 0, 0, 0, IsLinux() ? 2 : 5,
|
||||
os);
|
||||
}
|
||||
}
|
||||
|
||||
static int Mprotect(void *addr, unsigned long size, int prot, int os) {
|
||||
return CallSystem((long)addr, size, prot, 0, 0, 0, 0, IsLinux() ? 10 : 74,
|
||||
os);
|
||||
int numba;
|
||||
if (IsLinux()) {
|
||||
if (IsAarch64()) {
|
||||
numba = 226;
|
||||
} else {
|
||||
numba = 10;
|
||||
}
|
||||
} else {
|
||||
numba = 74;
|
||||
}
|
||||
return CallSystem((long)addr, size, prot, 0, 0, 0, 0, numba, os);
|
||||
}
|
||||
|
||||
static long Mmap(void *addr, unsigned long size, int prot, int flags, int fd,
|
||||
long off, int os) {
|
||||
long magi;
|
||||
long numba;
|
||||
if (IsLinux()) {
|
||||
magi = 9;
|
||||
if (IsAarch64()) {
|
||||
numba = 222;
|
||||
} else {
|
||||
numba = 9;
|
||||
}
|
||||
} else if (IsXnu()) {
|
||||
magi = 0x2000000 | 197;
|
||||
numba = 0x2000000 | 197;
|
||||
} else if (IsFreebsd()) {
|
||||
magi = 477;
|
||||
numba = 477;
|
||||
} else if (IsOpenbsd()) {
|
||||
magi = 49; /* OpenBSD v7.3+ */
|
||||
numba = 49; /* OpenBSD v7.3+ */
|
||||
} else if (IsNetbsd()) {
|
||||
magi = 197;
|
||||
numba = 197;
|
||||
} else {
|
||||
__builtin_unreachable();
|
||||
}
|
||||
return SystemCall((long)addr, size, prot, flags, fd, off, off, magi);
|
||||
return SystemCall((long)addr, size, prot, flags, fd, off, off, numba);
|
||||
}
|
||||
|
||||
static long Print(int os, int fd, const char *s, ...) {
|
||||
|
@ -703,9 +785,15 @@ static const char *TryElf(struct ApeLoader *M, const char *exe, int fd,
|
|||
if (e->e_type != ET_EXEC && e->e_type != ET_DYN) {
|
||||
return "ELF not ET_EXEC or ET_DYN";
|
||||
}
|
||||
#ifdef __aarch64__
|
||||
if (e->e_machine != EM_AARCH64) {
|
||||
return "couldn't find ELF header with AARCH64 machine type";
|
||||
}
|
||||
#else
|
||||
if (e->e_machine != EM_NEXGEN32E) {
|
||||
return "couldn't find ELF header with x86-64 machine type";
|
||||
}
|
||||
#endif
|
||||
if (e->e_phentsize != sizeof(struct ElfPhdr)) {
|
||||
Pexit(os, exe, 0, "e_phentsize is wrong");
|
||||
}
|
||||
|
@ -796,7 +884,7 @@ static __attribute__((__noreturn__)) void ShowUsage(int os, int fd, int rc) {
|
|||
Print(os, fd,
|
||||
"NAME\n"
|
||||
"\n"
|
||||
" actually portable executable loader version 1.4\n"
|
||||
" actually portable executable loader version 1.5\n"
|
||||
" copyright 2023 justine alexandra roberts tunney\n"
|
||||
" https://justine.lol/ape.html\n"
|
||||
"\n"
|
||||
|
@ -814,10 +902,10 @@ static __attribute__((__noreturn__)) void ShowUsage(int os, int fd, int rc) {
|
|||
Exit(rc, os);
|
||||
}
|
||||
|
||||
__attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl) {
|
||||
__attribute__((__noreturn__)) //
|
||||
void ApeLoader(long di, long *sp, char dl) {
|
||||
int rc;
|
||||
unsigned i, n;
|
||||
int usetheforce;
|
||||
int c, fd, os, argc;
|
||||
struct ApeLoader *M;
|
||||
unsigned long pagesz;
|
||||
|
@ -879,14 +967,11 @@ __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl) {
|
|||
}
|
||||
|
||||
/* parse flags */
|
||||
usetheforce = 0;
|
||||
while (argc > 1) {
|
||||
if (argv[1][0] != '-') break; /* normal argument */
|
||||
if (!argv[1][1]) break; /* hyphen argument */
|
||||
if (!StrCmp(argv[1], "-h") || !StrCmp(argv[1], "--help")) {
|
||||
ShowUsage(os, 1, 0);
|
||||
} else if (!StrCmp(argv[1], "-f")) {
|
||||
usetheforce = 1;
|
||||
} else {
|
||||
Print(os, 2, ape, ": invalid flag (pass -h for help)\n", 0l);
|
||||
Exit(1, os);
|
||||
|
@ -926,25 +1011,16 @@ __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl) {
|
|||
pe = M->ehdr.buf + rc;
|
||||
|
||||
/* change argv[0] to resolved path if it's ambiguous */
|
||||
if (argc > 0 && *prog != '/' && *exe == '/' && !StrCmp(prog, argv[0])) {
|
||||
if ((argc > 0 && *prog != '/' && *exe == '/' && !StrCmp(prog, argv[0])) ||
|
||||
!StrCmp(BaseName(prog), argv[0])) {
|
||||
argv[0] = exe;
|
||||
}
|
||||
|
||||
/* ape intended behavior
|
||||
1. if file is a native executable, try to run it natively
|
||||
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 8192 bytes of file
|
||||
5. elf program headers may appear anywhere in the binary */
|
||||
if (!usetheforce &&
|
||||
((IsXnu() && READ32(M->ehdr.buf) == 0xFEEDFACE + 1) ||
|
||||
(!IsXnu() && READ32(M->ehdr.buf) == READ32("\177ELF")))) {
|
||||
Close(fd, os);
|
||||
Execve(exe, argv, envp, os);
|
||||
if ((fd = Open(exe, O_RDONLY, 0, os)) < 0) {
|
||||
Pexit(os, exe, rc, "execve and open failed");
|
||||
}
|
||||
}
|
||||
1. if ape, will scan shell script for elf printf statements
|
||||
2. shell script may have multiple lines producing elf headers
|
||||
3. all elf printf lines must exist in the first 8192 bytes of file
|
||||
4. elf program headers may appear anywhere in the binary */
|
||||
if (READ64(M->ehdr.buf) == READ64("MZqFpD='") ||
|
||||
READ64(M->ehdr.buf) == READ64("jartsr='") ||
|
||||
READ64(M->ehdr.buf) == READ64("APEDBG='")) {
|
||||
|
|
13
ape/start.S
13
ape/start.S
|
@ -19,6 +19,15 @@
|
|||
#include "libc/dce.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
#ifdef __aarch64__
|
||||
|
||||
_start: mov x1,sp
|
||||
mov x29,0
|
||||
bl ApeLoader
|
||||
.endfn _start,globl
|
||||
|
||||
#else
|
||||
|
||||
XnuEntrypoint:
|
||||
mov $_HOSTXNU,%dl // xnu's not unix!
|
||||
ElfEntrypoint:
|
||||
|
@ -56,6 +65,8 @@ ape.ident:
|
|||
.long 1
|
||||
1: .asciz "APE"
|
||||
2: .balign 4
|
||||
3: .long 104000000
|
||||
3: .long 105000000
|
||||
4: .size ape.ident,.-ape.ident
|
||||
.type ape.ident,@object
|
||||
|
||||
#endif
|
||||
|
|
|
@ -28,6 +28,16 @@
|
|||
// errors are returned as `-errno`. BSD systems are normalized
|
||||
// to follow this convention automatically.
|
||||
SystemCall:
|
||||
#ifdef __aarch64__
|
||||
mov x8,x7
|
||||
mov x9,0
|
||||
adds x9,x9,0
|
||||
svc 0
|
||||
bcs 1f
|
||||
ret
|
||||
1: neg x0,x0
|
||||
ret
|
||||
#else
|
||||
mov %rcx,%r10
|
||||
mov 16(%rsp),%eax
|
||||
clc
|
||||
|
@ -35,4 +45,5 @@ SystemCall:
|
|||
jnc 1f
|
||||
neg %rax
|
||||
1: ret
|
||||
#endif
|
||||
.endfn SystemCall,globl
|
||||
|
|
BIN
build/bootstrap/ape.aarch64
Executable file
BIN
build/bootstrap/ape.aarch64
Executable file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -75,7 +75,7 @@ extern char *ttyraster(char *, const struct TtyRgb *, size_t, size_t,
|
|||
|
||||
#ifndef ttyquant
|
||||
#define ttyquant() (&g_ttyquant_)
|
||||
#define TTYQUANT() VEIL("r", &g_ttyquant_)
|
||||
#define TTYQUANT() __veil("r", &g_ttyquant_)
|
||||
#define rgb2tty(...) (ttyquant()->rgb2tty(__VA_ARGS__))
|
||||
#define tty2rgb(...) (ttyquant()->tty2rgb(__VA_ARGS__))
|
||||
#define rgb2ttyf(...) (ttyquant()->rgb2ttyf(__VA_ARGS__))
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include "third_party/mbedtls/ssl.h"
|
||||
#include "third_party/mbedtls/x509_crt.h"
|
||||
|
||||
STATIC_YOINK("ssl_root_support");
|
||||
__static_yoink("ssl_root_support");
|
||||
|
||||
#define MODE_NONE 0
|
||||
#define MODE_FILE 1
|
||||
|
|
|
@ -75,8 +75,8 @@
|
|||
* the following functions to further expand the information shown by
|
||||
* the NDEBUG check failure:
|
||||
*
|
||||
* STATIC_YOINK("__die");
|
||||
* STATIC_YOINK("strerror");
|
||||
* __static_yoink("__die");
|
||||
* __static_yoink("strerror");
|
||||
*
|
||||
* Please note that backtraces aren't ever available in MODE=tiny.
|
||||
*/
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
* o//examples/crashreport.com
|
||||
*/
|
||||
|
||||
noubsan int main(int argc, char *argv[]) {
|
||||
dontubsan int main(int argc, char *argv[]) {
|
||||
kprintf("----------------\n");
|
||||
kprintf(" THIS IS A TEST \n");
|
||||
kprintf("SIMULATING CRASH\n");
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
|
||||
STATIC_YOINK("strerror");
|
||||
__static_yoink("strerror");
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
sigset_t ss;
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
#include "third_party/libcxx/vector"
|
||||
#include "tool/viz/lib/knobs.h"
|
||||
|
||||
STATIC_YOINK("zipos");
|
||||
__static_yoink("zipos");
|
||||
|
||||
#define USAGE \
|
||||
" [ROM] [FMV]\n\
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
* Yes this works on Windows.
|
||||
*/
|
||||
|
||||
STATIC_YOINK("_tr");
|
||||
STATIC_YOINK("_sed");
|
||||
__static_yoink("_tr");
|
||||
__static_yoink("_sed");
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
system("x=world\n"
|
||||
|
|
|
@ -28,12 +28,12 @@
|
|||
* Please note that, by default, APE binaries only use the serial port
|
||||
* for stdio. To get the VGA console as an added bonus:
|
||||
*
|
||||
* STATIC_YOINK("vga_console");
|
||||
* __static_yoink("vga_console");
|
||||
*
|
||||
* Should be added to the top of your main() program source file.
|
||||
*/
|
||||
|
||||
STATIC_YOINK("vga_console");
|
||||
__static_yoink("vga_console");
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
volatile long double x = -.5;
|
||||
|
|
|
@ -24,9 +24,9 @@
|
|||
* qemu-system-x86_64 -hda o//examples/vga2.com -serial stdio
|
||||
*/
|
||||
|
||||
STATIC_YOINK("vga_console");
|
||||
STATIC_YOINK("_idt");
|
||||
STATIC_YOINK("EfiMain");
|
||||
__static_yoink("vga_console");
|
||||
__static_yoink("_idt");
|
||||
__static_yoink("EfiMain");
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int i;
|
||||
|
|
|
@ -18,8 +18,8 @@ void __assert_fail(const char *, const char *, int) relegated;
|
|||
#ifdef COSMO
|
||||
extern bool __assert_disable;
|
||||
#ifndef NDEBUG
|
||||
#define _unassert(x) __assert_macro(x, #x)
|
||||
#define _npassert(x) __assert_macro(x, #x)
|
||||
#define unassert(x) __assert_macro(x, #x)
|
||||
#define npassert(x) __assert_macro(x, #x)
|
||||
#define __assert_macro(x, s) \
|
||||
({ \
|
||||
if (__builtin_expect(!(x), 0)) { \
|
||||
|
@ -29,14 +29,14 @@ extern bool __assert_disable;
|
|||
(void)0; \
|
||||
})
|
||||
#else
|
||||
#define _npassert(x) \
|
||||
#define npassert(x) \
|
||||
({ \
|
||||
if (__builtin_expect(!(x), 0)) { \
|
||||
__builtin_trap(); \
|
||||
} \
|
||||
(void)0; \
|
||||
})
|
||||
#define _unassert(x) \
|
||||
#define unassert(x) \
|
||||
({ \
|
||||
if (__builtin_expect(!(x), 0)) { \
|
||||
__builtin_unreachable(); \
|
||||
|
|
|
@ -35,7 +35,7 @@ unsigned alarm(unsigned seconds) {
|
|||
struct itimerval it;
|
||||
bzero(&it, sizeof(it));
|
||||
it.it_value.tv_sec = seconds;
|
||||
_npassert(!setitimer(ITIMER_REAL, &it, &it));
|
||||
npassert(!setitimer(ITIMER_REAL, &it, &it));
|
||||
if (!it.it_value.tv_sec && !it.it_value.tv_usec) {
|
||||
return 0;
|
||||
} else {
|
||||
|
|
|
@ -80,11 +80,11 @@ static struct timespec GetNanosleepLatency(void) {
|
|||
if (!(nanos = g_nanosleep_latency)) {
|
||||
BLOCK_CANCELLATIONS;
|
||||
for (cgt = __clock_gettime_get(0);;) {
|
||||
_npassert(!cgt(CLOCK_REALTIME_PRECISE, &x));
|
||||
npassert(!cgt(CLOCK_REALTIME_PRECISE, &x));
|
||||
rc = sys_clock_nanosleep(CLOCK_REALTIME, 0, &w, 0);
|
||||
_npassert(!rc || rc == EINTR);
|
||||
npassert(!rc || rc == EINTR);
|
||||
if (!rc) {
|
||||
_npassert(!cgt(CLOCK_REALTIME_PRECISE, &y));
|
||||
npassert(!cgt(CLOCK_REALTIME_PRECISE, &y));
|
||||
nanos = timespec_tonanos(timespec_sub(y, x));
|
||||
g_nanosleep_latency = nanos;
|
||||
break;
|
||||
|
@ -115,10 +115,10 @@ static errno_t SpinNanosleep(int clock, int flags, const struct timespec *req,
|
|||
return rc;
|
||||
}
|
||||
cgt = __clock_gettime_get(0);
|
||||
_npassert(!cgt(CLOCK_REALTIME, &start));
|
||||
npassert(!cgt(CLOCK_REALTIME, &start));
|
||||
for (;;) {
|
||||
sched_yield();
|
||||
_npassert(!cgt(CLOCK_REALTIME, &now));
|
||||
npassert(!cgt(CLOCK_REALTIME, &now));
|
||||
if (flags & TIMER_ABSTIME) {
|
||||
if (timespec_cmp(now, *req) >= 0) {
|
||||
return 0;
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
// Implements dup(), dup2(), dup3(), and F_DUPFD for Windows.
|
||||
textwindows int sys_dup_nt(int oldfd, int newfd, int flags, int start) {
|
||||
int64_t rc, proc, handle;
|
||||
_unassert(!(flags & ~O_CLOEXEC));
|
||||
unassert(!(flags & ~O_CLOEXEC));
|
||||
|
||||
__fds_lock();
|
||||
|
||||
|
|
|
@ -45,9 +45,9 @@ static void sys_dup3_test(void) {
|
|||
|
||||
int32_t sys_dup3(int32_t oldfd, int32_t newfd, int flags) {
|
||||
int how;
|
||||
_unassert(oldfd >= 0);
|
||||
_unassert(newfd >= 0);
|
||||
_unassert(!(flags & ~O_CLOEXEC));
|
||||
unassert(oldfd >= 0);
|
||||
unassert(newfd >= 0);
|
||||
unassert(!(flags & ~O_CLOEXEC));
|
||||
|
||||
if (IsFreebsd()) {
|
||||
if (flags & O_CLOEXEC) {
|
||||
|
|
|
@ -85,8 +85,8 @@ int sys_execve(const char *prog, char *const argv[], char *const envp[]) {
|
|||
(CanExecute((ape = "/usr/bin/ape")) ||
|
||||
CanExecute((ape = Join(firstnonnull(getenv("TMPDIR"),
|
||||
firstnonnull(getenv("HOME"), ".")),
|
||||
".ape-1.4", buf))) ||
|
||||
CanExecute((ape = Join(firstnonnull(getenv("HOME"), "."), ".ape-1.4",
|
||||
".ape-1.5", buf))) ||
|
||||
CanExecute((ape = Join(firstnonnull(getenv("HOME"), "."), ".ape-1.5",
|
||||
buf))))) {
|
||||
shargs[0] = ape;
|
||||
shargs[1] = "-";
|
||||
|
|
|
@ -52,7 +52,7 @@ int fadvise(int fd, uint64_t offset, uint64_t len, int advice) {
|
|||
} else {
|
||||
rc = sys_fadvise_netbsd(fd, offset, offset, len, advice);
|
||||
}
|
||||
_npassert(rc >= 0);
|
||||
npassert(rc >= 0);
|
||||
if (rc) {
|
||||
errno = rc;
|
||||
rc = -1;
|
||||
|
|
|
@ -158,7 +158,7 @@ static int fd_to_mem_fd(const int infd, char *path) {
|
|||
if (path) {
|
||||
FormatInt32(stpcpy(path, "COSMOPOLITAN_INIT_ZIPOS="), fd);
|
||||
}
|
||||
_unassert(readRc == st.st_size);
|
||||
unassert(readRc == st.st_size);
|
||||
return fd;
|
||||
} else if (!success) {
|
||||
errno = e;
|
||||
|
|
|
@ -29,12 +29,12 @@ int __fixupnewfd(int fd, int flags) {
|
|||
int file_mode;
|
||||
if (fd != -1) {
|
||||
if (flags & O_CLOEXEC) {
|
||||
_unassert((file_mode = __sys_fcntl(fd, F_GETFD)) != -1);
|
||||
_unassert(!__sys_fcntl(fd, F_SETFD, file_mode | FD_CLOEXEC));
|
||||
unassert((file_mode = __sys_fcntl(fd, F_GETFD)) != -1);
|
||||
unassert(!__sys_fcntl(fd, F_SETFD, file_mode | FD_CLOEXEC));
|
||||
}
|
||||
if (flags & O_NONBLOCK) {
|
||||
_unassert((file_mode = __sys_fcntl(fd, F_GETFL)) != -1);
|
||||
_unassert(!__sys_fcntl(fd, F_SETFL, file_mode | O_NONBLOCK));
|
||||
unassert((file_mode = __sys_fcntl(fd, F_GETFL)) != -1);
|
||||
unassert(!__sys_fcntl(fd, F_SETFL, file_mode | O_NONBLOCK));
|
||||
}
|
||||
}
|
||||
return fd;
|
||||
|
|
|
@ -31,7 +31,7 @@ textwindows int sys_ftruncate_nt(int64_t handle, uint64_t length) {
|
|||
if ((ok = SetFilePointerEx(handle, 0, &tell, kNtFileCurrent))) {
|
||||
ok = SetFilePointerEx(handle, length, NULL, kNtFileBegin) &&
|
||||
SetEndOfFile(handle);
|
||||
_npassert(SetFilePointerEx(handle, tell, NULL, kNtFileBegin));
|
||||
npassert(SetFilePointerEx(handle, tell, NULL, kNtFileBegin));
|
||||
}
|
||||
if (ok) {
|
||||
return 0;
|
||||
|
|
|
@ -52,7 +52,7 @@ char *getcwd(char *buf, size_t size) {
|
|||
return 0;
|
||||
}
|
||||
} else if (_weaken(malloc)) {
|
||||
_unassert(!__vforked);
|
||||
unassert(!__vforked);
|
||||
if (!size) size = PATH_MAX;
|
||||
if (!(p = _weaken(malloc)(size))) {
|
||||
STRACE("getcwd(%p, %'zu) %m", buf, size);
|
||||
|
@ -60,7 +60,7 @@ char *getcwd(char *buf, size_t size) {
|
|||
}
|
||||
} else {
|
||||
einval();
|
||||
STRACE("getcwd() needs buf≠0 or STATIC_YOINK(\"malloc\")");
|
||||
STRACE("getcwd() needs buf≠0 or __static_yoink(\"malloc\")");
|
||||
return 0;
|
||||
}
|
||||
*p = '\0';
|
||||
|
|
|
@ -44,7 +44,7 @@ int getppid(void) {
|
|||
} else {
|
||||
rc = sys_getppid_nt();
|
||||
}
|
||||
_npassert(rc >= 0);
|
||||
npassert(rc >= 0);
|
||||
STRACE("%s() → %d", "getppid", rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ uint32_t getuid(void) {
|
|||
} else {
|
||||
rc = GetUserNameHash();
|
||||
}
|
||||
_npassert(rc >= 0);
|
||||
npassert(rc >= 0);
|
||||
STRACE("%s() → %d", "getuid", rc);
|
||||
return rc;
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ uint32_t getgid(void) {
|
|||
} else {
|
||||
rc = GetUserNameHash();
|
||||
}
|
||||
_npassert(rc >= 0);
|
||||
npassert(rc >= 0);
|
||||
STRACE("%s() → %d", "getgid", rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -291,7 +291,7 @@ static textwindows int createHostInfo(
|
|||
char name[IFNAMSIZ];
|
||||
int count, i;
|
||||
/* __hostInfo must be empty */
|
||||
_unassert(__hostInfo == NULL);
|
||||
unassert(__hostInfo == NULL);
|
||||
for (aa = firstAdapter; aa; aa = aa->Next) {
|
||||
/* Skip all the interfaces with no address and the ones that are not AF_INET
|
||||
*/
|
||||
|
|
|
@ -47,12 +47,12 @@
|
|||
#define MAP_FIXED_linux 0x00000010
|
||||
#define MAP_SHARED_linux 0x00000001
|
||||
|
||||
STATIC_YOINK("_init_metalfile");
|
||||
__static_yoink("_init_metalfile");
|
||||
|
||||
void *__ape_com_base;
|
||||
size_t __ape_com_size = 0;
|
||||
|
||||
textstartup noasan void InitializeMetalFile(void) {
|
||||
textstartup dontasan void InitializeMetalFile(void) {
|
||||
if (IsMetal()) {
|
||||
/*
|
||||
* Copy out a pristine image of the program — before the program might
|
||||
|
@ -61,7 +61,7 @@ textstartup noasan void InitializeMetalFile(void) {
|
|||
* This code is included if a symbol "file:/proc/self/exe" is defined
|
||||
* (see libc/calls/metalfile.internal.h & libc/calls/metalfile_init.S).
|
||||
* 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 - __executable_start, 4096);
|
||||
// TODO(jart): Restore support for ZIPOS on metal.
|
||||
|
@ -70,7 +70,7 @@ textstartup noasan void InitializeMetalFile(void) {
|
|||
dm = sys_mmap_metal(NULL, size, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED_linux | MAP_ANONYMOUS_linux, -1, 0);
|
||||
copied_base = dm.addr;
|
||||
_npassert(copied_base != (void *)-1);
|
||||
npassert(copied_base != (void *)-1);
|
||||
memcpy(copied_base, (void *)(BANE + IMAGE_BASE_PHYSICAL), size);
|
||||
__ape_com_base = copied_base;
|
||||
__ape_com_size = size;
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "libc/runtime/pc.internal.h"
|
||||
#ifdef __x86_64__
|
||||
|
||||
noasan int sys_munmap_metal(void *addr, size_t size) {
|
||||
dontasan int sys_munmap_metal(void *addr, size_t size) {
|
||||
size_t i;
|
||||
uint64_t *e, paddr;
|
||||
struct mman *mm = __get_mm();
|
||||
|
|
|
@ -92,7 +92,7 @@ static long double nowl_art(void) {
|
|||
static long double nowl_vdso(void) {
|
||||
long double secs;
|
||||
struct timespec tv;
|
||||
_unassert(__gettime);
|
||||
unassert(__gettime);
|
||||
__gettime(CLOCK_REALTIME_PRECISE, &tv);
|
||||
secs = tv.tv_nsec;
|
||||
secs *= 1 / 1e9L;
|
||||
|
|
|
@ -53,7 +53,7 @@ static textwindows int sys_open_nt_console(int dirfd,
|
|||
-1) {
|
||||
g_fds.p[fd].extra = sys_open_nt_impl(dirfd, mp->conout,
|
||||
(flags & ~O_ACCMODE) | O_WRONLY, mode);
|
||||
_npassert(g_fds.p[fd].extra != -1);
|
||||
npassert(g_fds.p[fd].extra != -1);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
*
|
||||
* If your main() source file has this statement:
|
||||
*
|
||||
* STATIC_YOINK("zipos");
|
||||
* __static_yoink("zipos");
|
||||
*
|
||||
* Then you can read zip assets by adding a `"/zip/..."` prefix to `file`, e.g.
|
||||
*
|
||||
|
|
|
@ -66,8 +66,8 @@ static int openpty_impl(int *mfd, int *sfd, char *name,
|
|||
*mfd = m;
|
||||
*sfd = s;
|
||||
if (name) strcpy(name, t.sname);
|
||||
if (tio) _npassert(!tcsetattr(s, TCSAFLUSH, tio));
|
||||
if (wsz) _npassert(!tcgetwinsize(s, wsz));
|
||||
if (tio) npassert(!tcsetattr(s, TCSAFLUSH, tio));
|
||||
if (wsz) npassert(!tcgetwinsize(s, wsz));
|
||||
return 0;
|
||||
OnError:
|
||||
if (m != -1) sys_close(m);
|
||||
|
|
|
@ -51,10 +51,10 @@ errno_t posix_fadvise(int fd, int64_t offset, int64_t len, int advice) {
|
|||
rc = sys_fadvise(fd, offset, len, advice);
|
||||
} else if (IsFreebsd()) {
|
||||
rc = sys_fadvise(fd, offset, len, advice);
|
||||
_unassert(rc >= 0);
|
||||
unassert(rc >= 0);
|
||||
} else if (IsNetbsd()) {
|
||||
rc = sys_fadvise_netbsd(fd, offset, offset, len, advice);
|
||||
_unassert(rc >= 0);
|
||||
unassert(rc >= 0);
|
||||
} else if (IsWindows()) {
|
||||
rc = sys_fadvise_nt(fd, offset, len, advice);
|
||||
} else {
|
||||
|
|
|
@ -76,7 +76,7 @@ ssize_t pread(int fd, void *buf, size_t size, int64_t offset) {
|
|||
} else {
|
||||
rc = ebadf();
|
||||
}
|
||||
_npassert(rc == -1 || (size_t)rc <= size);
|
||||
npassert(rc == -1 || (size_t)rc <= size);
|
||||
|
||||
END_CANCELLATION_POINT;
|
||||
DATATRACE("pread(%d, [%#.*hhs%s], %'zu, %'zd) → %'zd% m", fd,
|
||||
|
|
|
@ -69,9 +69,9 @@ ssize_t pwrite(int fd, const void *buf, size_t size, int64_t offset) {
|
|||
if (rc != -1) {
|
||||
wrote = (size_t)rc;
|
||||
if (!wrote) {
|
||||
_npassert(size == 0);
|
||||
npassert(size == 0);
|
||||
} else {
|
||||
_npassert(wrote <= size);
|
||||
npassert(wrote <= size);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ static textwindows inline bool HasWorkingConsole(void) {
|
|||
return !!(__ntconsolemode[0] | __ntconsolemode[1] | __ntconsolemode[2]);
|
||||
}
|
||||
|
||||
static noubsan void RaiseSigFpe(void) {
|
||||
static dontubsan void RaiseSigFpe(void) {
|
||||
volatile int x = 0;
|
||||
x = 1 / x;
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ static textwindows ssize_t sys_read_nt_impl(struct Fd *fd, void *data,
|
|||
if (!ok && GetLastError() == kNtErrorIoPending) ok = true;
|
||||
if (ok) ok = GetOverlappedResult(fd->handle, &overlap, &got, true);
|
||||
// restore file pointer which windows clobbers, even on error
|
||||
_unassert(SetFilePointerEx(fd->handle, position, 0, SEEK_SET));
|
||||
unassert(SetFilePointerEx(fd->handle, position, 0, SEEK_SET));
|
||||
}
|
||||
if (ok) {
|
||||
return got;
|
||||
|
|
|
@ -181,7 +181,7 @@ skip_readlink:
|
|||
continue;
|
||||
}
|
||||
k = rc;
|
||||
_npassert(k <= p);
|
||||
npassert(k <= p);
|
||||
if (k==p)
|
||||
goto toolong;
|
||||
if (!k) {
|
||||
|
|
|
@ -49,13 +49,13 @@
|
|||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
#ifdef SYSDEBUG
|
||||
STATIC_YOINK("strsignal"); // for kprintf()
|
||||
__static_yoink("strsignal"); // for kprintf()
|
||||
#endif
|
||||
|
||||
#if SupportsWindows()
|
||||
STATIC_YOINK("_init_onntconsoleevent");
|
||||
STATIC_YOINK("_check_sigwinch");
|
||||
STATIC_YOINK("_init_wincrash");
|
||||
__static_yoink("_init_onntconsoleevent");
|
||||
__static_yoink("_check_sigwinch");
|
||||
__static_yoink("_init_wincrash");
|
||||
#endif
|
||||
|
||||
#define SA_RESTORER 0x04000000
|
||||
|
|
|
@ -28,7 +28,7 @@ sigset_t _sigsetmask(sigset_t neu) {
|
|||
if (IsMetal() || IsWindows()) {
|
||||
__sig_mask(SIG_SETMASK, &neu, &res);
|
||||
} else {
|
||||
_npassert(!sys_sigprocmask(SIG_SETMASK, &neu, &res));
|
||||
npassert(!sys_sigprocmask(SIG_SETMASK, &neu, &res));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ unsigned sleep(unsigned seconds) {
|
|||
struct timespec tv = {seconds};
|
||||
if (!(rc = clock_nanosleep(CLOCK_REALTIME, 0, &tv, &tv))) return 0;
|
||||
if (rc == ECANCELED) return -1u;
|
||||
_npassert(rc == EINTR);
|
||||
npassert(rc == EINTR);
|
||||
unslept = tv.tv_sec;
|
||||
if (tv.tv_nsec && unslept < UINT_MAX) {
|
||||
++unslept;
|
||||
|
|
|
@ -29,6 +29,6 @@
|
|||
*/
|
||||
struct timespec timespec_mono(void) {
|
||||
struct timespec ts;
|
||||
_npassert(!clock_gettime(CLOCK_MONOTONIC, &ts));
|
||||
npassert(!clock_gettime(CLOCK_MONOTONIC, &ts));
|
||||
return ts;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,6 @@
|
|||
*/
|
||||
struct timespec timespec_real(void) {
|
||||
struct timespec ts;
|
||||
_npassert(!clock_gettime(CLOCK_REALTIME, &ts));
|
||||
npassert(!clock_gettime(CLOCK_REALTIME, &ts));
|
||||
return ts;
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ struct timespec timespec_sleep(struct timespec delay) {
|
|||
BLOCK_CANCELLATIONS;
|
||||
bzero(&remain, sizeof(remain));
|
||||
if ((rc = clock_nanosleep(CLOCK_REALTIME, 0, &delay, &remain))) {
|
||||
_npassert(rc == EINTR);
|
||||
npassert(rc == EINTR);
|
||||
}
|
||||
ALLOW_CANCELLATIONS;
|
||||
return remain;
|
||||
|
|
|
@ -33,6 +33,6 @@
|
|||
errno_t timespec_sleep_until(struct timespec abs_deadline) {
|
||||
errno_t rc;
|
||||
rc = clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &abs_deadline, 0);
|
||||
_npassert(!rc || rc == EINTR || rc == ECANCELED);
|
||||
npassert(!rc || rc == EINTR || rc == ECANCELED);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,6 @@
|
|||
*/
|
||||
struct timeval timeval_real(void) {
|
||||
struct timeval tv;
|
||||
_npassert(!gettimeofday(&tv, 0));
|
||||
npassert(!gettimeofday(&tv, 0));
|
||||
return tv;
|
||||
}
|
||||
|
|
|
@ -76,15 +76,15 @@ static textwindows void GetNtName(char *name, int kind) {
|
|||
}
|
||||
}
|
||||
|
||||
static inline textwindows noasan int GetNtMajorVersion(void) {
|
||||
static inline textwindows dontasan int GetNtMajorVersion(void) {
|
||||
return NtGetPeb()->OSMajorVersion;
|
||||
}
|
||||
|
||||
static inline textwindows noasan int GetNtMinorVersion(void) {
|
||||
static inline textwindows dontasan int GetNtMinorVersion(void) {
|
||||
return NtGetPeb()->OSMinorVersion;
|
||||
}
|
||||
|
||||
static inline textwindows noasan int GetNtBuildNumber(void) {
|
||||
static inline textwindows dontasan int GetNtBuildNumber(void) {
|
||||
return NtGetPeb()->OSBuildNumber;
|
||||
}
|
||||
|
||||
|
|
|
@ -473,10 +473,10 @@ int unveil(const char *path, const char *permissions) {
|
|||
if (permissions) return einval();
|
||||
if (IsOpenbsd()) return 0;
|
||||
if (landlock_abi_version != -1) {
|
||||
_unassert(landlock_abi_version >= 1);
|
||||
unassert(landlock_abi_version >= 1);
|
||||
return landlock_abi_version;
|
||||
} else {
|
||||
_unassert(landlock_abi_errno);
|
||||
unassert(landlock_abi_errno);
|
||||
errno = landlock_abi_errno;
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ static textwindows ssize_t sys_write_nt_impl(int fd, void *data, size_t size,
|
|||
if (!ok && GetLastError() == kNtErrorIoPending) ok = true;
|
||||
if (ok) ok = GetOverlappedResult(handle, &overlap, &sent, true);
|
||||
// restore file pointer which windows clobbers, even on error
|
||||
_unassert(SetFilePointerEx(handle, position, 0, SEEK_SET));
|
||||
unassert(SetFilePointerEx(handle, position, 0, SEEK_SET));
|
||||
}
|
||||
if (ok) {
|
||||
return sent;
|
||||
|
|
|
@ -55,6 +55,6 @@
|
|||
* @see unbing() for inverse
|
||||
*/
|
||||
int bing(int b, int intent) {
|
||||
_unassert(0 <= b && b < 256);
|
||||
unassert(0 <= b && b < 256);
|
||||
return kCp437[b & 0xff];
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
size_t uint64toarray_fixed16(uint64_t x, char b[hasatleast 17], uint8_t k) {
|
||||
char *p;
|
||||
_unassert(k <= 64 && !(k & 3));
|
||||
unassert(k <= 64 && !(k & 3));
|
||||
for (p = b; k > 0;) *p++ = "0123456789abcdef"[(x >> (k -= 4)) & 15];
|
||||
*p = '\0';
|
||||
return p - b;
|
||||
|
|
|
@ -194,19 +194,22 @@ typedef struct {
|
|||
#endif
|
||||
|
||||
#ifndef privileged
|
||||
#if !defined(__STRICT_ANSI__) && \
|
||||
(__has_attribute(__visibility__) || defined(__GNUC__))
|
||||
#define privileged _Section(".privileged")
|
||||
#else
|
||||
#define privileged _Section(".privileged")
|
||||
#endif
|
||||
#define privileged \
|
||||
_Section(".privileged") dontinline dontinstrument dontubsan dontasan
|
||||
#endif
|
||||
|
||||
#ifndef dontinstrument
|
||||
#if !defined(__STRICT_ANSI__) && \
|
||||
(__has_attribute(__no_instrument_function__) || \
|
||||
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 204)
|
||||
#if ((__GNUC__ + 0) >= 7 && !defined(__chibicc__)) || \
|
||||
__has_attribute(__patchable_function_entry__)
|
||||
#define dontinstrument \
|
||||
__attribute__((__no_instrument_function__, \
|
||||
__patchable_function_entry__(0, 0)))
|
||||
#else
|
||||
#define dontinstrument __attribute__((__no_instrument_function__))
|
||||
#endif
|
||||
#else
|
||||
#define dontinstrument
|
||||
#endif
|
||||
|
@ -569,17 +572,17 @@ typedef struct {
|
|||
#if ((__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 408 || \
|
||||
__has_attribute(__no_sanitize_address__)) && \
|
||||
!defined(__STRICT_ANSI__)
|
||||
#define noasan __attribute__((__no_sanitize_address__))
|
||||
#define dontasan __attribute__((__no_sanitize_address__))
|
||||
#else
|
||||
#define noasan
|
||||
#define dontasan
|
||||
#endif
|
||||
|
||||
#if ((__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 408 || \
|
||||
__has_attribute(__no_sanitize_undefined__)) && \
|
||||
!defined(__STRICT_ANSI__)
|
||||
#define noubsan __attribute__((__no_sanitize_undefined__))
|
||||
#define dontubsan __attribute__((__no_sanitize_undefined__))
|
||||
#else
|
||||
#define noubsan
|
||||
#define dontubsan
|
||||
#endif
|
||||
|
||||
#ifdef __STRICT_ANSI__
|
||||
|
@ -645,11 +648,7 @@ void abort(void) wontreturn;
|
|||
#endif
|
||||
|
||||
#ifndef _Section
|
||||
#if !defined(__STRICT_ANSI__) && !defined(__APPLE__)
|
||||
#define _Section(s) __attribute__((__section__(s)))
|
||||
#else
|
||||
#define _Section(s)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__x86_64__) && !defined(__llvm__)
|
||||
|
@ -772,67 +771,67 @@ void abort(void) wontreturn;
|
|||
#endif
|
||||
|
||||
#ifndef __STRICT_ANSI__
|
||||
#define VEIL(CONSTRAINT, EXPRESSION) \
|
||||
#define __veil(CONSTRAINT, EXPRESSION) \
|
||||
({ \
|
||||
autotype(EXPRESSION) VeiledValue = (EXPRESSION); \
|
||||
asm("" : "=" CONSTRAINT ""(VeiledValue) : "0"(VeiledValue)); \
|
||||
VeiledValue; \
|
||||
})
|
||||
#else
|
||||
#define VEIL(CONSTRAINT, EXPRESSION) (EXPRESSION)
|
||||
#define __veil(CONSTRAINT, EXPRESSION) (EXPRESSION)
|
||||
#endif
|
||||
|
||||
#ifndef __STRICT_ANSI__
|
||||
#define CONCEAL(CONSTRAINT, EXPRESSION) \
|
||||
#define __conceal(CONSTRAINT, EXPRESSION) \
|
||||
({ \
|
||||
autotype(EXPRESSION) VeiledValue = (EXPRESSION); \
|
||||
asm volatile("" : "=" CONSTRAINT ""(VeiledValue) : "0"(VeiledValue)); \
|
||||
VeiledValue; \
|
||||
})
|
||||
#else
|
||||
#define CONCEAL(CONSTRAINT, EXPRESSION) (EXPRESSION)
|
||||
#define __conceal(CONSTRAINT, EXPRESSION) (EXPRESSION)
|
||||
#endif
|
||||
|
||||
#ifndef __STRICT_ANSI__
|
||||
#define EXPROPRIATE(EXPRESSION) \
|
||||
#define __expropriate(EXPRESSION) \
|
||||
({ \
|
||||
asm volatile("" ::"g"(EXPRESSION) : "memory"); \
|
||||
0; \
|
||||
})
|
||||
#else
|
||||
#define EXPROPRIATE(EXPRESSION) (EXPRESSION)
|
||||
#define __expropriate(EXPRESSION) (EXPRESSION)
|
||||
#endif
|
||||
|
||||
#if !defined(__STRICT_ANSI__) && !defined(__APPLE__) && defined(__x86_64__)
|
||||
#define YOINK(SYMBOL) \
|
||||
#define __yoink(SYMBOL) \
|
||||
asm(".section .yoink\n\tnopl\t%0\n\t.previous" : : "m"(SYMBOL))
|
||||
#elif defined(__aarch64__)
|
||||
#define YOINK(SYMBOL) \
|
||||
#define __yoink(SYMBOL) \
|
||||
asm(".section .yoink\n\tb\t%0\n\t.previous" : : "m"(SYMBOL))
|
||||
#else
|
||||
#define YOINK(SYMBOL) (void)0
|
||||
#define __yoink(SYMBOL) (void)0
|
||||
#endif
|
||||
|
||||
#if !defined(__STRICT_ANSI__) && !defined(__APPLE__) && defined(__x86_64__)
|
||||
#define STATIC_YOINK(SYMBOLSTR) \
|
||||
#define __static_yoink(SYMBOLSTR) \
|
||||
asm(".section .yoink\n\tnopl\t\"" SYMBOLSTR "\"\n\t.previous")
|
||||
#elif defined(__aarch64__)
|
||||
#define STATIC_YOINK(SYMBOLSTR) \
|
||||
#define __static_yoink(SYMBOLSTR) \
|
||||
asm(".section .yoink\n\tb\t\"" SYMBOLSTR "\"\n\t.previous")
|
||||
#else
|
||||
#define STATIC_YOINK(SYMBOLSTR)
|
||||
#define __static_yoink(SYMBOLSTR)
|
||||
#endif
|
||||
|
||||
#if !defined(IM_FEELING_NAUGHTY)
|
||||
#define STATIC_YOINK_SOURCE(PATH) STATIC_YOINK(PATH)
|
||||
#define __static_yoink_source(PATH) __static_yoink(PATH)
|
||||
#else
|
||||
#define STATIC_YOINK_SOURCE(PATH)
|
||||
#define __static_yoink_source(PATH)
|
||||
#endif
|
||||
|
||||
#define __strong_reference(sym, aliassym) \
|
||||
extern typeof(sym) aliassym __attribute__((__alias__(#sym)))
|
||||
extern __typeof(sym) aliassym __attribute__((__alias__(#sym)))
|
||||
#define __weak_reference(sym, alias) \
|
||||
asm(".weak\t" #alias "\n\t" \
|
||||
__asm__(".weak\t" #alias "\n\t" \
|
||||
".equ\t" #alias ", " #sym "\n\t" \
|
||||
".type\t" #alias ",@notype")
|
||||
|
||||
|
|
|
@ -83,7 +83,6 @@
|
|||
#define APE_STACKSIZE 4194304 /* default 4mb stack */
|
||||
#endif
|
||||
#define APE_PAGESIZE 0x10000 /* i386+ */
|
||||
#define APE_GUARDSIZE 0x4000 /* b/c apple m1 */
|
||||
|
||||
#define BUFSIZ 0x1000 /* best stdio default */
|
||||
#define CHAR_BIT 8 /* b/c von neumann */
|
||||
|
|
|
@ -20,19 +20,15 @@
|
|||
#include "libc/runtime/runtime.h"
|
||||
|
||||
/**
|
||||
* Returns auxiliary value, or zero if kernel didn't provide it.
|
||||
*
|
||||
* This function is typically regarded as a libc implementation detail;
|
||||
* thus, the source code is the documentation.
|
||||
* Returns auxiliary value better.
|
||||
*
|
||||
* @param at is `AT_...` search key
|
||||
* @return true if value was found
|
||||
* @see libc/sysv/consts.sh
|
||||
* @see System Five Application Binary Interface § 3.4.3
|
||||
* @error ENOENT when value not found
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
struct AuxiliaryValue _getauxval(unsigned long at) {
|
||||
dontasan struct AuxiliaryValue _getauxval(unsigned long at) {
|
||||
unsigned long *ap;
|
||||
for (ap = __auxv; ap[0]; ap += 2) {
|
||||
if (at == ap[0]) {
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
|
||||
noasan bool AreMemoryIntervalsOk(const struct MemoryIntervals *mm) {
|
||||
dontasan bool AreMemoryIntervalsOk(const struct MemoryIntervals *mm) {
|
||||
/* asan runtime depends on this function */
|
||||
int i;
|
||||
size_t wantsize;
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
#include "third_party/dlmalloc/dlmalloc.h"
|
||||
#ifdef __x86_64__
|
||||
|
||||
STATIC_YOINK("_init_asan");
|
||||
__static_yoink("_init_asan");
|
||||
|
||||
#if IsModeDbg()
|
||||
// MODE=dbg
|
||||
|
@ -342,7 +342,7 @@ static char *__asan_hexcpy(char *p, uint64_t x, uint8_t k) {
|
|||
|
||||
static void __asan_exit(void) {
|
||||
kprintf("your asan runtime needs\n"
|
||||
"\tSTATIC_YOINK(\"__die\");\n"
|
||||
"\t__static_yoink(\"__die\");\n"
|
||||
"in order to show you backtraces\n");
|
||||
_Exitr(99);
|
||||
}
|
||||
|
@ -457,7 +457,7 @@ static struct AsanFault __asan_checka(const signed char *s, long ndiv8) {
|
|||
* This is normally abstracted by the compiler. In some cases, it may be
|
||||
* desirable to perform an ASAN memory safety check explicitly, e.g. for
|
||||
* system call wrappers that need to vet memory passed to the kernel, or
|
||||
* string library routines that use the `noasan` keyword due to compiler
|
||||
* string library routines that use the `dontasan` keyword due to compiler
|
||||
* generated ASAN being too costly. This function is fast especially for
|
||||
* large memory ranges since this takes a few picoseconds for each byte.
|
||||
*
|
||||
|
@ -766,11 +766,11 @@ static void __asan_report_memory_origin_image(intptr_t a, int z) {
|
|||
kprintf("\tunknown please supply .com.dbg symbols or set COMDBG\n");
|
||||
}
|
||||
} else {
|
||||
kprintf("\tunknown please STATIC_YOINK(\"GetSymbolTable\");\n");
|
||||
kprintf("\tunknown please __static_yoink(\"GetSymbolTable\");\n");
|
||||
}
|
||||
}
|
||||
|
||||
static noasan void __asan_onmemory(void *x, void *y, size_t n, void *a) {
|
||||
static dontasan void __asan_onmemory(void *x, void *y, size_t n, void *a) {
|
||||
const unsigned char *p = x;
|
||||
struct ReportOriginHeap *t = a;
|
||||
if ((p <= t->a && t->a < p + n) ||
|
||||
|
@ -790,7 +790,7 @@ static void __asan_report_memory_origin_heap(const unsigned char *a, int z) {
|
|||
t.z = z;
|
||||
_weaken(malloc_inspect_all)(__asan_onmemory, &t);
|
||||
} else {
|
||||
kprintf("\tunknown please STATIC_YOINK(\"malloc_inspect_all\");\n");
|
||||
kprintf("\tunknown please __static_yoink(\"malloc_inspect_all\");\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1117,7 +1117,7 @@ int __asan_print_trace(void *p) {
|
|||
kprintf("\n%*lx %s", 12, e->bt.p[i],
|
||||
_weaken(GetSymbolByAddr)
|
||||
? _weaken(GetSymbolByAddr)(e->bt.p[i])
|
||||
: "please STATIC_YOINK(\"GetSymbolByAddr\")");
|
||||
: "please __static_yoink(\"GetSymbolByAddr\")");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1482,7 +1482,8 @@ static textstartup void __asan_shadow_mapping(struct MemoryIntervals *m,
|
|||
static textstartup void __asan_shadow_existing_mappings(void) {
|
||||
__asan_shadow_mapping(&_mmi, 0);
|
||||
__asan_map_shadow(GetStackAddr(), GetStackSize());
|
||||
__asan_poison((void *)GetStackAddr(), APE_GUARDSIZE, kAsanStackOverflow);
|
||||
__asan_poison((void *)GetStackAddr(), getauxval(AT_PAGESZ),
|
||||
kAsanStackOverflow);
|
||||
}
|
||||
|
||||
forceinline ssize_t __write_str(const char *s) {
|
||||
|
@ -1509,7 +1510,7 @@ void __asan_init(int argc, char **argv, char **envp, intptr_t *auxv) {
|
|||
__asan_shadow_existing_mappings();
|
||||
__asan_map_shadow((uintptr_t)__executable_start, _end - __executable_start);
|
||||
__asan_map_shadow(0, 4096);
|
||||
__asan_poison(0, APE_GUARDSIZE, kAsanNullPage);
|
||||
__asan_poison(0, getauxval(AT_PAGESZ), kAsanNullPage);
|
||||
if (!IsWindows()) {
|
||||
sys_mprotect((void *)0x7fff8000, 0x10000, PROT_READ);
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ void _bt(const char *fmt, ...) {
|
|||
errno = e;
|
||||
} else {
|
||||
kprintf("_bt() can't show backtrace because you need:\n"
|
||||
"\tSTATIC_YOINK(\"ShowBacktrace\");\n"
|
||||
"\t__static_yoink(\"ShowBacktrace\");\n"
|
||||
"to be linked.\n");
|
||||
if (_weaken(PrintBacktraceUsingSymbols) && _weaken(GetSymbolTable)) {
|
||||
e = errno;
|
||||
|
@ -58,8 +58,8 @@ void _bt(const char *fmt, ...) {
|
|||
errno = e;
|
||||
} else {
|
||||
kprintf("_bt() can't show backtrace because you need:\n"
|
||||
"\tSTATIC_YOINK(\"PrintBacktraceUsingSymbols\");\n"
|
||||
"\tSTATIC_YOINK(\"GetSymbolTable\");\n"
|
||||
"\t__static_yoink(\"PrintBacktraceUsingSymbols\");\n"
|
||||
"\t__static_yoink(\"GetSymbolTable\");\n"
|
||||
"to be linked.\n");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
STATIC_YOINK("__cxa_finalize");
|
||||
__static_yoink("__cxa_finalize");
|
||||
|
||||
/**
|
||||
* Adds global destructor.
|
||||
|
@ -42,7 +42,7 @@ STATIC_YOINK("__cxa_finalize");
|
|||
* @return 0 on success or nonzero w/ errno
|
||||
* @note folks have forked libc in past just to unbloat atexit()
|
||||
*/
|
||||
noasan int __cxa_atexit(void *fp, void *arg, void *pred) {
|
||||
dontasan int __cxa_atexit(void *fp, void *arg, void *pred) {
|
||||
/* asan runtime depends on this function */
|
||||
unsigned i;
|
||||
struct CxaAtexitBlock *b, *b2;
|
||||
|
@ -61,7 +61,7 @@ noasan int __cxa_atexit(void *fp, void *arg, void *pred) {
|
|||
}
|
||||
}
|
||||
i = _bsr(~b->mask);
|
||||
_unassert(i < ARRAYLEN(b->p));
|
||||
unassert(i < ARRAYLEN(b->p));
|
||||
b->mask |= 1u << i;
|
||||
b->p[i].fp = fp;
|
||||
b->p[i].arg = arg;
|
||||
|
|
|
@ -60,7 +60,7 @@ StartOverLocked:
|
|||
if (!pred) {
|
||||
b2 = b->next;
|
||||
if (b2) {
|
||||
_unassert(b != &__cxa_blocks.root);
|
||||
unassert(b != &__cxa_blocks.root);
|
||||
if (_weaken(free)) {
|
||||
_weaken(free)(b);
|
||||
}
|
||||
|
|
|
@ -32,14 +32,14 @@
|
|||
|
||||
static uint64_t sys_mmap_metal_break;
|
||||
|
||||
noasan static struct DirectMap bad_mmap(void) {
|
||||
dontasan static struct DirectMap bad_mmap(void) {
|
||||
struct DirectMap res;
|
||||
res.addr = (void *)-1;
|
||||
res.maphandle = -1;
|
||||
return res;
|
||||
}
|
||||
|
||||
noasan struct DirectMap sys_mmap_metal(void *vaddr, size_t size, int prot,
|
||||
dontasan struct DirectMap sys_mmap_metal(void *vaddr, size_t size, int prot,
|
||||
int flags, int fd, int64_t off) {
|
||||
/* asan runtime depends on this function */
|
||||
size_t i;
|
||||
|
|
|
@ -72,7 +72,7 @@ textwindows struct DirectMap sys_mmap_nt(void *addr, size_t size, int prot,
|
|||
}
|
||||
}
|
||||
} else {
|
||||
_unassert(flags & MAP_ANONYMOUS);
|
||||
unassert(flags & MAP_ANONYMOUS);
|
||||
fl = (struct ProtectNt){kNtPageExecuteReadwrite,
|
||||
kNtFileMapWrite | kNtFileMapExecute};
|
||||
}
|
||||
|
|
|
@ -43,11 +43,11 @@ static void *_mapframe(void *p, int f) {
|
|||
if (!rc) {
|
||||
return p;
|
||||
} else {
|
||||
_unassert(errno == ENOMEM);
|
||||
unassert(errno == ENOMEM);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
_unassert(errno == ENOMEM);
|
||||
unassert(errno == ENOMEM);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -71,14 +71,14 @@ static void *_mapframe(void *p, int f) {
|
|||
* @return new value for `e` or null w/ errno
|
||||
* @raise ENOMEM if we require more vespene gas
|
||||
*/
|
||||
noasan void *_extend(void *p, size_t n, void *e, int f, intptr_t h) {
|
||||
dontasan void *_extend(void *p, size_t n, void *e, int f, intptr_t h) {
|
||||
char *q;
|
||||
_unassert(!((uintptr_t)SHADOW(p) & (G - 1)));
|
||||
_unassert((uintptr_t)p + (G << kAsanScale) <= h);
|
||||
unassert(!((uintptr_t)SHADOW(p) & (G - 1)));
|
||||
unassert((uintptr_t)p + (G << kAsanScale) <= h);
|
||||
// TODO(jart): Make this spin less in non-ASAN mode.
|
||||
for (q = e; q < ((char *)p + n); q += 8) {
|
||||
if (!((uintptr_t)q & (G - 1))) {
|
||||
_unassert(q + G <= (char *)h);
|
||||
unassert(q + G <= (char *)h);
|
||||
if (!_mapframe(q, f)) return 0;
|
||||
if (IsAsan()) {
|
||||
if (!((uintptr_t)SHADOW(q) & (G - 1))) {
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include "libc/assert.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
|
||||
noasan unsigned FindMemoryInterval(const struct MemoryIntervals *mm, int x) {
|
||||
dontasan unsigned FindMemoryInterval(const struct MemoryIntervals *mm, int x) {
|
||||
unsigned l, m, r;
|
||||
l = 0;
|
||||
r = mm->i;
|
||||
|
@ -31,6 +31,6 @@ noasan unsigned FindMemoryInterval(const struct MemoryIntervals *mm, int x) {
|
|||
r = m;
|
||||
}
|
||||
}
|
||||
_unassert(l == mm->i || x <= mm->p[l].y);
|
||||
unassert(l == mm->i || x <= mm->p[l].y);
|
||||
return l;
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#include "libc/thread/thread.h"
|
||||
|
||||
#ifdef __x86_64__
|
||||
STATIC_YOINK("_init_g_fds");
|
||||
__static_yoink("_init_g_fds");
|
||||
#endif
|
||||
|
||||
struct Fds g_fds;
|
||||
|
@ -49,7 +49,7 @@ static textwindows dontinline void SetupWinStd(struct Fds *fds, int i, int x) {
|
|||
textstartup void __init_fds(void) {
|
||||
struct Fds *fds;
|
||||
__fds_lock_obj._type = PTHREAD_MUTEX_RECURSIVE;
|
||||
fds = VEIL("r", &g_fds);
|
||||
fds = __veil("r", &g_fds);
|
||||
fds->n = 4;
|
||||
atomic_store_explicit(&fds->f, 3, memory_order_relaxed);
|
||||
if (_weaken(_extend)) {
|
||||
|
@ -73,9 +73,9 @@ textstartup void __init_fds(void) {
|
|||
fds->p[1].kind = pushpop(kFdSerial);
|
||||
fds->p[2].kind = pushpop(kFdSerial);
|
||||
}
|
||||
fds->p[0].handle = VEIL("r", 0x3F8ull);
|
||||
fds->p[1].handle = VEIL("r", 0x3F8ull);
|
||||
fds->p[2].handle = VEIL("r", 0x3F8ull);
|
||||
fds->p[0].handle = __veil("r", 0x3F8ull);
|
||||
fds->p[1].handle = __veil("r", 0x3F8ull);
|
||||
fds->p[2].handle = __veil("r", 0x3F8ull);
|
||||
} else if (IsWindows()) {
|
||||
SetupWinStd(fds, 0, kNtStdInputHandle);
|
||||
SetupWinStd(fds, 1, kNtStdOutputHandle);
|
||||
|
|
|
@ -16,28 +16,33 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/_getauxval.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
|
||||
/**
|
||||
* Returns auxiliary value, or zero if kernel didn't provide it.
|
||||
* Returns auxiliary value.
|
||||
*
|
||||
* This function is typically regarded as a libc implementation detail;
|
||||
* thus, the source code is the documentation.
|
||||
*
|
||||
* @return auxiliary value or 0 if `at` not found
|
||||
* @return auxiliary value or 0 if `key` not found
|
||||
* @see libc/sysv/consts.sh
|
||||
* @see System Five Application Binary Interface § 3.4.3
|
||||
* @error ENOENT when value not found
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
unsigned long getauxval(unsigned long at) {
|
||||
unsigned long res, *ap;
|
||||
for (ap = __auxv; ap[0]; ap += 2) {
|
||||
if (at == ap[0]) {
|
||||
return ap[1];
|
||||
unsigned long getauxval(unsigned long key) {
|
||||
struct AuxiliaryValue x;
|
||||
x = _getauxval(key);
|
||||
if (key == AT_PAGESZ) {
|
||||
if (!x.isfound) {
|
||||
x.value = 16384;
|
||||
}
|
||||
x.isfound = true;
|
||||
}
|
||||
enoent();
|
||||
if (x.isfound) {
|
||||
return x.value;
|
||||
} else {
|
||||
errno = ENOENT;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#define kBufSize 1024
|
||||
#define kPid "TracerPid:\t"
|
||||
|
||||
static textwindows noasan bool IsBeingDebugged(void) {
|
||||
static textwindows dontasan bool IsBeingDebugged(void) {
|
||||
return !!NtGetPeb()->BeingDebugged;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ bool IsWsl1(void) {
|
|||
if (res) return res & 1;
|
||||
if (!IsLinux()) return res = 2, false;
|
||||
int e = errno;
|
||||
_unassert(__sys_mmap((void *)1, 4096, PROT_READ | PROT_WRITE,
|
||||
unassert(__sys_mmap((void *)1, 4096, PROT_READ | PROT_WRITE,
|
||||
MAP_FIXED | MAP_PRIVATE | ANONYMOUS | GROWSDOWN, -1, 0,
|
||||
0) == MAP_FAILED);
|
||||
bool tmp = errno == ENOTSUP;
|
||||
|
|
|
@ -82,7 +82,7 @@ void *kmalloc(size_t size) {
|
|||
}
|
||||
__kmalloc_unlock();
|
||||
if (p) {
|
||||
_unassert(!((intptr_t)(p + i) & (KMALLOC_ALIGN - 1)));
|
||||
unassert(!((intptr_t)(p + i) & (KMALLOC_ALIGN - 1)));
|
||||
if (IsAsan()) __asan_poison(p + i + size, n - size, kAsanHeapOverrun);
|
||||
return p + i;
|
||||
} else {
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
#include "libc/str/str.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
#include "libc/str/utf16.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
#include "libc/sysv/consts/nr.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/thread/tls.h"
|
||||
|
@ -187,7 +188,7 @@ privileged bool kisdangerous(const void *p) {
|
|||
if (IsStackFrame(frame)) return false;
|
||||
if (kismapped(frame)) return false;
|
||||
}
|
||||
if (GetStackAddr() + APE_GUARDSIZE <= (uintptr_t)p &&
|
||||
if (GetStackAddr() + 16384 <= (uintptr_t)p &&
|
||||
(uintptr_t)p < GetStackAddr() + GetStackSize()) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
COSMOPOLITAN_C_START_
|
||||
|
||||
#define IGNORE_LEAKS(FUNC) \
|
||||
STATIC_YOINK("_leaky_start"); \
|
||||
__static_yoink("_leaky_start"); \
|
||||
void *_leaky_##FUNC[] _Section(".piro.relo.sort.leaky.2." #FUNC \
|
||||
",\"aw\",@init_array #") = {FUNC}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ static inline const unsigned char *memchr_pure(const unsigned char *s,
|
|||
}
|
||||
|
||||
#ifdef __x86_64__
|
||||
noasan static inline const unsigned char *memchr_sse(const unsigned char *s,
|
||||
dontasan static inline const unsigned char *memchr_sse(const unsigned char *s,
|
||||
unsigned char c,
|
||||
size_t n) {
|
||||
size_t i;
|
||||
|
|
|
@ -36,7 +36,7 @@ static inline const unsigned char *memrchr_pure(const unsigned char *s,
|
|||
}
|
||||
|
||||
#ifdef __x86_64__
|
||||
noasan static inline const unsigned char *memrchr_sse(const unsigned char *s,
|
||||
dontasan static inline const unsigned char *memrchr_sse(const unsigned char *s,
|
||||
unsigned char c,
|
||||
size_t n) {
|
||||
size_t i;
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
static void *MoveMemoryIntervals(struct MemoryInterval *d,
|
||||
const struct MemoryInterval *s, int n) {
|
||||
int i;
|
||||
_unassert(n >= 0);
|
||||
unassert(n >= 0);
|
||||
if (d > s) {
|
||||
for (i = n; i--;) {
|
||||
d[i] = s[i];
|
||||
|
@ -64,8 +64,8 @@ static void *MoveMemoryIntervals(struct MemoryInterval *d,
|
|||
}
|
||||
|
||||
static void RemoveMemoryIntervals(struct MemoryIntervals *mm, int i, int n) {
|
||||
_unassert(i >= 0);
|
||||
_unassert(i + n <= mm->i);
|
||||
unassert(i >= 0);
|
||||
unassert(i + n <= mm->i);
|
||||
MoveMemoryIntervals(mm->p + i, mm->p + i + n, mm->i - (i + n));
|
||||
mm->i -= n;
|
||||
}
|
||||
|
@ -109,9 +109,9 @@ static bool ExtendMemoryIntervals(struct MemoryIntervals *mm) {
|
|||
}
|
||||
|
||||
int CreateMemoryInterval(struct MemoryIntervals *mm, int i) {
|
||||
_unassert(i >= 0);
|
||||
_unassert(i <= mm->i);
|
||||
_unassert(mm->n >= 0);
|
||||
unassert(i >= 0);
|
||||
unassert(i <= mm->i);
|
||||
unassert(mm->n >= 0);
|
||||
if (UNLIKELY(mm->i == mm->n) && !ExtendMemoryIntervals(mm)) return enomem();
|
||||
MoveMemoryIntervals(mm->p + i + 1, mm->p + i, mm->i++ - i);
|
||||
return 0;
|
||||
|
@ -130,7 +130,7 @@ int ReleaseMemoryIntervals(struct MemoryIntervals *mm, int x, int y,
|
|||
void wf(struct MemoryIntervals *, int, int)) {
|
||||
unsigned l, r;
|
||||
ASSERT_MEMTRACK();
|
||||
_unassert(y >= x);
|
||||
unassert(y >= x);
|
||||
if (!mm->i) return 0;
|
||||
// binary search for the lefthand side
|
||||
l = FindMemoryInterval(mm, x);
|
||||
|
@ -140,8 +140,8 @@ int ReleaseMemoryIntervals(struct MemoryIntervals *mm, int x, int y,
|
|||
// binary search for the righthand side
|
||||
r = FindMemoryInterval(mm, y);
|
||||
if (r == mm->i || (r > l && y < mm->p[r].x)) --r;
|
||||
_unassert(r >= l);
|
||||
_unassert(x <= mm->p[r].y);
|
||||
unassert(r >= l);
|
||||
unassert(x <= mm->p[r].y);
|
||||
|
||||
// remove the middle of an existing map
|
||||
//
|
||||
|
@ -162,11 +162,11 @@ int ReleaseMemoryIntervals(struct MemoryIntervals *mm, int x, int y,
|
|||
// ----|mmmm|----------------- after
|
||||
//
|
||||
if (x > mm->p[l].x && x <= mm->p[l].y) {
|
||||
_unassert(y >= mm->p[l].y);
|
||||
unassert(y >= mm->p[l].y);
|
||||
if (IsWindows()) return einval();
|
||||
mm->p[l].size -= (size_t)(mm->p[l].y - (x - 1)) * FRAMESIZE;
|
||||
mm->p[l].y = x - 1;
|
||||
_unassert(mm->p[l].x <= mm->p[l].y);
|
||||
unassert(mm->p[l].x <= mm->p[l].y);
|
||||
++l;
|
||||
}
|
||||
|
||||
|
@ -177,11 +177,11 @@ int ReleaseMemoryIntervals(struct MemoryIntervals *mm, int x, int y,
|
|||
// ---------------|mm|-------- after
|
||||
//
|
||||
if (y >= mm->p[r].x && y < mm->p[r].y) {
|
||||
_unassert(x <= mm->p[r].x);
|
||||
unassert(x <= mm->p[r].x);
|
||||
if (IsWindows()) return einval();
|
||||
mm->p[r].size -= (size_t)((y + 1) - mm->p[r].x) * FRAMESIZE;
|
||||
mm->p[r].x = y + 1;
|
||||
_unassert(mm->p[r].x <= mm->p[r].y);
|
||||
unassert(mm->p[r].x <= mm->p[r].y);
|
||||
--r;
|
||||
}
|
||||
|
||||
|
@ -199,7 +199,7 @@ int TrackMemoryInterval(struct MemoryIntervals *mm, int x, int y, long h,
|
|||
long offset, long size) {
|
||||
unsigned i;
|
||||
ASSERT_MEMTRACK();
|
||||
_unassert(y >= x);
|
||||
unassert(y >= x);
|
||||
i = FindMemoryInterval(mm, x);
|
||||
|
||||
// try to extend the righthand side of the lefthand entry
|
||||
|
|
|
@ -54,14 +54,14 @@ struct ReclaimedPage {
|
|||
/**
|
||||
* Allocates new page of physical memory.
|
||||
*/
|
||||
noasan texthead uint64_t __new_page(struct mman *mm) {
|
||||
dontasan texthead uint64_t __new_page(struct mman *mm) {
|
||||
uint64_t p = mm->frp;
|
||||
if (p != NOPAGE) {
|
||||
uint64_t q;
|
||||
struct ReclaimedPage *rp = (struct ReclaimedPage *)(BANE + p);
|
||||
_unassert(p == (p & PAGE_TA));
|
||||
unassert(p == (p & PAGE_TA));
|
||||
q = rp->next;
|
||||
_unassert(q == (q & PAGE_TA) || q == NOPAGE);
|
||||
unassert(q == (q & PAGE_TA) || q == NOPAGE);
|
||||
mm->frp = q;
|
||||
return p;
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ noasan texthead uint64_t __new_page(struct mman *mm) {
|
|||
* Returns pointer to page table entry for page at virtual address.
|
||||
* Additional page tables are allocated if needed as a side-effect.
|
||||
*/
|
||||
noasan textreal uint64_t *__get_virtual(struct mman *mm, uint64_t *t,
|
||||
dontasan textreal uint64_t *__get_virtual(struct mman *mm, uint64_t *t,
|
||||
int64_t vaddr, bool maketables) {
|
||||
uint64_t *e, p;
|
||||
unsigned char h;
|
||||
|
@ -101,7 +101,7 @@ noasan textreal uint64_t *__get_virtual(struct mman *mm, uint64_t *t,
|
|||
/**
|
||||
* Sorts, rounds, and filters BIOS memory map.
|
||||
*/
|
||||
static noasan textreal void __normalize_e820(struct mman *mm, uint64_t top) {
|
||||
static dontasan textreal void __normalize_e820(struct mman *mm, uint64_t top) {
|
||||
uint64_t a, b;
|
||||
uint64_t x, y;
|
||||
unsigned i, j, n;
|
||||
|
@ -134,8 +134,9 @@ static noasan textreal void __normalize_e820(struct mman *mm, uint64_t top) {
|
|||
/**
|
||||
* Identity maps an area of physical memory to its negative address.
|
||||
*/
|
||||
noasan textreal uint64_t *__invert_memory_area(struct mman *mm, uint64_t *pml4t,
|
||||
uint64_t ps, uint64_t size,
|
||||
dontasan textreal uint64_t *__invert_memory_area(struct mman *mm,
|
||||
uint64_t *pml4t, uint64_t ps,
|
||||
uint64_t size,
|
||||
uint64_t pte_flags) {
|
||||
uint64_t pe = ps + size, p, *m = NULL;
|
||||
ps = ROUNDDOWN(ps, 4096);
|
||||
|
@ -152,7 +153,7 @@ noasan textreal uint64_t *__invert_memory_area(struct mman *mm, uint64_t *pml4t,
|
|||
/**
|
||||
* Increments the reference count for a page of physical memory.
|
||||
*/
|
||||
noasan void __ref_page(struct mman *mm, uint64_t *pml4t, uint64_t p) {
|
||||
dontasan void __ref_page(struct mman *mm, uint64_t *pml4t, uint64_t p) {
|
||||
uint64_t *m, e;
|
||||
m = __invert_memory_area(mm, pml4t, p, 4096, PAGE_RW | PAGE_XD);
|
||||
if (m) {
|
||||
|
@ -167,7 +168,7 @@ noasan void __ref_page(struct mman *mm, uint64_t *pml4t, uint64_t p) {
|
|||
/**
|
||||
* Increments the reference counts for an area of physical memory.
|
||||
*/
|
||||
noasan void __ref_pages(struct mman *mm, uint64_t *pml4t, uint64_t ps,
|
||||
dontasan void __ref_pages(struct mman *mm, uint64_t *pml4t, uint64_t ps,
|
||||
uint64_t size) {
|
||||
uint64_t p = ROUNDDOWN(ps, 4096), e = ROUNDUP(ps + size, 4096);
|
||||
while (p != e) {
|
||||
|
@ -179,9 +180,9 @@ noasan void __ref_pages(struct mman *mm, uint64_t *pml4t, uint64_t ps,
|
|||
/**
|
||||
* Reclaims a page of physical memory for later use.
|
||||
*/
|
||||
static noasan void __reclaim_page(struct mman *mm, uint64_t p) {
|
||||
static dontasan void __reclaim_page(struct mman *mm, uint64_t p) {
|
||||
struct ReclaimedPage *rp = (struct ReclaimedPage *)(BANE + p);
|
||||
_unassert(p == (p & PAGE_TA));
|
||||
unassert(p == (p & PAGE_TA));
|
||||
rp->next = mm->frp;
|
||||
mm->frp = p;
|
||||
}
|
||||
|
@ -191,7 +192,7 @@ static noasan void __reclaim_page(struct mman *mm, uint64_t p) {
|
|||
* page if there are no virtual addresses (excluding the negative space)
|
||||
* referring to it.
|
||||
*/
|
||||
noasan void __unref_page(struct mman *mm, uint64_t *pml4t, uint64_t p) {
|
||||
dontasan void __unref_page(struct mman *mm, uint64_t *pml4t, uint64_t p) {
|
||||
uint64_t *m, e;
|
||||
m = __invert_memory_area(mm, pml4t, p, 4096, PAGE_RW | PAGE_XD);
|
||||
if (m) {
|
||||
|
@ -207,7 +208,8 @@ noasan void __unref_page(struct mman *mm, uint64_t *pml4t, uint64_t p) {
|
|||
/**
|
||||
* Identity maps all usable physical memory to its negative address.
|
||||
*/
|
||||
static noasan textreal void __invert_memory(struct mman *mm, uint64_t *pml4t) {
|
||||
static dontasan textreal void __invert_memory(struct mman *mm,
|
||||
uint64_t *pml4t) {
|
||||
uint64_t i, j, *m, p, pe;
|
||||
for (i = 0; i < mm->e820n; ++i) {
|
||||
uint64_t ps = mm->e820[i].addr, size = mm->e820[i].size;
|
||||
|
@ -230,7 +232,7 @@ static noasan textreal void __invert_memory(struct mman *mm, uint64_t *pml4t) {
|
|||
: "i"(offsetof(type, member))); \
|
||||
} while (0)
|
||||
|
||||
noasan textreal void __setup_mman(struct mman *mm, uint64_t *pml4t,
|
||||
dontasan textreal void __setup_mman(struct mman *mm, uint64_t *pml4t,
|
||||
uint64_t top) {
|
||||
export_offsetof(struct mman, pc_drive_base_table);
|
||||
export_offsetof(struct mman, pc_drive_last_sector);
|
||||
|
@ -257,7 +259,7 @@ noasan textreal void __setup_mman(struct mman *mm, uint64_t *pml4t,
|
|||
/**
|
||||
* Maps APE-defined ELF program headers into memory and clears BSS.
|
||||
*/
|
||||
noasan textreal void __map_phdrs(struct mman *mm, uint64_t *pml4t, uint64_t b,
|
||||
dontasan textreal void __map_phdrs(struct mman *mm, uint64_t *pml4t, uint64_t b,
|
||||
uint64_t top) {
|
||||
struct Elf64_Phdr *p;
|
||||
uint64_t i, f, v, m, *e;
|
||||
|
@ -292,7 +294,8 @@ noasan textreal void __map_phdrs(struct mman *mm, uint64_t *pml4t, uint64_t b,
|
|||
* Reclaims memory pages which were used at boot time but which can now be
|
||||
* made available for the application.
|
||||
*/
|
||||
noasan textreal void __reclaim_boot_pages(struct mman *mm, uint64_t skip_start,
|
||||
dontasan textreal void __reclaim_boot_pages(struct mman *mm,
|
||||
uint64_t skip_start,
|
||||
uint64_t skip_end) {
|
||||
uint64_t p = mm->frp, q = IMAGE_BASE_REAL, i, n = mm->e820n, b, e;
|
||||
for (i = 0; i < n; ++i) {
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include "libc/thread/thread.h"
|
||||
|
||||
#ifdef __x86_64__
|
||||
STATIC_YOINK("_init__mmi");
|
||||
__static_yoink("_init__mmi");
|
||||
#endif
|
||||
|
||||
struct MemoryIntervals _mmi;
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
*/
|
||||
bool __nocolor;
|
||||
|
||||
optimizesize textstartup noasan void __nocolor_init(int argc, char **argv,
|
||||
optimizesize textstartup dontasan void __nocolor_init(int argc, char **argv,
|
||||
char **envp,
|
||||
intptr_t *auxv) {
|
||||
char *s;
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
*
|
||||
* @see IsAtLeastWindows10()
|
||||
*/
|
||||
textwindows noasan int NtGetVersion(void) {
|
||||
textwindows dontasan int NtGetVersion(void) {
|
||||
return (NtGetPeb()->OSMajorVersion & 0xff) << 8 | NtGetPeb()->OSMinorVersion;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
void(pthread_cleanup_pop)(struct _pthread_cleanup_buffer *cb, int execute) {
|
||||
struct PosixThread *pt;
|
||||
if (__tls_enabled && (pt = (struct PosixThread *)__get_tls()->tib_pthread)) {
|
||||
_unassert(cb == pt->cleanup);
|
||||
unassert(cb == pt->cleanup);
|
||||
pt->cleanup = cb->__prev;
|
||||
}
|
||||
if (execute) {
|
||||
|
|
|
@ -35,7 +35,7 @@ void *pthread_getspecific(pthread_key_t k) {
|
|||
// pthread_key_create() or after key has been deleted with
|
||||
// pthread_key_delete() is undefined."
|
||||
// ──Quoth POSIX.1-2017
|
||||
_unassert(0 <= k && k < PTHREAD_KEYS_MAX);
|
||||
_unassert(atomic_load_explicit(_pthread_key_dtor + k, memory_order_acquire));
|
||||
unassert(0 <= k && k < PTHREAD_KEYS_MAX);
|
||||
unassert(atomic_load_explicit(_pthread_key_dtor + k, memory_order_acquire));
|
||||
return __get_tls()->tib_keys[k];
|
||||
}
|
||||
|
|
|
@ -35,8 +35,8 @@
|
|||
*/
|
||||
int pthread_key_delete(pthread_key_t k) {
|
||||
uint64_t mask;
|
||||
_unassert(0 <= k && k < PTHREAD_KEYS_MAX);
|
||||
_unassert(atomic_load_explicit(_pthread_key_dtor + k, memory_order_acquire));
|
||||
unassert(0 <= k && k < PTHREAD_KEYS_MAX);
|
||||
unassert(atomic_load_explicit(_pthread_key_dtor + k, memory_order_acquire));
|
||||
atomic_store_explicit(_pthread_key_dtor + k, 0, memory_order_release);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -35,8 +35,8 @@ int pthread_setspecific(pthread_key_t k, const void *val) {
|
|||
// pthread_key_create() or after key has been deleted with
|
||||
// pthread_key_delete() is undefined."
|
||||
// ──Quoth POSIX.1-2017
|
||||
_unassert(0 <= k && k < PTHREAD_KEYS_MAX);
|
||||
_unassert(atomic_load_explicit(_pthread_key_dtor + k, memory_order_acquire));
|
||||
unassert(0 <= k && k < PTHREAD_KEYS_MAX);
|
||||
unassert(atomic_load_explicit(_pthread_key_dtor + k, memory_order_acquire));
|
||||
__get_tls()->tib_keys[k] = val;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -48,14 +48,14 @@ errno_t(pthread_spin_lock)(pthread_spinlock_t *spin) {
|
|||
LOCKTRACE("pthread_spin_lock(%t)", spin);
|
||||
break;
|
||||
}
|
||||
_unassert(x == 1);
|
||||
unassert(x == 1);
|
||||
LOCKTRACE("pthread_spin_lock(%t) trying...", spin);
|
||||
}
|
||||
#else
|
||||
for (;;) {
|
||||
x = atomic_exchange_explicit(&spin->_lock, 1, memory_order_acquire);
|
||||
if (!x) break;
|
||||
_unassert(x == 1);
|
||||
unassert(x == 1);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
|
|
|
@ -34,6 +34,6 @@ errno_t(pthread_spin_trylock)(pthread_spinlock_t *spin) {
|
|||
int x;
|
||||
x = atomic_exchange_explicit(&spin->_lock, 1, memory_order_acquire);
|
||||
if (!x) return 0;
|
||||
_unassert(x == 1);
|
||||
unassert(x == 1);
|
||||
return EBUSY;
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(16)));
|
|||
* @return pointer to nul byte
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
noasan char *stpcpy(char *d, const char *s) {
|
||||
dontasan char *stpcpy(char *d, const char *s) {
|
||||
size_t i = 0;
|
||||
if (IsAsan()) {
|
||||
__asan_verify(d, strlen(s) + 1);
|
||||
|
|
|
@ -32,7 +32,7 @@ static inline const char *strchr_pure(const char *s, int c) {
|
|||
|
||||
#ifdef __x86_64__
|
||||
typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(16)));
|
||||
noasan static inline const char *strchr_sse(const char *s, unsigned char c) {
|
||||
dontasan static inline const char *strchr_sse(const char *s, unsigned char c) {
|
||||
unsigned k;
|
||||
unsigned m;
|
||||
xmm_t v, *p;
|
||||
|
@ -55,7 +55,7 @@ noasan static inline const char *strchr_sse(const char *s, unsigned char c) {
|
|||
}
|
||||
#endif
|
||||
|
||||
static noasan inline const char *strchr_x64(const char *p, uint64_t c) {
|
||||
static dontasan inline const char *strchr_x64(const char *p, uint64_t c) {
|
||||
unsigned a, b;
|
||||
uint64_t w, x, y;
|
||||
for (c *= 0x0101010101010101;; p += 8) {
|
||||
|
@ -103,7 +103,7 @@ char *strchr(const char *s, int c) {
|
|||
} else {
|
||||
r = strchr_pure(s, c);
|
||||
}
|
||||
_unassert(!r || *r || !(c & 255));
|
||||
unassert(!r || *r || !(c & 255));
|
||||
return (char *)r;
|
||||
#else
|
||||
char *r;
|
||||
|
@ -112,7 +112,7 @@ char *strchr(const char *s, int c) {
|
|||
if (!*s) return NULL;
|
||||
}
|
||||
r = strchr_x64(s, c);
|
||||
_unassert(!r || *r || !c);
|
||||
unassert(!r || *r || !c);
|
||||
return r;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -32,7 +32,8 @@ static inline const char *strchrnul_pure(const char *s, int c) {
|
|||
|
||||
#ifdef __x86_64__
|
||||
typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(16)));
|
||||
noasan static inline const char *strchrnul_sse(const char *s, unsigned char c) {
|
||||
dontasan static inline const char *strchrnul_sse(const char *s,
|
||||
unsigned char c) {
|
||||
unsigned k;
|
||||
unsigned m;
|
||||
xmm_t v, *p;
|
||||
|
@ -52,7 +53,7 @@ noasan static inline const char *strchrnul_sse(const char *s, unsigned char c) {
|
|||
}
|
||||
#endif
|
||||
|
||||
noasan static const char *strchrnul_x64(const char *p, uint64_t c) {
|
||||
dontasan static const char *strchrnul_x64(const char *p, uint64_t c) {
|
||||
unsigned a, b;
|
||||
uint64_t w, x, y;
|
||||
for (c *= 0x0101010101010101;; p += 8) {
|
||||
|
@ -101,7 +102,7 @@ char *strchrnul(const char *s, int c) {
|
|||
} else {
|
||||
r = strchrnul_pure(s, c);
|
||||
}
|
||||
_unassert((*r & 255) == (c & 255) || !*r);
|
||||
unassert((*r & 255) == (c & 255) || !*r);
|
||||
return (char *)r;
|
||||
#else
|
||||
char *r;
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
* @return is <0, 0, or >0 based on uint8_t comparison
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
noasan int strcmp(const char *a, const char *b) {
|
||||
dontasan int strcmp(const char *a, const char *b) {
|
||||
int c;
|
||||
size_t i = 0;
|
||||
uint64_t v, w, d;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue