Make improvements

This change progresses our AARCH64 support:

- The AARCH64 build and tests are now passing
- Add 128-bit floating-point support to printf()
- Fix clone() so it initializes cosmo's x28 TLS register
- Fix TLS memory layout issue with aarch64 _Alignas vars
- Revamp microbenchmarking tools so they work on aarch64
- Make some subtle improvements to aarch64 crash reporting
- Make kisdangerous() memory checks more accurate on aarch64
- Remove sys_open() since it's not available on Linux AARCH64

This change makes general improvements to Cosmo and Redbean:

- Introduce GetHostIsa() function in Redbean
- You can now feature check using pledge(0, 0)
- You can now feature check using unveil("",0)
- Refactor some more x86-specific asm comments
- Refactor and write docs for some libm functions
- Make the mmap() API behave more similar to Linux
- Fix WIFSIGNALED() which wrongly returned true for zero
- Rename some obscure cosmo keywords from noFOO to dontFOO
This commit is contained in:
Justine Tunney 2023-06-03 08:12:13 -07:00
parent 5655c9a4e7
commit 8f522cb702
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
116 changed files with 1194 additions and 1025 deletions

View file

@ -56,14 +56,19 @@ sys_clone_linux:
syscall
1: hlt // ctid was corrupted by program!
#elif defined(__aarch64__)
stp x29,x30,[sp,#-16]!
mov x29,sp
mov x8,x3 // swap x3 and x4
mov x3,x4 // swap x3 and x4
mov x4,x8 // swap x3 and x4
mov x8,#220 // __NR_clone
svc #0
cbz x0,2f
ldp x29,x30,[sp],#16
ret
2: mov x0,x6 // child thread
2: mov x29,#0 // wipe backtrace
mov x28,x3 // set cosmo tls
mov x0,x6 // child thread
ldr w1,[x4] // arg2 = *ctid
blr x5
mov x8,#93 // __NR_exit

View file

@ -24,11 +24,14 @@
#include "libc/runtime/internal.h"
#include "libc/runtime/memtrack.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/stack.h"
#include "libc/runtime/syslib.internal.h"
#include "libc/sysv/consts/prot.h"
#include "libc/thread/thread.h"
#include "libc/thread/tls.h"
#ifndef __x86_64__
void __wipe(uintptr_t);
int main(int, char **, char **) __attribute__((__weak__));
typedef int init_f(int argc, char **argv, char **envp, unsigned long *auxv);
@ -46,6 +49,9 @@ 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_end[] __attribute__((__weak__));
extern char ape_stack_vaddr[] __attribute__((__weak__));
extern char ape_stack_memsz[] __attribute__((__weak__));
extern char ape_stack_prot[] __attribute__((__weak__));
extern pthread_mutex_t __mmi_lock_obj;
extern int hostos asm("__hostos");
@ -86,11 +92,21 @@ textstartup void cosmo(long *sp, struct Syslib *m1) {
__oldstack = (intptr_t)sp;
__pid = sys_getpid().ax;
// initialize mmap() manager extremely early
// initialize memory manager
_mmi.n = ARRAYLEN(_mmi.s);
_mmi.p = _mmi.s;
__mmi_lock_obj._type = PTHREAD_MUTEX_RECURSIVE;
if (!IsTiny()) {
// record system-provided stack to memory manager
_mmi.i = 1;
_mmi.p->x = (uintptr_t)GetStackAddr() >> 16;
_mmi.p->y =
(uintptr_t)(GetStackAddr() + (GetStackSize() - FRAMESIZE)) >> 16;
_mmi.p->size = GetStackSize();
_mmi.p->prot = PROT_READ | PROT_WRITE;
}
#if 0
#if IsAsan()
__asan_init(argc, argv, envp, auxv);
@ -118,6 +134,7 @@ textstartup void cosmo(long *sp, struct Syslib *m1) {
}
// run program
if (!IsTiny()) __wipe(0);
exit(main(argc, argv, envp));
}

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "ape/sections.internal.h"
#include "libc/assert.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/errno.h"
@ -93,7 +94,7 @@ _Alignas(TLS_ALIGNMENT) static char __static_tls[6016];
*/
textstartup void __enable_tls(void) {
int tid;
size_t siz;
size_t hiz, siz;
char *mem, *tls;
struct CosmoTib *tib;
@ -146,8 +147,8 @@ textstartup void __enable_tls(void) {
#elif defined(__aarch64__)
siz = ROUNDUP(sizeof(*tib) + 2 * sizeof(void *) + I(_tls_size),
_Alignof(__static_tls));
hiz = ROUNDUP(sizeof(*tib) + 2 * sizeof(void *), I(_tls_align));
siz = hiz + I(_tls_size);
if (siz <= sizeof(__static_tls)) {
mem = __static_tls;
} else {
@ -160,12 +161,12 @@ textstartup void __enable_tls(void) {
if (IsAsan()) {
// there's a roundup(pagesize) gap between .tdata and .tbss
// poison that empty space
__asan_poison(mem + sizeof(*tib) + 2 * sizeof(void *) + I(_tdata_size),
I(_tbss_offset) - I(_tdata_size), kAsanProtected);
__asan_poison(mem + hiz + I(_tdata_size), I(_tbss_offset) - I(_tdata_size),
kAsanProtected);
}
tib = (struct CosmoTib *)mem;
tls = mem + sizeof(*tib) + 2 * sizeof(void *);
tls = mem + hiz;
// Set the DTV.
//

View file

@ -70,11 +70,45 @@ size_t GetMemtrackSize(struct MemoryIntervals *);
#define __mmi_unlock() (__threaded ? __mmi_unlock() : 0)
#endif
#ifdef __x86_64__
/*
* AMD64 has 48-bit signed pointers (PML4T)
* AMD64 is trying to go bigger, i.e. 57-bit (PML5T)
* LINUX forbids userspace from leveraging negative pointers
* Q-EMU may impose smaller vaspaces emulating AMD on non-AMD
*
* Having "signed pointers" means these top sixteen bits
*
* 0x0000000000000000
* ^^^^
*
* must be
*
* - 0000 for positive pointers
* - FFFF for negative pointers
*
* otherwise the instruction using the faulty pointer will fault.
*/
#define IsLegalPointer(p) \
(-0x800000000000 <= (intptr_t)(p) && (intptr_t)(p) <= 0x7fffffffffff)
#define ADDR_32_TO_48(x) (intptr_t)((uint64_t)(int)(x) << 16)
#elif defined(__aarch64__)
/*
* ARM64 has 48-bit unsigned pointers (Armv8.0-A)
* ARM64 can possibly go bigger, i.e. 52-bit (Armv8.2-A)
* ARM64 can impose arbitrarily smaller vaspaces, e.g. 40/44-bit
* APPLE in their limitless authoritarianism forbids 32-bit pointers
*/
#define IsLegalPointer(p) ((uintptr_t)(p) <= 0xffffffffffff)
#define ADDR_32_TO_48(x) (uintptr_t)((uint64_t)(uint32_t)(x) << 16)
#else
/* RISC-V Sipeed Nezha has 39-bit vaspace */
#error "unsupported architecture"
#endif
forceinline pureconst bool IsLegalSize(size_t n) {
return n <= 0x7fffffffffff;
forceinline pureconst bool IsLegalSize(uint64_t n) {
/* subtract frame size so roundup is safe */
return n <= 0x800000000000 - FRAMESIZE;
}
forceinline pureconst bool IsAutoFrame(int x) {

View file

@ -61,11 +61,10 @@
#define IP(X) (intptr_t)(X)
#define VIP(X) (void *)IP(X)
#define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1)))
#define ADDR(x) ((int64_t)((uint64_t)(x) << 32) >> 16)
#define SHADE(x) (((intptr_t)(x) >> 3) + 0x7fff8000)
#define FRAME(x) ((int)((intptr_t)(x) >> 16))
static unsigned long RoundDownTwoPow(unsigned long x) {
static pureconst unsigned long RoundDownTwoPow(unsigned long x) {
return x ? 1ul << _bsrl(x) : 0;
}
@ -247,62 +246,49 @@ noasan inline void *_Mmap(void *addr, size_t size, int prot, int flags, int fd,
size_t virtualused, virtualneed;
if (VERY_UNLIKELY(!size)) {
STRACE("size=0");
return VIP(einval());
}
if (VERY_UNLIKELY(!IsLegalPointer(p))) {
STRACE("p isn't 48-bit");
STRACE("can't mmap zero bytes");
return VIP(einval());
}
if (VERY_UNLIKELY(!ALIGNED(p))) {
STRACE("p isn't 64kb aligned");
return VIP(einval());
}
if (VERY_UNLIKELY(fd < -1)) {
STRACE("mmap(%.12p, %'zu, fd=%d) EBADF", p, size, fd);
return VIP(ebadf());
}
if (VERY_UNLIKELY(!((fd != -1) ^ !!(flags & MAP_ANONYMOUS)))) {
STRACE("fd anonymous mismatch");
return VIP(einval());
}
if (VERY_UNLIKELY(!(!!(flags & MAP_PRIVATE) ^ !!(flags & MAP_SHARED)))) {
STRACE("MAP_SHARED ^ MAP_PRIVATE");
return VIP(einval());
}
if (VERY_UNLIKELY(off < 0)) {
STRACE("neg off");
return VIP(einval());
}
if (VERY_UNLIKELY(!ALIGNED(off))) {
STRACE("p isn't 64kb aligned");
return VIP(einval());
}
if (fd == -1) {
size = ROUNDUP(size, FRAMESIZE);
if (IsWindows()) {
prot |= PROT_WRITE; /* kludge */
}
} else if (__isfdkind(fd, kFdZip)) {
STRACE("fd is zipos handle");
STRACE("cosmo mmap is 64kb aligned");
return VIP(einval());
}
if (VERY_UNLIKELY(!IsLegalSize(size))) {
STRACE("size isn't 48-bit");
STRACE("mmap size isn't legal");
return VIP(einval());
}
if (VERY_UNLIKELY(INT64_MAX - size < off)) {
STRACE("too large");
if (VERY_UNLIKELY(!IsLegalPointer(p))) {
STRACE("mmap addr isn't 48-bit");
return VIP(einval());
}
if ((flags & (MAP_SHARED | MAP_PRIVATE)) == (MAP_SHARED | MAP_PRIVATE)) {
flags = MAP_SHARED; // cf. MAP_SHARED_VALIDATE
}
if (flags & MAP_ANONYMOUS) {
fd = -1;
off = 0;
size = ROUNDUP(size, FRAMESIZE);
if (IsWindows()) prot |= PROT_WRITE; // kludge
if ((flags & MAP_TYPE) == MAP_FILE) {
STRACE("need MAP_PRIVATE or MAP_SHARED");
return VIP(einval());
}
} else if (__isfdkind(fd, kFdZip)) {
STRACE("mmap fd is zipos handle");
return VIP(einval());
} else if (VERY_UNLIKELY(off < 0)) {
STRACE("mmap negative offset");
return VIP(einval());
} else if (VERY_UNLIKELY(!ALIGNED(off))) {
STRACE("mmap off isn't 64kb aligned");
return VIP(einval());
} else if (VERY_UNLIKELY(INT64_MAX - size < off)) {
STRACE("mmap too large");
return VIP(einval());
}
@ -310,26 +296,25 @@ noasan inline void *_Mmap(void *addr, size_t size, int prot, int flags, int fd,
(__builtin_add_overflow((virtualused = GetMemtrackSize(&_mmi)), size,
&virtualneed) ||
virtualneed > __virtualmax)) {
STRACE("%'zu size + %'zu inuse exceeds virtual memory limit %'zu", size,
virtualused, __virtualmax);
STRACE("mmap %'zu size + %'zu inuse exceeds virtual memory limit %'zu",
size, virtualused, __virtualmax);
return VIP(enomem());
}
clashes = OverlapsImageSpace(p, size) || OverlapsExistingMapping(p, size);
if ((flags & MAP_FIXED_NOREPLACE) == MAP_FIXED_NOREPLACE && clashes) {
STRACE("noreplace overlaps existing");
STRACE("mmap noreplace overlaps existing");
return VIP(eexist());
}
if (__builtin_add_overflow((int)(size >> 16), (int)!!(size & (FRAMESIZE - 1)),
&n)) {
STRACE("memory range overflows");
STRACE("mmap range overflows");
return VIP(einval());
}
a = max(1, RoundDownTwoPow(size) >> 16);
a = MAX(1, RoundDownTwoPow(size) >> 16);
f = (flags & ~MAP_FIXED_NOREPLACE) | MAP_FIXED;
if (flags & MAP_FIXED) {
x = FRAME(p);
@ -347,7 +332,7 @@ noasan inline void *_Mmap(void *addr, size_t size, int prot, int flags, int fd,
}
needguard = false;
p = (char *)ADDR(x);
p = (char *)ADDR_32_TO_48(x);
if ((f & MAP_TYPE) == MAP_STACK) {
if (~f & MAP_ANONYMOUS) {
STRACE("MAP_STACK must be anonymous");
@ -446,7 +431,7 @@ noasan inline void *_Mmap(void *addr, size_t size, int prot, int flags, int fd,
* is specified
* @param prot can have PROT_READ/PROT_WRITE/PROT_EXEC/PROT_NONE/etc.
* @param flags should have one of the following masked by `MAP_TYPE`
* - `MAP_FILE` in which case `fd != -1` should be the case
* - `MAP_FILE` in which case `MAP_ANONYMOUS` shouldn't be used
* - `MAP_PRIVATE` for copy-on-write behavior of writeable pages
* - `MAP_SHARED` to create shared memory between processes
* - `MAP_STACK` to create a grows-down alloc, where a guard page
@ -460,7 +445,7 @@ noasan inline void *_Mmap(void *addr, size_t size, int prot, int flags, int fd,
* compile-time checks to ensure some char[8192] vars will not
* create an undetectable overflow into another thread's stack
* Your `flags` may optionally bitwise or any of the following:
* - `MAP_ANONYMOUS` in which case `fd == -1` should be the case
* - `MAP_ANONYMOUS` in which case `fd` and `off` are ignored
* - `MAP_FIXED` in which case `addr` becomes more than a hint
* - `MAP_FIXED_NOREPLACE` to protect existing mappings; this is
* always polyfilled by mmap() which tracks its own memory and
@ -476,8 +461,7 @@ noasan inline void *_Mmap(void *addr, size_t size, int prot, int flags, int fd,
* - `MAP_INHERIT` is NetBSD-only
* - `MAP_LOCKED` is Linux-only
* @param fd is an open()'d file descriptor, whose contents shall be
* made available w/ automatic reading at the chosen address and
* must be -1 if MAP_ANONYMOUS is specified
* made available w/ automatic reading at the chosen address
* @param off specifies absolute byte index of fd's file for mapping,
* should be zero if MAP_ANONYMOUS is specified, and sadly needs
* to be 64kb aligned too

View file

@ -21,8 +21,6 @@
#include "libc/runtime/internal.h"
#include "libc/runtime/memtrack.internal.h"
#define ADDR(x) ((char *)((int64_t)((uint64_t)(x) << 32) >> 16))
textwindows int sys_mprotect_nt(void *addr, size_t size, int prot) {
int rc = 0;
unsigned i;
@ -31,7 +29,7 @@ textwindows int sys_mprotect_nt(void *addr, size_t size, int prot) {
__mmi_lock();
p = addr;
i = FindMemoryInterval(&_mmi, (intptr_t)p >> 16);
if (i == _mmi.i || (!i && p + size <= ADDR(_mmi.p[0].x))) {
if (i == _mmi.i || (!i && p + size <= (char *)ADDR_32_TO_48(_mmi.p[0].x))) {
// memory isn't in memtrack
// let's just trust the user then
// it's probably part of the executable
@ -42,7 +40,7 @@ textwindows int sys_mprotect_nt(void *addr, size_t size, int prot) {
// memory is in memtrack, so use memtrack, to do dimensioning
// we unfortunately must do something similar to this for cow
for (; i < _mmi.i; ++i) {
x = ADDR(_mmi.p[i].x);
x = (char *)ADDR_32_TO_48(_mmi.p[i].x);
y = x + _mmi.p[i].size;
if ((x <= p && p < y) || (x < p + size && p + size <= y) ||
(p < x && y < p + size)) {

View file

@ -36,7 +36,6 @@
#define IP(X) (intptr_t)(X)
#define VIP(X) (void *)IP(X)
#define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1)))
#define ADDR(x) ((int64_t)((uint64_t)(x) << 32) >> 16)
#define SHADE(x) (((intptr_t)(x) >> 3) + 0x7fff8000)
#define FRAME(x) ((int)((intptr_t)(x) >> 16))
@ -53,8 +52,8 @@ static size_t GetMapSize(size_t i, size_t *j) {
}
static bool MustMoveMap(intptr_t y, size_t j) {
return ADDR(_mmi.p[j].y) + FRAMESIZE > y ||
(j + 1 < _mmi.i && ADDR(_mmi.p[j + 1].x) < y);
return ADDR_32_TO_48(_mmi.p[j].y) + FRAMESIZE > y ||
(j + 1 < _mmi.i && ADDR_32_TO_48(_mmi.p[j + 1].x) < y);
}
/**
@ -178,9 +177,9 @@ void *mremap(void *p, size_t n, size_t m, int f, ... /* void *q */) {
return VIP(enomem());
}
q = sys_mremap((void *)p, n, m, MREMAP_MAYMOVE | MREMAP_FIXED,
(void *)ADDR(a));
(void *)ADDR_32_TO_48(a));
KERNTRACE("sys_mremap(%p, %'zu, %'zu, %#b, %p) → %p", p, n, m,
MREMAP_MAYMOVE | MREMAP_FIXED, ADDR(a), q);
MREMAP_MAYMOVE | MREMAP_FIXED, ADDR_32_TO_48(a), q);
if (q == MAP_FAILED) return 0;
if (ReleaseMemoryIntervals(&_mmi, (uintptr_t)p >> 16,
((uintptr_t)p + n - FRAMESIZE) >> 16, 0) != -1 &&
@ -194,7 +193,7 @@ void *mremap(void *p, size_t n, size_t m, int f, ... /* void *q */) {
_weaken(__asan_map_shadow)((intptr_t)q, m);
}
}
return (void *)ADDR(a);
return (void *)ADDR_32_TO_48(a);
} else {
abort();
}

View file

@ -25,14 +25,12 @@
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h"
#define ADDR(x) ((char *)((int64_t)((uint64_t)(x) << 32) >> 16))
noasan textwindows int sys_msync_nt(char *addr, size_t size, int flags) {
int i, rc = 0;
char *a, *b, *x, *y;
__mmi_lock();
for (i = FindMemoryInterval(&_mmi, (intptr_t)addr >> 16); i < _mmi.i; ++i) {
x = ADDR(_mmi.p[i].x);
x = (char *)ADDR_32_TO_48(_mmi.p[i].x);
y = x + _mmi.p[i].size;
if ((x <= addr && addr < y) || (x < addr + size && addr + size <= y) ||
(addr < x && y < addr + size)) {

View file

@ -37,7 +37,6 @@
#define IP(X) (intptr_t)(X)
#define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1)))
#define ADDR(x) ((int64_t)((uint64_t)(x) << 32) >> 16)
#define FRAME(x) ((int)((intptr_t)(x) >> 16))
static noasan void MunmapShadow(char *p, size_t n) {
@ -97,9 +96,9 @@ static noasan void MunmapImpl(char *p, size_t n) {
}
// openbsd even requires that if we mapped, for instance a 5 byte
// file, that we be sure to call munmap(file, 5). let's abstract!
a = ADDR(beg);
b = ADDR(end) + FRAMESIZE;
c = ADDR(_mmi.p[i].x) + _mmi.p[i].size;
a = ADDR_32_TO_48(beg);
b = ADDR_32_TO_48(end) + FRAMESIZE;
c = ADDR_32_TO_48(_mmi.p[i].x) + _mmi.p[i].size;
q = (char *)a;
m = MIN(b, c) - a;
if (!IsWindows()) {
@ -119,23 +118,23 @@ noasan int _Munmap(char *p, size_t n) {
intptr_t a, b, x, y;
_unassert(!__vforked);
if (UNLIKELY(!n)) {
STRACE("n=0");
STRACE("munmap n is 0");
return einval();
}
if (UNLIKELY(!IsLegalSize(n))) {
STRACE("n isn't 48-bit");
STRACE("munmap n isn't 48-bit");
return einval();
}
if (UNLIKELY(!IsLegalPointer(p))) {
STRACE("p isn't 48-bit");
STRACE("munmap p isn't 48-bit");
return einval();
}
if (UNLIKELY(!IsLegalPointer(p + (n - 1)))) {
STRACE("p+(n-1) isn't 48-bit");
STRACE("munmap p+(n-1) isn't 48-bit");
return einval();
}
if (UNLIKELY(!ALIGNED(p))) {
STRACE("p isn't 64kb aligned");
STRACE("munmap(%p) isn't 64kb aligned", p);
return einval();
}
MunmapImpl(p, n);

View file

@ -33,50 +33,50 @@
_OpenExecutable:
push %rbp
mov %rsp,%rbp
pushq __NR_open(%rip) # -0x08(%rbp)
pushq __NR_mmap(%rip) # -0x10(%rbp)
pushq __NR_munmap(%rip) # -0x18(%rbp)
pushq O_RDWR(%rip) # -0x20(%rbp)
pushq MAP_ANONYMOUS(%rip) # -0x28(%rbp)
pushq MAP_PRIVATE(%rip) # -0x30(%rbp)
pushq MAP_FIXED(%rip) # -0x38(%rbp)
pushq __NR_mprotect(%rip) # -0x40(%rbp)
pushq O_RDONLY(%rip) # -0x48(%rbp)
push %rbx # code buffer
push %r12 # data buffer
push %r14 # filename
push %r15 # fd
pushq __NR_open(%rip) // -0x08(%rbp)
pushq __NR_mmap(%rip) // -0x10(%rbp)
pushq __NR_munmap(%rip) // -0x18(%rbp)
pushq O_RDWR(%rip) // -0x20(%rbp)
pushq MAP_ANONYMOUS(%rip) // -0x28(%rbp)
pushq MAP_PRIVATE(%rip) // -0x30(%rbp)
pushq MAP_FIXED(%rip) // -0x38(%rbp)
pushq __NR_mprotect(%rip) // -0x40(%rbp)
pushq O_RDONLY(%rip) // -0x48(%rbp)
push %rbx // code buffer
push %r12 // data buffer
push %r14 // filename
push %r15 // fd
// Get filename.
lea program_executable_name(%rip),%r14
// Allocate code buffer.
mov -0x10(%rbp),%eax # __NR_mmap
mov -0x10(%rbp),%eax // __NR_mmap
xor %edi,%edi
mov $PAGESIZE,%esi
mov $PROT_READ|PROT_WRITE,%edx
mov -0x28(%rbp),%r10d # MAP_ANONYMOUS
or -0x30(%rbp),%r10d # MAP_PRIVATE
mov -0x28(%rbp),%r10d // MAP_ANONYMOUS
or -0x30(%rbp),%r10d // MAP_PRIVATE
mov $-1,%r8
mov $0,%r9
push %r9 # openbsd:pad
push %r9 # openbsd:align
push %r9 // openbsd:pad
push %r9 // openbsd:align
syscall
pop %r9
pop %r9
mov %rax,%rbx
// Allocate data buffer.
mov -0x10(%rbp),%eax # __NR_mmap
mov -0x10(%rbp),%eax // __NR_mmap
xor %edi,%edi
mov $ape_ram_filesz,%esi
mov $PROT_READ|PROT_WRITE,%edx
mov -0x28(%rbp),%r10d # MAP_ANONYMOUS
or -0x30(%rbp),%r10d # MAP_PRIVATE
mov -0x28(%rbp),%r10d // MAP_ANONYMOUS
or -0x30(%rbp),%r10d // MAP_PRIVATE
mov $-1,%r8
mov $0,%r9
push %r9 # openbsd:pad
push %r9 # openbsd:align
push %r9 // openbsd:pad
push %r9 // openbsd:align
syscall
pop %r9
pop %r9
@ -95,7 +95,7 @@ _OpenExecutable:
rep movsb
// Change protection.
mov -0x40(%rbp),%eax # __NR_mprotect
mov -0x40(%rbp),%eax // __NR_mprotect
mov %rbx,%rdi
mov $PAGESIZE,%esi
mov $PROT_READ|PROT_EXEC,%edx
@ -106,63 +106,63 @@ _OpenExecutable:
// <LIMBO>
// Unmap code segment.
8: mov -0x18(%rbp),%eax # __NR_munmap
8: mov -0x18(%rbp),%eax // __NR_munmap
mov $ape_rom_vaddr,%edi
mov $ape_rom_filesz,%esi
syscall
// Unmap data segment.
mov -0x18(%rbp),%eax # __NR_munmap
mov -0x18(%rbp),%eax // __NR_munmap
mov $ape_ram_vaddr,%edi
mov $ape_ram_filesz,%esi
syscall
// Open executable in read-write mode.
mov -0x08(%rbp),%eax # __NR_open
mov -0x08(%rbp),%eax // __NR_open
mov %r14,%rdi
mov -0x20(%rbp),%esi # O_RDWR
clc # clear carry flag
mov -0x20(%rbp),%esi // O_RDWR
clc // clear carry flag
syscall
jc .Lohno # bsd error
jc .Lohno // bsd error
cmp $-4095,%eax
jae .Lohno # linux error
jae .Lohno // linux error
jmp .Lok
// Open executable in read-only mode.
.Lohno: mov -0x08(%rbp),%eax # __NR_open
.Lohno: mov -0x08(%rbp),%eax // __NR_open
mov %r14,%rdi
mov -0x48(%rbp),%esi # O_RDONLY
mov -0x48(%rbp),%esi // O_RDONLY
syscall
.Lok: mov %eax,%r15d
// Map code segment.
mov -0x10(%rbp),%eax # __NR_mmap
mov -0x10(%rbp),%eax // __NR_mmap
mov $ape_rom_vaddr,%edi
mov $ape_rom_filesz,%esi
mov $PROT_READ|PROT_EXEC,%edx
mov -0x38(%rbp),%r10d # MAP_FIXED
or -0x30(%rbp),%r10d # MAP_PRIVATE
mov -0x38(%rbp),%r10d // MAP_FIXED
or -0x30(%rbp),%r10d // MAP_PRIVATE
mov %r15d,%r8d
mov $ape_rom_offset,%r9d
push %r9 # openbsd:pad
push %r9 # openbsd:align
push %r9 // openbsd:pad
push %r9 // openbsd:align
syscall
pop %r9
pop %r9
// Allocate data segment.
mov -0x10(%rbp),%eax # __NR_mmap
mov -0x10(%rbp),%eax // __NR_mmap
mov $ape_ram_vaddr,%edi
mov $ape_ram_filesz,%esi
mov $PROT_READ|PROT_WRITE,%edx
mov -0x38(%rbp),%r10d # MAP_FIXED
or -0x30(%rbp),%r10d # MAP_PRIVATE
or -0x28(%rbp),%r10d # MAP_ANONYMOUS
mov -0x38(%rbp),%r10d // MAP_FIXED
or -0x30(%rbp),%r10d // MAP_PRIVATE
or -0x28(%rbp),%r10d // MAP_ANONYMOUS
mov $-1,%r8
mov $0,%r9
push %r9 # openbsd:pad
push %r9 # openbsd:align
push %r9 // openbsd:pad
push %r9 // openbsd:align
syscall
pop %r9
pop %r9

View file

@ -127,6 +127,8 @@ endif
# these assembly files are safe to build on aarch64
o/$(MODE)/libc/runtime/init.o: libc/runtime/init.S
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
o/$(MODE)/libc/runtime/wipe.o: libc/runtime/wipe.S
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
o/$(MODE)/libc/runtime/vfork.o: libc/runtime/vfork.S
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
o/$(MODE)/libc/runtime/clone-linux.o: libc/runtime/clone-linux.S

84
libc/runtime/wipe.S Normal file
View file

@ -0,0 +1,84 @@
/*-*- 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 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/nexgen32e/x86feature.h"
#include "libc/macros.internal.h"
// Zeroes as many registers as possible.
//
// Each caller should declare an appropriate prototype.
//
// @param is return value
// @return is copied from parameter
__wipe:
#ifdef __x86_64__
mov %rdi,%rax
xor %edi,%edi
xor %esi,%esi
xor %edx,%edx
xor %ecx,%ecx
xor %r8d,%r8d
xor %r9d,%r9d
xor %r10d,%r10d
xor %r11d,%r11d
testb X86_HAVE(AVX)+kCpuids(%rip)
jz .Lsse
vpxor %xmm0,%xmm0,%xmm0
vpxor %xmm1,%xmm1,%xmm1
vpxor %xmm2,%xmm2,%xmm2
vpxor %xmm3,%xmm3,%xmm3
vpxor %xmm4,%xmm4,%xmm4
vpxor %xmm5,%xmm5,%xmm5
vpxor %xmm6,%xmm6,%xmm6
vpxor %xmm7,%xmm7,%xmm7
ret
.Lsse: xorps %xmm0,%xmm0
xorps %xmm1,%xmm1
xorps %xmm2,%xmm2
xorps %xmm3,%xmm3
xorps %xmm4,%xmm4
xorps %xmm5,%xmm5
xorps %xmm6,%xmm6
xorps %xmm7,%xmm7
ret
#elif defined(__aarch64__)
mov x1,#0
mov x2,#0
mov x3,#0
mov x4,#0
mov x5,#0
mov x6,#0
mov x7,#0
mov x9,#0
mov x10,#0
mov x11,#0
mov x12,#0
mov x13,#0
mov x14,#0
mov x15,#0
movi v0.16b,#0
movi v1.16b,#0
movi v2.16b,#0
movi v3.16b,#0
movi v4.16b,#0
movi v5.16b,#0
movi v6.16b,#0
movi v7.16b,#0
ret
#endif
.endfn __wipe,globl,hidden