mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-09-11 11:13:49 +00:00
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:
parent
5655c9a4e7
commit
8f522cb702
116 changed files with 1194 additions and 1025 deletions
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
//
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
84
libc/runtime/wipe.S
Normal 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
|
Loading…
Add table
Add a link
Reference in a new issue