mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-27 14:58:30 +00:00
Add MODE=optlinux build mode (#141)
This commit is contained in:
parent
226aaf3547
commit
67b5200a0b
111 changed files with 934 additions and 854 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 "";
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue