mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-30 06:20:28 +00:00
Improve memory safety
This commit makes numerous refinements to cosmopolitan memory handling. The default stack size has been reduced from 2mb to 128kb. A new macro is now provided so you can easily reconfigure the stack size to be any value you want. Work around the breaking change by adding to your main: STATIC_STACK_SIZE(0x00200000); // 2mb stack If you're not sure how much stack you need, then you can use: STATIC_YOINK("stack_usage_logging"); After which you can `sort -nr o/$MODE/stack.log`. Based on the unit test suite, nothing in the Cosmopolitan repository (except for Python) needs a stack size greater than 30kb. There are also new macros for detecting the size and address of the stack at runtime, e.g. GetStackAddr(). We also now support sigaltstack() so if you want to see nice looking crash reports whenever a stack overflow happens, you can put this in main(): ShowCrashReports(); Under `make MODE=dbg` and `make MODE=asan` the unit testing framework will now automatically print backtraces of memory allocations when things like memory leaks happen. Bugs are now fixed in ASAN global variable overrun detection. The memtrack and asan runtimes also handle edge cases now. The new tools helped to identify a few memory leaks, which are fixed by this change. This change should fix an issue reported in #288 with ARG_MAX limits. Fixing this doubled the performance of MKDEPS.COM and AR.COM yet again.
This commit is contained in:
parent
a0b39f886c
commit
226aaf3547
317 changed files with 6474 additions and 3993 deletions
File diff suppressed because it is too large
Load diff
|
@ -1,53 +1,61 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_INTRIN_ASAN_H_
|
||||
#define COSMOPOLITAN_LIBC_INTRIN_ASAN_H_
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
#define kAsanScale 3
|
||||
#define kAsanMagic 0x7fff8000
|
||||
#define kAsanHeapFree -1 /* F */
|
||||
#define kAsanStackFree -2 /* F */
|
||||
#define kAsanRelocated -3 /* R */
|
||||
#define kAsanHeapUnderrun -4 /* U */
|
||||
#define kAsanHeapOverrun -5 /* O */
|
||||
#define kAsanGlobalOverrun -6 /* O */
|
||||
#define kAsanGlobalUnregistered -7 /* G */
|
||||
#define kAsanStackUnderrun -8 /* U */
|
||||
#define kAsanStackOverrun -9 /* O */
|
||||
#define kAsanAllocaUnderrun -10 /* U */
|
||||
#define kAsanAllocaOverrun -11 /* O */
|
||||
#define kAsanUnscoped -12 /* S */
|
||||
#define kAsanUnmapped -13 /* M */
|
||||
#define kAsanProtected -14 /* P */
|
||||
#define kAsanStackGuard -15 /* _ */
|
||||
#define kAsanNullPage -16
|
||||
#define kAsanScale 3
|
||||
#define kAsanMagic 0x7fff8000
|
||||
#define kAsanNullPage -1 /* ∅ 0xff */
|
||||
#define kAsanProtected -2 /* P 0xfe */
|
||||
#define kAsanHeapFree -3 /* F 0xfd */
|
||||
#define kAsanHeapRelocated -4 /* R 0xfc */
|
||||
#define kAsanAllocaOverrun -5 /* 𝑂 0xfb */
|
||||
#define kAsanHeapUnderrun -6 /* U 0xfa */
|
||||
#define kAsanHeapOverrun -7 /* O 0xf9 */
|
||||
#define kAsanStackUnscoped -8 /* s 0xf8 */
|
||||
#define kAsanStackOverflow -9 /* ! 0xf7 */
|
||||
#define kAsanGlobalOrder -10 /* I 0xf6 */
|
||||
#define kAsanStackFree -11 /* r 0xf5 */
|
||||
#define kAsanStackPartial -12 /* p 0xf4 */
|
||||
#define kAsanStackOverrun -13 /* o 0xf3 */
|
||||
#define kAsanStackMiddle -14 /* m 0xf2 */
|
||||
#define kAsanStackUnderrun -15 /* u 0xf1 */
|
||||
#define kAsanAllocaUnderrun -16 /* 𝑈 0xf0 */
|
||||
#define kAsanUnmapped -17 /* M 0xef */
|
||||
#define kAsanGlobalRedzone -18 /* G 0xee */
|
||||
#define kAsanGlobalGone -19 /* 𝐺 0xed */
|
||||
|
||||
#define SHADOW(x) ((signed char *)(((uintptr_t)(x) >> kAsanScale) + kAsanMagic))
|
||||
#define UNSHADOW(x) ((void *)(((uintptr_t)(x) + 0x7fff8000) << 3))
|
||||
#define SHADOW(x) ((signed char *)(((intptr_t)(x) >> kAsanScale) + kAsanMagic))
|
||||
#define UNSHADOW(x) ((void *)(MAX(0, (intptr_t)(x)-kAsanMagic) << kAsanScale))
|
||||
|
||||
typedef void __asan_die_f(void);
|
||||
|
||||
struct AsanFault {
|
||||
char kind;
|
||||
signed char kind;
|
||||
signed char *shadow;
|
||||
};
|
||||
|
||||
void __asan_unpoison(uintptr_t, size_t);
|
||||
extern bool __asan_noreentry;
|
||||
|
||||
void __asan_unpoison(long, long);
|
||||
void __asan_poison(long, long, signed char);
|
||||
void __asan_verify(const void *, size_t);
|
||||
void __asan_map_shadow(uintptr_t, size_t);
|
||||
void __asan_poison(uintptr_t, size_t, int);
|
||||
bool __asan_is_valid(const void *, size_t);
|
||||
bool __asan_is_valid_strlist(char *const *);
|
||||
bool __asan_is_valid_iov(const struct iovec *, int);
|
||||
struct AsanFault __asan_check(const void *, size_t);
|
||||
void __asan_report_memory_fault(void *, int, const char *) wontreturn;
|
||||
void __asan_report(void *, int, const char *, char) wontreturn;
|
||||
void *__asan_memalign(size_t, size_t);
|
||||
bool __asan_is_valid(const void *, long) nosideeffect;
|
||||
bool __asan_is_valid_strlist(char *const *) strlenesque;
|
||||
bool __asan_is_valid_iov(const struct iovec *, int) nosideeffect;
|
||||
wint_t __asan_symbolize_access_poison(signed char) pureconst;
|
||||
const char *__asan_describe_access_poison(signed char) pureconst;
|
||||
struct AsanFault __asan_check(const void *, long) nosideeffect;
|
||||
|
||||
void __asan_free(void *);
|
||||
void *__asan_malloc(size_t);
|
||||
int __asan_malloc_trim(size_t);
|
||||
int __asan_print_trace(void *);
|
||||
void *__asan_calloc(size_t, size_t);
|
||||
void *__asan_realloc(void *, size_t);
|
||||
void *__asan_memalign(size_t, size_t);
|
||||
size_t __asan_get_heap_size(const void *);
|
||||
void *__asan_realloc_in_place(void *, size_t);
|
||||
void *__asan_valloc(size_t);
|
||||
void *__asan_pvalloc(size_t);
|
||||
int __asan_malloc_trim(size_t);
|
||||
void __asan_die(const char *) wontreturn;
|
||||
|
||||
#endif /* COSMOPOLITAN_LIBC_INTRIN_ASAN_H_ */
|
||||
|
|
33
libc/intrin/atexit.c
Normal file
33
libc/intrin/atexit.c
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*-*- 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. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
/**
|
||||
* Adds global destructor.
|
||||
*
|
||||
* Destructors are called in reverse order. They won't be called
|
||||
* if the program aborts or _exit() is called. Invocations of this
|
||||
* function are usually generated by the C++ compiler.
|
||||
*
|
||||
* @param rdi callback typed void(*)(T) (nullable)
|
||||
* @return 0 on success or nonzero if out of space
|
||||
*/
|
||||
int atexit(void f(void)) {
|
||||
return __cxa_atexit(f, 0, 0);
|
||||
}
|
|
@ -28,7 +28,7 @@ typedef long long xmm_a __attribute__((__vector_size__(16), __aligned__(16)));
|
|||
|
||||
noasan static noinline antiquity void bzero_sse(char *p, size_t n) {
|
||||
xmm_t v = {0};
|
||||
if (IsAsan()) __asan_check(p, n);
|
||||
if (IsAsan()) __asan_verify(p, n);
|
||||
if (n <= 32) {
|
||||
*(xmm_t *)(p + n - 16) = v;
|
||||
*(xmm_t *)p = v;
|
||||
|
@ -45,7 +45,7 @@ noasan static noinline antiquity void bzero_sse(char *p, size_t n) {
|
|||
|
||||
noasan microarchitecture("avx") static void bzero_avx(char *p, size_t n) {
|
||||
xmm_t v = {0};
|
||||
if (IsAsan()) __asan_check(p, n);
|
||||
if (IsAsan()) __asan_verify(p, n);
|
||||
if (n <= 32) {
|
||||
*(xmm_t *)(p + n - 16) = v;
|
||||
*(xmm_t *)p = v;
|
||||
|
@ -134,11 +134,6 @@ void(bzero)(void *p, size_t n) {
|
|||
char *b;
|
||||
uint64_t x;
|
||||
b = p;
|
||||
if (IsTiny()) {
|
||||
if (IsAsan()) __asan_check(p, n);
|
||||
asm("rep stosb" : "+D"(b), "+c"(n), "=m"(*(char(*)[n])b) : "0"(p), "a"(0));
|
||||
return;
|
||||
}
|
||||
asm("xorl\t%k0,%k0" : "=r"(x));
|
||||
if (n <= 16) {
|
||||
if (n >= 8) {
|
||||
|
@ -153,6 +148,9 @@ void(bzero)(void *p, size_t n) {
|
|||
b[--n] = x;
|
||||
} while (n);
|
||||
}
|
||||
} else if (IsTiny()) {
|
||||
asm("rep stosb" : "+D"(b), "+c"(n), "=m"(*(char(*)[n])b) : "0"(p), "a"(0));
|
||||
return;
|
||||
} else if (X86_HAVE(AVX)) {
|
||||
bzero_avx(b, n);
|
||||
} else {
|
||||
|
|
67
libc/intrin/cxaatexit.c
Normal file
67
libc/intrin/cxaatexit.c
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*-*- 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. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nexgen32e/bsr.h"
|
||||
#include "libc/runtime/cxaatexit.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
STATIC_YOINK("__cxa_finalize");
|
||||
|
||||
/**
|
||||
* Adds global destructor.
|
||||
*
|
||||
* Destructors are called in reverse order. They won't be called if the
|
||||
* program aborts or _exit() is called. Invocations of this function are
|
||||
* usually generated by the C++ compiler. Behavior is limitless if some
|
||||
* other module has linked calloc().
|
||||
*
|
||||
* @param fp is void(*)(T)
|
||||
* @param arg is passed to callback
|
||||
* @param pred can be non-null for things like dso modules
|
||||
* @return 0 on success or nonzero w/ errno
|
||||
* @note folks have forked libc in past just to unbloat atexit()
|
||||
*/
|
||||
noasan int __cxa_atexit(void *fp, void *arg, void *pred) {
|
||||
/* asan runtime depends on this function */
|
||||
unsigned i;
|
||||
struct CxaAtexitBlock *b, *b2;
|
||||
_Static_assert(ATEXIT_MAX == CHAR_BIT * sizeof(b->mask), "");
|
||||
b = __cxa_blocks.p;
|
||||
if (!b) b = __cxa_blocks.p = &__cxa_blocks.root;
|
||||
if (!~b->mask) {
|
||||
if (weaken(calloc) &&
|
||||
(b2 = weaken(calloc)(1, sizeof(struct CxaAtexitBlock)))) {
|
||||
b2->next = b;
|
||||
__cxa_blocks.p = b = b2;
|
||||
} else {
|
||||
return enomem();
|
||||
}
|
||||
}
|
||||
i = bsr(~b->mask);
|
||||
assert(i < ARRAYLEN(b->p));
|
||||
b->mask |= 1u << i;
|
||||
b->p[i].fp = fp;
|
||||
b->p[i].arg = arg;
|
||||
b->p[i].pred = pred;
|
||||
return 0;
|
||||
}
|
21
libc/intrin/cxablocks.c
Normal file
21
libc/intrin/cxablocks.c
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*-*- 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 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/runtime/cxaatexit.internal.h"
|
||||
|
||||
struct CxaAtexitBlocks __cxa_blocks;
|
72
libc/intrin/cxafinalize.c
Normal file
72
libc/intrin/cxafinalize.c
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*-*- 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 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nexgen32e/bsf.h"
|
||||
#include "libc/runtime/cxaatexit.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
/**
|
||||
* Triggers global destructors.
|
||||
*
|
||||
* They're called in LIFO order. If a destructor adds more destructors,
|
||||
* then those destructors will be called immediately following, before
|
||||
* iteration continues.
|
||||
*
|
||||
* @param pred can be null to match all
|
||||
*/
|
||||
void __cxa_finalize(void *pred) {
|
||||
unsigned i, mask;
|
||||
struct CxaAtexitBlock *b, *b2;
|
||||
StartOver:
|
||||
if ((b = __cxa_blocks.p)) {
|
||||
for (;;) {
|
||||
mask = b->mask;
|
||||
while (mask) {
|
||||
i = bsf(mask);
|
||||
mask &= ~(1u << i);
|
||||
if (!pred || pred == b->p[i].pred) {
|
||||
b->mask &= ~(1u << i);
|
||||
if (b->p[i].fp) {
|
||||
((void (*)(void *))b->p[i].fp)(b->p[i].arg);
|
||||
goto StartOver;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!pred) {
|
||||
b2 = b->next;
|
||||
if (b2) {
|
||||
assert(b != &__cxa_blocks.root);
|
||||
if (weaken(free)) {
|
||||
weaken(free)(b);
|
||||
}
|
||||
}
|
||||
__cxa_blocks.p = b2;
|
||||
goto StartOver;
|
||||
} else {
|
||||
if (b->next) {
|
||||
b = b->next;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
53
libc/intrin/exit.c
Normal file
53
libc/intrin/exit.c
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*-*- 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 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nexgen32e/vendor.internal.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
#include "libc/sysv/consts/nr.h"
|
||||
|
||||
extern void(__msabi* __imp_ExitProcess)(uint32_t);
|
||||
|
||||
/**
|
||||
* Terminates process, ignoring destructors and atexit() handlers.
|
||||
*
|
||||
* When running on bare metal, this function will reboot your computer
|
||||
* by hosing the interrupt descriptors and triple faulting the system.
|
||||
*
|
||||
* @param exitcode is masked with 255
|
||||
* @asyncsignalsafe
|
||||
* @vforksafe
|
||||
* @noreturn
|
||||
*/
|
||||
privileged noinstrument noasan noubsan wontreturn void _Exit(int exitcode) {
|
||||
if ((!IsWindows() && !IsMetal()) || (IsMetal() && IsGenuineCosmo())) {
|
||||
asm volatile("syscall"
|
||||
: /* no outputs */
|
||||
: "a"(__NR_exit_group), "D"(exitcode)
|
||||
: "memory");
|
||||
} else if (IsWindows()) {
|
||||
__imp_ExitProcess(exitcode & 0xff);
|
||||
}
|
||||
asm("push\t$0\n\t"
|
||||
"push\t$0\n\t"
|
||||
"cli\n\t"
|
||||
"lidt\t(%rsp)");
|
||||
for (;;) asm("ud2");
|
||||
}
|
|
@ -41,12 +41,27 @@ $(LIBC_INTRIN_A).pkg: \
|
|||
$(LIBC_INTRIN_A_OBJS) \
|
||||
$(foreach x,$(LIBC_INTRIN_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
$(LIBC_INTRIN_A_OBJS): \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-foptimize-sibling-calls
|
||||
|
||||
o/$(MODE)/libc/intrin/asan.o \
|
||||
o/$(MODE)/libc/intrin/ubsan.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-fno-sanitize=all \
|
||||
-fno-stack-protector \
|
||||
-O3
|
||||
-fno-stack-protector
|
||||
|
||||
o/$(MODE)/libc/intrin/asan.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-O2 \
|
||||
-finline \
|
||||
-finline-functions
|
||||
|
||||
o/$(MODE)/libc/intrin/asan.o \
|
||||
o/$(MODE)/libc/intrin/ubsan.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-fno-sanitize=all \
|
||||
-fno-stack-protector
|
||||
|
||||
o/$(MODE)/libc/intrin/memcmp.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
|
@ -63,12 +78,18 @@ o//libc/intrin/memmove.o: \
|
|||
OVERRIDE_CFLAGS += \
|
||||
-O3
|
||||
|
||||
o/tiny/libc/intrin/memcmp.o \
|
||||
o/tiny/libc/intrin/memmove.o \
|
||||
o/tiny/libc/intrin/memmove-gcc.asm: \
|
||||
o/$(MODE)/libc/intrin/bzero.o \
|
||||
o/$(MODE)/libc/intrin/memcmp.o \
|
||||
o/$(MODE)/libc/intrin/memmove.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-fpie
|
||||
|
||||
o/$(MODE)/libc/intrin/printf.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-Os \
|
||||
-fpie \
|
||||
-mgeneral-regs-only
|
||||
|
||||
LIBC_INTRIN_LIBS = $(foreach x,$(LIBC_INTRIN_ARTIFACTS),$($(x)))
|
||||
LIBC_INTRIN_HDRS = $(foreach x,$(LIBC_INTRIN_ARTIFACTS),$($(x)_HDRS))
|
||||
LIBC_INTRIN_SRCS = $(foreach x,$(LIBC_INTRIN_ARTIFACTS),$($(x)_SRCS))
|
||||
|
|
58
libc/intrin/isdebuggerpresent.c
Normal file
58
libc/intrin/isdebuggerpresent.c
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*-*- 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. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/nexgen32e/vendor.internal.h"
|
||||
#include "libc/nt/struct/teb.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
||||
#define kBufSize 1024
|
||||
#define kPid "TracerPid:\t"
|
||||
|
||||
/**
|
||||
* Determines if gdb, strace, windbg, etc. is controlling process.
|
||||
* @return non-zero if attached, otherwise 0
|
||||
*/
|
||||
noasan noubsan int IsDebuggerPresent(bool force) {
|
||||
/* asan runtime depends on this function */
|
||||
int fd, res;
|
||||
ssize_t got;
|
||||
char *p, buf[1024];
|
||||
if (!force) {
|
||||
if (IsGenuineCosmo()) return 0;
|
||||
if (__getenv(__envp, "HEISENDEBUG")) return 0;
|
||||
}
|
||||
if (IsWindows()) {
|
||||
return NtGetPeb()->BeingDebugged; /* needs noasan */
|
||||
} else {
|
||||
res = 0;
|
||||
if ((fd = __sysv_open("/proc/self/status", O_RDONLY, 0)) >= 0) {
|
||||
if ((got = __sysv_read(fd, buf, sizeof(buf) - 1)) > 0) {
|
||||
buf[got] = '\0';
|
||||
if ((p = __strstr(buf, kPid))) {
|
||||
p += sizeof(kPid) - 1;
|
||||
res = __atoul(p);
|
||||
}
|
||||
}
|
||||
__sysv_close(fd);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
40
libc/intrin/isrunningundermake.c
Normal file
40
libc/intrin/isrunningundermake.c
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*-*- 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. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
bool g_isrunningundermake;
|
||||
|
||||
/**
|
||||
* Returns true if current process was spawned by GNU Make.
|
||||
*/
|
||||
bool IsRunningUnderMake(void) {
|
||||
return g_isrunningundermake;
|
||||
}
|
||||
|
||||
textstartup void g_isrunningundermake_init(int argc, char **argv, char **envp,
|
||||
intptr_t *auxv) {
|
||||
g_isrunningundermake = !!__getenv(envp, "MAKEFLAGS");
|
||||
}
|
||||
|
||||
const void *const g_isrunningundermake_ctor[] initarray = {
|
||||
g_isrunningundermake_init,
|
||||
};
|
46
libc/intrin/isterminalinarticulate.c
Normal file
46
libc/intrin/isterminalinarticulate.c
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*-*- 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. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.internal.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/nt/enum/version.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
bool g_isterminalinarticulate;
|
||||
|
||||
bool IsTerminalInarticulate(void) {
|
||||
return g_isterminalinarticulate;
|
||||
}
|
||||
|
||||
textstartup noasan void g_isterminalinarticulate_init(int argc, char **argv,
|
||||
char **envp,
|
||||
intptr_t *auxv) {
|
||||
char *s;
|
||||
if (IsWindows() && NtGetVersion() < kNtVersionWindows10) {
|
||||
g_isterminalinarticulate = true;
|
||||
} else if ((s = __getenv(envp, "TERM"))) {
|
||||
g_isterminalinarticulate = !__strcmp(s, "dumb");
|
||||
}
|
||||
}
|
||||
|
||||
const void *const g_isterminalinarticulate_ctor[] initarray = {
|
||||
g_isterminalinarticulate_init,
|
||||
};
|
|
@ -21,6 +21,8 @@
|
|||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
#define PMOVMSKB(x) __builtin_ia32_pmovmskb128(x)
|
||||
|
||||
typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(1)));
|
||||
|
||||
static noinline antiquity int memcmp_sse(const unsigned char *p,
|
||||
|
@ -29,9 +31,7 @@ static noinline antiquity int memcmp_sse(const unsigned char *p,
|
|||
unsigned u, u0, u1, u2, u3;
|
||||
if (n > 32) {
|
||||
while (n > 16 + 16) {
|
||||
if (!(u = __builtin_ia32_pmovmskb128(*(const xmm_t *)p ==
|
||||
*(const xmm_t *)q) -
|
||||
0xffff)) {
|
||||
if (!(u = PMOVMSKB(*(xmm_t *)p == *(xmm_t *)q) ^ 0xffff)) {
|
||||
n -= 16;
|
||||
p += 16;
|
||||
q += 16;
|
||||
|
@ -41,10 +41,8 @@ static noinline antiquity int memcmp_sse(const unsigned char *p,
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!(u = __builtin_ia32_pmovmskb128(*(const xmm_t *)p == *(const xmm_t *)q) -
|
||||
0xffff)) {
|
||||
if (!(u = __builtin_ia32_pmovmskb128(*(const xmm_t *)(p + n - 16) ==
|
||||
*(const xmm_t *)(q + n - 16)) -
|
||||
if (!(u = PMOVMSKB(*(xmm_t *)p == *(xmm_t *)q) ^ 0xffff)) {
|
||||
if (!(u = PMOVMSKB(*(xmm_t *)(p + n - 16) == *(xmm_t *)(q + n - 16)) ^
|
||||
0xffff)) {
|
||||
return 0;
|
||||
} else {
|
||||
|
@ -61,19 +59,13 @@ microarchitecture("avx") static int memcmp_avx(const unsigned char *p,
|
|||
const unsigned char *q,
|
||||
size_t n) {
|
||||
uint64_t w;
|
||||
unsigned u, u0, u1, u2, u3;
|
||||
unsigned u;
|
||||
if (n > 32) {
|
||||
while (n >= 16 + 64) {
|
||||
u0 = __builtin_ia32_pmovmskb128(
|
||||
(((const xmm_t *)p)[0] == ((const xmm_t *)q)[0]));
|
||||
u1 = __builtin_ia32_pmovmskb128(
|
||||
(((const xmm_t *)p)[1] == ((const xmm_t *)q)[1]));
|
||||
u2 = __builtin_ia32_pmovmskb128(
|
||||
(((const xmm_t *)p)[2] == ((const xmm_t *)q)[2]));
|
||||
u3 = __builtin_ia32_pmovmskb128(
|
||||
(((const xmm_t *)p)[3] == ((const xmm_t *)q)[3]));
|
||||
w = (uint64_t)u0 | (uint64_t)u1 << 16 | (uint64_t)u2 << 32 |
|
||||
(uint64_t)u3 << 48;
|
||||
w = (uint64_t)PMOVMSKB(((xmm_t *)p)[0] == ((xmm_t *)q)[0]) << 000 |
|
||||
(uint64_t)PMOVMSKB(((xmm_t *)p)[1] == ((xmm_t *)q)[1]) << 020 |
|
||||
(uint64_t)PMOVMSKB(((xmm_t *)p)[2] == ((xmm_t *)q)[2]) << 040 |
|
||||
(uint64_t)PMOVMSKB(((xmm_t *)p)[3] == ((xmm_t *)q)[3]) << 060;
|
||||
if (w == -1) {
|
||||
n -= 64;
|
||||
p += 64;
|
||||
|
@ -84,9 +76,7 @@ microarchitecture("avx") static int memcmp_avx(const unsigned char *p,
|
|||
}
|
||||
}
|
||||
while (n > 16 + 16) {
|
||||
if (!(u = __builtin_ia32_pmovmskb128(*(const xmm_t *)p ==
|
||||
*(const xmm_t *)q) -
|
||||
0xffff)) {
|
||||
if (!(u = PMOVMSKB(*(xmm_t *)p == *(xmm_t *)q) ^ 0xffff)) {
|
||||
n -= 16;
|
||||
p += 16;
|
||||
q += 16;
|
||||
|
@ -96,10 +86,8 @@ microarchitecture("avx") static int memcmp_avx(const unsigned char *p,
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!(u = __builtin_ia32_pmovmskb128(*(const xmm_t *)p == *(const xmm_t *)q) -
|
||||
0xffff)) {
|
||||
if (!(u = __builtin_ia32_pmovmskb128(*(const xmm_t *)(p + n - 16) ==
|
||||
*(const xmm_t *)(q + n - 16)) -
|
||||
if (!(u = PMOVMSKB(*(xmm_t *)p == *(xmm_t *)q) ^ 0xffff)) {
|
||||
if (!(u = PMOVMSKB(*(xmm_t *)(p + n - 16) == *(xmm_t *)(q + n - 16)) ^
|
||||
0xffff)) {
|
||||
return 0;
|
||||
} else {
|
||||
|
|
|
@ -26,9 +26,6 @@
|
|||
typedef long long xmm_t __attribute__((__vector_size__(16), __aligned__(1)));
|
||||
typedef long long xmm_a __attribute__((__vector_size__(16), __aligned__(16)));
|
||||
|
||||
asm("memcpy = memmove\n\t"
|
||||
".globl\tmemcpy");
|
||||
|
||||
/**
|
||||
* Copies memory.
|
||||
*
|
||||
|
@ -120,8 +117,6 @@ void *memmove(void *dst, const void *src, size_t n) {
|
|||
*d = *s;
|
||||
}
|
||||
} else {
|
||||
if (IsAsan()) __asan_check(d, n);
|
||||
if (IsAsan()) __asan_check(s, n);
|
||||
if (d <= s) {
|
||||
asm("rep movsb"
|
||||
: "+D"(d), "+S"(s), "+c"(n), "=m"(*(char(*)[n])dst)
|
||||
|
@ -224,8 +219,8 @@ void *memmove(void *dst, const void *src, size_t n) {
|
|||
*(xmm_t *)(d + n + 16) = w;
|
||||
} while (n >= 32);
|
||||
} else {
|
||||
if (IsAsan()) __asan_check(d, n);
|
||||
if (IsAsan()) __asan_check(s, n);
|
||||
if (IsAsan()) __asan_verify(d, n);
|
||||
if (IsAsan()) __asan_verify(s, n);
|
||||
asm("std\n\t"
|
||||
"rep movsb\n\t"
|
||||
"cld"
|
||||
|
@ -246,8 +241,8 @@ void *memmove(void *dst, const void *src, size_t n) {
|
|||
s += i;
|
||||
n -= i;
|
||||
} else {
|
||||
if (IsAsan()) __asan_check(d, n);
|
||||
if (IsAsan()) __asan_check(s, n);
|
||||
if (IsAsan()) __asan_verify(d, n);
|
||||
if (IsAsan()) __asan_verify(s, n);
|
||||
asm("rep movsb"
|
||||
: "+D"(d), "+S"(s), "+c"(n), "=m"(*(char(*)[n])d)
|
||||
: "m"(*(char(*)[n])s));
|
||||
|
@ -313,3 +308,6 @@ void *memmove(void *dst, const void *src, size_t n) {
|
|||
return dst;
|
||||
}
|
||||
}
|
||||
|
||||
asm("memcpy = memmove\n\t"
|
||||
".globl\tmemcpy");
|
||||
|
|
|
@ -28,7 +28,7 @@ typedef long long xmm_a __attribute__((__vector_size__(16), __aligned__(16)));
|
|||
|
||||
noasan static noinline antiquity void *memset_sse(char *p, char c, size_t n) {
|
||||
xmm_t v = {c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c};
|
||||
if (IsAsan()) __asan_check(p, n);
|
||||
if (IsAsan()) __asan_verify(p, n);
|
||||
if (n <= 32) {
|
||||
*(xmm_t *)(p + n - 16) = v;
|
||||
*(xmm_t *)p = v;
|
||||
|
@ -48,7 +48,7 @@ noasan microarchitecture("avx") static void *memset_avx(char *p, char c,
|
|||
size_t n) {
|
||||
char *t;
|
||||
xmm_t v = {c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c};
|
||||
if (IsAsan()) __asan_check(p, n);
|
||||
if (IsAsan()) __asan_verify(p, n);
|
||||
if (n <= 32) {
|
||||
*(xmm_t *)(p + n - 16) = v;
|
||||
*(xmm_t *)p = v;
|
||||
|
@ -140,11 +140,6 @@ void *memset(void *p, int c, size_t n) {
|
|||
uint32_t u;
|
||||
uint64_t x;
|
||||
b = p;
|
||||
if (IsTiny()) {
|
||||
if (IsAsan()) __asan_check(p, n);
|
||||
asm("rep stosb" : "+D"(b), "+c"(n), "=m"(*(char(*)[n])b) : "0"(p), "a"(c));
|
||||
return p;
|
||||
}
|
||||
if (n <= 16) {
|
||||
if (n >= 8) {
|
||||
x = 0x0101010101010101ul * (c & 255);
|
||||
|
@ -161,6 +156,9 @@ void *memset(void *p, int c, size_t n) {
|
|||
} while (n);
|
||||
}
|
||||
return b;
|
||||
} else if (IsTiny()) {
|
||||
asm("rep stosb" : "+D"(b), "+c"(n), "=m"(*(char(*)[n])b) : "0"(p), "a"(c));
|
||||
return p;
|
||||
} else if (X86_HAVE(AVX)) {
|
||||
return memset_avx(b, c, n);
|
||||
} else {
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
#include "libc/nexgen32e/bsr.h"
|
||||
#include "libc/nexgen32e/uart.internal.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
@ -26,23 +25,25 @@
|
|||
#include "libc/sysv/consts/nr.h"
|
||||
|
||||
/**
|
||||
* Low-level printf.
|
||||
* Privileged printf.
|
||||
*
|
||||
* This will work without any cosmopolitan runtime support once the
|
||||
* executable has been loaded into memory.
|
||||
*/
|
||||
privileged noasan noinstrument void __printf(const char *fmt, ...) {
|
||||
long d, ax;
|
||||
privileged noasan noubsan noinstrument void __printf(const char *fmt, ...) {
|
||||
/* system call support runtime depends on this function */
|
||||
/* function tracing runtime depends on this function */
|
||||
/* asan runtime depends on this function */
|
||||
short w[2];
|
||||
va_list va;
|
||||
uint16_t dx;
|
||||
const char *s;
|
||||
const void *s;
|
||||
uint32_t wrote;
|
||||
unsigned long x;
|
||||
unsigned char al;
|
||||
const char16_t *S;
|
||||
int i, n, t, w, plus;
|
||||
char c, f, *p, *e, b[2048];
|
||||
w = 0;
|
||||
int i, j, t, cstr;
|
||||
long d, rax, rdi, rsi, rdx, dot;
|
||||
char c, *p, *e, pad, bits, base, sign, thou, z[28], b[2048];
|
||||
p = b;
|
||||
e = p + sizeof(b);
|
||||
va_start(va, fmt);
|
||||
|
@ -56,98 +57,132 @@ privileged noasan noinstrument void __printf(const char *fmt, ...) {
|
|||
case '\0':
|
||||
break;
|
||||
case '%':
|
||||
w = 0;
|
||||
f = ' ';
|
||||
plus = 0;
|
||||
n = INT_MAX;
|
||||
dot = 0;
|
||||
pad = ' ';
|
||||
sign = 0;
|
||||
bits = 0;
|
||||
thou = 0;
|
||||
w[0] = 0;
|
||||
w[1] = SHRT_MAX;
|
||||
NeedMoar:
|
||||
switch ((c = *fmt++)) {
|
||||
case '\0':
|
||||
break;
|
||||
case '0':
|
||||
f = c;
|
||||
case 'l':
|
||||
case 'z':
|
||||
goto NeedMoar;
|
||||
case ' ':
|
||||
case '+':
|
||||
plus = c;
|
||||
sign = c;
|
||||
goto NeedMoar;
|
||||
case 'e':
|
||||
dot = 1;
|
||||
goto NeedMoar;
|
||||
case ',':
|
||||
thou = c;
|
||||
goto NeedMoar;
|
||||
case 'h':
|
||||
bits = 16;
|
||||
goto NeedMoar;
|
||||
case '0':
|
||||
pad = c;
|
||||
/* fallthrough */
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
w[dot] *= 10;
|
||||
w[dot] += c - '0';
|
||||
goto NeedMoar;
|
||||
case '*':
|
||||
w = va_arg(va, int);
|
||||
w[dot] = va_arg(va, int);
|
||||
goto NeedMoar;
|
||||
case 'd':
|
||||
d = va_arg(va, long);
|
||||
ApiAbuse:
|
||||
if (p + 22 <= e) {
|
||||
if (d || !plus) {
|
||||
if (d > 0 && plus) {
|
||||
*p++ = plus;
|
||||
}
|
||||
p = __intcpy(p, d);
|
||||
x = d;
|
||||
if (d < 0) {
|
||||
x = -x;
|
||||
sign = '-';
|
||||
}
|
||||
for (i = j = 0;;) {
|
||||
z[i++] = x % 10 + '0';
|
||||
if (!(x /= 10)) break;
|
||||
if (thou && !(++j % 3)) {
|
||||
z[i++] = thou;
|
||||
}
|
||||
}
|
||||
if (sign) {
|
||||
z[i++] = sign;
|
||||
}
|
||||
EmitNumber:
|
||||
while (w[0]-- > i) {
|
||||
if (p < e) *p++ = pad;
|
||||
}
|
||||
do {
|
||||
if (p < e) *p++ = z[--i];
|
||||
} while (i);
|
||||
break;
|
||||
case 'b':
|
||||
base = 1;
|
||||
BinaryNumber:
|
||||
i = 0;
|
||||
x = va_arg(va, unsigned long);
|
||||
do z[i++] = "0123456789abcdef"[x & ((1 << base) - 1)];
|
||||
while ((x >>= base) && i < w[1]);
|
||||
goto EmitNumber;
|
||||
case 'p':
|
||||
w = 12;
|
||||
f = '0';
|
||||
pad = '0';
|
||||
w[0] = 12;
|
||||
w[1] = 12;
|
||||
/* fallthrough */
|
||||
case 'x':
|
||||
x = va_arg(va, unsigned long);
|
||||
if (x) {
|
||||
n = __builtin_clzl(x) ^ (sizeof(long) * 8 - 1);
|
||||
n >>= 2;
|
||||
n += 1;
|
||||
} else {
|
||||
n = 1;
|
||||
}
|
||||
while (w-- > n) {
|
||||
if (p < e) {
|
||||
*p++ = f;
|
||||
}
|
||||
}
|
||||
while (n--) {
|
||||
if (p < e) {
|
||||
*p++ = "0123456789abcdef"[(x >> (n << 2)) & 15];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'S':
|
||||
n = va_arg(va, int);
|
||||
/* fallthrough */
|
||||
base = 4;
|
||||
goto BinaryNumber;
|
||||
case 'o':
|
||||
base = 3;
|
||||
goto BinaryNumber;
|
||||
case 'c':
|
||||
cstr = va_arg(va, int);
|
||||
s = &cstr;
|
||||
goto EmitString;
|
||||
case 's':
|
||||
s = va_arg(va, const char *);
|
||||
s = va_arg(va, const void *);
|
||||
EmitString:
|
||||
if (!s) {
|
||||
EmitNullString:
|
||||
s = "NULL";
|
||||
}
|
||||
if ((uintptr_t)s < PAGESIZE) {
|
||||
bits = 0;
|
||||
} else if ((uintptr_t)s < PAGESIZE) {
|
||||
d = (intptr_t)s;
|
||||
goto ApiAbuse;
|
||||
}
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (!s[i]) {
|
||||
n = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (w-- > n) {
|
||||
if (p < e) {
|
||||
*p++ = f;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < n && p < e; ++i) {
|
||||
*p++ = s[i];
|
||||
}
|
||||
break;
|
||||
case 'u':
|
||||
S = va_arg(va, const char16_t *);
|
||||
if (!S) goto EmitNullString;
|
||||
while ((t = *S++)) {
|
||||
if (p + 3 <= e && (t & 0xfc00) != 0xdc00) {
|
||||
if (t <= 0x7ff) {
|
||||
p[0] = 0300 | t >> 6;
|
||||
p[1] = 0200 | x << 8 | t & 077;
|
||||
p += 2;
|
||||
for (i = 0; i < w[1]; ++i) {
|
||||
if (!bits) {
|
||||
t = ((const char *)s)[i];
|
||||
EmitByte:
|
||||
if (t) {
|
||||
if (p < e) {
|
||||
*p++ = t;
|
||||
}
|
||||
} else {
|
||||
if (t > 0xffff) t = 0xfffd;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
t = ((const char16_t *)s)[i];
|
||||
if (t <= 0x7f) {
|
||||
goto EmitByte;
|
||||
} else if (t <= 0x7ff) {
|
||||
if (p + 1 < e) {
|
||||
p[0] = 0300 | t >> 6;
|
||||
p[1] = 0200 | x << 8 | t & 077;
|
||||
p += 2;
|
||||
}
|
||||
} else if (p + 2 < e) {
|
||||
p[0] = 0340 | t >> 12;
|
||||
p[1] = 0200 | x << 8 | (t >> 6) & 077;
|
||||
p[2] = 0200 | x << 8 | t & 077;
|
||||
|
@ -155,6 +190,9 @@ privileged noasan noinstrument void __printf(const char *fmt, ...) {
|
|||
}
|
||||
}
|
||||
}
|
||||
while (w[0]-- > i) {
|
||||
if (p < e) *p++ = pad;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -186,8 +224,8 @@ privileged noasan noinstrument void __printf(const char *fmt, ...) {
|
|||
}
|
||||
} else {
|
||||
asm volatile("syscall"
|
||||
: "=a"(ax)
|
||||
: "0"(__NR_write), "D"(2), "S"(b), "d"(p - b)
|
||||
: "rcx", "r11", "memory");
|
||||
: "=a"(rax), "=D"(rdi), "=S"(rsi), "=d"(rdx)
|
||||
: "0"(__NR_write), "1"(2L), "2"(b), "3"(p - b)
|
||||
: "rcx", "r8", "r9", "r10", "r11", "memory", "cc");
|
||||
}
|
||||
}
|
||||
|
|
37
libc/intrin/printsystemmappings.c
Normal file
37
libc/intrin/printsystemmappings.c
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*-*- 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 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
||||
privileged void PrintSystemMappings(int outfd) {
|
||||
int infd;
|
||||
ssize_t rc;
|
||||
char buf[64];
|
||||
if (!IsWindows()) {
|
||||
if ((infd = __sysv_open("/proc/self/maps", O_RDONLY, 0)) >= 0) {
|
||||
__sysv_write(outfd, "\n", 1);
|
||||
while ((rc = __sysv_read(infd, buf, sizeof(buf))) > 0) {
|
||||
__sysv_write(outfd, buf, rc);
|
||||
}
|
||||
}
|
||||
__sysv_close(infd);
|
||||
}
|
||||
}
|
|
@ -19,384 +19,165 @@
|
|||
#include "libc/macros.internal.h"
|
||||
.source __FILE__
|
||||
|
||||
.macro .acall fn:req
|
||||
xor %eax,%eax
|
||||
mov $1,%r10b
|
||||
cmpxchg %r10b,__asan_noreentry(%rip)
|
||||
jnz 2f
|
||||
call \fn
|
||||
decb __asan_noreentry(%rip)
|
||||
2: nop
|
||||
.endm
|
||||
|
||||
.rodata.cst4
|
||||
__asan_option_detect_stack_use_after_return:
|
||||
.long 0
|
||||
.endobj __asan_option_detect_stack_use_after_return,globl
|
||||
.previous
|
||||
|
||||
.bss
|
||||
__asan_noreentry:
|
||||
.byte 0
|
||||
.endobj __asan_noreentry
|
||||
.previous
|
||||
|
||||
__asan_report_load1:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $1,%esi
|
||||
.acall __asan_report_load
|
||||
pop %rbp
|
||||
ret
|
||||
push $1
|
||||
jmp 1f
|
||||
.endfn __asan_report_load1,globl
|
||||
|
||||
__asan_report_load2:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $2,%esi
|
||||
.acall __asan_report_load
|
||||
pop %rbp
|
||||
ret
|
||||
push $2
|
||||
jmp 1f
|
||||
.endfn __asan_report_load2,globl
|
||||
|
||||
__asan_report_load4:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $4,%esi
|
||||
.acall __asan_report_load
|
||||
pop %rbp
|
||||
ret
|
||||
push $4
|
||||
jmp 1f
|
||||
.endfn __asan_report_load4,globl
|
||||
|
||||
__asan_report_load8:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $8,%esi
|
||||
.acall __asan_report_load
|
||||
pop %rbp
|
||||
ret
|
||||
push $8
|
||||
jmp 1f
|
||||
.endfn __asan_report_load8,globl
|
||||
|
||||
__asan_report_load16:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $16,%esi
|
||||
.acall __asan_report_load
|
||||
pop %rbp
|
||||
ret
|
||||
push $16
|
||||
jmp 1f
|
||||
.endfn __asan_report_load16,globl
|
||||
|
||||
__asan_report_load32:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $32,%esi
|
||||
.acall __asan_report_load
|
||||
pop %rbp
|
||||
ret
|
||||
push $32
|
||||
1: pop %rsi
|
||||
0: jmp __asan_report_load
|
||||
.endfn __asan_report_load32,globl
|
||||
|
||||
__asan_report_load_n:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
.acall __asan_report_load
|
||||
pop %rbp
|
||||
ret
|
||||
jmp 0b
|
||||
.endfn __asan_report_load_n,globl
|
||||
|
||||
__asan_report_store1:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $1,%esi
|
||||
.acall __asan_report_store
|
||||
pop %rbp
|
||||
ret
|
||||
push $1
|
||||
jmp 1f
|
||||
.endfn __asan_report_store1,globl
|
||||
|
||||
__asan_report_store2:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $2,%esi
|
||||
.acall __asan_report_store
|
||||
pop %rbp
|
||||
ret
|
||||
push $2
|
||||
jmp 1f
|
||||
.endfn __asan_report_store2,globl
|
||||
|
||||
__asan_report_store4:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $4,%esi
|
||||
.acall __asan_report_store
|
||||
pop %rbp
|
||||
ret
|
||||
push $4
|
||||
jmp 1f
|
||||
.endfn __asan_report_store4,globl
|
||||
|
||||
__asan_report_store8:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $8,%esi
|
||||
.acall __asan_report_store
|
||||
pop %rbp
|
||||
ret
|
||||
push $8
|
||||
jmp 1f
|
||||
.endfn __asan_report_store8,globl
|
||||
|
||||
__asan_report_store16:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $16,%esi
|
||||
.acall __asan_report_store
|
||||
pop %rbp
|
||||
ret
|
||||
push $16
|
||||
jmp 1f
|
||||
.endfn __asan_report_store16,globl
|
||||
|
||||
__asan_report_store32:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $32,%esi
|
||||
.acall __asan_report_store
|
||||
pop %rbp
|
||||
ret
|
||||
push $32
|
||||
1: pop %rsi
|
||||
0: jmp __asan_report_store
|
||||
.endfn __asan_report_store32,globl
|
||||
|
||||
__asan_report_store_n:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
.acall __asan_report_store
|
||||
pop %rbp
|
||||
ret
|
||||
jmp 0b
|
||||
.endfn __asan_report_store_n,globl
|
||||
|
||||
__asan_stack_free_0:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $0,%edx
|
||||
call __asan_stack_free
|
||||
pop %rbp
|
||||
ret
|
||||
push $0
|
||||
jmp 1f
|
||||
.endfn __asan_stack_free_0,globl
|
||||
|
||||
__asan_stack_free_1:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $1,%edx
|
||||
call __asan_stack_free
|
||||
pop %rbp
|
||||
ret
|
||||
push $1
|
||||
jmp 1f
|
||||
.endfn __asan_stack_free_1,globl
|
||||
|
||||
__asan_stack_free_2:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $2,%edx
|
||||
call __asan_stack_free
|
||||
pop %rbp
|
||||
ret
|
||||
push $2
|
||||
jmp 1f
|
||||
.endfn __asan_stack_free_2,globl
|
||||
|
||||
__asan_stack_free_3:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $3,%edx
|
||||
call __asan_stack_free
|
||||
pop %rbp
|
||||
ret
|
||||
push $3
|
||||
jmp 1f
|
||||
.endfn __asan_stack_free_3,globl
|
||||
|
||||
__asan_stack_free_4:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $4,%edx
|
||||
call __asan_stack_free
|
||||
pop %rbp
|
||||
ret
|
||||
push $4
|
||||
jmp 1f
|
||||
.endfn __asan_stack_free_4,globl
|
||||
|
||||
__asan_stack_free_5:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $5,%edx
|
||||
call __asan_stack_free
|
||||
pop %rbp
|
||||
ret
|
||||
push $5
|
||||
.endfn __asan_stack_free_5,globl
|
||||
|
||||
__asan_stack_free_hop:
|
||||
1: pop %rdx
|
||||
jmp __asan_stack_free
|
||||
.endfn __asan_report_store_n,globl
|
||||
__asan_stack_free_6:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $6,%edx
|
||||
call __asan_stack_free
|
||||
pop %rbp
|
||||
ret
|
||||
push $6
|
||||
jmp 1b
|
||||
.endfn __asan_stack_free_6,globl
|
||||
|
||||
__asan_stack_free_7:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $7,%edx
|
||||
call __asan_stack_free
|
||||
pop %rbp
|
||||
ret
|
||||
push $7
|
||||
jmp 1b
|
||||
.endfn __asan_stack_free_7,globl
|
||||
|
||||
__asan_stack_free_8:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $8,%edx
|
||||
call __asan_stack_free
|
||||
pop %rbp
|
||||
ret
|
||||
push $8
|
||||
jmp 1b
|
||||
.endfn __asan_stack_free_8,globl
|
||||
|
||||
__asan_stack_free_9:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $9,%edx
|
||||
call __asan_stack_free
|
||||
pop %rbp
|
||||
ret
|
||||
push $9
|
||||
jmp 1b
|
||||
.endfn __asan_stack_free_9,globl
|
||||
|
||||
__asan_stack_free_10:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $10,%edx
|
||||
call __asan_stack_free
|
||||
pop %rbp
|
||||
ret
|
||||
push $10
|
||||
jmp 1b
|
||||
.endfn __asan_stack_free_10,globl
|
||||
|
||||
__asan_stack_malloc_0:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $0,%esi
|
||||
call __asan_stack_malloc
|
||||
pop %rbp
|
||||
ret
|
||||
push $0
|
||||
jmp 1f
|
||||
.endfn __asan_stack_malloc_0,globl
|
||||
|
||||
__asan_stack_malloc_1:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $1,%esi
|
||||
call __asan_stack_malloc
|
||||
pop %rbp
|
||||
ret
|
||||
push $1
|
||||
jmp 1f
|
||||
.endfn __asan_stack_malloc_1,globl
|
||||
|
||||
__asan_stack_malloc_2:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $2,%esi
|
||||
call __asan_stack_malloc
|
||||
pop %rbp
|
||||
ret
|
||||
push $2
|
||||
jmp 1f
|
||||
.endfn __asan_stack_malloc_2,globl
|
||||
|
||||
__asan_stack_malloc_3:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $3,%esi
|
||||
call __asan_stack_malloc
|
||||
pop %rbp
|
||||
ret
|
||||
push $3
|
||||
jmp 1f
|
||||
.endfn __asan_stack_malloc_3,globl
|
||||
|
||||
__asan_stack_malloc_4:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $4,%esi
|
||||
call __asan_stack_malloc
|
||||
pop %rbp
|
||||
ret
|
||||
push $4
|
||||
jmp 1f
|
||||
.endfn __asan_stack_malloc_4,globl
|
||||
|
||||
__asan_stack_malloc_5:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $5,%esi
|
||||
call __asan_stack_malloc
|
||||
pop %rbp
|
||||
ret
|
||||
push $5
|
||||
jmp 1f
|
||||
.endfn __asan_stack_malloc_5,globl
|
||||
|
||||
__asan_stack_malloc_hop:
|
||||
1: pop %rsi
|
||||
jmp __asan_stack_malloc
|
||||
.endfn __asan_report_store_n,globl
|
||||
__asan_stack_malloc_6:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $6,%esi
|
||||
call __asan_stack_malloc
|
||||
pop %rbp
|
||||
ret
|
||||
push $6
|
||||
jmp 1b
|
||||
.endfn __asan_stack_malloc_6,globl
|
||||
|
||||
__asan_stack_malloc_7:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $7,%esi
|
||||
call __asan_stack_malloc
|
||||
pop %rbp
|
||||
ret
|
||||
push $7
|
||||
jmp 1b
|
||||
.endfn __asan_stack_malloc_7,globl
|
||||
|
||||
__asan_stack_malloc_8:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $8,%esi
|
||||
call __asan_stack_malloc
|
||||
pop %rbp
|
||||
ret
|
||||
push $8
|
||||
jmp 1b
|
||||
.endfn __asan_stack_malloc_8,globl
|
||||
|
||||
__asan_stack_malloc_9:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $9,%esi
|
||||
call __asan_stack_malloc
|
||||
pop %rbp
|
||||
ret
|
||||
push $9
|
||||
jmp 1b
|
||||
.endfn __asan_stack_malloc_9,globl
|
||||
|
||||
__asan_stack_malloc_10:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
mov $10,%esi
|
||||
call __asan_stack_malloc
|
||||
pop %rbp
|
||||
ret
|
||||
push $10
|
||||
jmp 1b
|
||||
.endfn __asan_stack_malloc_10,globl
|
||||
|
||||
__asan_version_mismatch_check_v8:
|
||||
|
|
|
@ -17,8 +17,49 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.internal.h"
|
||||
.privileged
|
||||
|
||||
// Invokes SYSCALL for libfatal forceinline asm() routines.
|
||||
//
|
||||
// @param rax is ordinal
|
||||
// @param rdi is arg1
|
||||
// @param rsi is arg2
|
||||
// @param rdx is arg3
|
||||
// @param rcx is arg4
|
||||
// @param r8 is arg5
|
||||
// @param r9 is arg6
|
||||
// @param rsp may contain more args
|
||||
// @return rdx:rax where rax holds -errno on error
|
||||
// @clob rax,rdx,memory,cc
|
||||
__syscall__:
|
||||
mov %rcx,.Lrcx(%rip)
|
||||
mov %rdi,.Lrdi(%rip)
|
||||
mov %rsi,.Lrsi(%rip)
|
||||
mov %r8,.Lr8(%rip)
|
||||
mov %r9,.Lr9(%rip)
|
||||
mov %r10,.Lr10(%rip)
|
||||
mov %r11,.Lr11(%rip)
|
||||
mov %rcx,%r10
|
||||
clc
|
||||
syscall
|
||||
jnc 1f
|
||||
neg %rax
|
||||
1: mov .Lrcx(%rip),%rcx
|
||||
mov .Lrdi(%rip),%rdi
|
||||
mov .Lrsi(%rip),%rsi
|
||||
mov .Lr8(%rip),%r8
|
||||
mov .Lr9(%rip),%r9
|
||||
mov .Lr10(%rip),%r10
|
||||
mov .Lr11(%rip),%r11
|
||||
ret
|
||||
.endfn __syscall__,globl,hidden
|
||||
|
||||
.bss
|
||||
.align 8
|
||||
.Lrcx: .quad 0 # clobbered by syscall
|
||||
.Lrdi: .quad 0 # just in case
|
||||
.Lrsi: .quad 0 # just in case
|
||||
.Lr8: .quad 0 # freebsd bug?
|
||||
.Lr9: .quad 0 # just in case
|
||||
.Lr10: .quad 0 # just in case
|
||||
.Lr11: .quad 0 # clobbered by syscall
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
|
@ -151,55 +152,19 @@ static bool __ubsan_negative(struct UbsanTypeDescriptor *t, uintptr_t x) {
|
|||
return __ubsan_signed(t) && (intptr_t)x < 0;
|
||||
}
|
||||
|
||||
static size_t __ubsan_strlen(const char *s) {
|
||||
size_t n = 0;
|
||||
while (*s++) ++n;
|
||||
return n;
|
||||
}
|
||||
|
||||
static char *__ubsan_stpcpy(char *d, const char *s) {
|
||||
size_t i;
|
||||
for (i = 0;; ++i) {
|
||||
if (!(d[i] = s[i])) {
|
||||
return d + i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static char *__ubsan_poscpy(char *p, uintptr_t i) {
|
||||
int j = 0;
|
||||
do {
|
||||
p[j++] = i % 10 + '0';
|
||||
i /= 10;
|
||||
} while (i > 0);
|
||||
reverse(p, j);
|
||||
return p + j;
|
||||
}
|
||||
|
||||
static char *__ubsan_intcpy(char *p, intptr_t i) {
|
||||
if (i >= 0) return __ubsan_poscpy(p, i);
|
||||
*p++ = '-';
|
||||
return __ubsan_poscpy(p, -i);
|
||||
}
|
||||
|
||||
static char *__ubsan_hexcpy(char *p, uintptr_t x, int k) {
|
||||
while (k) *p++ = "0123456789abcdef"[(x >> (k -= 4)) & 15];
|
||||
return p;
|
||||
}
|
||||
|
||||
static char *__ubsan_itpcpy(char *p, struct UbsanTypeDescriptor *t,
|
||||
uintptr_t x) {
|
||||
if (__ubsan_signed(t)) {
|
||||
return __ubsan_intcpy(p, x);
|
||||
return __intcpy(p, x);
|
||||
} else {
|
||||
return __ubsan_poscpy(p, x);
|
||||
return __uintcpy(p, x);
|
||||
}
|
||||
}
|
||||
|
||||
static const char *__ubsan_dubnul(const char *s, unsigned i) {
|
||||
size_t n;
|
||||
while (i--) {
|
||||
if ((n = __ubsan_strlen(s))) {
|
||||
if ((n = __strlen(s))) {
|
||||
s += n + 1;
|
||||
} else {
|
||||
return NULL;
|
||||
|
@ -222,53 +187,11 @@ static uintptr_t __ubsan_extend(struct UbsanTypeDescriptor *t, uintptr_t x) {
|
|||
return x;
|
||||
}
|
||||
|
||||
static privileged noinline wontreturn void __ubsan_exit(int rc) {
|
||||
if (!IsWindows()) {
|
||||
asm volatile("syscall"
|
||||
: /* no outputs */
|
||||
: "a"(__NR_exit_group), "D"(rc)
|
||||
: "memory");
|
||||
unreachable;
|
||||
} else {
|
||||
ExitProcess(rc);
|
||||
}
|
||||
}
|
||||
|
||||
static privileged noinline ssize_t __ubsan_write(const void *data,
|
||||
size_t size) {
|
||||
ssize_t rc;
|
||||
uint32_t wrote;
|
||||
if (!IsWindows()) {
|
||||
asm volatile("syscall"
|
||||
: "=a"(rc)
|
||||
: "0"(__NR_write), "D"(2), "S"(data), "d"(size)
|
||||
: "rcx", "r11", "memory");
|
||||
return rc;
|
||||
} else {
|
||||
if (WriteFile(GetStdHandle(kNtStdErrorHandle), data, size, &wrote, 0)) {
|
||||
return wrote;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t __ubsan_write_string(const char *s) {
|
||||
return __ubsan_write(s, __ubsan_strlen(s));
|
||||
}
|
||||
|
||||
void __ubsan_abort(const struct UbsanSourceLocation *loc,
|
||||
const char *description) {
|
||||
char buf[1024], *p = buf;
|
||||
p = __ubsan_stpcpy(p, "error: ");
|
||||
p = __ubsan_stpcpy(p, loc->file), *p++ = ':';
|
||||
p = __ubsan_intcpy(p, loc->line);
|
||||
p = __ubsan_stpcpy(p, ": ");
|
||||
p = __ubsan_stpcpy(p, description);
|
||||
p = __ubsan_stpcpy(p, "\r\n");
|
||||
__ubsan_write_string(buf);
|
||||
__printf("\r\n%s:%d: ubsan error: %s\r\n", loc->file, loc->line, description);
|
||||
if (weaken(__die)) weaken(__die)();
|
||||
__ubsan_exit(134);
|
||||
_Exit(134);
|
||||
}
|
||||
|
||||
static const char *__ubsan_describe_shift(
|
||||
|
@ -291,11 +214,11 @@ void __ubsan_handle_shift_out_of_bounds(struct UbsanShiftOutOfBoundsInfo *info,
|
|||
char buf[512], *p = buf;
|
||||
lhs = __ubsan_extend(info->lhs_type, lhs);
|
||||
rhs = __ubsan_extend(info->rhs_type, rhs);
|
||||
p = __ubsan_stpcpy(p, __ubsan_describe_shift(info, lhs, rhs)), *p++ = ' ';
|
||||
p = __stpcpy(p, __ubsan_describe_shift(info, lhs, rhs)), *p++ = ' ';
|
||||
p = __ubsan_itpcpy(p, info->lhs_type, lhs), *p++ = ' ';
|
||||
p = __ubsan_stpcpy(p, info->lhs_type->name), *p++ = ' ';
|
||||
p = __stpcpy(p, info->lhs_type->name), *p++ = ' ';
|
||||
p = __ubsan_itpcpy(p, info->rhs_type, rhs), *p++ = ' ';
|
||||
p = __ubsan_stpcpy(p, info->rhs_type->name);
|
||||
p = __stpcpy(p, info->rhs_type->name);
|
||||
__ubsan_abort(&info->location, buf);
|
||||
}
|
||||
|
||||
|
@ -307,12 +230,12 @@ void __ubsan_handle_shift_out_of_bounds_abort(
|
|||
void __ubsan_handle_out_of_bounds(struct UbsanOutOfBoundsInfo *info,
|
||||
uintptr_t index) {
|
||||
char buf[512], *p = buf;
|
||||
p = __ubsan_stpcpy(p, info->index_type->name);
|
||||
p = __ubsan_stpcpy(p, " index ");
|
||||
p = __stpcpy(p, info->index_type->name);
|
||||
p = __stpcpy(p, " index ");
|
||||
p = __ubsan_itpcpy(p, info->index_type, index);
|
||||
p = __ubsan_stpcpy(p, " into ");
|
||||
p = __ubsan_stpcpy(p, info->array_type->name);
|
||||
p = __ubsan_stpcpy(p, " out of bounds");
|
||||
p = __stpcpy(p, " into ");
|
||||
p = __stpcpy(p, info->array_type->name);
|
||||
p = __stpcpy(p, " out of bounds");
|
||||
__ubsan_abort(&info->location, buf);
|
||||
}
|
||||
|
||||
|
@ -328,19 +251,19 @@ void __ubsan_handle_type_mismatch(struct UbsanTypeMismatchInfo *info,
|
|||
if (!pointer) __ubsan_abort(&info->location, "null pointer access");
|
||||
kind = __ubsan_dubnul(kUbsanTypeCheckKinds, info->type_check_kind);
|
||||
if (info->alignment && (pointer & (info->alignment - 1))) {
|
||||
p = __ubsan_stpcpy(p, "unaligned ");
|
||||
p = __ubsan_stpcpy(p, kind), *p++ = ' ';
|
||||
p = __ubsan_stpcpy(p, info->type->name), *p++ = ' ', *p++ = '@';
|
||||
p = __stpcpy(p, "unaligned ");
|
||||
p = __stpcpy(p, kind), *p++ = ' ';
|
||||
p = __stpcpy(p, info->type->name), *p++ = ' ', *p++ = '@';
|
||||
p = __ubsan_itpcpy(p, info->type, pointer);
|
||||
p = __ubsan_stpcpy(p, " align ");
|
||||
p = __ubsan_intcpy(p, info->alignment);
|
||||
p = __stpcpy(p, " align ");
|
||||
p = __intcpy(p, info->alignment);
|
||||
} else {
|
||||
p = __ubsan_stpcpy(p, "insufficient size\r\n\t");
|
||||
p = __ubsan_stpcpy(p, kind);
|
||||
p = __ubsan_stpcpy(p, " address 0x");
|
||||
p = __ubsan_hexcpy(p, pointer, sizeof(pointer) * CHAR_BIT);
|
||||
p = __ubsan_stpcpy(p, " with insufficient space for object of type ");
|
||||
p = __ubsan_stpcpy(p, info->type->name);
|
||||
p = __stpcpy(p, "insufficient size\r\n\t");
|
||||
p = __stpcpy(p, kind);
|
||||
p = __stpcpy(p, " address 0x");
|
||||
p = __fixcpy(p, pointer, sizeof(pointer) * CHAR_BIT);
|
||||
p = __stpcpy(p, " with insufficient space for object of type ");
|
||||
p = __stpcpy(p, info->type->name);
|
||||
}
|
||||
__ubsan_abort(&info->location, buf);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue