mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-28 15:28:30 +00:00
Make improvements
- Emulator can now test the αcτµαlly pδrταblε εxεcµταblε bootloader - Whipped up a webserver named redbean. It services 150k requests per second on a single core. Bundling assets inside zip enables extremely fast serving for two reasons. The first is that zip central directory lookups go faster than stat() system calls. The second is that both zip and gzip content-encoding use DEFLATE, therefore, compressed responses can be served via the sendfile() system call which does an in-kernel copy directly from the zip executable structure. Also note that red bean zip executables can be deployed easily to all platforms, since these native executables work on Linux, Mac, BSD, and Windows. - Address sanitizer now works very well
This commit is contained in:
parent
7327c345f9
commit
416fd86676
230 changed files with 9835 additions and 5682 deletions
319
libc/log/asan.c
319
libc/log/asan.c
|
@ -102,6 +102,111 @@ struct AsanGlobal {
|
|||
char *odr_indicator;
|
||||
};
|
||||
|
||||
struct AsanMorgue {
|
||||
unsigned i;
|
||||
void *p[16];
|
||||
};
|
||||
|
||||
static struct AsanMorgue __asan_morgue;
|
||||
|
||||
static const char *__asan_dscribe_free_poison(int c) {
|
||||
switch (c) {
|
||||
case kAsanHeapFree:
|
||||
return "heap double free";
|
||||
case kAsanRelocated:
|
||||
return "free after relocate";
|
||||
case kAsanStackFree:
|
||||
return "stack double free";
|
||||
default:
|
||||
return "invalid pointer";
|
||||
}
|
||||
}
|
||||
|
||||
static const char *__asan_describe_access_poison(int c) {
|
||||
switch (c) {
|
||||
case kAsanHeapFree:
|
||||
return "heap use after free";
|
||||
case kAsanStackFree:
|
||||
return "stack use after release";
|
||||
case kAsanRelocated:
|
||||
return "heap use after relocate";
|
||||
case kAsanHeapUnderrun:
|
||||
return "heap underrun";
|
||||
case kAsanHeapOverrun:
|
||||
return "heap overrun";
|
||||
case kAsanGlobalOverrun:
|
||||
return "global overrun";
|
||||
case kAsanGlobalUnregistered:
|
||||
return "global unregistered";
|
||||
case kAsanStackUnderrun:
|
||||
return "stack underflow";
|
||||
case kAsanStackOverrun:
|
||||
return "stack overflow";
|
||||
case kAsanAllocaOverrun:
|
||||
return "alloca overflow";
|
||||
case kAsanUnscoped:
|
||||
return "unscoped";
|
||||
default:
|
||||
return "poisoned";
|
||||
}
|
||||
}
|
||||
|
||||
static noreturn void __asan_die(const char *msg, size_t size) {
|
||||
__print(msg, size);
|
||||
PrintBacktraceUsingSymbols(stderr, __builtin_frame_address(0),
|
||||
getsymboltable());
|
||||
DebugBreak();
|
||||
_Exit(66);
|
||||
}
|
||||
|
||||
static noreturn void __asan_report_deallocate_fault(void *addr, int c) {
|
||||
char *p, ibuf[21], buf[256];
|
||||
p = buf;
|
||||
p = stpcpy(p, "error: ");
|
||||
p = stpcpy(p, __asan_dscribe_free_poison(c));
|
||||
p = stpcpy(p, " ");
|
||||
p = mempcpy(p, ibuf, int64toarray_radix10(c, ibuf));
|
||||
p = stpcpy(p, " at 0x");
|
||||
p = mempcpy(p, ibuf, uint64toarray_fixed16((intptr_t)addr, ibuf, 48));
|
||||
p = stpcpy(p, "\n");
|
||||
__asan_die(buf, p - buf);
|
||||
}
|
||||
|
||||
static noreturn void __asan_report_memory_fault(uint8_t *addr, int size,
|
||||
const char *kind) {
|
||||
char *p, ibuf[21], buf[256];
|
||||
p = buf;
|
||||
p = stpcpy(p, "error: ");
|
||||
p = stpcpy(p, __asan_describe_access_poison(*(char *)SHADOW((intptr_t)addr)));
|
||||
p = stpcpy(p, " ");
|
||||
p = mempcpy(p, ibuf, uint64toarray_radix10(size, ibuf));
|
||||
p = stpcpy(p, "-byte ");
|
||||
p = stpcpy(p, kind);
|
||||
p = stpcpy(p, " at 0x");
|
||||
p = mempcpy(p, ibuf, uint64toarray_fixed16((intptr_t)addr, ibuf, 48));
|
||||
p = stpcpy(p, "\n");
|
||||
__asan_die(buf, p - buf);
|
||||
}
|
||||
|
||||
static const void *__asan_morgue_add(void *p) {
|
||||
void *r;
|
||||
r = __asan_morgue.p[__asan_morgue.i];
|
||||
__asan_morgue.p[__asan_morgue.i] = p;
|
||||
__asan_morgue.i += 1;
|
||||
__asan_morgue.i &= ARRAYLEN(__asan_morgue.p) - 1;
|
||||
return r;
|
||||
}
|
||||
|
||||
static void __asan_morgue_flush(void) {
|
||||
void *p;
|
||||
unsigned i;
|
||||
for (i = 0; i < ARRAYLEN(__asan_morgue.p); ++i) {
|
||||
p = __asan_morgue.p[i];
|
||||
__asan_morgue.p[i] = NULL;
|
||||
dlfree(p);
|
||||
}
|
||||
}
|
||||
|
||||
static bool __asan_is_mapped(void *p) {
|
||||
int x, i;
|
||||
x = (intptr_t)p >> 16;
|
||||
|
@ -109,41 +214,8 @@ static bool __asan_is_mapped(void *p) {
|
|||
return i < _mmi.i && x >= _mmi.p[i].x && x <= _mmi.p[i].y;
|
||||
}
|
||||
|
||||
void __asan_map_shadow(void *addr, size_t size) {
|
||||
int i, n, x;
|
||||
char *a, *b;
|
||||
struct DirectMap sm;
|
||||
a = (char *)ROUNDDOWN(SHADOW((intptr_t)addr), FRAMESIZE);
|
||||
b = (char *)ROUNDDOWN(SHADOW((intptr_t)addr + size - 1), FRAMESIZE);
|
||||
for (; a <= b; a += FRAMESIZE) {
|
||||
if (!__asan_is_mapped(a)) {
|
||||
sm = DirectMap(a, FRAMESIZE, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
|
||||
if (sm.addr == MAP_FAILED ||
|
||||
TrackMemoryInterval(&_mmi, (intptr_t)a >> 16, (intptr_t)a >> 16,
|
||||
sm.maphandle) == -1) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t __asan_malloc_usable_size(const void *vp) {
|
||||
char *s;
|
||||
size_t n;
|
||||
for (n = 0, s = (char *)SHADOW((intptr_t)vp);; ++s) {
|
||||
if (!*s) {
|
||||
n += 8;
|
||||
} else if (*s > 0) {
|
||||
n += *s & 7;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void *__asan_allocate(size_t align, size_t size, int underrun, int overrun) {
|
||||
static void *__asan_allocate(size_t align, size_t size, int underrun,
|
||||
int overrun) {
|
||||
char *p, *s;
|
||||
size_t q, r, i;
|
||||
if (!(p = dlmemalign(align, ROUNDUP(size, 8) + 16))) return NULL;
|
||||
|
@ -160,29 +232,59 @@ void *__asan_allocate(size_t align, size_t size, int underrun, int overrun) {
|
|||
return p;
|
||||
}
|
||||
|
||||
void __asan_deallocate(char *p, int kind) {
|
||||
static void __asan_deallocate(char *p, int kind) {
|
||||
char *s;
|
||||
s = (char *)SHADOW((intptr_t)p);
|
||||
if ((*s < 0 && *s != kAsanHeapOverrun) || *s >= 8) {
|
||||
__asan_report_deallocate_fault(p, *s);
|
||||
}
|
||||
for (; *s >= 0; ++s) *s = kind;
|
||||
dlfree(__asan_morgue_add(p));
|
||||
}
|
||||
|
||||
static void __asan_poison_redzone(intptr_t addr, size_t size, size_t redsize,
|
||||
int kind) {
|
||||
char *s;
|
||||
intptr_t p;
|
||||
size_t a, b, w;
|
||||
w = (intptr_t)addr & 7;
|
||||
p = (intptr_t)addr - w;
|
||||
a = w + size;
|
||||
b = w + redsize;
|
||||
s = (char *)SHADOW(p + a);
|
||||
if (a & 7) *s++ = a & 7;
|
||||
memset(s, kind, (b - ROUNDUP(a, 8)) >> 3);
|
||||
}
|
||||
|
||||
static size_t __asan_malloc_usable_size(const void *vp) {
|
||||
char *s;
|
||||
size_t n;
|
||||
s = (char *)SHADOW((intptr_t)p);
|
||||
n = dlmalloc_usable_size(p);
|
||||
n /= 8;
|
||||
memset(s, kind, n);
|
||||
dlfree(p);
|
||||
for (n = 0, s = (char *)SHADOW((intptr_t)vp);; ++s) {
|
||||
if (!*s) {
|
||||
n += 8;
|
||||
} else if (*s > 0) {
|
||||
n += *s & 7;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void __asan_free(void *vp) {
|
||||
__asan_deallocate(vp, kAsanHeapFree);
|
||||
static void __asan_free(void *p) {
|
||||
if (!p) return;
|
||||
__asan_deallocate(p, kAsanHeapFree);
|
||||
}
|
||||
|
||||
void *__asan_memalign(size_t align, size_t size) {
|
||||
static void *__asan_memalign(size_t align, size_t size) {
|
||||
return __asan_allocate(align, size, kAsanHeapUnderrun, kAsanHeapOverrun);
|
||||
}
|
||||
|
||||
void *__asan_malloc(size_t size) {
|
||||
static void *__asan_malloc(size_t size) {
|
||||
return __asan_memalign(16, size);
|
||||
}
|
||||
|
||||
void *__asan_calloc(size_t n, size_t m) {
|
||||
static void *__asan_calloc(size_t n, size_t m) {
|
||||
char *p;
|
||||
size_t size;
|
||||
if (__builtin_mul_overflow(n, m, &size)) size = -1;
|
||||
|
@ -190,7 +292,7 @@ void *__asan_calloc(size_t n, size_t m) {
|
|||
return p;
|
||||
}
|
||||
|
||||
void *__asan_realloc(void *p, size_t n) {
|
||||
static void *__asan_realloc(void *p, size_t n) {
|
||||
char *p2;
|
||||
if (p) {
|
||||
if (n) {
|
||||
|
@ -208,86 +310,32 @@ void *__asan_realloc(void *p, size_t n) {
|
|||
return p2;
|
||||
}
|
||||
|
||||
void *__asan_valloc(size_t n) {
|
||||
static void *__asan_valloc(size_t n) {
|
||||
return __asan_memalign(PAGESIZE, n);
|
||||
}
|
||||
|
||||
void *__asan_pvalloc(size_t n) {
|
||||
static void *__asan_pvalloc(size_t n) {
|
||||
return __asan_valloc(ROUNDUP(n, PAGESIZE));
|
||||
}
|
||||
|
||||
void __asan_poison(intptr_t addr, size_t size, size_t redsize, int kind) {
|
||||
char *s;
|
||||
intptr_t p;
|
||||
size_t a, b, w;
|
||||
w = (intptr_t)addr & 7;
|
||||
p = (intptr_t)addr - w;
|
||||
a = w + size;
|
||||
b = w + redsize;
|
||||
s = (char *)SHADOW(p + a);
|
||||
if (a & 7) *s++ = a & 7;
|
||||
memset(s, kind, (b - ROUNDUP(a, 8)) >> 3);
|
||||
}
|
||||
|
||||
void __asan_register_globals(struct AsanGlobal g[], int n) {
|
||||
size_t i;
|
||||
unsigned i;
|
||||
for (i = 0; i < n; ++i) {
|
||||
__asan_poison((intptr_t)g[i].addr, g[i].size, g[i].size_with_redzone,
|
||||
kAsanGlobalOverrun);
|
||||
__asan_poison_redzone((intptr_t)g[i].addr, g[i].size,
|
||||
g[i].size_with_redzone, kAsanGlobalOverrun);
|
||||
}
|
||||
}
|
||||
|
||||
void __asan_report_memory_fault(uint8_t *addr, int size, const char *kind) {
|
||||
char *p, *s, ibuf[21], buf[256];
|
||||
switch (*(char *)SHADOW((intptr_t)addr)) {
|
||||
case kAsanStackFree:
|
||||
s = "stack use after release";
|
||||
break;
|
||||
case kAsanHeapFree:
|
||||
s = "heap use after free";
|
||||
break;
|
||||
case kAsanRelocated:
|
||||
s = "heap use after relocate";
|
||||
break;
|
||||
case kAsanHeapUnderrun:
|
||||
s = "heap underrun";
|
||||
break;
|
||||
case kAsanHeapOverrun:
|
||||
s = "heap overrun";
|
||||
break;
|
||||
case kAsanStackUnderrun:
|
||||
s = "stack underflow";
|
||||
break;
|
||||
case kAsanStackOverrun:
|
||||
s = "stack overflow";
|
||||
break;
|
||||
case kAsanAllocaOverrun:
|
||||
s = "alloca overflow";
|
||||
break;
|
||||
case kAsanUnscoped:
|
||||
s = "unscoped";
|
||||
break;
|
||||
default:
|
||||
s = "poisoned";
|
||||
break;
|
||||
void __asan_unregister_globals(struct AsanGlobal g[], int n) {
|
||||
unsigned i;
|
||||
intptr_t a, b;
|
||||
for (i = 0; i < n; ++i) {
|
||||
a = ROUNDUP((intptr_t)g[i].addr, 8);
|
||||
b = ROUNDDOWN((intptr_t)g[i].addr + g[i].size_with_redzone, 8);
|
||||
if (b > a) {
|
||||
memset((char *)SHADOW(a), kAsanGlobalUnregistered, (b - a) >> 3);
|
||||
}
|
||||
}
|
||||
p = buf;
|
||||
p = stpcpy(p, "error: ");
|
||||
p = stpcpy(p, s);
|
||||
p = stpcpy(p, " ");
|
||||
uint64toarray_radix10(size, ibuf);
|
||||
p = stpcpy(p, ibuf);
|
||||
p = stpcpy(p, "-byte ");
|
||||
p = stpcpy(p, kind);
|
||||
p = stpcpy(p, " at 0x");
|
||||
uint64toarray_fixed16((intptr_t)addr, ibuf, 48);
|
||||
p = stpcpy(p, ibuf);
|
||||
p = stpcpy(p, "\n");
|
||||
__print(buf, p - buf);
|
||||
PrintBacktraceUsingSymbols(stderr, __builtin_frame_address(0),
|
||||
getsymboltable());
|
||||
DebugBreak();
|
||||
_Exit(66);
|
||||
}
|
||||
|
||||
void *__asan_stack_malloc(size_t size, int classid) {
|
||||
|
@ -295,7 +343,7 @@ void *__asan_stack_malloc(size_t size, int classid) {
|
|||
}
|
||||
|
||||
void __asan_stack_free(char *p, size_t size, int classid) {
|
||||
return __asan_deallocate(p, kAsanStackFree);
|
||||
dlfree(p);
|
||||
}
|
||||
|
||||
void __asan_report_load_n(uint8_t *addr, int size) {
|
||||
|
@ -316,16 +364,8 @@ void __asan_unpoison_stack_memory(uintptr_t p, size_t n) {
|
|||
if (n & 7) *(char *)SHADOW(p + n) = n & 7;
|
||||
}
|
||||
|
||||
void __asan_loadN(intptr_t ptr, size_t size) {
|
||||
DebugBreak();
|
||||
}
|
||||
|
||||
void __asan_storeN(intptr_t ptr, size_t size) {
|
||||
DebugBreak();
|
||||
}
|
||||
|
||||
void __asan_alloca_poison(intptr_t addr, size_t size) {
|
||||
__asan_poison(addr, size, size + 32, kAsanAllocaOverrun);
|
||||
__asan_poison_redzone(addr, size, size + 32, kAsanAllocaOverrun);
|
||||
}
|
||||
|
||||
void __asan_allocas_unpoison(uintptr_t top, uintptr_t bottom) {
|
||||
|
@ -352,7 +392,27 @@ void __asan_install_malloc_hooks(void) {
|
|||
HOOK(hook$malloc_usable_size, __asan_malloc_usable_size);
|
||||
}
|
||||
|
||||
void __asan_init(int argc, char *argv[], char **envp, intptr_t *auxv) {
|
||||
void __asan_map_shadow(void *addr, size_t size) {
|
||||
int i, n, x;
|
||||
char *a, *b;
|
||||
struct DirectMap sm;
|
||||
a = (char *)ROUNDDOWN(SHADOW((intptr_t)addr), FRAMESIZE);
|
||||
b = (char *)ROUNDDOWN(SHADOW((intptr_t)addr + size - 1), FRAMESIZE);
|
||||
for (; a <= b; a += FRAMESIZE) {
|
||||
if (!__asan_is_mapped(a)) {
|
||||
sm = DirectMap(a, FRAMESIZE, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
|
||||
if (sm.addr == MAP_FAILED ||
|
||||
TrackMemoryInterval(&_mmi, (intptr_t)a >> 16, (intptr_t)a >> 16,
|
||||
sm.maphandle) == -1) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
textstartup void __asan_init(int argc, char *argv[], char **envp,
|
||||
intptr_t *auxv) {
|
||||
int i;
|
||||
static bool once;
|
||||
register intptr_t rsp asm("rsp");
|
||||
|
@ -367,4 +427,9 @@ void __asan_init(int argc, char *argv[], char **envp, intptr_t *auxv) {
|
|||
}
|
||||
}
|
||||
|
||||
const void *const g_asan_ctor[] initarray = {getsymboltable};
|
||||
static textstartup void __asan_ctor(void) {
|
||||
/* __cxa_atexit(__asan_morgue_flush, NULL, NULL); */
|
||||
getsymboltable();
|
||||
}
|
||||
|
||||
const void *const g_asan_ctor[] initarray = {__asan_ctor};
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_LOG_ASAN_H_
|
||||
#define COSMOPOLITAN_LIBC_LOG_ASAN_H_
|
||||
|
||||
#define kAsanScale 3
|
||||
#define kAsanMagic 0x7fff8000
|
||||
#define kAsanHeapFree -1
|
||||
#define kAsanStackFree -2
|
||||
#define kAsanRelocated -3
|
||||
#define kAsanHeapUnderrun -4
|
||||
#define kAsanHeapOverrun -5
|
||||
#define kAsanGlobalOverrun -6
|
||||
#define kAsanStackUnderrun -7
|
||||
#define kAsanStackOverrun -8
|
||||
#define kAsanAllocaOverrun -9
|
||||
#define kAsanUnscoped -10
|
||||
#define kAsanScale 3
|
||||
#define kAsanMagic 0x7fff8000
|
||||
#define kAsanHeapFree -1
|
||||
#define kAsanStackFree -2
|
||||
#define kAsanRelocated -3
|
||||
#define kAsanHeapUnderrun -4
|
||||
#define kAsanHeapOverrun -5
|
||||
#define kAsanGlobalOverrun -6
|
||||
#define kAsanGlobalUnregistered -7
|
||||
#define kAsanStackUnderrun -8
|
||||
#define kAsanStackOverrun -9
|
||||
#define kAsanAllocaOverrun -10
|
||||
#define kAsanUnscoped -11
|
||||
|
||||
#define SHADOW(x) (((x) >> kAsanScale) + kAsanMagic)
|
||||
|
||||
|
|
|
@ -18,41 +18,29 @@
|
|||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/alg/bisectcarleft.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/conv/itoa.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/backtrace.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/nexgen32e/gc.h"
|
||||
#include "libc/nexgen32e/stackframe.h"
|
||||
#include "libc/runtime/missioncritical.h"
|
||||
#include "libc/runtime/symbols.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
static char *FormatAddress(FILE *f, const struct SymbolTable *st, intptr_t addr,
|
||||
char *out, unsigned size, bool symbolic) {
|
||||
int64_t addend;
|
||||
const char *name;
|
||||
const struct Symbol *symbol;
|
||||
if (st->count && ((intptr_t)addr >= (intptr_t)&_base &&
|
||||
(intptr_t)addr <= (intptr_t)&_end && symbolic)) {
|
||||
symbol = &st->symbols[bisectcarleft((const int32_t(*)[2])st->symbols,
|
||||
st->count, addr - st->addr_base - 1)];
|
||||
addend = addr - st->addr_base - symbol->addr_rva;
|
||||
name = &st->name_base[symbol->name_rva];
|
||||
snprintf(out, size, "%s%c%#x", name, addend >= 0 ? '+' : '-', ABS(addend));
|
||||
} else {
|
||||
snprintf(out, size, "%p", addr);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
#include "libc/str/str.h"
|
||||
|
||||
int PrintBacktraceUsingSymbols(FILE *f, const struct StackFrame *bp,
|
||||
struct SymbolTable *symbols) {
|
||||
struct SymbolTable *st) {
|
||||
size_t gi;
|
||||
char buf[256];
|
||||
intptr_t addr;
|
||||
int64_t addend;
|
||||
struct Garbages *garbage;
|
||||
char *p, buf[256], ibuf[21];
|
||||
const struct Symbol *symbol;
|
||||
const struct StackFrame *frame;
|
||||
if (!symbols) return -1;
|
||||
if (!st) return -1;
|
||||
garbage = weaken(g_garbage);
|
||||
gi = garbage ? garbage->i : 0;
|
||||
for (frame = bp; frame; frame = frame->next) {
|
||||
|
@ -62,8 +50,25 @@ int PrintBacktraceUsingSymbols(FILE *f, const struct StackFrame *bp,
|
|||
--gi;
|
||||
} while ((addr = garbage->p[gi].ret) == weakaddr("CollectGarbage"));
|
||||
}
|
||||
fprintf(f, "%p %p %s\n", frame, addr,
|
||||
FormatAddress(f, symbols, addr, buf, sizeof(buf), true));
|
||||
p = buf;
|
||||
p = mempcpy(p, ibuf, uint64toarray_fixed16((intptr_t)frame, ibuf, 48));
|
||||
*p++ = ' ';
|
||||
p = mempcpy(p, ibuf, uint64toarray_fixed16(addr, ibuf, 48));
|
||||
*p++ = ' ';
|
||||
if (st->count && ((intptr_t)addr >= (intptr_t)&_base &&
|
||||
(intptr_t)addr <= (intptr_t)&_end)) {
|
||||
symbol = &st->symbols[bisectcarleft((const int32_t(*)[2])st->symbols,
|
||||
st->count, addr - st->addr_base - 1)];
|
||||
p = stpcpy(p, &st->name_base[symbol->name_rva]);
|
||||
addend = addr - st->addr_base - symbol->addr_rva;
|
||||
*p++ = addend >= 0 ? '+' : '-';
|
||||
if (addend) *p++ = '0', *p++ = 'x';
|
||||
p = mempcpy(p, ibuf, uint64toarray_radix16(ABS(addend), ibuf));
|
||||
} else {
|
||||
p = stpcpy(p, "UNKNOWN");
|
||||
}
|
||||
*p++ = '\n';
|
||||
__print(buf, p - buf);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -17,11 +17,11 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/conv/itoa.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/runtime/missioncritical.h"
|
||||
|
||||
/**
|
||||
* Handles failure of CHECK_xx() macros in -DNDEBUG mode.
|
||||
|
@ -35,8 +35,17 @@
|
|||
*/
|
||||
relegated void ___check_fail_ndebug(uint64_t want, uint64_t got,
|
||||
const char *opchar) {
|
||||
int lasterr = errno;
|
||||
char bx[21];
|
||||
int lasterr;
|
||||
lasterr = errno;
|
||||
startfatal_ndebug();
|
||||
fprintf(stderr, "%s: %#lx %s %#lx (%s)\n", "check failed", want, opchar, got,
|
||||
strerror(lasterr));
|
||||
__print_string("check failed: 0x");
|
||||
__print(bx, uint64toarray_radix16(want, bx));
|
||||
__print_string(" ");
|
||||
__print_string(opchar);
|
||||
__print_string(" 0x");
|
||||
__print(bx, uint64toarray_radix16(got, bx));
|
||||
__print_string(" (");
|
||||
__print(bx, int64toarray_radix10(lasterr, bx));
|
||||
__print_string(")\n");
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/ok.h"
|
||||
|
||||
|
@ -31,12 +32,12 @@ nodiscard char *commandvenv(const char *var, const char *cmd) {
|
|||
char pathbuf[PATH_MAX];
|
||||
if ((exepath = getenv(var))) {
|
||||
if (!isempty(exepath) && access(exepath, X_OK) != -1) {
|
||||
return exepath;
|
||||
return strdup(exepath);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
} else if ((exepath = commandv(cmd, pathbuf))) {
|
||||
return exepath;
|
||||
return strdup(exepath);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
STATIC_YOINK("ntoa");
|
||||
|
||||
void malloc_stats(void) {
|
||||
struct MallocStats res = dlmalloc_stats(gm);
|
||||
struct MallocStats res = dlmalloc_stats(g_dlmalloc);
|
||||
(fprintf)(stderr, "max system bytes = %'10zu\n", res.maxfp);
|
||||
(fprintf)(stderr, "system bytes = %'10zu\n", res.fp);
|
||||
(fprintf)(stderr, "in use bytes = %'10zu\n", res.used);
|
||||
|
|
|
@ -27,64 +27,6 @@
|
|||
/ since ASAN has the same stylistic hugeness as UBSAN.
|
||||
/ We also guard all the functions, against reentrancy.
|
||||
|
||||
__asan_load1:
|
||||
push $1
|
||||
jmp OnLoad
|
||||
.endfn __asan_load1,globl
|
||||
__asan_load2:
|
||||
push $2
|
||||
jmp OnLoad
|
||||
.endfn __asan_load2,globl
|
||||
__asan_load4:
|
||||
push $4
|
||||
jmp OnLoad
|
||||
.endfn __asan_load4,globl
|
||||
__asan_load8:
|
||||
push $8
|
||||
jmp OnLoad
|
||||
.endfn __asan_load8,globl
|
||||
__asan_load16:
|
||||
push $16
|
||||
jmp OnLoad
|
||||
.endfn __asan_load16,globl
|
||||
__asan_load32:
|
||||
push $32
|
||||
/ 𝑠𝑙𝑖𝑑𝑒
|
||||
.endfn __asan_load32,globl
|
||||
OnLoad: pop %rsi
|
||||
ezlea __asan_loadN,ax
|
||||
jmp __asan_report_noreentry
|
||||
.endfn OnStore
|
||||
|
||||
__asan_store1:
|
||||
push $1
|
||||
jmp OnStore
|
||||
.endfn __asan_store1,globl
|
||||
__asan_store2:
|
||||
push $2
|
||||
jmp OnStore
|
||||
.endfn __asan_store2,globl
|
||||
__asan_store4:
|
||||
push $4
|
||||
jmp OnStore
|
||||
.endfn __asan_store4,globl
|
||||
__asan_store8:
|
||||
push $8
|
||||
jmp OnStore
|
||||
.endfn __asan_store8,globl
|
||||
__asan_store16:
|
||||
push $16
|
||||
jmp OnStore
|
||||
.endfn __asan_store16,globl
|
||||
__asan_store32:
|
||||
push $32
|
||||
/ 𝑠𝑙𝑖𝑑𝑒
|
||||
.endfn __asan_store32,globl
|
||||
OnStore:pop %rsi
|
||||
ezlea __asan_storeN,ax
|
||||
jmp __asan_report_noreentry
|
||||
.endfn OnStore
|
||||
|
||||
__asan_report_load1:
|
||||
push $1
|
||||
jmp OnReportLoad
|
||||
|
@ -264,10 +206,6 @@ __asan_after_dynamic_init:
|
|||
ret
|
||||
.endfn __asan_after_dynamic_init,globl
|
||||
|
||||
__asan_unregister_globals:
|
||||
ret
|
||||
.endfn __asan_unregister_globals,globl
|
||||
|
||||
__asan_version_mismatch_check_v8:
|
||||
ret
|
||||
.endfn __asan_version_mismatch_check_v8,globl
|
||||
|
@ -287,7 +225,7 @@ __asan_version_mismatch_check_v8:
|
|||
|
||||
.rodata.cst4
|
||||
__asan_option_detect_stack_use_after_return:
|
||||
.long 1
|
||||
.long 0
|
||||
.endobj __asan_option_detect_stack_use_after_return,globl
|
||||
.previous
|
||||
|
||||
|
|
|
@ -17,10 +17,8 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/missioncritical.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/calls/calls.h"
|
||||
|
||||
/**
|
||||
* Prints initial part of fatal message.
|
||||
|
@ -31,7 +29,7 @@
|
|||
relegated void startfatal_ndebug(void) {
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
stderr->bufmode = _IOFBF;
|
||||
fprintf(stderr, "%s%s%s:%s%s: ", RED, "error", BLUE1, program_invocation_name,
|
||||
RESET);
|
||||
__print_string("error:");
|
||||
__print_string(program_invocation_name);
|
||||
__print_string(": ");
|
||||
}
|
||||
|
|
|
@ -32,17 +32,18 @@
|
|||
|
||||
static char __ubsan_buf[256];
|
||||
|
||||
static const char kUbsanTypeCheckKinds[] = "load of\0"
|
||||
"store to\0"
|
||||
"reference binding to\0"
|
||||
"member access within\0"
|
||||
"member call on\0"
|
||||
"constructor call on\0"
|
||||
"downcast of\0"
|
||||
"downcast of\0"
|
||||
"upcast of\0"
|
||||
"cast to virtual base of\0"
|
||||
"\0";
|
||||
static const char kUbsanTypeCheckKinds[] = "\
|
||||
load of\0\
|
||||
store to\0\
|
||||
reference binding to\0\
|
||||
member access within\0\
|
||||
member call on\0\
|
||||
constructor call on\0\
|
||||
downcast of\0\
|
||||
downcast of\0\
|
||||
upcast of\0\
|
||||
cast to virtual base of\0\
|
||||
\0";
|
||||
|
||||
void __ubsan_abort(const struct UbsanSourceLocation *loc,
|
||||
const char *description) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue