Make improvements

- Get threads working on NetBSD
- Get threads working on OpenBSD
- Fix Emacs config for Emacs v28
- Improve --strace logging of sigset_t
- Improve --strace logging of struct stat
- Improve memory safety of DescribeThing functions
- Refactor auto stack allocation into LIBC_RUNTIME
- Introduce shell.com example which works on Windows
- Refactor __strace_thing into DescribeThing functions
- Document the CHECK macros and improve them in NDEBUG mode
- Rewrite MAP_STACK so it uses FreeBSD behavior across platforms
- Deprecate and discourage the use of MAP_GROWSDOWN (it's weird)
This commit is contained in:
Justine Tunney 2022-05-12 06:43:59 -07:00
parent dd9ab01d25
commit e7611a8476
101 changed files with 967 additions and 464 deletions

View file

@ -24,19 +24,20 @@ COSMOPOLITAN_C_START_
#define DCHECK_NOTNULL(X, ...) \
__DCHK(ne, !=, NULL, "NULL", X, #X, "" __VA_ARGS__)
#define CHECK_ALIGNED(BYTES, VAR) \
do { \
if (((uintptr_t)VAR & ((BYTES)-1u))) { \
__check_fail_aligned(BYTES, (uintptr_t)VAR); \
unreachable; \
} \
VAR = (typeof(VAR))__builtin_assume_aligned(VAR, BYTES); \
#define CHECK_ALIGNED(BYTES, VAR, ...) \
do { \
if (((uintptr_t)VAR & ((BYTES)-1u))) { \
__check_fail_aligned(BYTES, (uintptr_t)VAR, __FILE__, __LINE__, \
"" __VA_ARGS__); \
unreachable; \
} \
VAR = (typeof(VAR))__builtin_assume_aligned(VAR, BYTES); \
} while (0)
#define DCHECK_ALIGNED(BYTES, VAR) \
#define DCHECK_ALIGNED(BYTES, VAR, ...) \
do { \
if (((uintptr_t)VAR & ((BYTES)-1u))) { \
__DCHK_ALIGNED(BYTES, (uintptr_t)VAR); \
__DCHK_ALIGNED(BYTES, (uintptr_t)VAR, "" __VA_ARGS__); \
unreachable; \
} \
VAR = (typeof(VAR))__builtin_assume_aligned(VAR, BYTES); \
@ -51,7 +52,8 @@ COSMOPOLITAN_C_START_
__check_fail(#SUFFIX, #OP, (uint64_t)Want, (WANTSTR), (uint64_t)Got, \
(GOTSTR), __FILE__, __LINE__, __VA_ARGS__); \
} else { \
__check_fail_##SUFFIX((uint64_t)Want, (uint64_t)Got); \
__check_fail_##SUFFIX((uint64_t)Want, (uint64_t)Got, __FILE__, \
__LINE__, 0, __VA_ARGS__); \
} \
unreachable; \
} \
@ -72,22 +74,30 @@ COSMOPOLITAN_C_START_
#endif /* NDEBUG */
#ifdef NDEBUG
#define __DCHK_ALIGNED(BYTES, VAR)
#define __DCHK_ALIGNED(BYTES, VAR, ...)
#else
#define __DCHK_ALIGNED(BYTES, VAR) __check_fail_aligned(BYTES, VAR)
#define __DCHK_ALIGNED(BYTES, VAR, ...) \
__check_fail_aligned(BYTES, VAR, __FILE__, __LINE__, __VA_ARGS__)
#endif
void __check_fail(const char *, const char *, uint64_t, const char *, uint64_t,
const char *, const char *, int, const char *,
...) relegated wontreturn;
void __check_fail_eq(uint64_t, uint64_t) relegated wontreturn;
void __check_fail_ne(uint64_t, uint64_t) relegated wontreturn;
void __check_fail_le(uint64_t, uint64_t) relegated wontreturn;
void __check_fail_lt(uint64_t, uint64_t) relegated wontreturn;
void __check_fail_ge(uint64_t, uint64_t) relegated wontreturn;
void __check_fail_gt(uint64_t, uint64_t) relegated wontreturn;
void __check_fail_aligned(unsigned, uint64_t) relegated wontreturn;
void __check_fail_eq(uint64_t, uint64_t, const char *, int, const char *,
const char *, ...) relegated wontreturn;
void __check_fail_ne(uint64_t, uint64_t, const char *, int, const char *,
const char *, ...) relegated wontreturn;
void __check_fail_le(uint64_t, uint64_t, const char *, int, const char *,
const char *, ...) relegated wontreturn;
void __check_fail_lt(uint64_t, uint64_t, const char *, int, const char *,
const char *, ...) relegated wontreturn;
void __check_fail_ge(uint64_t, uint64_t, const char *, int, const char *,
const char *, ...) relegated wontreturn;
void __check_fail_gt(uint64_t, uint64_t, const char *, int, const char *,
const char *, ...) relegated wontreturn;
void __check_fail_aligned(unsigned, uint64_t, const char *, int, const char *,
...) relegated wontreturn;
#ifdef __VSCODE_INTELLISENSE__
#undef __CHK

View file

@ -18,14 +18,16 @@
*/
#include "libc/calls/calls.h"
#include "libc/dce.h"
#include "libc/intrin/kprintf.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/stdio/stdio.h"
void __check_fail_aligned(unsigned bytes, uint64_t ptr) {
void __check_fail_aligned(unsigned bytes, uint64_t ptr, const char *file,
int line, const char *fmt, ...) {
fflush(stderr);
if (!IsTiny()) memsummary(fileno(stderr));
(dprintf)(fileno(stderr), "%s%d%s%#p\n", "error: pointer not ", bytes,
"-byte aligned: ", ptr);
kprintf("%s:%d: error: pointer not %d-byte aligned: %p\n", file, line, bytes,
ptr);
__die();
}

View file

@ -16,12 +16,12 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/errno.h"
#include "libc/bits/weaken.h"
#include "libc/intrin/kprintf.h"
#include "libc/log/internal.h"
#include "libc/log/log.h"
#include "libc/runtime/internal.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
/**
* Handles failure of CHECK_xx() macros in -DNDEBUG mode.
@ -33,12 +33,22 @@
*
* @see libc/log/thunks/__check_fail_ndebug.S
*/
relegated void ___check_fail_ndebug(uint64_t want, uint64_t got,
const char *opchar) {
relegated wontreturn void __check_fail_ndebug(uint64_t want, uint64_t got,
const char *file, int line,
const char *opchar,
const char *fmt, ...) {
va_list va;
__restore_tty();
(fprintf)(stderr, "\n%serror: %s: check failed: 0x%x %s 0x%x (%s)\n",
!__nocolor ? "\e[J" : "", program_invocation_name, want, opchar,
got, strerror(errno));
kprintf("%rerror:%s:%d: check failed: %'ld %s %'ld% m", file, line, want,
opchar, got);
if (*fmt) {
kprintf(": ");
va_start(va, fmt);
kvprintf(fmt, va);
va_end(va);
}
kprintf("\n");
if (weaken(__die)) weaken(__die)();
__restorewintty();
_Exit(68);
}

View file

@ -201,7 +201,7 @@ relegated void ShowCrashReport(int err, int sig, struct siginfo *si,
uname(&names);
p = buf;
errno = err;
kprintf("\n%serror%s: Uncaught %G (%s) on %s pid %d\n"
kprintf("\n%serror%s: Uncaught %G (%s) on %s pid %d tid %d\n"
" %s\n"
" %m\n"
" %s %s %s %s\n",
@ -210,8 +210,8 @@ relegated void ShowCrashReport(int err, int sig, struct siginfo *si,
ctx->uc_mcontext.rsp <= GetStaticStackAddr(0) + PAGESIZE))
? "Stack Overflow"
: GetSiCodeName(sig, si->si_code),
host, getpid(), program_invocation_name, names.sysname, names.version,
names.nodename, names.release);
host, getpid(), gettid(), program_invocation_name, names.sysname,
names.version, names.nodename, names.release);
if (ctx) {
kprintf("\n");
ShowFunctionCalls(ctx);

View file

@ -19,6 +19,8 @@
#include "libc/calls/sigbits.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/sigaltstack.h"
#include "libc/intrin/kprintf.h"
#include "libc/log/backtrace.internal.h"
#include "libc/log/internal.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
@ -33,6 +35,10 @@ STATIC_YOINK("__get_symbol_by_addr"); /* for asan memory origin */
extern const unsigned char __oncrash_thunks[8][11];
static void FreeSigaltstack(void *p) {
free(p);
}
/**
* Installs crash signal handlers.
*
@ -67,7 +73,7 @@ void ShowCrashReports(void) {
ss.ss_flags = 0;
ss.ss_size = SIGSTKSZ;
ss.ss_sp = malloc(SIGSTKSZ);
__cxa_atexit(free, ss.ss_sp, 0);
__cxa_atexit(FreeSigaltstack, ss.ss_sp, 0);
sa.sa_flags = SA_SIGINFO | SA_NODEFER | SA_ONSTACK;
sigfillset(&sa.sa_mask);
for (i = 0; i < ARRAYLEN(kCrashSigs); ++i) {

View file

@ -21,6 +21,10 @@
// Code-size saving thunk for CHECK_EQ() in NDEBUG mode.
__check_fail_eq:
loadstr "==",dx
lea .Lop(%rip),%r8
jmp __check_fail_ndebug
.endfn __check_fail_eq,globl
.rodata.str1.1
.Lop: .asciz "=="
.previous

View file

@ -21,6 +21,10 @@
// Code-size saving thunk for CHECK_GE() in NDEBUG mode.
__check_fail_ge:
loadstr ">=",dx
lea .Lop(%rip),%r8
jmp __check_fail_ndebug
.endfn __check_fail_ge,globl
.rodata.str1.1
.Lop: .asciz ">="
.previous

View file

@ -21,6 +21,10 @@
// Code-size saving thunk for CHECK_GT() in NDEBUG mode.
__check_fail_gt:
loadstr ">",dx
lea .Lop(%rip),%r8
jmp __check_fail_ndebug
.endfn __check_fail_gt,globl
.rodata.str1.1
.Lop: .asciz ">"
.previous

View file

@ -21,6 +21,10 @@
// Code-size saving thunk for CHECK_LE() in NDEBUG mode.
__check_fail_le:
loadstr "<=",dx
lea .Lop(%rip),%r8
jmp __check_fail_ndebug
.endfn __check_fail_le,globl
.rodata.str1.1
.Lop: .asciz "<="
.previous

View file

@ -21,6 +21,10 @@
// Code-size saving thunk for CHECK_LT() in NDEBUG mode.
__check_fail_lt:
loadstr "<",dx
lea .Lop(%rip),%r8
jmp __check_fail_ndebug
.endfn __check_fail_lt,globl
.rodata.str1.1
.Lop: .asciz "<"
.previous

View file

@ -1,27 +0,0 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 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/macros.internal.h"
__check_fail_ndebug:
push %rbp
mov %rsp,%rbp
call ___check_fail_ndebug
pop %rbp
jmp __die # fewer elements in backtrace
.endfn __check_fail_ndebug,globl

View file

@ -21,6 +21,10 @@
// Code-size saving thunk for CHECK_NE() in NDEBUG mode.
__check_fail_ne:
loadstr "!=",dx
lea .Lop(%rip),%r8
jmp __check_fail_ndebug
.endfn __check_fail_ne,globl
.rodata.str1.1
.Lop: .asciz "!="
.previous