Add MODE=optlinux build mode (#141)

This commit is contained in:
Justine Tunney 2021-10-14 19:36:49 -07:00
parent 226aaf3547
commit 67b5200a0b
111 changed files with 934 additions and 854 deletions

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/sysdebug.internal.h"
#include "libc/runtime/memtrack.internal.h"
noasan bool AreMemoryIntervalsOk(const struct MemoryIntervals *mm) {
@ -23,6 +24,7 @@ noasan bool AreMemoryIntervalsOk(const struct MemoryIntervals *mm) {
int i;
for (i = 0; i < mm->i; ++i) {
if (mm->p[i].y < mm->p[i].x) {
SYSDEBUG("AreMemoryIntervalsOk() y should be >= x!");
return false;
}
if (i) {
@ -32,6 +34,7 @@ noasan bool AreMemoryIntervalsOk(const struct MemoryIntervals *mm) {
}
} else {
if (!(mm->p[i - 1].y + 1 <= mm->p[i].x)) {
SYSDEBUG("AreMemoryIntervalsOk() out of order or overlap!");
return false;
}
}

View file

@ -21,6 +21,7 @@
#include "libc/bits/weaken.h"
#include "libc/log/libfatal.internal.h"
#include "libc/log/log.h"
#include "libc/runtime/runtime.h"
/**
* Handles failure of assert() macro.
@ -28,14 +29,14 @@
relegated wontreturn void __assert_fail(const char *expr, const char *file,
int line) {
static bool noreentry;
__printf("\r\n%s:%d: assert(%s) failed\r\n", file, line, expr);
__printf("%s:%d: assert(%s) failed\r\n", file, line, expr);
if (cmpxchg(&noreentry, false, true)) {
if (weaken(__die)) {
weaken(__die)();
} else {
__printf("can't backtrace b/c `__die` not linked\r\n");
}
exit(23);
quick_exit(23);
}
_exit(24);
_Exit(24);
}

View file

@ -41,7 +41,7 @@ noasan const char *DescribeFrame(int x) {
return " fixed ";
} else if (IsArenaFrame(x)) {
return " arena ";
} else if (IsStackFrame(x)) {
} else if (IsStaticStackFrame(x)) {
return " stack ";
} else {
return "";

View file

@ -91,7 +91,7 @@ textwindows noasan struct DirectMap sys_mmap_nt(void *addr, size_t size,
SYSDEBUG(
"MapViewOfFileExNuma(prot:%s, off:0x%x, size:0x%x, addr:0x%x) -> "
"addr:0x%x",
(prot & PROT_WRITE) ? "WX" : "RX", off, size, addr);
(prot & PROT_WRITE) ? "WX" : "RX", off, size, addr, dm.addr);
if (dm.addr) {
return dm;
} else {

View file

@ -19,6 +19,7 @@
#include "libc/bits/bits.h"
#include "libc/bits/safemacros.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/errno.h"
#include "libc/macros.internal.h"
#include "libc/runtime/runtime.h"

View file

@ -21,19 +21,29 @@
#include "libc/str/tpenc.h"
#include "libc/str/utf16.h"
#define ToUpper(c) ((c) >= 'a' && (c) <= 'z' ? (c) - 'a' + 'A' : (c))
static textwindows noasan noinstrument axdx_t Recode16to8(char *dst,
size_t dstsize,
const char16_t *src) {
bool v;
axdx_t r;
uint64_t w;
wint_t x, y;
for (r.ax = 0, r.dx = 0;;) {
for (v = r.ax = 0, r.dx = 0;;) {
if (!(x = src[r.dx++])) break;
if (IsUtf16Cont(x)) continue;
if (!IsUcs2(x)) {
y = src[r.dx++];
x = MergeUtf16(x, y);
}
if (!v) {
if (x == '=') {
v = true;
} else {
x = ToUpper(x);
}
}
w = tpenc(x);
do {
if (r.ax + 1 >= dstsize) break;

View file

@ -18,6 +18,7 @@
*/
#include "libc/assert.h"
#include "libc/bits/bits.h"
#include "libc/bits/likely.h"
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/sysdebug.internal.h"
@ -61,71 +62,52 @@ static noasan void RemoveMemoryIntervals(struct MemoryIntervals *mm, int i,
mm->i -= n;
}
static noasan void MapNewMappingArray(struct MemoryIntervals *mm) {
/* asan runtime depends on this function */
void *a;
int i, x, y, g;
size_t n, m, f;
static noasan bool ExtendMemoryIntervals(struct MemoryIntervals *mm) {
int prot, flags;
char *base, *shad;
size_t gran, size;
struct DirectMap dm;
struct MemoryInterval *p, *q;
assert(mm->i);
assert(AreMemoryIntervalsOk(mm));
n = mm->n;
n = n * sizeof(*mm->p);
n = ROUNDUP(n, FRAMESIZE);
gran = kMemtrackGran;
base = (char *)kMemtrackStart;
prot = PROT_READ | PROT_WRITE;
flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED;
if (mm->p == mm->s) {
m = n;
q = 0;
} else {
q = mm->p;
m = n + (n >> 1);
m = ROUNDUP(m, FRAMESIZE);
}
/*
* find a hole in the automap range
* we pad the sides for easier insertion logic
* only time this fails is MODE=tiny which makes no stack
*/
i = 0;
f = m >> 16;
for (;;) {
if (++i == mm->i || mm->p[i].x - mm->p[i - 1].y >= 1 + f + 1) {
x = mm->p[i - 1].y + 1;
y = x + f - 1;
a = (void *)((intptr_t)((uint64_t)x << 32) >> 16);
if (i == mm->i || (kAutomapStart <= (intptr_t)a &&
(intptr_t)a + m < kAutomapStart + kAutomapSize)) {
break;
if (IsAsan()) {
shad = (char *)(((intptr_t)base >> 3) + 0x7fff8000);
dm = sys_mmap(shad, gran >> 3, prot, flags, -1, 0);
if (!dm.addr) {
SYSDEBUG("ExtendMemoryIntervals() fail #1");
return false;
}
}
}
flags = MAP_ANONYMOUS | MAP_PRIVATE;
prot = PROT_READ | PROT_WRITE;
SYSDEBUG("MapNewMappingArray(0x%x, 0x%x) %d/%d/%d", a, m, i, mm->i, mm->n);
dm = sys_mmap(a, m, prot, flags | MAP_FIXED, -1, 0);
if ((p = dm.addr) != MAP_FAILED) {
MoveMemoryIntervals(p, mm->p, i);
MoveMemoryIntervals(p + i + 1, mm->p + i, mm->i - i);
mm->i += 1;
mm->n = m / sizeof(*mm->p);
mm->p = p;
mm->p[i].x = x;
mm->p[i].y = y;
mm->p[i].h = dm.maphandle;
mm->p[i].prot = prot;
mm->p[i].flags = flags;
if (q) {
munmap(q, n);
dm = sys_mmap(base, gran, prot, flags, -1, 0);
if (!dm.addr) {
SYSDEBUG("ExtendMemoryIntervals() fail #2");
return false;
}
if (IsAsan()) {
__asan_map_shadow((uintptr_t)a, m);
}
SYSDEBUG("MapNewMappingArray() succeeded");
MoveMemoryIntervals(dm.addr, mm->p, mm->i);
mm->p = dm.addr;
mm->n = gran / sizeof(*mm->p);
} else {
SYSDEBUG("MapNewMappingArray() failed: %s", strerror(errno));
size = ROUNDUP(mm->n * sizeof(*mm->p), gran);
base += size;
if (IsAsan()) {
shad = (char *)(((intptr_t)base >> 3) + 0x7fff8000);
dm = sys_mmap(shad, gran >> 3, prot, flags, -1, 0);
if (!dm.addr) {
SYSDEBUG("ExtendMemoryIntervals() fail #3");
return false;
}
}
dm = sys_mmap(base, gran, prot, flags, -1, 0);
if (!dm.addr) {
SYSDEBUG("ExtendMemoryIntervals() fail #4");
return false;
}
mm->n = (size + gran) / sizeof(*mm->p);
}
assert(AreMemoryIntervalsOk(mm));
return true;
}
noasan int CreateMemoryInterval(struct MemoryIntervals *mm, int i) {
@ -135,16 +117,12 @@ noasan int CreateMemoryInterval(struct MemoryIntervals *mm, int i) {
assert(i >= 0);
assert(i <= mm->i);
assert(mm->n >= 0);
if (mm->i == mm->n) {
SYSDEBUG("CreateMemoryInterval() failed");
return enomem();
}
if (UNLIKELY(mm->i == mm->n) && !ExtendMemoryIntervals(mm)) return enomem();
MoveMemoryIntervals(mm->p + i + 1, mm->p + i, mm->i++ - i);
return 0;
}
static noasan int PunchHole(struct MemoryIntervals *mm, int x, int y, int i) {
if (mm->i == mm->n) return enomem();
if (CreateMemoryInterval(mm, i) == -1) return -1;
mm->p[i].y = x - 1;
mm->p[i + 1].x = y + 1;
@ -210,16 +188,12 @@ noasan int TrackMemoryInterval(struct MemoryIntervals *mm, int x, int y, long h,
prot == mm->p[i].prot && flags == mm->p[i].flags) {
mm->p[i].x = x;
} else {
if (mm->i == mm->n) return enomem();
if (CreateMemoryInterval(mm, i) == -1) return -1;
mm->p[i].x = x;
mm->p[i].y = y;
mm->p[i].h = h;
mm->p[i].prot = prot;
mm->p[i].flags = flags;
if (mm->i >= mm->n / 2) {
MapNewMappingArray(mm);
}
}
return 0;
}

View file

@ -5,24 +5,26 @@
#include "libc/nt/enum/version.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/stack.h"
#include "libc/sysv/consts/ss.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define _kAutomapStart 0x0000100080000000
#define _kAutomapSize 0x00000fff80000000
#define _kFixedmapStart 0x0000300000000000
#define _kFixedmapSize 0x00000fff80000000
/*
* TODO: Why can't we allocate addresses above 4GB on Windows 7 x64?
* https://github.com/jart/cosmopolitan/issues/19
*/
#define MEMTRACK_ADDRESS(NORMAL, WIN7) \
#define kAutomapStart _kMem(0x100080000000, 0x000010000000)
#define kAutomapSize \
_kMem(0x200000000000 - 0x100080000000 - _kMmi(0x800000000000), \
0x000040000000 - 0x000010000000 - _kMmi(0x000080000000))
#define kMemtrackStart \
_kMem(0x200000000000 - _kMmi(0x800000000000), \
0x000040000000 - _kMmi(0x000080000000))
#define kMemtrackSize _kMem(_kMmi(0x800000000000), _kMmi(0x000080000000))
#define kMemtrackGran (!IsAsan() ? FRAMESIZE : FRAMESIZE * 8)
#define kFixedmapStart _kMem(0x300000000000, 0x000040000000)
#define kFixedmapSize \
_kMem(0x400000000000 - 0x300000000000, 0x000070000000 - 0x000040000000)
#define _kMmi(VSPACE) \
ROUNDUP(VSPACE / FRAMESIZE * sizeof(struct MemoryInterval), FRAMESIZE)
#define _kMem(NORMAL, WIN7) \
(!(IsWindows() && NtGetVersion() < kNtVersionWindows10) ? NORMAL : WIN7)
#define kAutomapStart MEMTRACK_ADDRESS(_kAutomapStart, 0x10000000)
#define kAutomapSize MEMTRACK_ADDRESS(_kAutomapSize, 0x30000000)
#define kFixedmapStart MEMTRACK_ADDRESS(_kFixedmapStart, 0x40000000)
#define kFixedmapSize MEMTRACK_ADDRESS(_kFixedmapSize, 0x30000000)
struct MemoryInterval {
int x;
@ -52,11 +54,19 @@ int ReleaseMemoryIntervals(struct MemoryIntervals *, int, int,
void ReleaseMemoryNt(struct MemoryIntervals *, int, int) hidden;
int UntrackMemoryIntervals(void *, size_t) hidden;
#define IsLegalPointer(p) \
(-0x800000000000 <= (intptr_t)(p) && (intptr_t)(p) <= 0x7fffffffffff)
forceinline pureconst bool IsAutoFrame(int x) {
return (kAutomapStart >> 16) <= x &&
x <= ((kAutomapStart + (kAutomapSize - 1)) >> 16);
}
forceinline pureconst bool IsMemtrackFrame(int x) {
return (kAutomapStart >> 16) <= x &&
x <= ((kAutomapStart + (kAutomapSize - 1)) >> 16);
}
forceinline pureconst bool IsArenaFrame(int x) {
return 0x5000 <= x && x < 0x7ffe;
}
@ -65,11 +75,21 @@ forceinline pureconst bool IsShadowFrame(int x) {
return 0x7fff <= x && x < 0x10008000;
}
forceinline pureconst bool IsStackFrame(int x) {
forceinline pureconst bool IsStaticStackFrame(int x) {
return (GetStaticStackAddr(0) >> 16) <= x &&
x <= ((GetStaticStackAddr(0) + (GetStackSize() - FRAMESIZE)) >> 16);
}
forceinline pureconst bool IsSigAltStackFrame(int x) {
return (GetStackAddr(0) >> 16) <= x &&
x <= ((GetStackAddr(0) + (SIGSTKSZ - FRAMESIZE)) >> 16);
}
forceinline pureconst bool IsOldStackFrame(int x) {
intptr_t old = ROUNDDOWN(__oldstack, STACKSIZE);
return (old >> 16) <= x && x <= ((old + (STACKSIZE - FRAMESIZE)) >> 16);
}
forceinline pureconst bool IsFixedFrame(int x) {
return (kFixedmapStart >> 16) <= x &&
x <= ((kFixedmapStart + (kFixedmapSize - 1)) >> 16);

View file

@ -23,8 +23,10 @@
#include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/asan.internal.h"
#include "libc/log/backtrace.internal.h"
#include "libc/log/libfatal.internal.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/rand/rand.h"
@ -40,7 +42,6 @@
#define VIP(X) (void *)IP(X)
#define SMALL(n) ((n) <= 0xffffffffffff)
#define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1)))
#define LEGAL(p) (-0x800000000000 <= IP(p) && IP(p) <= 0x7fffffffffff)
#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))
@ -104,6 +105,87 @@ noasan static bool Automap(int n, int *res) {
}
}
static noasan void *MapMemory(void *addr, size_t size, int prot, int flags,
int fd, int64_t off, int f, int x, int n) {
struct DirectMap dm;
dm = sys_mmap(addr, size, prot, f, fd, off);
if (UNLIKELY(dm.addr == MAP_FAILED)) {
if (IsWindows() && (flags & MAP_FIXED)) {
SYSDEBUG("mmap(0x%p, 0x%x) -> %s (%s)", addr, size, strerror(errno),
"can't recover from MAP_FIXED errors on Windows");
assert(!"MapMemory() failed");
Die();
}
return MAP_FAILED;
}
if (UNLIKELY(dm.addr != addr)) {
SYSDEBUG("KERNEL DIDN'T RESPECT MAP_FIXED");
assert(!"MapMemory() failed");
Die();
}
if (!IsWindows() && (flags & MAP_FIXED)) {
if (UntrackMemoryIntervals(addr, size)) {
SYSDEBUG("FIXED UNTRACK FAILED %s", strerror(errno));
assert(!"MapMemory() failed");
Die();
}
}
if (TrackMemoryInterval(&_mmi, x, x + (n - 1), dm.maphandle, prot, flags)) {
if (sys_munmap(addr, n) == -1) {
SYSDEBUG("TRACK MUNMAP FAILED %s", strerror(errno));
assert(!"MapMemory() failed");
Die();
}
return MAP_FAILED;
}
if (weaken(__asan_map_shadow) && !OverlapsShadowSpace(addr, size)) {
weaken(__asan_map_shadow)((intptr_t)addr, size);
}
return addr;
}
/**
* Maps memory from system, one frame at a time.
*
* This is useful on Windows since it allows us to partially unmap or
* punch holes into existing mappings.
*/
static textwindows noinline noasan void *MapMemories(char *addr, size_t size,
int prot, int flags,
int fd, int64_t off, int f,
int x, size_t n) {
struct DirectMap dm;
size_t i, m = (n - 1) * FRAMESIZE;
assert(m < size && m + FRAMESIZE >= size);
dm = sys_mmap(addr + m, size - m, prot, f, fd, fd == -1 ? 0 : off + m);
if (dm.addr == MAP_FAILED) {
SYSDEBUG("MapMemories(%p+%x/%x) %s", addr, m, size, strerror(errno));
return MAP_FAILED;
}
if (TrackMemoryInterval(&_mmi, x + (n - 1), x + (n - 1), dm.maphandle, prot,
flags) == -1) {
SYSDEBUG("MapMemories(%p+%x/%x) unrecoverable failure #1 %s", addr, m, size,
strerror(errno));
assert(!"MapMemories() failed");
Die();
}
for (i = 0; i < m; i += FRAMESIZE) {
dm = sys_mmap(addr + i, FRAMESIZE, prot, f, fd, fd == -1 ? 0 : off + i);
if (dm.addr == MAP_FAILED ||
TrackMemoryInterval(&_mmi, x + i / FRAMESIZE, x + i / FRAMESIZE,
dm.maphandle, prot, flags) == -1) {
SYSDEBUG("MapMemories(%p+%x/%x) unrecoverable failure #2 %s", addr, i,
size, strerror(errno));
assert(!"MapMemories() failed");
Die();
}
}
if (weaken(__asan_map_shadow) && !OverlapsShadowSpace(addr, size)) {
weaken(__asan_map_shadow)((intptr_t)addr, size);
}
return addr;
}
/**
* Beseeches system for page-table entries, e.g.
*
@ -146,7 +228,7 @@ noasan void *mmap(void *addr, size_t size, int prot, int flags, int fd,
SYSDEBUG("mmap(0x%p, 0x%x) EINVAL (size isn't 48-bit)", p, size);
return VIP(einval());
}
if (UNLIKELY(!LEGAL(p))) {
if (UNLIKELY(!IsLegalPointer(p))) {
SYSDEBUG("mmap(0x%p, 0x%x) EINVAL (p isn't 48-bit)", p, size);
return VIP(einval());
}
@ -202,6 +284,7 @@ noasan void *mmap(void *addr, size_t size, int prot, int flags, int fd,
if (IsWindows()) {
if (UntrackMemoryIntervals(p, size)) {
SYSDEBUG("FIXED UNTRACK FAILED %s", strerror(errno));
assert(!"mmap() failed");
Die();
}
}
@ -215,34 +298,9 @@ noasan void *mmap(void *addr, size_t size, int prot, int flags, int fd,
dm = sys_mmap(p, size, prot, f & ~MAP_GROWSDOWN, fd, off);
if (dm.addr == MAP_FAILED) return MAP_FAILED;
}
dm = sys_mmap(p, size, prot, f, fd, off);
if (UNLIKELY(dm.addr == MAP_FAILED)) {
if (IsWindows() && (flags & MAP_FIXED)) {
SYSDEBUG("mmap(0x%p, 0x%x) -> %s (%s)", p, size, strerror(errno),
"can't recover from MAP_FIXED errors on Windows");
Die();
}
return MAP_FAILED;
if (!IsWindows()) {
return MapMemory(p, size, prot, flags, fd, off, f, x, n);
} else {
return MapMemories(p, size, prot, flags, fd, off, f, x, n);
}
if (UNLIKELY(dm.addr != p)) {
SYSDEBUG("KERNEL DIDN'T RESPECT MAP_FIXED");
Die();
}
if (!IsWindows() && (flags & MAP_FIXED)) {
if (UntrackMemoryIntervals(p, size)) {
SYSDEBUG("FIXED UNTRACK FAILED %s", strerror(errno));
Die();
}
}
if (TrackMemoryInterval(&_mmi, x, x + (n - 1), dm.maphandle, prot, flags)) {
if (sys_munmap(p, n) == -1) {
SYSDEBUG("TRACK MUNMAP FAILED %s", strerror(errno));
Die();
}
return MAP_FAILED;
}
if (weaken(__asan_map_shadow) && !OverlapsShadowSpace(p, size)) {
weaken(__asan_map_shadow)((intptr_t)p, size);
}
return p;
}

View file

@ -38,7 +38,6 @@
#define VIP(X) (void *)IP(X)
#define SMALL(n) ((n) <= 0xffffffffffff)
#define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1)))
#define LEGAL(p) (-0x800000000000 <= IP(p) && IP(p) <= 0x7fffffffffff)
#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))

View file

@ -20,6 +20,7 @@
#include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/asan.internal.h"
#include "libc/log/libfatal.internal.h"
#include "libc/macros.internal.h"
@ -32,7 +33,6 @@
#define IP(X) (intptr_t)(X)
#define SMALL(n) ((n) <= 0xffffffffffff)
#define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1)))
#define LEGAL(p) (-0x800000000000 <= IP(p) && IP(p) <= 0x7fffffffffff)
#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))
@ -64,11 +64,11 @@ noasan int munmap(void *v, size_t n) {
SYSDEBUG("munmap(0x%p, 0x%x) EINVAL (n isn't 48-bit)", p, n);
return einval();
}
if (UNLIKELY(!LEGAL(p))) {
if (UNLIKELY(!IsLegalPointer(p))) {
SYSDEBUG("munmap(0x%p, 0x%x) EINVAL (p isn't 48-bit)", p, n);
return einval();
}
if (UNLIKELY(!LEGAL(p + (n - 1)))) {
if (UNLIKELY(!IsLegalPointer(p + (n - 1)))) {
SYSDEBUG("munmap(0x%p, 0x%x) EINVAL (p+(n-1) isn't 48-bit)", p, n);
return einval();
}
@ -80,7 +80,6 @@ noasan int munmap(void *v, size_t n) {
SYSDEBUG("munmap(0x%p, 0x%x) EFAULT (interval not tracked)", p, n);
return efault();
}
SYSDEBUG("munmap(0x%p, 0x%x)", p, n);
if (UntrackMemoryIntervals(p, n) != -1) {
if (!IsWindows()) {
rc = sys_munmap(p, n);
@ -105,11 +104,13 @@ noasan int munmap(void *v, size_t n) {
}
}
}
return rc;
} else {
return 0; /* UntrackMemoryIntervals does it for NT */
rc = 0; /* UntrackMemoryIntervals does it for NT */
}
} else {
return -1;
rc = -1;
}
SYSDEBUG("munmap(0x%p, 0x%x) -> %d %s", p, n, (long)rc,
rc == -1 ? strerror(errno) : "");
return rc;
}

View file

@ -23,9 +23,17 @@
_peekall:
.leafprologue
ezlea _base,si
ezlea _etext,cx
add $0x1000,%rsi
0: xor (%rsi),%eax
add $PAGESIZE,%rsi
cmp %rcx,%rsi
jb 0b
ezlea _etext,si
ezlea _end,cx
add $0x1000,%rsi
0: mov (%rsi),%eax
0: incq (%rsi)
decq (%rsi)
add $PAGESIZE,%rsi
cmp %rcx,%rsi
jb 0b

View file

@ -1,76 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#define ShouldUseMsabiAttribute() 1
#include "libc/dce.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/fileno.h"
#include "libc/sysv/consts/nr.h"
/* TODO(jart): DELETE */
#define WasImported(SLOT) \
((void *)*SLOT && *SLOT != (void *)&missingno /* see libc/crt/crt.S */)
static void __sys_print_nt(const void *data, size_t len) {
int64_t hand;
char xmm[256];
uint32_t wrote;
_savexmm(xmm + 128);
hand = __imp_GetStdHandle(kNtStdErrorHandle);
__imp_WriteFile(hand, data, len, &wrote, NULL);
_loadxmm(xmm + 128);
}
/**
* Prints string, by any means necessary.
*
* This function offers a subset of write(STDERR_FILENO) functionality.
* It's designed to work even when the runtime hasn't initialized, e.g.
* before _init() gets called.
*
* @param len can be computed w/ tinystrlen()
* @clob nothing except flags
*/
privileged noinline void __print(const void *data, size_t len) {
int64_t ax, ordinal;
if (WasImported(__imp_WriteFile)) {
__sys_print_nt(data, len);
} else {
ordinal = __NR_write > 0 ? __NR_write : IsXnu() ? 0x2000004 : 4;
asm volatile("syscall"
: "=a"(ax)
: "0"(ordinal), "D"(STDERR_FILENO), "S"(data), "d"(len)
: "rcx", "r11", "memory", "cc");
if (ax == -1 && !__hostos && !__NR_write) {
asm volatile("syscall"
: "=a"(ax)
: "0"(ordinal), "D"(STDERR_FILENO), "S"(data), "d"(len)
: "rcx", "r11", "memory", "cc");
}
}
}
void __print_string(const char *s) {
size_t n = 0;
while (s[n]) ++n;
__print(s, n);
}

View file

@ -26,9 +26,10 @@
static bool IsNoteworthyHole(unsigned i, const struct MemoryIntervals *mm) {
// gaps between shadow frames aren't interesting
// the chasm from heap to stack ruins statistics
return !((IsArenaFrame(mm->p[i].y) && !IsArenaFrame(mm->p[i + 1].x)) ||
(IsShadowFrame(mm->p[i].y) || IsShadowFrame(mm->p[i + 1].x)) ||
(!IsStackFrame(mm->p[i].y) && IsStackFrame(mm->p[i + 1].x)));
return !(
(IsArenaFrame(mm->p[i].y) && !IsArenaFrame(mm->p[i + 1].x)) ||
(IsShadowFrame(mm->p[i].y) || IsShadowFrame(mm->p[i + 1].x)) ||
(!IsStaticStackFrame(mm->p[i].y) && IsStaticStackFrame(mm->p[i + 1].x)));
}
void PrintMemoryIntervals(int fd, const struct MemoryIntervals *mm) {
@ -40,8 +41,7 @@ void PrintMemoryIntervals(int fd, const struct MemoryIntervals *mm) {
for (i = 0; i < mm->i; ++i) {
frames = mm->p[i].y + 1 - mm->p[i].x;
maptally += frames;
__printf("%0*x-%0*x %s %,*dx%s", 12, ADDR(mm->p[i].x), 12,
ADDR(mm->p[i].y + 1),
__printf("%012x-%012x %s %,*dx%s", ADDR(mm->p[i].x), ADDR(mm->p[i].y + 1),
DescribeMapping(mm->p[i].prot, mm->p[i].flags, mode), w, frames,
DescribeFrame(mm->p[i].x));
if (i + 1 < _mmi.i) {

View file

@ -33,6 +33,7 @@
#include "libc/sysv/consts/at.h"
#include "libc/sysv/consts/auxv.h"
#include "libc/sysv/consts/ok.h"
#include "libc/sysv/consts/prot.h"
#define SIZE 1024
#define CTL_KERN 1

View file

@ -13,6 +13,7 @@ extern const int __argc; /* CRT */
extern char **const __argv; /* CRT */
extern char **const __envp; /* CRT */
extern unsigned long *const __auxv; /* CRT */
extern intptr_t __oldstack; /* CRT */
extern char program_executable_name[]; /* RII */
extern char *program_invocation_name; /* RII */
extern char *program_invocation_short_name; /* RII */
@ -86,8 +87,6 @@ bool _isheap(void *);
int NtGetVersion(void) pureconst;
long missingno();
void __oom_hook(size_t);
void __print(const void *, size_t);
void __print_string(const char *);
void _loadxmm(void *);
void _peekall(void);
void _savexmm(void *);

View file

@ -2,6 +2,7 @@
#define COSMOPOLITAN_LIBC_RUNTIME_STACK_H_
#include "ape/config.h"
#include "libc/dce.h"
#include "libc/runtime/runtime.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
/**
@ -63,14 +64,18 @@ extern char ape_stack_memsz[] __attribute__((__weak__));
/**
* Returns preferred bottom address of stack.
*/
#define GetStaticStackAddr(ADDEND) \
({ \
intptr_t vAddr = 0; \
asm(".weak\tape_stack_vaddr\n\t" \
"movabs\t%1+ape_stack_vaddr,%0" \
: "=r"(vAddr) \
: "i"(ADDEND)); \
vAddr; \
#define GetStaticStackAddr(ADDEND) \
({ \
intptr_t vAddr; \
if (!IsWindows() || NtGetVersion() >= kNtVersionWindows10) { \
asm(".weak\tape_stack_vaddr\n\t" \
"movabs\t%1+ape_stack_vaddr,%0" \
: "=r"(vAddr) \
: "i"(ADDEND)); \
} else { \
vAddr = 0x10000000; \
} \
vAddr; \
})
COSMOPOLITAN_C_END_

View file

@ -98,6 +98,7 @@ static noasan textwindows wontreturn noinstrument void WinMainNew(void) {
extern char os asm("__hostos");
os = WINDOWS; /* madness https://news.ycombinator.com/item?id=21019722 */
version = NtGetPeb()->OSMajorVersion;
__oldstack = (intptr_t)__builtin_frame_address(0);
if ((intptr_t)v_ntsubsystem == kNtImageSubsystemWindowsCui && version >= 10) {
SetConsoleCP(kNtCpUtf8);
SetConsoleOutputCP(kNtCpUtf8);
@ -114,9 +115,9 @@ static noasan textwindows wontreturn noinstrument void WinMainNew(void) {
kNtEnableVirtualTerminalProcessing);
}
_mmi.p = _mmi.s;
_mmi.n = OPEN_MAX;
_mmi.n = ARRAYLEN(_mmi.s);
argsize = ROUNDUP(sizeof(struct WinArgs), FRAMESIZE);
stackaddr = version < 10 ? 0x10000000 : GetStaticStackAddr(0);
stackaddr = GetStaticStackAddr(0);
stacksize = GetStackSize();
allocsize = argsize + stacksize;
allocaddr = stackaddr - argsize;