2021-02-01 11:33:13 +00:00
|
|
|
|
/*-*- 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. │
|
|
|
|
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
2021-03-01 07:42:35 +00:00
|
|
|
|
#include "libc/alg/reverse.internal.h"
|
2021-10-14 00:27:13 +00:00
|
|
|
|
#include "libc/assert.h"
|
2021-02-01 11:33:13 +00:00
|
|
|
|
#include "libc/bits/bits.h"
|
2021-02-03 23:53:33 +00:00
|
|
|
|
#include "libc/bits/likely.h"
|
2021-02-01 11:33:13 +00:00
|
|
|
|
#include "libc/bits/weaken.h"
|
|
|
|
|
#include "libc/calls/calls.h"
|
2022-03-16 20:33:13 +00:00
|
|
|
|
#include "libc/calls/internal.h"
|
Introduce --strace flag for system call tracing
This is similar to the --ftrace (c function call trace) flag, except
it's less noisy since it only logs system calls to stderr. Having this
flag is valuable because (1) system call tracing tells us a lot about
the behavior of complex programs and (2) it's usually very hard to get
system call tracing on various operating systems, e.g. strace, ktrace,
dtruss, truss, nttrace, etc. Especially on Apple platforms where even
with the special boot trick, debuggers still aren't guaranteed to work.
make -j8 o//examples
o//examples/hello.com --strace
This is enabled by default in MODE=, MODE=opt, and MODE=dbg. In MODE=dbg
extra information will be printed.
make -j8 MODE=dbg o/dbg/examples
o/dbg/examples/hello.com --strace |& less
This change also changes:
- Rename IsText() → _istext()
- Rename IsUtf8() → _isutf8()
- Fix madvise() on Windows NT
- Fix empty string case of inet_ntop()
- vfork() wrapper now saves and restores errno
- Update xsigaction() to yoink syscall support
2022-03-19 01:07:28 +00:00
|
|
|
|
#include "libc/calls/strace.internal.h"
|
2021-05-14 12:36:58 +00:00
|
|
|
|
#include "libc/calls/struct/iovec.h"
|
2021-02-03 14:22:51 +00:00
|
|
|
|
#include "libc/dce.h"
|
2021-02-01 11:33:13 +00:00
|
|
|
|
#include "libc/intrin/asan.internal.h"
|
2022-03-23 04:04:08 +00:00
|
|
|
|
#include "libc/intrin/asancodes.h"
|
2022-03-16 20:33:13 +00:00
|
|
|
|
#include "libc/intrin/kprintf.h"
|
2021-10-14 00:27:13 +00:00
|
|
|
|
#include "libc/log/backtrace.internal.h"
|
|
|
|
|
#include "libc/log/internal.h"
|
2021-09-28 05:58:51 +00:00
|
|
|
|
#include "libc/log/libfatal.internal.h"
|
2021-02-01 11:33:13 +00:00
|
|
|
|
#include "libc/log/log.h"
|
2021-03-01 07:42:35 +00:00
|
|
|
|
#include "libc/macros.internal.h"
|
2021-02-06 08:24:35 +00:00
|
|
|
|
#include "libc/mem/hook/hook.internal.h"
|
2021-10-14 00:27:13 +00:00
|
|
|
|
#include "libc/nexgen32e/gc.internal.h"
|
|
|
|
|
#include "libc/nexgen32e/stackframe.h"
|
2021-02-03 14:22:51 +00:00
|
|
|
|
#include "libc/nt/enum/version.h"
|
|
|
|
|
#include "libc/nt/runtime.h"
|
2021-02-24 04:23:19 +00:00
|
|
|
|
#include "libc/runtime/directmap.internal.h"
|
2022-03-23 13:31:55 +00:00
|
|
|
|
#include "libc/runtime/internal.h"
|
2021-09-04 20:20:47 +00:00
|
|
|
|
#include "libc/runtime/memtrack.internal.h"
|
2021-02-01 11:33:13 +00:00
|
|
|
|
#include "libc/runtime/runtime.h"
|
2021-10-14 00:27:13 +00:00
|
|
|
|
#include "libc/runtime/symbols.internal.h"
|
2021-09-28 05:58:51 +00:00
|
|
|
|
#include "libc/str/str.h"
|
|
|
|
|
#include "libc/str/tpenc.h"
|
2021-02-01 11:33:13 +00:00
|
|
|
|
#include "libc/sysv/consts/auxv.h"
|
|
|
|
|
#include "libc/sysv/consts/map.h"
|
2021-02-03 14:22:51 +00:00
|
|
|
|
#include "libc/sysv/consts/nr.h"
|
2021-02-01 11:33:13 +00:00
|
|
|
|
#include "libc/sysv/consts/prot.h"
|
2021-10-14 00:27:13 +00:00
|
|
|
|
#include "libc/sysv/errfuns.h"
|
2021-02-01 11:33:13 +00:00
|
|
|
|
#include "third_party/dlmalloc/dlmalloc.internal.h"
|
|
|
|
|
|
|
|
|
|
STATIC_YOINK("_init_asan");
|
|
|
|
|
|
2022-03-18 09:33:37 +00:00
|
|
|
|
#define ASAN_MORGUE_ITEMS 512
|
|
|
|
|
#define ASAN_MORGUE_THRESHOLD 65536 // morgue memory O(ITEMS*THRESHOLD)
|
|
|
|
|
#define ASAN_TRACE_ITEMS 16 // backtrace limit on malloc origin
|
|
|
|
|
|
2021-02-01 11:33:13 +00:00
|
|
|
|
/**
|
|
|
|
|
* @fileoverview Cosmopolitan Address Sanitizer Runtime.
|
|
|
|
|
*
|
|
|
|
|
* Someone brilliant at Google figured out a way to improve upon memory
|
|
|
|
|
* protection. Rather than invent another Java or Rust they changed GCC
|
|
|
|
|
* so it can emit fast code, that checks the validity of each memory op
|
|
|
|
|
* with byte granularity, by probing shadow memory.
|
|
|
|
|
*
|
|
|
|
|
* - AddressSanitizer dedicates one-eighth of the virtual address space
|
|
|
|
|
* to its shadow memory and uses a direct mapping with a scale and
|
|
|
|
|
* offset to translate an application address to its corresponding
|
|
|
|
|
* shadow address. Given the application memory address Addr, the
|
|
|
|
|
* address of the shadow byte is computed as (Addr>>3)+Offset."
|
|
|
|
|
*
|
|
|
|
|
* - We use the following encoding for each shadow byte: 0 means that
|
|
|
|
|
* all 8 bytes of the corresponding application memory region are
|
|
|
|
|
* addressable; k (1 ≤ k ≤ 7) means that the first k bytes are
|
|
|
|
|
* addressible; any negative value indicates that the entire 8-byte
|
|
|
|
|
* word is unaddressable. We use different negative values to
|
|
|
|
|
* distinguish between different kinds of unaddressable memory (heap
|
|
|
|
|
* redzones, stack redzones, global redzones, freed memory).
|
|
|
|
|
*
|
|
|
|
|
* Here's what the generated code looks like for 64-bit reads:
|
|
|
|
|
*
|
|
|
|
|
* movq %addr,%tmp
|
|
|
|
|
* shrq $3,%tmp
|
|
|
|
|
* cmpb $0,0x7fff8000(%tmp)
|
|
|
|
|
* jnz abort
|
|
|
|
|
* movq (%addr),%dst
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#define HOOK(HOOK, IMPL) \
|
|
|
|
|
do { \
|
|
|
|
|
if (weaken(HOOK)) { \
|
|
|
|
|
*weaken(HOOK) = IMPL; \
|
|
|
|
|
} \
|
|
|
|
|
} while (0)
|
|
|
|
|
|
2022-03-16 20:33:13 +00:00
|
|
|
|
#define REQUIRE(FUNC) \
|
|
|
|
|
do { \
|
|
|
|
|
if (!weaken(FUNC)) { \
|
|
|
|
|
kprintf("error: asan needs %s%n", #FUNC); \
|
|
|
|
|
__asan_die()(); \
|
|
|
|
|
__asan_unreachable(); \
|
|
|
|
|
} \
|
2021-02-01 11:33:13 +00:00
|
|
|
|
} while (0)
|
|
|
|
|
|
2021-09-28 05:58:51 +00:00
|
|
|
|
typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(1)));
|
|
|
|
|
|
2021-10-14 00:27:13 +00:00
|
|
|
|
struct AsanTrace {
|
2022-03-18 09:33:37 +00:00
|
|
|
|
uint32_t p[ASAN_TRACE_ITEMS]; // assumes linkage into 32-bit space
|
2021-10-14 00:27:13 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct AsanExtra {
|
|
|
|
|
uint64_t size;
|
|
|
|
|
struct AsanTrace bt;
|
|
|
|
|
};
|
|
|
|
|
|
2021-02-01 11:33:13 +00:00
|
|
|
|
struct AsanSourceLocation {
|
|
|
|
|
const char *filename;
|
|
|
|
|
int line;
|
|
|
|
|
int column;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct AsanAccessInfo {
|
|
|
|
|
const uintptr_t addr;
|
|
|
|
|
const uintptr_t first_bad_addr;
|
|
|
|
|
size_t size;
|
|
|
|
|
bool iswrite;
|
|
|
|
|
unsigned long ip;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct AsanGlobal {
|
|
|
|
|
const uintptr_t addr;
|
|
|
|
|
size_t size;
|
|
|
|
|
size_t size_with_redzone;
|
|
|
|
|
const void *name;
|
|
|
|
|
const void *module_name;
|
|
|
|
|
unsigned long has_cxx_init;
|
|
|
|
|
struct AsanSourceLocation *location;
|
|
|
|
|
char *odr_indicator;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct AsanMorgue {
|
|
|
|
|
unsigned i;
|
2022-03-18 09:33:37 +00:00
|
|
|
|
void *p[ASAN_MORGUE_ITEMS];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct ReportOriginHeap {
|
|
|
|
|
const unsigned char *a;
|
|
|
|
|
int z;
|
2021-02-01 11:33:13 +00:00
|
|
|
|
};
|
|
|
|
|
|
2021-10-14 00:27:13 +00:00
|
|
|
|
bool __asan_noreentry;
|
2022-03-16 20:33:13 +00:00
|
|
|
|
extern bool __nomultics;
|
2021-02-01 11:33:13 +00:00
|
|
|
|
static struct AsanMorgue __asan_morgue;
|
|
|
|
|
|
2021-10-14 00:27:13 +00:00
|
|
|
|
static wontreturn void __asan_unreachable(void) {
|
|
|
|
|
for (;;) __builtin_trap();
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-10-14 00:27:13 +00:00
|
|
|
|
static int __asan_bsf(uint64_t x) {
|
|
|
|
|
_Static_assert(sizeof(long long) == sizeof(uint64_t), "");
|
|
|
|
|
return __builtin_ctzll(x);
|
2021-09-28 05:58:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-10-14 00:27:13 +00:00
|
|
|
|
static int __asan_bsr(uint64_t x) {
|
|
|
|
|
_Static_assert(sizeof(long long) == sizeof(uint64_t), "");
|
|
|
|
|
return __builtin_clzll(x) ^ 63;
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-10-14 00:27:13 +00:00
|
|
|
|
static uint64_t __asan_roundup2pow(uint64_t x) {
|
|
|
|
|
return 2ull << __asan_bsr(x - 1);
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-10-14 00:27:13 +00:00
|
|
|
|
static char *__asan_utf8cpy(char *p, unsigned c) {
|
|
|
|
|
uint64_t z;
|
|
|
|
|
z = tpenc(c);
|
|
|
|
|
do *p++ = z;
|
|
|
|
|
while ((z >>= 8));
|
|
|
|
|
return p;
|
2021-02-02 11:45:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-10-14 00:27:13 +00:00
|
|
|
|
static void *__asan_memset(void *p, char c, size_t n) {
|
2021-02-01 11:33:13 +00:00
|
|
|
|
char *b;
|
|
|
|
|
size_t i;
|
|
|
|
|
uint64_t x;
|
|
|
|
|
b = p;
|
2021-05-16 18:16:28 +00:00
|
|
|
|
x = 0x0101010101010101ul * (c & 255);
|
2021-02-01 11:33:13 +00:00
|
|
|
|
switch (n) {
|
|
|
|
|
case 0:
|
|
|
|
|
return p;
|
|
|
|
|
case 1:
|
|
|
|
|
__builtin_memcpy(b, &x, 1);
|
|
|
|
|
return p;
|
|
|
|
|
case 2:
|
|
|
|
|
__builtin_memcpy(b, &x, 2);
|
|
|
|
|
return p;
|
|
|
|
|
case 3:
|
|
|
|
|
__builtin_memcpy(b, &x, 2);
|
|
|
|
|
__builtin_memcpy(b + 1, &x, 2);
|
|
|
|
|
return p;
|
|
|
|
|
case 4:
|
|
|
|
|
__builtin_memcpy(b, &x, 4);
|
|
|
|
|
return p;
|
|
|
|
|
case 5:
|
|
|
|
|
case 6:
|
|
|
|
|
case 7:
|
|
|
|
|
__builtin_memcpy(b, &x, 4);
|
|
|
|
|
__builtin_memcpy(b + n - 4, &x, 4);
|
|
|
|
|
return p;
|
|
|
|
|
case 8:
|
|
|
|
|
__builtin_memcpy(b, &x, 8);
|
|
|
|
|
return p;
|
|
|
|
|
case 9:
|
|
|
|
|
case 10:
|
|
|
|
|
case 11:
|
|
|
|
|
case 12:
|
|
|
|
|
case 13:
|
|
|
|
|
case 14:
|
|
|
|
|
case 15:
|
|
|
|
|
case 16:
|
|
|
|
|
__builtin_memcpy(b, &x, 8);
|
|
|
|
|
__builtin_memcpy(b + n - 8, &x, 8);
|
|
|
|
|
return p;
|
|
|
|
|
default:
|
|
|
|
|
if (n <= 64) {
|
|
|
|
|
i = 0;
|
|
|
|
|
do {
|
|
|
|
|
__builtin_memcpy(b + i, &x, 8);
|
|
|
|
|
asm volatile("" ::: "memory");
|
|
|
|
|
__builtin_memcpy(b + i + 8, &x, 8);
|
|
|
|
|
} while ((i += 16) + 16 <= n);
|
|
|
|
|
for (; i < n; ++i) b[i] = x;
|
|
|
|
|
} else {
|
2021-10-14 00:27:13 +00:00
|
|
|
|
__repstosb(p, c, n);
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void *__asan_mempcpy(void *dst, const void *src, size_t n) {
|
|
|
|
|
size_t i;
|
2022-03-16 20:33:13 +00:00
|
|
|
|
char *d;
|
|
|
|
|
const char *s;
|
2021-02-01 11:33:13 +00:00
|
|
|
|
uint64_t a, b;
|
|
|
|
|
d = dst;
|
|
|
|
|
s = src;
|
|
|
|
|
switch (n) {
|
|
|
|
|
case 0:
|
|
|
|
|
return d;
|
|
|
|
|
case 1:
|
|
|
|
|
*d = *s;
|
|
|
|
|
return d + 1;
|
|
|
|
|
case 2:
|
|
|
|
|
__builtin_memcpy(&a, s, 2);
|
|
|
|
|
__builtin_memcpy(d, &a, 2);
|
|
|
|
|
return d + 2;
|
|
|
|
|
case 3:
|
|
|
|
|
__builtin_memcpy(&a, s, 2);
|
|
|
|
|
__builtin_memcpy(&b, s + 1, 2);
|
|
|
|
|
__builtin_memcpy(d, &a, 2);
|
|
|
|
|
__builtin_memcpy(d + 1, &b, 2);
|
|
|
|
|
return d + 3;
|
|
|
|
|
case 4:
|
|
|
|
|
__builtin_memcpy(&a, s, 4);
|
|
|
|
|
__builtin_memcpy(d, &a, 4);
|
|
|
|
|
return d + 4;
|
|
|
|
|
case 5:
|
|
|
|
|
case 6:
|
|
|
|
|
case 7:
|
|
|
|
|
__builtin_memcpy(&a, s, 4);
|
|
|
|
|
__builtin_memcpy(&b, s + n - 4, 4);
|
|
|
|
|
__builtin_memcpy(d, &a, 4);
|
|
|
|
|
__builtin_memcpy(d + n - 4, &b, 4);
|
|
|
|
|
return d + n;
|
|
|
|
|
case 8:
|
|
|
|
|
__builtin_memcpy(&a, s, 8);
|
|
|
|
|
__builtin_memcpy(d, &a, 8);
|
|
|
|
|
return d + 8;
|
|
|
|
|
case 9:
|
|
|
|
|
case 10:
|
|
|
|
|
case 11:
|
|
|
|
|
case 12:
|
|
|
|
|
case 13:
|
|
|
|
|
case 14:
|
|
|
|
|
case 15:
|
|
|
|
|
case 16:
|
|
|
|
|
__builtin_memcpy(&a, s, 8);
|
|
|
|
|
__builtin_memcpy(&b, s + n - 8, 8);
|
|
|
|
|
__builtin_memcpy(d, &a, 8);
|
|
|
|
|
__builtin_memcpy(d + n - 8, &b, 8);
|
|
|
|
|
return d + n;
|
|
|
|
|
default:
|
2021-02-02 11:45:31 +00:00
|
|
|
|
if (n <= 64) {
|
|
|
|
|
i = 0;
|
|
|
|
|
do {
|
|
|
|
|
__builtin_memcpy(&a, s + i, 8);
|
|
|
|
|
asm volatile("" ::: "memory");
|
|
|
|
|
__builtin_memcpy(d + i, &a, 8);
|
|
|
|
|
} while ((i += 8) + 8 <= n);
|
|
|
|
|
for (; i < n; ++i) d[i] = s[i];
|
|
|
|
|
return d + i;
|
|
|
|
|
} else {
|
2021-10-14 00:27:13 +00:00
|
|
|
|
return __repmovsb(d, s, n);
|
2021-02-02 11:45:31 +00:00
|
|
|
|
}
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void *__asan_memcpy(void *dst, const void *src, size_t n) {
|
|
|
|
|
__asan_mempcpy(dst, src, n);
|
|
|
|
|
return dst;
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-14 12:36:58 +00:00
|
|
|
|
static char *__asan_hexcpy(char *p, uint64_t x, uint8_t k) {
|
|
|
|
|
while (k) *p++ = "0123456789abcdef"[(x >> (k -= 4)) & 15];
|
|
|
|
|
return p;
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-10-14 00:27:13 +00:00
|
|
|
|
static void __asan_exit(void) {
|
2022-03-16 20:33:13 +00:00
|
|
|
|
kprintf("your asan runtime needs%n"
|
|
|
|
|
"\tSTATIC_YOINK(\"__die\");%n"
|
|
|
|
|
"in order to show you backtraces%n");
|
2022-03-23 13:31:55 +00:00
|
|
|
|
__restorewintty();
|
2021-10-14 00:27:13 +00:00
|
|
|
|
_Exit(99);
|
2021-09-28 05:58:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
Import C++ Standard Template Library
You can now use the hardest fastest and most dangerous language there is
with Cosmopolitan. So far about 75% of LLVM libcxx has been added. A few
breaking changes needed to be made to help this go smoothly.
- Rename nothrow to dontthrow
- Rename nodiscard to dontdiscard
- Add some libm functions, e.g. lgamma, nan, etc.
- Change intmax_t from int128 to int64 like everything else
- Introduce %jjd formatting directive for int128_t
- Introduce strtoi128(), strtou128(), etc.
- Rename bsrmax() to bsr128()
Some of the templates that should be working currently are std::vector,
std::string, std::map, std::set, std::deque, etc.
2022-03-22 12:51:41 +00:00
|
|
|
|
dontdiscard static __asan_die_f *__asan_die(void) {
|
2021-10-02 15:17:04 +00:00
|
|
|
|
if (weaken(__die)) {
|
2021-10-14 00:27:13 +00:00
|
|
|
|
return weaken(__die);
|
2021-10-02 15:17:04 +00:00
|
|
|
|
} else {
|
2021-10-14 00:27:13 +00:00
|
|
|
|
return __asan_exit;
|
2021-10-02 15:17:04 +00:00
|
|
|
|
}
|
2021-05-14 12:36:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-10-14 00:27:13 +00:00
|
|
|
|
void __asan_poison(long p, long n, signed char t) {
|
2021-05-14 12:36:58 +00:00
|
|
|
|
signed char k, *s;
|
|
|
|
|
s = (signed char *)((p >> 3) + 0x7fff8000);
|
2021-10-14 00:27:13 +00:00
|
|
|
|
if ((k = p & 7)) {
|
|
|
|
|
if ((!*s && n >= 8 - k) || *s > k) *s = k;
|
2021-09-28 05:58:51 +00:00
|
|
|
|
n -= MIN(8 - k, n);
|
|
|
|
|
s += 1;
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
2021-05-14 12:36:58 +00:00
|
|
|
|
__asan_memset(s, t, n >> 3);
|
2021-02-01 11:33:13 +00:00
|
|
|
|
if ((k = n & 7)) {
|
2021-05-14 12:36:58 +00:00
|
|
|
|
s += n >> 3;
|
2021-10-14 00:27:13 +00:00
|
|
|
|
if (*s < 0 || (*s > 0 && *s <= k)) *s = t;
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-14 00:27:13 +00:00
|
|
|
|
void __asan_unpoison(long p, long n) {
|
2021-05-14 12:36:58 +00:00
|
|
|
|
signed char k, *s;
|
|
|
|
|
k = p & 7;
|
|
|
|
|
s = (signed char *)((p >> 3) + 0x7fff8000);
|
|
|
|
|
if (UNLIKELY(k)) {
|
2021-09-28 05:58:51 +00:00
|
|
|
|
if (k + n < 8) {
|
2021-10-14 00:27:13 +00:00
|
|
|
|
if (n > 0) *s = MAX(*s, k + n);
|
2021-09-28 05:58:51 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
n -= MIN(8 - k, n);
|
2021-10-14 00:27:13 +00:00
|
|
|
|
*s++ = 0;
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
2021-05-14 12:36:58 +00:00
|
|
|
|
__asan_memset(s, 0, n >> 3);
|
2021-02-01 11:33:13 +00:00
|
|
|
|
if ((k = n & 7)) {
|
2021-05-14 12:36:58 +00:00
|
|
|
|
s += n >> 3;
|
2021-10-14 00:27:13 +00:00
|
|
|
|
if (*s < 0) *s = k;
|
|
|
|
|
if (*s > 0) *s = MAX(*s, k);
|
2021-05-14 12:36:58 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-14 00:27:13 +00:00
|
|
|
|
static bool __asan_is_mapped(int x) {
|
2021-09-28 05:58:51 +00:00
|
|
|
|
int i;
|
|
|
|
|
struct MemoryIntervals *m;
|
|
|
|
|
m = weaken(_mmi);
|
|
|
|
|
i = FindMemoryInterval(m, x);
|
2022-03-16 20:33:13 +00:00
|
|
|
|
return i < m->i && x >= m->p[i].x;
|
2021-09-28 05:58:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-10-14 00:27:13 +00:00
|
|
|
|
static bool __asan_is_image(const unsigned char *p) {
|
2021-09-28 05:58:51 +00:00
|
|
|
|
return _base <= p && p < _end;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-14 00:27:13 +00:00
|
|
|
|
static bool __asan_exists(const void *x) {
|
2022-03-16 20:33:13 +00:00
|
|
|
|
return !kisdangerous(x);
|
2021-09-28 05:58:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-10-14 00:27:13 +00:00
|
|
|
|
static struct AsanFault __asan_fault(const signed char *s, signed char dflt) {
|
2021-09-28 05:58:51 +00:00
|
|
|
|
struct AsanFault r;
|
|
|
|
|
if (s[0] < 0) {
|
|
|
|
|
r.kind = s[0];
|
|
|
|
|
} else if (((uintptr_t)(s + 1) & (PAGESIZE - 1)) && s[1] < 0) {
|
|
|
|
|
r.kind = s[1];
|
|
|
|
|
} else {
|
|
|
|
|
r.kind = dflt;
|
|
|
|
|
}
|
|
|
|
|
r.shadow = s;
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-14 00:27:13 +00:00
|
|
|
|
static struct AsanFault __asan_checka(const signed char *s, long ndiv8) {
|
2021-09-28 05:58:51 +00:00
|
|
|
|
intptr_t a;
|
|
|
|
|
uint64_t w;
|
2022-03-16 20:33:13 +00:00
|
|
|
|
const signed char *e = s + ndiv8;
|
2021-10-14 00:27:13 +00:00
|
|
|
|
for (; ((intptr_t)s & 7) && s < e; ++s) {
|
|
|
|
|
if (*s) return __asan_fault(s - 1, kAsanHeapOverrun);
|
2021-09-28 05:58:51 +00:00
|
|
|
|
}
|
|
|
|
|
for (; s + 8 <= e; s += 8) {
|
|
|
|
|
if (UNLIKELY(!((a = (intptr_t)s) & 0xffff))) {
|
2022-03-16 20:33:13 +00:00
|
|
|
|
if (kisdangerous((void *)a)) {
|
2021-09-28 05:58:51 +00:00
|
|
|
|
return (struct AsanFault){kAsanUnmapped, s};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ((w = ((uint64_t)(255 & s[0]) << 000 | (uint64_t)(255 & s[1]) << 010 |
|
|
|
|
|
(uint64_t)(255 & s[2]) << 020 | (uint64_t)(255 & s[3]) << 030 |
|
|
|
|
|
(uint64_t)(255 & s[4]) << 040 | (uint64_t)(255 & s[5]) << 050 |
|
|
|
|
|
(uint64_t)(255 & s[6]) << 060 | (uint64_t)(255 & s[7]) << 070))) {
|
2021-10-14 00:27:13 +00:00
|
|
|
|
s += __asan_bsf(w) >> 3;
|
2021-09-28 05:58:51 +00:00
|
|
|
|
return __asan_fault(s, kAsanHeapOverrun);
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-10-14 00:27:13 +00:00
|
|
|
|
for (; s < e; ++s) {
|
|
|
|
|
if (*s) return __asan_fault(s - 1, kAsanHeapOverrun);
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
2021-10-14 00:27:13 +00:00
|
|
|
|
return (struct AsanFault){0};
|
2021-05-14 12:36:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-10-14 00:27:13 +00:00
|
|
|
|
/**
|
|
|
|
|
* Checks validity of memory range.
|
|
|
|
|
*
|
|
|
|
|
* Normally this is abstracted by the compiler.
|
|
|
|
|
*
|
|
|
|
|
* @param p is starting virtual address
|
|
|
|
|
* @param n is number of bytes to check
|
|
|
|
|
* @return kind is 0 on success or <0 on invalid
|
|
|
|
|
* @return shadow points to first poisoned shadow byte
|
|
|
|
|
* @note this takes 6 picoseconds per byte
|
|
|
|
|
*/
|
|
|
|
|
struct AsanFault __asan_check(const void *p, long n) {
|
|
|
|
|
intptr_t a;
|
2021-09-28 05:58:51 +00:00
|
|
|
|
struct AsanFault f;
|
2021-10-14 00:27:13 +00:00
|
|
|
|
signed char c, k, *s;
|
|
|
|
|
if (n > 0) {
|
|
|
|
|
k = (intptr_t)p & 7;
|
|
|
|
|
a = ((intptr_t)p >> 3) + 0x7fff8000;
|
|
|
|
|
s = (signed char *)a;
|
|
|
|
|
if (OverlapsShadowSpace(p, n)) {
|
|
|
|
|
return (struct AsanFault){kAsanProtected, s};
|
2022-03-16 20:33:13 +00:00
|
|
|
|
} else if (kisdangerous((void *)a)) {
|
2021-10-14 00:27:13 +00:00
|
|
|
|
return (struct AsanFault){kAsanUnmapped, s};
|
|
|
|
|
}
|
|
|
|
|
if (UNLIKELY(k)) {
|
|
|
|
|
if (!(c = *s)) {
|
|
|
|
|
n -= MIN(8 - k, n);
|
|
|
|
|
s += 1;
|
|
|
|
|
} else if (c > 0 && n < 8 && c >= k + n) {
|
|
|
|
|
return (struct AsanFault){0};
|
|
|
|
|
} else {
|
|
|
|
|
return __asan_fault(s, kAsanHeapOverrun);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
k = n & 7;
|
|
|
|
|
n >>= 3;
|
|
|
|
|
if ((f = __asan_checka(s, n)).kind) {
|
|
|
|
|
return f;
|
|
|
|
|
} else if (!k || !(c = s[n]) || k <= c) {
|
|
|
|
|
return (struct AsanFault){0};
|
|
|
|
|
} else {
|
|
|
|
|
return __asan_fault(s, kAsanHeapOverrun);
|
|
|
|
|
}
|
|
|
|
|
} else if (!n) {
|
|
|
|
|
return (struct AsanFault){0};
|
|
|
|
|
} else {
|
|
|
|
|
return (struct AsanFault){kAsanNullPage, 0};
|
2021-09-28 05:58:51 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-14 00:27:13 +00:00
|
|
|
|
bool __asan_is_valid(const void *p, long n) {
|
|
|
|
|
struct AsanFault f;
|
|
|
|
|
f = __asan_check(p, n);
|
|
|
|
|
return !f.kind;
|
2021-09-28 05:58:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-05-14 12:36:58 +00:00
|
|
|
|
bool __asan_is_valid_iov(const struct iovec *iov, int iovlen) {
|
|
|
|
|
int i;
|
|
|
|
|
size_t size;
|
|
|
|
|
if (iovlen >= 0 &&
|
|
|
|
|
!__builtin_mul_overflow(iovlen, sizeof(struct iovec), &size) &&
|
|
|
|
|
__asan_is_valid(iov, size)) {
|
|
|
|
|
for (i = 0; i < iovlen; ++i) {
|
|
|
|
|
if (!__asan_is_valid(iov[i].iov_base, iov[i].iov_len)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-08-22 22:02:18 +00:00
|
|
|
|
bool __asan_is_valid_strlist(char *const *p) {
|
|
|
|
|
for (;; ++p) {
|
|
|
|
|
if (!__asan_is_valid(p, sizeof(char *))) return false;
|
|
|
|
|
if (!*p) return true;
|
|
|
|
|
if (!__asan_is_valid(*p, 1)) return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-14 00:27:13 +00:00
|
|
|
|
wint_t __asan_symbolize_access_poison(signed char kind) {
|
2021-09-28 05:58:51 +00:00
|
|
|
|
switch (kind) {
|
2021-10-14 00:27:13 +00:00
|
|
|
|
case kAsanNullPage:
|
|
|
|
|
return L'∅';
|
|
|
|
|
case kAsanProtected:
|
|
|
|
|
return L'P';
|
2021-02-01 11:33:13 +00:00
|
|
|
|
case kAsanHeapFree:
|
2021-10-14 00:27:13 +00:00
|
|
|
|
return L'F';
|
|
|
|
|
case kAsanHeapRelocated:
|
|
|
|
|
return L'R';
|
|
|
|
|
case kAsanAllocaOverrun:
|
|
|
|
|
return L'𝑂';
|
|
|
|
|
case kAsanHeapUnderrun:
|
|
|
|
|
return L'U';
|
|
|
|
|
case kAsanHeapOverrun:
|
|
|
|
|
return L'O';
|
|
|
|
|
case kAsanStackUnscoped:
|
|
|
|
|
return L's';
|
|
|
|
|
case kAsanStackOverflow:
|
|
|
|
|
return L'!';
|
|
|
|
|
case kAsanGlobalOrder:
|
|
|
|
|
return L'I';
|
2021-02-01 11:33:13 +00:00
|
|
|
|
case kAsanStackFree:
|
2021-10-14 00:27:13 +00:00
|
|
|
|
return L'r';
|
|
|
|
|
case kAsanStackPartial:
|
|
|
|
|
return L'p';
|
|
|
|
|
case kAsanStackOverrun:
|
|
|
|
|
return L'o';
|
|
|
|
|
case kAsanStackMiddle:
|
|
|
|
|
return L'm';
|
|
|
|
|
case kAsanStackUnderrun:
|
|
|
|
|
return L'u';
|
|
|
|
|
case kAsanAllocaUnderrun:
|
|
|
|
|
return L'𝑈';
|
|
|
|
|
case kAsanUnmapped:
|
|
|
|
|
return L'M';
|
|
|
|
|
case kAsanGlobalRedzone:
|
|
|
|
|
return L'G';
|
|
|
|
|
case kAsanGlobalGone:
|
|
|
|
|
return L'𝐺';
|
2022-03-16 20:33:13 +00:00
|
|
|
|
case kAsanGlobalUnderrun:
|
|
|
|
|
return L'μ';
|
|
|
|
|
case kAsanGlobalOverrun:
|
|
|
|
|
return L'Ω';
|
2021-10-14 00:27:13 +00:00
|
|
|
|
default:
|
|
|
|
|
return L'?';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *__asan_describe_access_poison(signed char kind) {
|
|
|
|
|
switch (kind) {
|
|
|
|
|
case kAsanNullPage:
|
|
|
|
|
return "null pointer dereference";
|
|
|
|
|
case kAsanProtected:
|
|
|
|
|
return "protected";
|
|
|
|
|
case kAsanHeapFree:
|
|
|
|
|
return "heap use after free";
|
|
|
|
|
case kAsanHeapRelocated:
|
2021-02-01 11:33:13 +00:00
|
|
|
|
return "heap use after relocate";
|
2021-10-14 00:27:13 +00:00
|
|
|
|
case kAsanAllocaOverrun:
|
|
|
|
|
return "alloca overflow";
|
2021-02-01 11:33:13 +00:00
|
|
|
|
case kAsanHeapUnderrun:
|
|
|
|
|
return "heap underrun";
|
|
|
|
|
case kAsanHeapOverrun:
|
|
|
|
|
return "heap overrun";
|
2021-10-14 00:27:13 +00:00
|
|
|
|
case kAsanStackUnscoped:
|
|
|
|
|
return "stack use after scope";
|
|
|
|
|
case kAsanStackOverflow:
|
|
|
|
|
return "stack overflow";
|
|
|
|
|
case kAsanGlobalOrder:
|
|
|
|
|
return "global init order";
|
|
|
|
|
case kAsanStackFree:
|
|
|
|
|
return "stack use after return";
|
|
|
|
|
case kAsanStackPartial:
|
|
|
|
|
return "stack partial";
|
|
|
|
|
case kAsanStackOverrun:
|
|
|
|
|
return "stack overrun";
|
|
|
|
|
case kAsanStackMiddle:
|
|
|
|
|
return "stack middle";
|
2021-02-01 11:33:13 +00:00
|
|
|
|
case kAsanStackUnderrun:
|
|
|
|
|
return "stack underflow";
|
|
|
|
|
case kAsanAllocaUnderrun:
|
|
|
|
|
return "alloca underflow";
|
|
|
|
|
case kAsanUnmapped:
|
|
|
|
|
return "unmapped";
|
2021-10-14 00:27:13 +00:00
|
|
|
|
case kAsanGlobalRedzone:
|
|
|
|
|
return "global redzone";
|
|
|
|
|
case kAsanGlobalGone:
|
|
|
|
|
return "global gone";
|
2022-03-16 20:33:13 +00:00
|
|
|
|
case kAsanGlobalUnderrun:
|
|
|
|
|
return "global underrun";
|
|
|
|
|
case kAsanGlobalOverrun:
|
|
|
|
|
return "global overrun";
|
2021-02-01 11:33:13 +00:00
|
|
|
|
default:
|
|
|
|
|
return "poisoned";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
Import C++ Standard Template Library
You can now use the hardest fastest and most dangerous language there is
with Cosmopolitan. So far about 75% of LLVM libcxx has been added. A few
breaking changes needed to be made to help this go smoothly.
- Rename nothrow to dontthrow
- Rename nodiscard to dontdiscard
- Add some libm functions, e.g. lgamma, nan, etc.
- Change intmax_t from int128 to int64 like everything else
- Introduce %jjd formatting directive for int128_t
- Introduce strtoi128(), strtou128(), etc.
- Rename bsrmax() to bsr128()
Some of the templates that should be working currently are std::vector,
std::string, std::map, std::set, std::deque, etc.
2022-03-22 12:51:41 +00:00
|
|
|
|
dontdiscard static __asan_die_f *__asan_report_invalid_pointer(
|
|
|
|
|
const void *addr) {
|
2022-03-16 20:33:13 +00:00
|
|
|
|
kprintf("%n\e[J\e[1;31masan error\e[0m: this corruption at %p shadow %p%n",
|
|
|
|
|
addr, SHADOW(addr));
|
|
|
|
|
return __asan_die();
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-09-28 05:58:51 +00:00
|
|
|
|
static char *__asan_format_interval(char *p, intptr_t a, intptr_t b) {
|
2021-10-14 00:27:13 +00:00
|
|
|
|
p = __asan_hexcpy(p, a, 48), *p++ = '-';
|
2021-09-28 05:58:51 +00:00
|
|
|
|
p = __asan_hexcpy(p, b, 48);
|
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-16 20:33:13 +00:00
|
|
|
|
static char *__asan_format_section(char *p, const void *p1, const void *p2,
|
|
|
|
|
const char *name, const void *addr) {
|
2021-09-28 05:58:51 +00:00
|
|
|
|
intptr_t a, b;
|
|
|
|
|
if ((a = (intptr_t)p1) < (b = (intptr_t)p2)) {
|
2021-10-14 00:27:13 +00:00
|
|
|
|
p = __asan_format_interval(p, a, b), *p++ = ' ';
|
|
|
|
|
p = __stpcpy(p, name);
|
2021-09-28 05:58:51 +00:00
|
|
|
|
if (a <= (intptr_t)addr && (intptr_t)addr <= b) {
|
2021-10-14 00:27:13 +00:00
|
|
|
|
p = __stpcpy(p, " ←address");
|
2021-09-28 05:58:51 +00:00
|
|
|
|
}
|
2022-03-16 20:33:13 +00:00
|
|
|
|
if (__nomultics) *p++ = '\r';
|
|
|
|
|
*p++ = '\n';
|
2021-09-28 05:58:51 +00:00
|
|
|
|
}
|
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-17 07:53:45 +00:00
|
|
|
|
static void __asan_report_memory_origin_image(intptr_t a, int z) {
|
|
|
|
|
unsigned l, m, r, n, k;
|
|
|
|
|
struct SymbolTable *st;
|
|
|
|
|
kprintf("%nthe memory belongs to image symbols%n");
|
|
|
|
|
if (weaken(GetSymbolTable)) {
|
|
|
|
|
if ((st = weaken(GetSymbolTable)())) {
|
|
|
|
|
l = 0;
|
|
|
|
|
r = n = st->count;
|
|
|
|
|
k = a - st->addr_base;
|
|
|
|
|
while (l < r) {
|
|
|
|
|
m = (l + r) >> 1;
|
|
|
|
|
if (st->symbols[m].y < k) {
|
|
|
|
|
l = m + 1;
|
|
|
|
|
} else {
|
|
|
|
|
r = m;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (; l < n; ++l) {
|
|
|
|
|
if ((st->symbols[l].x <= k && k <= st->symbols[l].y) ||
|
|
|
|
|
(st->symbols[l].x <= k + z && k + z <= st->symbols[l].y) ||
|
|
|
|
|
(k < st->symbols[l].x && st->symbols[l].y < k + z)) {
|
|
|
|
|
kprintf("\t%s [%#x,%#x] size %'d%n", st->name_base + st->names[l],
|
|
|
|
|
st->addr_base + st->symbols[l].x,
|
|
|
|
|
st->addr_base + st->symbols[l].y,
|
|
|
|
|
st->symbols[l].y - st->symbols[l].x + 1);
|
|
|
|
|
} else {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
kprintf("\tunknown please supply .com.dbg symbols or set COMDBG%n");
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
kprintf("\tunknown please STATIC_YOINK(\"GetSymbolTable\");%n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static noasan void OnMemory(void *x, void *y, size_t n, void *a) {
|
|
|
|
|
const unsigned char *p = x;
|
|
|
|
|
struct ReportOriginHeap *t = a;
|
|
|
|
|
if ((p <= t->a && t->a < p + n) ||
|
|
|
|
|
(p <= t->a + t->z && t->a + t->z < p + n) ||
|
|
|
|
|
(t->a < p && p + n <= t->a + t->z)) {
|
|
|
|
|
kprintf("%p %,lu bytes [dlmalloc]", x, n);
|
|
|
|
|
__asan_print_trace(x);
|
|
|
|
|
kprintf("\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __asan_report_memory_origin_heap(const unsigned char *a, int z) {
|
|
|
|
|
struct ReportOriginHeap t;
|
|
|
|
|
kprintf("%nthe memory was allocated by%n");
|
|
|
|
|
if (weaken(malloc_inspect_all)) {
|
|
|
|
|
t.a = a;
|
|
|
|
|
t.z = z;
|
|
|
|
|
weaken(malloc_inspect_all)(OnMemory, &t);
|
|
|
|
|
} else {
|
|
|
|
|
kprintf("\tunknown please STATIC_YOINK(\"malloc_inspect_all\");%n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __asan_report_memory_origin(const unsigned char *addr, int size,
|
|
|
|
|
signed char kind) {
|
|
|
|
|
switch (kind) {
|
|
|
|
|
case kAsanStackOverrun:
|
|
|
|
|
case kAsanGlobalOverrun:
|
|
|
|
|
case kAsanAllocaOverrun:
|
|
|
|
|
case kAsanHeapOverrun:
|
|
|
|
|
addr -= 1;
|
|
|
|
|
size += 1;
|
|
|
|
|
break;
|
|
|
|
|
case kAsanHeapUnderrun:
|
|
|
|
|
case kAsanStackUnderrun:
|
|
|
|
|
case kAsanAllocaUnderrun:
|
|
|
|
|
case kAsanGlobalUnderrun:
|
|
|
|
|
size += 1;
|
|
|
|
|
break;
|
|
|
|
|
case kAsanGlobalRedzone:
|
|
|
|
|
addr -= 1;
|
|
|
|
|
size += 2;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (_base <= addr && addr < _end) {
|
|
|
|
|
__asan_report_memory_origin_image((intptr_t)addr, size);
|
|
|
|
|
} else if (IsAutoFrame((intptr_t)addr >> 16)) {
|
|
|
|
|
__asan_report_memory_origin_heap(addr, size);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
Import C++ Standard Template Library
You can now use the hardest fastest and most dangerous language there is
with Cosmopolitan. So far about 75% of LLVM libcxx has been added. A few
breaking changes needed to be made to help this go smoothly.
- Rename nothrow to dontthrow
- Rename nodiscard to dontdiscard
- Add some libm functions, e.g. lgamma, nan, etc.
- Change intmax_t from int128 to int64 like everything else
- Introduce %jjd formatting directive for int128_t
- Introduce strtoi128(), strtou128(), etc.
- Rename bsrmax() to bsr128()
Some of the templates that should be working currently are std::vector,
std::string, std::map, std::set, std::deque, etc.
2022-03-22 12:51:41 +00:00
|
|
|
|
dontdiscard static __asan_die_f *__asan_report(const void *addr, int size,
|
|
|
|
|
const char *message,
|
|
|
|
|
signed char kind) {
|
2022-03-16 20:33:13 +00:00
|
|
|
|
int i;
|
2021-09-28 05:58:51 +00:00
|
|
|
|
wint_t c;
|
|
|
|
|
signed char t;
|
|
|
|
|
uint64_t x, y, z;
|
|
|
|
|
char *p, *q, *base;
|
|
|
|
|
struct MemoryIntervals *m;
|
2022-03-18 09:33:37 +00:00
|
|
|
|
++g_ftrace;
|
2021-10-14 00:27:13 +00:00
|
|
|
|
p = __fatalbuf;
|
2022-03-16 20:33:13 +00:00
|
|
|
|
kprintf("%n\e[J\e[1;31masan error\e[0m: %s %d-byte %s at %p shadow %p%n%s%n",
|
|
|
|
|
__asan_describe_access_poison(kind), size, message, addr,
|
|
|
|
|
SHADOW(addr), __argv[0]);
|
2021-09-28 05:58:51 +00:00
|
|
|
|
if (0 < size && size < 80) {
|
|
|
|
|
base = (char *)addr - ((80 >> 1) - (size >> 1));
|
|
|
|
|
for (i = 0; i < 80; ++i) {
|
|
|
|
|
if ((char *)addr <= base + i && base + i < (char *)addr + size) {
|
|
|
|
|
if (__asan_is_valid(base + i, 1)) {
|
|
|
|
|
*p++ = '*';
|
|
|
|
|
} else {
|
|
|
|
|
*p++ = 'x';
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
*p++ = ' ';
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-03-16 20:33:13 +00:00
|
|
|
|
if (__nomultics) *p++ = '\r';
|
|
|
|
|
*p++ = '\n';
|
2021-09-28 05:58:51 +00:00
|
|
|
|
for (c = i = 0; i < 80; ++i) {
|
|
|
|
|
if (!(t = __asan_check(base + i, 1).kind)) {
|
2022-03-16 20:33:13 +00:00
|
|
|
|
if (c != 32) {
|
2021-10-14 00:27:13 +00:00
|
|
|
|
p = __stpcpy(p, "\e[32m");
|
2021-09-28 05:58:51 +00:00
|
|
|
|
c = 32;
|
|
|
|
|
}
|
|
|
|
|
*p++ = '.';
|
|
|
|
|
} else {
|
2022-03-16 20:33:13 +00:00
|
|
|
|
if (c != 31) {
|
2021-10-14 00:27:13 +00:00
|
|
|
|
p = __stpcpy(p, "\e[31m");
|
2021-09-28 05:58:51 +00:00
|
|
|
|
c = 31;
|
|
|
|
|
}
|
2021-10-14 00:27:13 +00:00
|
|
|
|
p = __asan_utf8cpy(p, __asan_symbolize_access_poison(t));
|
2021-09-28 05:58:51 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-03-16 20:33:13 +00:00
|
|
|
|
p = __stpcpy(p, "\e[39m");
|
|
|
|
|
if (__nomultics) *p++ = '\r';
|
|
|
|
|
*p++ = '\n';
|
2021-09-28 05:58:51 +00:00
|
|
|
|
for (i = 0; (intptr_t)(base + i) & 7; ++i) *p++ = ' ';
|
|
|
|
|
for (; i + 8 <= 80; i += 8) {
|
|
|
|
|
q = p + 8;
|
|
|
|
|
*p++ = '|';
|
|
|
|
|
z = ((intptr_t)(base + i) >> 3) + 0x7fff8000;
|
2022-03-16 20:33:13 +00:00
|
|
|
|
if (!kisdangerous((void *)z)) {
|
2021-10-14 00:27:13 +00:00
|
|
|
|
p = __intcpy(p, *(signed char *)z);
|
2021-09-28 05:58:51 +00:00
|
|
|
|
} else {
|
|
|
|
|
*p++ = '!';
|
|
|
|
|
}
|
|
|
|
|
while (p < q) {
|
|
|
|
|
*p++ = ' ';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (; i < 80; ++i) *p++ = ' ';
|
2022-03-16 20:33:13 +00:00
|
|
|
|
if (__nomultics) *p++ = '\r';
|
|
|
|
|
*p++ = '\n';
|
2021-09-28 05:58:51 +00:00
|
|
|
|
for (i = 0; i < 80; ++i) {
|
2021-10-14 00:27:13 +00:00
|
|
|
|
p = __asan_utf8cpy(p, __asan_exists(base + i)
|
|
|
|
|
? kCp437[((unsigned char *)base)[i]]
|
|
|
|
|
: L'⋅');
|
2021-09-28 05:58:51 +00:00
|
|
|
|
}
|
2022-03-16 20:33:13 +00:00
|
|
|
|
if (__nomultics) *p++ = '\r';
|
|
|
|
|
*p++ = '\n';
|
2021-09-28 05:58:51 +00:00
|
|
|
|
}
|
|
|
|
|
p = __asan_format_section(p, _base, _etext, ".text", addr);
|
|
|
|
|
p = __asan_format_section(p, _etext, _edata, ".data", addr);
|
|
|
|
|
p = __asan_format_section(p, _end, _edata, ".bss", addr);
|
|
|
|
|
for (m = weaken(_mmi), i = 0; i < m->i; ++i) {
|
|
|
|
|
x = m->p[i].x;
|
|
|
|
|
y = m->p[i].y;
|
|
|
|
|
p = __asan_format_interval(p, x << 16, (y << 16) + (FRAMESIZE - 1));
|
|
|
|
|
z = (intptr_t)addr >> 16;
|
2021-10-14 00:27:13 +00:00
|
|
|
|
if (x <= z && z <= y) p = __stpcpy(p, " ←address");
|
2021-09-28 05:58:51 +00:00
|
|
|
|
z = (((intptr_t)addr >> 3) + 0x7fff8000) >> 16;
|
2021-10-14 00:27:13 +00:00
|
|
|
|
if (x <= z && z <= y) p = __stpcpy(p, " ←shadow");
|
2022-03-16 20:33:13 +00:00
|
|
|
|
if (__nomultics) *p++ = '\r';
|
|
|
|
|
*p++ = '\n';
|
2021-09-28 05:58:51 +00:00
|
|
|
|
}
|
|
|
|
|
*p = 0;
|
2022-03-16 20:33:13 +00:00
|
|
|
|
kprintf("%s", __fatalbuf);
|
2022-03-17 07:53:45 +00:00
|
|
|
|
__asan_report_memory_origin(addr, size, kind);
|
|
|
|
|
kprintf("%nthe crash was caused by%n");
|
2022-03-18 09:33:37 +00:00
|
|
|
|
--g_ftrace;
|
2022-03-16 20:33:13 +00:00
|
|
|
|
return __asan_die();
|
2021-09-28 05:58:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-10-14 00:27:13 +00:00
|
|
|
|
void __asan_verify(const void *p, size_t n) {
|
|
|
|
|
const char *q;
|
|
|
|
|
struct AsanFault f;
|
|
|
|
|
if (!(f = __asan_check(p, n)).kind) return;
|
|
|
|
|
q = UNSHADOW(f.shadow);
|
|
|
|
|
if ((uintptr_t)q != ((uintptr_t)p & -8) && (uintptr_t)q - (uintptr_t)p < n) {
|
|
|
|
|
n -= (uintptr_t)q - (uintptr_t)p;
|
|
|
|
|
p = q;
|
|
|
|
|
}
|
|
|
|
|
__asan_report(p, n, "verify", f.kind)();
|
|
|
|
|
__asan_unreachable();
|
|
|
|
|
}
|
|
|
|
|
|
Import C++ Standard Template Library
You can now use the hardest fastest and most dangerous language there is
with Cosmopolitan. So far about 75% of LLVM libcxx has been added. A few
breaking changes needed to be made to help this go smoothly.
- Rename nothrow to dontthrow
- Rename nodiscard to dontdiscard
- Add some libm functions, e.g. lgamma, nan, etc.
- Change intmax_t from int128 to int64 like everything else
- Introduce %jjd formatting directive for int128_t
- Introduce strtoi128(), strtou128(), etc.
- Rename bsrmax() to bsr128()
Some of the templates that should be working currently are std::vector,
std::string, std::map, std::set, std::deque, etc.
2022-03-22 12:51:41 +00:00
|
|
|
|
dontdiscard __asan_die_f *__asan_report_memory_fault(void *addr, int size,
|
|
|
|
|
const char *message) {
|
2021-10-14 00:27:13 +00:00
|
|
|
|
return __asan_report(addr, size, message,
|
|
|
|
|
__asan_fault(SHADOW(addr), -128).kind);
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-03-16 20:33:13 +00:00
|
|
|
|
void *__asan_morgue_add(void *p) {
|
2021-02-01 11:33:13 +00:00
|
|
|
|
void *r;
|
2021-05-14 12:36:58 +00:00
|
|
|
|
int i, j;
|
2021-02-01 11:33:13 +00:00
|
|
|
|
for (;;) {
|
|
|
|
|
i = __asan_morgue.i;
|
|
|
|
|
j = (i + 1) & (ARRAYLEN(__asan_morgue.p) - 1);
|
|
|
|
|
if (cmpxchg(&__asan_morgue.i, i, j)) {
|
|
|
|
|
r = __asan_morgue.p[i];
|
|
|
|
|
__asan_morgue.p[i] = p;
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __asan_morgue_flush(void) {
|
2021-05-14 12:36:58 +00:00
|
|
|
|
int i;
|
2021-02-01 11:33:13 +00:00
|
|
|
|
void *p;
|
|
|
|
|
for (i = 0; i < ARRAYLEN(__asan_morgue.p); ++i) {
|
|
|
|
|
p = __asan_morgue.p[i];
|
2021-10-14 00:27:13 +00:00
|
|
|
|
if (cmpxchg(__asan_morgue.p + i, p, 0)) {
|
2021-02-01 11:33:13 +00:00
|
|
|
|
if (weaken(dlfree)) {
|
|
|
|
|
weaken(dlfree)(p);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-28 05:58:51 +00:00
|
|
|
|
static size_t __asan_user_size(size_t n) {
|
|
|
|
|
if (n) {
|
|
|
|
|
return n;
|
|
|
|
|
} else {
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-14 00:27:13 +00:00
|
|
|
|
static size_t __asan_heap_size(size_t n) {
|
|
|
|
|
if (n < 0x7fffffff0000) {
|
|
|
|
|
n = ROUNDUP(n, alignof(struct AsanExtra));
|
|
|
|
|
return __asan_roundup2pow(n + sizeof(struct AsanExtra));
|
2021-09-28 05:58:51 +00:00
|
|
|
|
} else {
|
2021-10-14 00:27:13 +00:00
|
|
|
|
return -1;
|
2021-09-28 05:58:51 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-14 00:27:13 +00:00
|
|
|
|
static void __asan_write48(uint64_t *value, uint64_t x) {
|
|
|
|
|
uint64_t cookie;
|
|
|
|
|
cookie = 'J' | 'T' << 8;
|
2021-09-28 05:58:51 +00:00
|
|
|
|
cookie ^= x & 0xffff;
|
2021-10-14 00:27:13 +00:00
|
|
|
|
*value = (x & 0xffffffffffff) | cookie << 48;
|
2021-09-28 05:58:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-10-14 00:27:13 +00:00
|
|
|
|
static bool __asan_read48(uint64_t value, uint64_t *x) {
|
|
|
|
|
uint64_t cookie;
|
2021-09-28 05:58:51 +00:00
|
|
|
|
cookie = value >> 48;
|
|
|
|
|
cookie ^= value & 0xffff;
|
|
|
|
|
*x = (int64_t)(value << 16) >> 16;
|
2021-10-14 00:27:13 +00:00
|
|
|
|
return cookie == ('J' | 'T' << 8);
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-16 20:33:13 +00:00
|
|
|
|
static void __asan_rawtrace(struct AsanTrace *bt, const struct StackFrame *bp) {
|
|
|
|
|
size_t i;
|
|
|
|
|
for (i = 0; bp && i < ARRAYLEN(bt->p); ++i, bp = bp->next) {
|
|
|
|
|
if (kisdangerous(bp)) break;
|
|
|
|
|
bt->p[i] = bp->addr;
|
|
|
|
|
}
|
|
|
|
|
for (; i < ARRAYLEN(bt->p); ++i) {
|
|
|
|
|
bt->p[i] = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-14 00:27:13 +00:00
|
|
|
|
static void __asan_trace(struct AsanTrace *bt, const struct StackFrame *bp) {
|
|
|
|
|
int f1, f2;
|
|
|
|
|
size_t i, gi;
|
|
|
|
|
intptr_t addr;
|
|
|
|
|
struct Garbages *garbage;
|
|
|
|
|
garbage = weaken(__garbage);
|
|
|
|
|
gi = garbage ? garbage->i : 0;
|
|
|
|
|
for (f1 = -1, i = 0; bp && i < ARRAYLEN(bt->p); ++i, bp = bp->next) {
|
|
|
|
|
if (f1 != (f2 = ((intptr_t)bp >> 16))) {
|
2022-03-16 20:33:13 +00:00
|
|
|
|
if (kisdangerous(bp)) break;
|
2021-10-14 00:27:13 +00:00
|
|
|
|
f1 = f2;
|
|
|
|
|
}
|
|
|
|
|
if (!__asan_checka(SHADOW(bp), sizeof(*bp) >> 3).kind) {
|
|
|
|
|
addr = bp->addr;
|
|
|
|
|
if (addr == weakaddr("__gc") && weakaddr("__gc")) {
|
|
|
|
|
do --gi;
|
|
|
|
|
while ((addr = garbage->p[gi].ret) == weakaddr("__gc"));
|
|
|
|
|
}
|
|
|
|
|
bt->p[i] = addr;
|
|
|
|
|
} else {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-03-16 20:33:13 +00:00
|
|
|
|
for (; i < ARRAYLEN(bt->p); ++i) {
|
|
|
|
|
bt->p[i] = 0;
|
|
|
|
|
}
|
2021-09-28 05:58:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-03-16 20:33:13 +00:00
|
|
|
|
#define __asan_trace __asan_rawtrace
|
|
|
|
|
|
2021-10-14 00:27:13 +00:00
|
|
|
|
static void *__asan_allocate(size_t a, size_t n, int underrun, int overrun,
|
|
|
|
|
struct AsanTrace *bt) {
|
2021-09-28 05:58:51 +00:00
|
|
|
|
char *p;
|
2021-02-01 11:33:13 +00:00
|
|
|
|
size_t c;
|
2021-10-14 00:27:13 +00:00
|
|
|
|
struct AsanExtra *e;
|
|
|
|
|
n = __asan_user_size(n);
|
2021-02-01 11:33:13 +00:00
|
|
|
|
if ((p = weaken(dlmemalign)(a, __asan_heap_size(n)))) {
|
|
|
|
|
c = weaken(dlmalloc_usable_size)(p);
|
2021-10-14 00:27:13 +00:00
|
|
|
|
e = (struct AsanExtra *)(p + c - sizeof(*e));
|
2021-02-01 11:33:13 +00:00
|
|
|
|
__asan_unpoison((uintptr_t)p, n);
|
|
|
|
|
__asan_poison((uintptr_t)p - 16, 16, underrun); /* see dlmalloc design */
|
|
|
|
|
__asan_poison((uintptr_t)p + n, c - n, overrun);
|
2021-02-03 04:21:06 +00:00
|
|
|
|
__asan_memset(p, 0xF9, n);
|
2021-10-14 00:27:13 +00:00
|
|
|
|
__asan_write48(&e->size, n);
|
|
|
|
|
__asan_memcpy(&e->bt, bt, sizeof(*bt));
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-16 20:33:13 +00:00
|
|
|
|
static struct AsanExtra *__asan_get_extra(const void *p, size_t *c) {
|
2021-10-14 00:27:13 +00:00
|
|
|
|
int f;
|
|
|
|
|
long x, n;
|
|
|
|
|
struct AsanExtra *e;
|
2022-03-16 20:33:13 +00:00
|
|
|
|
f = (intptr_t)p >> 16;
|
|
|
|
|
if (!kisdangerous(p) && (n = weaken(dlmalloc_usable_size)(p)) > sizeof(*e) &&
|
2021-10-14 00:27:13 +00:00
|
|
|
|
!__builtin_add_overflow((intptr_t)p, n, &x) && x <= 0x800000000000 &&
|
2022-03-16 20:33:13 +00:00
|
|
|
|
(LIKELY(f == (int)((x - 1) >> 16)) || !kisdangerous((void *)(x - 1))) &&
|
2021-10-14 00:27:13 +00:00
|
|
|
|
(LIKELY(f == (int)((x = x - sizeof(*e)) >> 16)) ||
|
|
|
|
|
__asan_is_mapped(x >> 16)) &&
|
|
|
|
|
!(x & (alignof(struct AsanExtra) - 1))) {
|
|
|
|
|
*c = n;
|
|
|
|
|
return (struct AsanExtra *)x;
|
|
|
|
|
} else {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t __asan_get_heap_size(const void *p) {
|
|
|
|
|
size_t n, c;
|
|
|
|
|
struct AsanExtra *e;
|
|
|
|
|
if ((e = __asan_get_extra(p, &c))) {
|
|
|
|
|
if (__asan_read48(e->size, &n)) {
|
|
|
|
|
return n;
|
|
|
|
|
} else {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-01 11:33:13 +00:00
|
|
|
|
static size_t __asan_malloc_usable_size(const void *p) {
|
2021-10-14 00:27:13 +00:00
|
|
|
|
size_t n, c;
|
|
|
|
|
struct AsanExtra *e;
|
|
|
|
|
if ((e = __asan_get_extra(p, &c))) {
|
|
|
|
|
if (__asan_read48(e->size, &n)) {
|
|
|
|
|
return n;
|
|
|
|
|
} else {
|
|
|
|
|
__asan_report_invalid_pointer(p)();
|
|
|
|
|
__asan_unreachable();
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
|
|
|
|
} else {
|
2021-10-14 00:27:13 +00:00
|
|
|
|
__asan_report_invalid_pointer(p)();
|
|
|
|
|
__asan_unreachable();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int __asan_print_trace(void *p) {
|
|
|
|
|
size_t c, i, n;
|
|
|
|
|
struct AsanExtra *e;
|
|
|
|
|
if (!(e = __asan_get_extra(p, &c))) {
|
2022-03-16 20:33:13 +00:00
|
|
|
|
kprintf(" bad pointer");
|
2021-10-14 00:27:13 +00:00
|
|
|
|
return einval();
|
|
|
|
|
}
|
|
|
|
|
if (!__asan_read48(e->size, &n)) {
|
2022-03-16 20:33:13 +00:00
|
|
|
|
kprintf(" bad cookie");
|
2021-10-14 00:27:13 +00:00
|
|
|
|
return -1;
|
|
|
|
|
}
|
2022-03-18 09:33:37 +00:00
|
|
|
|
kprintf("%n%p %,lu bytes [asan]", (char *)p, n);
|
2021-10-14 00:27:13 +00:00
|
|
|
|
if (!__asan_is_mapped((((intptr_t)p >> 3) + 0x7fff8000) >> 16)) {
|
2022-03-16 20:33:13 +00:00
|
|
|
|
kprintf(" (shadow not mapped?!)");
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
2021-10-14 00:27:13 +00:00
|
|
|
|
for (i = 0; i < ARRAYLEN(e->bt.p) && e->bt.p[i]; ++i) {
|
2022-03-16 20:33:13 +00:00
|
|
|
|
kprintf("%n%*lx %s", 12, e->bt.p[i],
|
|
|
|
|
weaken(__get_symbol_by_addr)
|
|
|
|
|
? weaken(__get_symbol_by_addr)(e->bt.p[i])
|
|
|
|
|
: "please STATIC_YOINK(\"__get_symbol_by_addr\")");
|
2021-10-14 00:27:13 +00:00
|
|
|
|
}
|
|
|
|
|
return 0;
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __asan_deallocate(char *p, long kind) {
|
|
|
|
|
size_t c, n;
|
2021-10-14 00:27:13 +00:00
|
|
|
|
struct AsanExtra *e;
|
|
|
|
|
if ((e = __asan_get_extra(p, &c))) {
|
|
|
|
|
if (__asan_read48(e->size, &n)) {
|
|
|
|
|
__asan_poison((uintptr_t)p, c, kind);
|
2022-03-18 09:33:37 +00:00
|
|
|
|
if (c <= ASAN_MORGUE_THRESHOLD) {
|
2021-10-14 00:27:13 +00:00
|
|
|
|
p = __asan_morgue_add(p);
|
|
|
|
|
}
|
|
|
|
|
weaken(dlfree)(p);
|
|
|
|
|
} else {
|
|
|
|
|
__asan_report_invalid_pointer(p)();
|
|
|
|
|
__asan_unreachable();
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
|
|
|
|
} else {
|
2021-10-14 00:27:13 +00:00
|
|
|
|
__asan_report_invalid_pointer(p)();
|
|
|
|
|
__asan_unreachable();
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-28 05:58:51 +00:00
|
|
|
|
void __asan_free(void *p) {
|
2021-02-01 11:33:13 +00:00
|
|
|
|
if (!p) return;
|
|
|
|
|
__asan_deallocate(p, kAsanHeapFree);
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-08 15:11:51 +00:00
|
|
|
|
size_t __asan_bulk_free(void *p[], size_t n) {
|
|
|
|
|
size_t i;
|
|
|
|
|
for (i = 0; i < n; ++i) {
|
|
|
|
|
if (p[i]) {
|
|
|
|
|
__asan_deallocate(p[i], kAsanHeapFree);
|
|
|
|
|
p[i] = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-14 00:27:13 +00:00
|
|
|
|
static void *__asan_realloc_nogrow(void *p, size_t n, size_t m,
|
|
|
|
|
struct AsanTrace *bt) {
|
2021-09-07 02:24:10 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-14 00:27:13 +00:00
|
|
|
|
static void *__asan_realloc_grow(void *p, size_t n, size_t m,
|
|
|
|
|
struct AsanTrace *bt) {
|
2021-09-07 02:24:10 +00:00
|
|
|
|
char *q;
|
2021-10-14 00:27:13 +00:00
|
|
|
|
if ((q = __asan_allocate(16, n, kAsanHeapUnderrun, kAsanHeapOverrun, bt))) {
|
2021-09-07 02:24:10 +00:00
|
|
|
|
__asan_memcpy(q, p, m);
|
2021-10-14 00:27:13 +00:00
|
|
|
|
__asan_deallocate(p, kAsanHeapRelocated);
|
2021-09-07 02:24:10 +00:00
|
|
|
|
}
|
|
|
|
|
return q;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void *__asan_realloc_impl(void *p, size_t n,
|
2021-10-14 00:27:13 +00:00
|
|
|
|
void *grow(void *, size_t, size_t,
|
|
|
|
|
struct AsanTrace *)) {
|
2021-02-01 11:33:13 +00:00
|
|
|
|
size_t c, m;
|
2021-10-14 00:27:13 +00:00
|
|
|
|
struct AsanExtra *e;
|
|
|
|
|
if ((e = __asan_get_extra(p, &c))) {
|
|
|
|
|
if (__asan_read48(e->size, &m)) {
|
2021-09-07 02:24:10 +00:00
|
|
|
|
if (n <= m) { /* shrink */
|
|
|
|
|
__asan_poison((uintptr_t)p + n, m - n, kAsanHeapOverrun);
|
2021-10-14 00:27:13 +00:00
|
|
|
|
__asan_write48(&e->size, n);
|
2021-09-07 02:24:10 +00:00
|
|
|
|
return p;
|
2021-10-14 00:27:13 +00:00
|
|
|
|
} else if (n <= c - sizeof(struct AsanExtra)) { /* small growth */
|
2021-09-07 02:24:10 +00:00
|
|
|
|
__asan_unpoison((uintptr_t)p + m, n - m);
|
2021-10-14 00:27:13 +00:00
|
|
|
|
__asan_write48(&e->size, n);
|
2021-09-07 02:24:10 +00:00
|
|
|
|
return p;
|
|
|
|
|
} else { /* exponential growth */
|
2021-10-14 00:27:13 +00:00
|
|
|
|
return grow(p, n, m, &e->bt);
|
2021-09-07 02:24:10 +00:00
|
|
|
|
}
|
|
|
|
|
} else {
|
2021-10-14 00:27:13 +00:00
|
|
|
|
__asan_report_invalid_pointer(p)();
|
|
|
|
|
__asan_unreachable();
|
2021-09-07 02:24:10 +00:00
|
|
|
|
}
|
|
|
|
|
} else {
|
2021-10-14 00:27:13 +00:00
|
|
|
|
__asan_report_invalid_pointer(p)();
|
|
|
|
|
__asan_unreachable();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void *__asan_malloc(size_t size) {
|
|
|
|
|
struct AsanTrace bt;
|
|
|
|
|
__asan_trace(&bt, __builtin_frame_address(0));
|
|
|
|
|
return __asan_allocate(16, size, kAsanHeapUnderrun, kAsanHeapOverrun, &bt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void *__asan_memalign(size_t align, size_t size) {
|
|
|
|
|
struct AsanTrace bt;
|
|
|
|
|
__asan_trace(&bt, __builtin_frame_address(0));
|
|
|
|
|
return __asan_allocate(align, size, kAsanHeapUnderrun, kAsanHeapOverrun, &bt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void *__asan_calloc(size_t n, size_t m) {
|
|
|
|
|
char *p;
|
|
|
|
|
struct AsanTrace bt;
|
|
|
|
|
__asan_trace(&bt, __builtin_frame_address(0));
|
|
|
|
|
if (__builtin_mul_overflow(n, m, &n)) n = -1;
|
|
|
|
|
if ((p = __asan_allocate(16, n, kAsanHeapUnderrun, kAsanHeapOverrun, &bt))) {
|
|
|
|
|
__asan_memset(p, 0, n);
|
2021-09-07 02:24:10 +00:00
|
|
|
|
}
|
2021-10-14 00:27:13 +00:00
|
|
|
|
return p;
|
2021-09-07 02:24:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-09-28 05:58:51 +00:00
|
|
|
|
void *__asan_realloc(void *p, size_t n) {
|
2021-10-14 00:27:13 +00:00
|
|
|
|
struct AsanTrace bt;
|
2021-02-01 11:33:13 +00:00
|
|
|
|
if (p) {
|
|
|
|
|
if (n) {
|
2021-09-07 02:24:10 +00:00
|
|
|
|
return __asan_realloc_impl(p, n, __asan_realloc_grow);
|
2021-02-01 11:33:13 +00:00
|
|
|
|
} else {
|
|
|
|
|
__asan_free(p);
|
2021-09-07 02:24:10 +00:00
|
|
|
|
return 0;
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
|
|
|
|
} else {
|
2021-10-14 00:27:13 +00:00
|
|
|
|
__asan_trace(&bt, __builtin_frame_address(0));
|
|
|
|
|
return __asan_allocate(16, n, kAsanHeapUnderrun, kAsanHeapOverrun, &bt);
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-28 05:58:51 +00:00
|
|
|
|
void *__asan_realloc_in_place(void *p, size_t n) {
|
2021-09-07 02:24:10 +00:00
|
|
|
|
if (p) {
|
|
|
|
|
return __asan_realloc_impl(p, n, __asan_realloc_nogrow);
|
|
|
|
|
} else {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2021-07-19 21:55:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-09-28 05:58:51 +00:00
|
|
|
|
int __asan_malloc_trim(size_t pad) {
|
2021-02-01 11:33:13 +00:00
|
|
|
|
__asan_morgue_flush();
|
|
|
|
|
if (weaken(dlmalloc_trim)) {
|
|
|
|
|
return weaken(dlmalloc_trim)(pad);
|
|
|
|
|
} else {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void *__asan_stack_malloc(size_t size, int classid) {
|
2021-10-14 00:27:13 +00:00
|
|
|
|
struct AsanTrace bt;
|
|
|
|
|
__asan_trace(&bt, __builtin_frame_address(0));
|
|
|
|
|
return __asan_allocate(16, size, kAsanStackUnderrun, kAsanStackOverrun, &bt);
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void __asan_stack_free(char *p, size_t size, int classid) {
|
|
|
|
|
__asan_deallocate(p, kAsanStackFree);
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-03 14:22:51 +00:00
|
|
|
|
void __asan_handle_no_return(void) {
|
2021-09-28 05:58:51 +00:00
|
|
|
|
uintptr_t stk, ssz;
|
|
|
|
|
stk = (uintptr_t)__builtin_frame_address(0);
|
2021-10-14 00:27:13 +00:00
|
|
|
|
ssz = GetStackSize();
|
2021-09-28 05:58:51 +00:00
|
|
|
|
__asan_unpoison(stk, ROUNDUP(stk, ssz) - stk);
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void __asan_register_globals(struct AsanGlobal g[], int n) {
|
|
|
|
|
int i;
|
2021-10-14 00:27:13 +00:00
|
|
|
|
__asan_poison((intptr_t)g, sizeof(*g) * n, kAsanProtected);
|
2021-02-01 11:33:13 +00:00
|
|
|
|
for (i = 0; i < n; ++i) {
|
|
|
|
|
__asan_poison(g[i].addr + g[i].size, g[i].size_with_redzone - g[i].size,
|
2021-10-14 00:27:13 +00:00
|
|
|
|
kAsanGlobalRedzone);
|
|
|
|
|
if (g[i].location) {
|
|
|
|
|
__asan_poison((intptr_t)g[i].location, sizeof(*g[i].location),
|
|
|
|
|
kAsanProtected);
|
|
|
|
|
}
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void __asan_unregister_globals(struct AsanGlobal g[], int n) {
|
|
|
|
|
int i;
|
|
|
|
|
for (i = 0; i < n; ++i) {
|
2021-10-14 00:27:13 +00:00
|
|
|
|
__asan_poison(g[i].addr, g[i].size, kAsanGlobalGone);
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-16 20:33:13 +00:00
|
|
|
|
void __asan_evil(uint8_t *addr, int size, const char *s1, const char *s2) {
|
|
|
|
|
struct AsanTrace tr;
|
|
|
|
|
__asan_rawtrace(&tr, __builtin_frame_address(0));
|
|
|
|
|
kprintf("WARNING: ASAN error during %s bad %d byte %s at %p bt %p %p %p %p%n",
|
|
|
|
|
s1, size, s2, addr, tr.p[0], tr.p[1], tr.p[2], tr.p[3]);
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-03 14:22:51 +00:00
|
|
|
|
void __asan_report_load(uint8_t *addr, int size) {
|
2021-10-14 00:27:13 +00:00
|
|
|
|
if (cmpxchg(&__asan_noreentry, false, true)) {
|
2022-03-16 20:33:13 +00:00
|
|
|
|
if (!__vforked) {
|
|
|
|
|
__asan_report_memory_fault(addr, size, "load")();
|
|
|
|
|
__asan_unreachable();
|
|
|
|
|
} else {
|
|
|
|
|
__asan_evil(addr, size, "vfork()", "load");
|
|
|
|
|
}
|
2021-10-14 00:27:13 +00:00
|
|
|
|
} else {
|
2022-03-16 20:33:13 +00:00
|
|
|
|
__asan_evil(addr, size, "ASAN Reporting", "load");
|
2021-10-14 00:27:13 +00:00
|
|
|
|
}
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-02-03 14:22:51 +00:00
|
|
|
|
void __asan_report_store(uint8_t *addr, int size) {
|
2021-10-14 00:27:13 +00:00
|
|
|
|
if (cmpxchg(&__asan_noreentry, false, true)) {
|
2022-03-16 20:33:13 +00:00
|
|
|
|
if (!__vforked) {
|
|
|
|
|
__asan_report_memory_fault(addr, size, "store")();
|
|
|
|
|
__asan_unreachable();
|
|
|
|
|
} else {
|
|
|
|
|
__asan_evil(addr, size, "vfork()", "store");
|
|
|
|
|
}
|
2021-10-14 00:27:13 +00:00
|
|
|
|
} else {
|
2022-03-16 20:33:13 +00:00
|
|
|
|
__asan_evil(addr, size, "ASAN reporting", "store");
|
2021-10-14 00:27:13 +00:00
|
|
|
|
}
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-02-03 04:21:06 +00:00
|
|
|
|
void __asan_poison_stack_memory(uintptr_t addr, size_t size) {
|
|
|
|
|
__asan_poison(addr, size, kAsanStackFree);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void __asan_unpoison_stack_memory(uintptr_t addr, size_t size) {
|
|
|
|
|
__asan_unpoison(addr, size);
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-01 11:33:13 +00:00
|
|
|
|
void __asan_alloca_poison(uintptr_t addr, size_t size) {
|
2022-04-02 05:44:43 +00:00
|
|
|
|
__asan_poison(addr - 32, 32, kAsanAllocaUnderrun);
|
2022-04-02 05:50:15 +00:00
|
|
|
|
__asan_poison(addr + size, 32, kAsanAllocaOverrun);
|
|
|
|
|
__asan_unpoison(addr, size);
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void __asan_allocas_unpoison(uintptr_t x, uintptr_t y) {
|
|
|
|
|
if (x && x > y) __asan_unpoison(x, y - x);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void *__asan_addr_is_in_fake_stack(void *fakestack, void *addr, void **beg,
|
|
|
|
|
void **end) {
|
2021-10-14 00:27:13 +00:00
|
|
|
|
return 0;
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void *__asan_get_current_fake_stack(void) {
|
2021-10-14 00:27:13 +00:00
|
|
|
|
return 0;
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-03-23 04:04:08 +00:00
|
|
|
|
void __sanitizer_annotate_contiguous_container(long beg, long end, long old_mid,
|
|
|
|
|
long new_mid) {
|
|
|
|
|
// the c++ stl uses this
|
|
|
|
|
// TODO(jart): make me faster
|
|
|
|
|
__asan_unpoison(beg, new_mid - beg);
|
|
|
|
|
__asan_poison(new_mid, end - new_mid, kAsanHeapOverrun);
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-01 11:33:13 +00:00
|
|
|
|
void __asan_install_malloc_hooks(void) {
|
2021-02-06 08:24:35 +00:00
|
|
|
|
HOOK(hook_free, __asan_free);
|
|
|
|
|
HOOK(hook_malloc, __asan_malloc);
|
|
|
|
|
HOOK(hook_calloc, __asan_calloc);
|
|
|
|
|
HOOK(hook_realloc, __asan_realloc);
|
|
|
|
|
HOOK(hook_memalign, __asan_memalign);
|
2021-10-08 15:11:51 +00:00
|
|
|
|
HOOK(hook_bulk_free, __asan_bulk_free);
|
2021-02-06 08:24:35 +00:00
|
|
|
|
HOOK(hook_malloc_trim, __asan_malloc_trim);
|
2021-07-19 21:55:20 +00:00
|
|
|
|
HOOK(hook_realloc_in_place, __asan_realloc_in_place);
|
2021-02-06 08:24:35 +00:00
|
|
|
|
HOOK(hook_malloc_usable_size, __asan_malloc_usable_size);
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void __asan_map_shadow(uintptr_t p, size_t n) {
|
2021-10-14 00:27:13 +00:00
|
|
|
|
void *addr;
|
2022-03-16 20:33:13 +00:00
|
|
|
|
int i, a, b;
|
2021-10-14 00:27:13 +00:00
|
|
|
|
size_t size;
|
|
|
|
|
int prot, flag;
|
2021-02-01 11:33:13 +00:00
|
|
|
|
struct DirectMap sm;
|
|
|
|
|
struct MemoryIntervals *m;
|
2021-10-14 00:27:13 +00:00
|
|
|
|
assert(!OverlapsShadowSpace((void *)p, n));
|
2021-02-01 11:33:13 +00:00
|
|
|
|
m = weaken(_mmi);
|
2021-10-14 00:27:13 +00:00
|
|
|
|
a = (0x7fff8000 + (p >> 3)) >> 16;
|
|
|
|
|
b = (0x7fff8000 + (p >> 3) + (n >> 3) + 0xffff) >> 16;
|
|
|
|
|
for (; a <= b; a += i) {
|
|
|
|
|
i = 1;
|
|
|
|
|
if (__asan_is_mapped(a)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
for (; a + i <= b; ++i) {
|
|
|
|
|
if (__asan_is_mapped(a + i)) {
|
|
|
|
|
break;
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2021-10-14 00:27:13 +00:00
|
|
|
|
size = (size_t)i << 16;
|
|
|
|
|
addr = (void *)(intptr_t)((int64_t)((uint64_t)a << 32) >> 16);
|
|
|
|
|
prot = PROT_READ | PROT_WRITE;
|
|
|
|
|
flag = MAP_PRIVATE | MAP_FIXED | *weaken(MAP_ANONYMOUS);
|
|
|
|
|
sm = weaken(sys_mmap)(addr, size, prot, flag, -1, 0);
|
|
|
|
|
if (sm.addr == MAP_FAILED ||
|
|
|
|
|
weaken(TrackMemoryInterval)(
|
|
|
|
|
m, a, a + i - 1, sm.maphandle, PROT_READ | PROT_WRITE,
|
2022-03-20 15:01:14 +00:00
|
|
|
|
MAP_PRIVATE | *weaken(MAP_ANONYMOUS) | MAP_FIXED, 0, size) == -1) {
|
2022-03-16 20:33:13 +00:00
|
|
|
|
kprintf("error: could not map asan shadow memory%n");
|
|
|
|
|
__asan_die()();
|
2021-10-14 00:27:13 +00:00
|
|
|
|
__asan_unreachable();
|
|
|
|
|
}
|
|
|
|
|
__repstosb((void *)(intptr_t)((int64_t)((uint64_t)a << 32) >> 16),
|
|
|
|
|
kAsanUnmapped, size);
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
|
|
|
|
__asan_unpoison((uintptr_t)p, n);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static textstartup void __asan_shadow_string(char *s) {
|
2021-10-14 00:27:13 +00:00
|
|
|
|
__asan_map_shadow((uintptr_t)s, __strlen(s) + 1);
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static textstartup void __asan_shadow_auxv(intptr_t *auxv) {
|
|
|
|
|
size_t i;
|
|
|
|
|
for (i = 0; auxv[i]; i += 2) {
|
|
|
|
|
if (weaken(AT_RANDOM) && auxv[i] == *weaken(AT_RANDOM)) {
|
|
|
|
|
__asan_map_shadow(auxv[i + 1], 16);
|
|
|
|
|
} else if (weaken(AT_EXECFN) && auxv[i] == *weaken(AT_EXECFN)) {
|
|
|
|
|
__asan_shadow_string((char *)auxv[i + 1]);
|
|
|
|
|
} else if (weaken(AT_PLATFORM) && auxv[i] == *weaken(AT_PLATFORM)) {
|
|
|
|
|
__asan_shadow_string((char *)auxv[i + 1]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
__asan_map_shadow((uintptr_t)auxv, (i + 2) * sizeof(intptr_t));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static textstartup void __asan_shadow_string_list(char **list) {
|
|
|
|
|
size_t i;
|
|
|
|
|
for (i = 0; list[i]; ++i) {
|
|
|
|
|
__asan_shadow_string(list[i]);
|
|
|
|
|
}
|
|
|
|
|
__asan_map_shadow((uintptr_t)list, (i + 1) * sizeof(char *));
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-16 20:33:13 +00:00
|
|
|
|
static textstartup void __asan_shadow_mapping(struct MemoryIntervals *m,
|
|
|
|
|
size_t i) {
|
|
|
|
|
uintptr_t x, y;
|
|
|
|
|
if (i < m->i) {
|
|
|
|
|
x = m->p[i].x;
|
|
|
|
|
y = m->p[i].y;
|
|
|
|
|
__asan_shadow_mapping(m, i + 1);
|
|
|
|
|
__asan_map_shadow(x << 16, (y - x + 1) << 16);
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-16 20:33:13 +00:00
|
|
|
|
static textstartup void __asan_shadow_existing_mappings(void) {
|
|
|
|
|
__asan_shadow_mapping(&_mmi, 0);
|
|
|
|
|
__asan_map_shadow(GetStackAddr(0), GetStackSize());
|
|
|
|
|
__asan_poison(GetStackAddr(0), PAGESIZE, kAsanStackOverflow);
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
textstartup void __asan_init(int argc, char **argv, char **envp,
|
|
|
|
|
intptr_t *auxv) {
|
|
|
|
|
static bool once;
|
|
|
|
|
if (!cmpxchg(&once, false, true)) return;
|
2021-02-03 14:22:51 +00:00
|
|
|
|
if (IsWindows() && NtGetVersion() < kNtVersionWindows10) {
|
2022-03-16 20:33:13 +00:00
|
|
|
|
__write_str("error: asan binaries require windows10\r\n");
|
2022-03-23 13:31:55 +00:00
|
|
|
|
__restorewintty();
|
2021-10-14 00:27:13 +00:00
|
|
|
|
_Exit(0); /* So `make MODE=dbg test` passes w/ Windows7 */
|
2021-02-03 14:22:51 +00:00
|
|
|
|
}
|
2021-02-01 11:33:13 +00:00
|
|
|
|
REQUIRE(_mmi);
|
2021-02-24 04:23:19 +00:00
|
|
|
|
REQUIRE(sys_mmap);
|
2021-02-01 11:33:13 +00:00
|
|
|
|
REQUIRE(MAP_ANONYMOUS);
|
|
|
|
|
REQUIRE(TrackMemoryInterval);
|
2021-02-06 08:24:35 +00:00
|
|
|
|
if (weaken(hook_malloc) || weaken(hook_calloc) || weaken(hook_realloc) ||
|
2021-10-14 00:27:13 +00:00
|
|
|
|
weaken(hook_realloc_in_place) || weaken(hook_free) ||
|
2021-02-06 08:24:35 +00:00
|
|
|
|
weaken(hook_malloc_usable_size)) {
|
2021-02-01 11:33:13 +00:00
|
|
|
|
REQUIRE(dlmemalign);
|
|
|
|
|
REQUIRE(dlmalloc_usable_size);
|
|
|
|
|
}
|
|
|
|
|
__asan_shadow_existing_mappings();
|
|
|
|
|
__asan_map_shadow((uintptr_t)_base, _end - _base);
|
2021-10-02 15:17:04 +00:00
|
|
|
|
__asan_map_shadow(0, 4096);
|
|
|
|
|
__asan_poison(0, PAGESIZE, kAsanNullPage);
|
2021-10-14 00:27:13 +00:00
|
|
|
|
if (!IsWindows()) {
|
2022-03-16 20:33:13 +00:00
|
|
|
|
__sysv_mprotect((void *)0x7fff8000, 0x10000, PROT_READ);
|
2021-10-14 00:27:13 +00:00
|
|
|
|
}
|
2021-02-01 11:33:13 +00:00
|
|
|
|
__asan_shadow_string_list(argv);
|
|
|
|
|
__asan_shadow_string_list(envp);
|
|
|
|
|
__asan_shadow_auxv(auxv);
|
|
|
|
|
__asan_install_malloc_hooks();
|
2022-03-23 13:31:55 +00:00
|
|
|
|
STRACE(" _ ____ _ _ _ ");
|
|
|
|
|
STRACE(" / \\ / ___| / \\ | \\ | |");
|
|
|
|
|
STRACE(" / _ \\ \\___ \\ / _ \\ | \\| |");
|
|
|
|
|
STRACE(" / ___ \\ ___) / ___ \\| |\\ |");
|
|
|
|
|
STRACE("/_/ \\_\\____/_/ \\_\\_| \\_|");
|
Introduce --strace flag for system call tracing
This is similar to the --ftrace (c function call trace) flag, except
it's less noisy since it only logs system calls to stderr. Having this
flag is valuable because (1) system call tracing tells us a lot about
the behavior of complex programs and (2) it's usually very hard to get
system call tracing on various operating systems, e.g. strace, ktrace,
dtruss, truss, nttrace, etc. Especially on Apple platforms where even
with the special boot trick, debuggers still aren't guaranteed to work.
make -j8 o//examples
o//examples/hello.com --strace
This is enabled by default in MODE=, MODE=opt, and MODE=dbg. In MODE=dbg
extra information will be printed.
make -j8 MODE=dbg o/dbg/examples
o/dbg/examples/hello.com --strace |& less
This change also changes:
- Rename IsText() → _istext()
- Rename IsUtf8() → _isutf8()
- Fix madvise() on Windows NT
- Fix empty string case of inet_ntop()
- vfork() wrapper now saves and restores errno
- Update xsigaction() to yoink syscall support
2022-03-19 01:07:28 +00:00
|
|
|
|
STRACE("cosmopolitan memory safety module initialized");
|
2021-02-01 11:33:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static textstartup void __asan_ctor(void) {
|
|
|
|
|
if (weaken(__cxa_atexit)) {
|
|
|
|
|
weaken(__cxa_atexit)(__asan_morgue_flush, NULL, NULL);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-14 00:27:13 +00:00
|
|
|
|
const void *const g_asan_ctor[] initarray = {
|
|
|
|
|
__asan_ctor,
|
|
|
|
|
};
|