mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-23 05:42:29 +00:00
Restart CI for New Technology and UBSAN hunting
Continuous Integration (via runit and runitd) is now re-enabled on win7 and win10. The `make test` command, which runs the tests on all systems is now the fastest and most stable it's been since the project started. UBSAN is now enabled in MODE=dbg in addition to ASAN. Many instances of undefined behavior have been removed. Mostly things like passing a NULL argument to memcpy(), which works fine with Cosmopolitan Libc, but that doesn't prevents the compiler from being unhappy. There was an issue w/ GNU make where static analysis claims a sprintf() call can overflow. We also now have nicer looking crash reports on Windows since uname should now be supported and msys64 addr2line works reliably.
This commit is contained in:
parent
d5ff2c3fb9
commit
5e8ae2d5bc
80 changed files with 506 additions and 249 deletions
|
@ -22,11 +22,11 @@
|
|||
#include "libc/nt/systeminfo.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
textwindows int gethostname_nt(char *name, size_t len) {
|
||||
textwindows int gethostname_nt(char *name, size_t len, int kind) {
|
||||
uint32_t nSize;
|
||||
char16_t name16[256];
|
||||
nSize = ARRAYLEN(name16);
|
||||
if (GetComputerNameEx(kNtComputerNamePhysicalDnsHostname, name16, &nSize)) {
|
||||
if (GetComputerNameEx(kind, name16, &nSize)) {
|
||||
tprecode16to8(name, len, name16);
|
||||
return 0;
|
||||
} else {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nt/enum/computernameformat.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
|
@ -37,6 +38,6 @@ int gethostname(char *name, size_t len) {
|
|||
return gethostname_bsd(name, len);
|
||||
}
|
||||
} else {
|
||||
return gethostname_nt(name, len);
|
||||
return gethostname_nt(name, len, kNtComputerNamePhysicalDnsHostname);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -234,7 +234,7 @@ void __sigenter_xnu(void *, i32, i32, struct __darwin_siginfo *,
|
|||
struct __darwin_ucontext *) hidden;
|
||||
int gethostname_linux(char *, size_t) hidden;
|
||||
int gethostname_bsd(char *, size_t) hidden;
|
||||
int gethostname_nt(char *, size_t) hidden;
|
||||
int gethostname_nt(char *, size_t, int) hidden;
|
||||
size_t __iovec_size(const struct iovec *, size_t) hidden;
|
||||
void __rusage2linux(struct rusage *) hidden;
|
||||
int __notziposat(int, const char *);
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
textwindows void ntcontext2linux(ucontext_t *ctx, const struct NtContext *cr) {
|
||||
if (!cr) return;
|
||||
ctx->uc_flags = cr->EFlags;
|
||||
ctx->uc_mcontext.gregs[REG_EFL] = cr->EFlags;
|
||||
ctx->uc_mcontext.rax = cr->Rax;
|
||||
ctx->uc_mcontext.rbx = cr->Rbx;
|
||||
ctx->uc_mcontext.rcx = cr->Rcx;
|
||||
|
|
|
@ -18,34 +18,72 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/struct/utsname.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/nt/enum/computernameformat.h"
|
||||
#include "libc/nt/struct/teb.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static inline textwindows noasan int NtGetMajorVersion(void) {
|
||||
return NtGetPeb()->OSMajorVersion;
|
||||
}
|
||||
|
||||
static inline textwindows noasan int NtGetMinorVersion(void) {
|
||||
return NtGetPeb()->OSMinorVersion;
|
||||
}
|
||||
|
||||
static inline textwindows noasan int NtGetBuildNumber(void) {
|
||||
return NtGetPeb()->OSBuildNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asks kernel to give us the `uname -a` data.
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
*/
|
||||
int uname(struct utsname *lool) {
|
||||
char *out;
|
||||
int rc, v;
|
||||
char *out, *p;
|
||||
size_t i, j, len;
|
||||
char tmp[sizeof(struct utsname)];
|
||||
bzero(tmp, sizeof(tmp));
|
||||
if (sys_uname(tmp) != -1) {
|
||||
out = (char *)lool;
|
||||
i = 0;
|
||||
j = 0;
|
||||
for (;;) {
|
||||
len = strlen(&tmp[j]);
|
||||
if (len >= sizeof(struct utsname) - i) break;
|
||||
memcpy(&out[i], &tmp[j], len + 1);
|
||||
i += SYS_NMLN;
|
||||
j += len;
|
||||
while (j < sizeof(tmp) && tmp[j] == '\0') ++j;
|
||||
if (j == sizeof(tmp)) break;
|
||||
}
|
||||
return 0;
|
||||
if (!lool) return efault();
|
||||
if (!lool || (IsAsan() && !__asan_is_valid(lool, sizeof(*lool)))) {
|
||||
rc = efault();
|
||||
} else {
|
||||
bzero(lool, sizeof(struct utsname));
|
||||
return -1;
|
||||
bzero(tmp, sizeof(tmp));
|
||||
if (!IsWindows()) {
|
||||
if ((rc = sys_uname(tmp)) != -1) {
|
||||
out = (char *)lool;
|
||||
for (i = j = 0;;) {
|
||||
len = strlen(&tmp[j]);
|
||||
if (len >= sizeof(struct utsname) - i) break;
|
||||
memcpy(&out[i], &tmp[j], len + 1);
|
||||
i += SYS_NMLN;
|
||||
j += len;
|
||||
while (j < sizeof(tmp) && tmp[j] == '\0') ++j;
|
||||
if (j == sizeof(tmp)) break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
v = NtGetVersion();
|
||||
p = lool->version;
|
||||
p = FormatUint32(p, NtGetMajorVersion()), *p++ = '.';
|
||||
p = FormatUint32(p, NtGetMinorVersion()), *p++ = '-';
|
||||
p = FormatUint32(p, NtGetBuildNumber());
|
||||
strcpy(lool->sysname, "The New Technology");
|
||||
strcpy(lool->machine, "x86_64");
|
||||
rc = gethostname_nt(lool->nodename, sizeof(lool->nodename),
|
||||
kNtComputerNamePhysicalDnsHostname);
|
||||
rc |= gethostname_nt(lool->domainname, sizeof(lool->domainname),
|
||||
kNtComputerNamePhysicalDnsDomain);
|
||||
}
|
||||
}
|
||||
STRACE("uname([%s, %s, %s, %s, %s, %s]) → %d% m", lool->sysname,
|
||||
lool->nodename, lool->release, lool->version, lool->machine,
|
||||
lool->domainname, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -24,9 +24,10 @@
|
|||
#include "libc/nt/enum/signal.h"
|
||||
#include "libc/nt/struct/ntexceptionpointers.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/sicode.h"
|
||||
|
||||
textwindows unsigned __wincrash(struct NtExceptionPointers *ep) {
|
||||
int sig, rva;
|
||||
int sig, rva, code;
|
||||
struct Goodies {
|
||||
ucontext_t ctx;
|
||||
struct siginfo si;
|
||||
|
@ -34,44 +35,69 @@ textwindows unsigned __wincrash(struct NtExceptionPointers *ep) {
|
|||
STRACE("__wincrash");
|
||||
switch (ep->ExceptionRecord->ExceptionCode) {
|
||||
case kNtSignalBreakpoint:
|
||||
code = TRAP_BRKPT;
|
||||
sig = SIGTRAP;
|
||||
break;
|
||||
case kNtSignalIllegalInstruction:
|
||||
code = ILL_ILLOPC;
|
||||
sig = SIGILL;
|
||||
break;
|
||||
case kNtSignalPrivInstruction:
|
||||
code = ILL_PRVOPC;
|
||||
sig = SIGILL;
|
||||
break;
|
||||
case kNtSignalGuardPage:
|
||||
case kNtSignalAccessViolation:
|
||||
case kNtSignalInPageError:
|
||||
code = SEGV_MAPERR;
|
||||
sig = SIGSEGV;
|
||||
break;
|
||||
case kNtSignalAccessViolation:
|
||||
code = SEGV_ACCERR;
|
||||
sig = SIGSEGV;
|
||||
break;
|
||||
case kNtSignalInvalidHandle:
|
||||
case kNtSignalInvalidParameter:
|
||||
case kNtSignalAssertionFailure:
|
||||
code = SI_USER;
|
||||
sig = SIGABRT;
|
||||
break;
|
||||
case kNtSignalFltDenormalOperand:
|
||||
case kNtSignalFltDivideByZero:
|
||||
case kNtSignalFltInexactResult:
|
||||
case kNtSignalFltInvalidOperation:
|
||||
code = FPE_FLTDIV;
|
||||
sig = SIGFPE;
|
||||
break;
|
||||
case kNtSignalFltOverflow:
|
||||
case kNtSignalFltStackCheck:
|
||||
code = FPE_FLTOVF;
|
||||
sig = SIGFPE;
|
||||
break;
|
||||
case kNtSignalFltUnderflow:
|
||||
code = FPE_FLTUND;
|
||||
sig = SIGFPE;
|
||||
break;
|
||||
case kNtSignalFltInexactResult:
|
||||
code = FPE_FLTRES;
|
||||
sig = SIGFPE;
|
||||
break;
|
||||
case kNtSignalFltDenormalOperand:
|
||||
case kNtSignalFltInvalidOperation:
|
||||
case kNtSignalFltStackCheck:
|
||||
case kNtSignalIntegerDivideByZero:
|
||||
case kNtSignalFloatMultipleFaults:
|
||||
case kNtSignalFloatMultipleTraps:
|
||||
code = FPE_FLTINV;
|
||||
sig = SIGFPE;
|
||||
break;
|
||||
case kNtSignalDllNotFound:
|
||||
case kNtSignalOrdinalNotFound:
|
||||
case kNtSignalEntrypointNotFound:
|
||||
case kNtSignalDllInitFailed:
|
||||
code = SI_KERNEL;
|
||||
sig = SIGSYS;
|
||||
break;
|
||||
default:
|
||||
return kNtExceptionContinueSearch;
|
||||
}
|
||||
bzero(&g, sizeof(g));
|
||||
g.si.si_code = code;
|
||||
rva = __sighandrvas[sig];
|
||||
if (rva >= kSigactionMinRva) {
|
||||
ntcontext2linux(&g.ctx, ep->ContextRecord);
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
#define IsOptimized() 0
|
||||
#endif
|
||||
|
||||
#ifdef __FSANITIZE_ADDRESS__
|
||||
#ifdef __SANITIZE_ADDRESS__
|
||||
#define IsAsan() 1
|
||||
#else
|
||||
#define IsAsan() 0
|
||||
|
|
|
@ -43,9 +43,6 @@
|
|||
#include "libc/sysv/consts/nr.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
|
||||
#define MAXT (24 * 60 * 60 * 1000000000ull)
|
||||
#define WRAP ((MAXT + 1) / 10 * 33)
|
||||
|
||||
struct Timestamps {
|
||||
unsigned long long birth;
|
||||
unsigned long long start;
|
||||
|
@ -56,6 +53,13 @@ extern bool __replmode;
|
|||
extern bool __nomultics;
|
||||
volatile unsigned long long __kbirth;
|
||||
|
||||
static inline uint64_t ClocksToNanos(uint64_t x, uint64_t y) {
|
||||
// approximation of round(x*.323018) which is usually
|
||||
// the ratio between inva rdtsc ticks and nanoseconds
|
||||
uint128_t difference = x - y;
|
||||
return (difference * 338709) >> 20;
|
||||
}
|
||||
|
||||
privileged static struct Timestamps kenter(void) {
|
||||
struct Timestamps ts;
|
||||
ts.start = rdtsc();
|
||||
|
@ -336,7 +340,7 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, va_list va,
|
|||
}
|
||||
continue;
|
||||
case 'T':
|
||||
x = unsignedsubtract(ts.start, ts.birth) % WRAP * 10 / 33;
|
||||
x = ClocksToNanos(ts.start, ts.birth) % 86400000000000;
|
||||
goto FormatUnsigned;
|
||||
case 'P':
|
||||
if (!__vforked) {
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/log/color.internal.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
#include "libc/log/log.h"
|
||||
|
@ -37,6 +38,8 @@
|
|||
#define kUbsanKindFloat 1
|
||||
#define kUbsanKindUnknown 0xffff
|
||||
|
||||
typedef void __ubsan_die_f(void);
|
||||
|
||||
struct UbsanSourceLocation {
|
||||
const char *file;
|
||||
uint32_t line;
|
||||
|
@ -188,17 +191,42 @@ static uintptr_t __ubsan_extend(struct UbsanTypeDescriptor *t, uintptr_t x) {
|
|||
return x;
|
||||
}
|
||||
|
||||
void __ubsan_abort(const struct UbsanSourceLocation *loc,
|
||||
const char *description) {
|
||||
kprintf("%n%s:%d: ubsan error: %s%n", loc->file, loc->line, description);
|
||||
if (weaken(__die)) weaken(__die)();
|
||||
_Exit(134);
|
||||
static wontreturn void __ubsan_unreachable(void) {
|
||||
for (;;) __builtin_trap();
|
||||
}
|
||||
|
||||
static void __ubsan_exit(void) {
|
||||
kprintf("your ubsan runtime needs%n"
|
||||
"\tSTATIC_YOINK(\"__die\");%n"
|
||||
"in order to show you backtraces%n");
|
||||
_Exit(99);
|
||||
}
|
||||
|
||||
nodiscard static __ubsan_die_f *__ubsan_die(void) {
|
||||
if (weaken(__die)) {
|
||||
return weaken(__die);
|
||||
} else {
|
||||
return __ubsan_exit;
|
||||
}
|
||||
}
|
||||
|
||||
static void __ubsan_warning(const struct UbsanSourceLocation *loc,
|
||||
const char *description) {
|
||||
kprintf("%s:%d: %subsan warning: %s is undefined behavior%s%n", loc->file,
|
||||
loc->line, SUBTLE, description, RESET);
|
||||
}
|
||||
|
||||
nodiscard __ubsan_die_f *__ubsan_abort(const struct UbsanSourceLocation *loc,
|
||||
const char *description) {
|
||||
kprintf("%n%s:%d: %subsan error%s: %s%n", loc->file, loc->line, RED2, RESET,
|
||||
description);
|
||||
return __ubsan_die();
|
||||
}
|
||||
|
||||
static const char *__ubsan_describe_shift(
|
||||
struct UbsanShiftOutOfBoundsInfo *info, uintptr_t lhs, uintptr_t rhs) {
|
||||
if (__ubsan_negative(info->rhs_type, rhs)) {
|
||||
return "shift exponent is negative";
|
||||
return "negative shift exponent";
|
||||
} else if (rhs >= __ubsan_bits(info->lhs_type)) {
|
||||
return "shift exponent too large for type";
|
||||
} else if (__ubsan_negative(info->lhs_type, lhs)) {
|
||||
|
@ -210,9 +238,10 @@ static const char *__ubsan_describe_shift(
|
|||
}
|
||||
}
|
||||
|
||||
void __ubsan_handle_shift_out_of_bounds(struct UbsanShiftOutOfBoundsInfo *info,
|
||||
uintptr_t lhs, uintptr_t rhs) {
|
||||
char buf[512], *p = buf;
|
||||
static char *__ubsan_describe_shift_out_of_bounds(
|
||||
char buf[512], struct UbsanShiftOutOfBoundsInfo *info, uintptr_t lhs,
|
||||
uintptr_t rhs) {
|
||||
char *p = buf;
|
||||
lhs = __ubsan_extend(info->lhs_type, lhs);
|
||||
rhs = __ubsan_extend(info->rhs_type, rhs);
|
||||
p = __stpcpy(p, __ubsan_describe_shift(info, lhs, rhs)), *p++ = ' ';
|
||||
|
@ -220,12 +249,22 @@ void __ubsan_handle_shift_out_of_bounds(struct UbsanShiftOutOfBoundsInfo *info,
|
|||
p = __stpcpy(p, info->lhs_type->name), *p++ = ' ';
|
||||
p = __ubsan_itpcpy(p, info->rhs_type, rhs), *p++ = ' ';
|
||||
p = __stpcpy(p, info->rhs_type->name);
|
||||
__ubsan_abort(&info->location, buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
void __ubsan_handle_shift_out_of_bounds(struct UbsanShiftOutOfBoundsInfo *info,
|
||||
uintptr_t lhs, uintptr_t rhs) {
|
||||
char buf[512];
|
||||
__ubsan_warning(&info->location,
|
||||
__ubsan_describe_shift_out_of_bounds(buf, info, lhs, rhs));
|
||||
}
|
||||
|
||||
void __ubsan_handle_shift_out_of_bounds_abort(
|
||||
struct UbsanShiftOutOfBoundsInfo *info, uintptr_t lhs, uintptr_t rhs) {
|
||||
__ubsan_handle_shift_out_of_bounds(info, lhs, rhs);
|
||||
char buf[512];
|
||||
__ubsan_abort(&info->location,
|
||||
__ubsan_describe_shift_out_of_bounds(buf, info, lhs, rhs))();
|
||||
__ubsan_unreachable();
|
||||
}
|
||||
|
||||
void __ubsan_handle_out_of_bounds(struct UbsanOutOfBoundsInfo *info,
|
||||
|
@ -237,7 +276,8 @@ void __ubsan_handle_out_of_bounds(struct UbsanOutOfBoundsInfo *info,
|
|||
p = __stpcpy(p, " into ");
|
||||
p = __stpcpy(p, info->array_type->name);
|
||||
p = __stpcpy(p, " out of bounds");
|
||||
__ubsan_abort(&info->location, buf);
|
||||
__ubsan_abort(&info->location, buf)();
|
||||
__ubsan_unreachable();
|
||||
}
|
||||
|
||||
void __ubsan_handle_out_of_bounds_abort(struct UbsanOutOfBoundsInfo *info,
|
||||
|
@ -245,11 +285,11 @@ void __ubsan_handle_out_of_bounds_abort(struct UbsanOutOfBoundsInfo *info,
|
|||
__ubsan_handle_out_of_bounds(info, index);
|
||||
}
|
||||
|
||||
void __ubsan_handle_type_mismatch(struct UbsanTypeMismatchInfo *info,
|
||||
uintptr_t pointer) {
|
||||
static __ubsan_die_f *__ubsan_type_mismatch_handler(
|
||||
struct UbsanTypeMismatchInfo *info, uintptr_t pointer) {
|
||||
const char *kind;
|
||||
char buf[512], *p = buf;
|
||||
if (!pointer) __ubsan_abort(&info->location, "null pointer access");
|
||||
if (!pointer) return __ubsan_abort(&info->location, "null pointer access");
|
||||
kind = __ubsan_dubnul(kUbsanTypeCheckKinds, info->type_check_kind);
|
||||
if (info->alignment && (pointer & (info->alignment - 1))) {
|
||||
p = __stpcpy(p, "unaligned ");
|
||||
|
@ -266,41 +306,57 @@ void __ubsan_handle_type_mismatch(struct UbsanTypeMismatchInfo *info,
|
|||
p = __stpcpy(p, " with insufficient space for object of type ");
|
||||
p = __stpcpy(p, info->type->name);
|
||||
}
|
||||
__ubsan_abort(&info->location, buf);
|
||||
return __ubsan_abort(&info->location, buf);
|
||||
}
|
||||
|
||||
void __ubsan_handle_type_mismatch(struct UbsanTypeMismatchInfo *info,
|
||||
uintptr_t pointer) {
|
||||
__ubsan_type_mismatch_handler(info, pointer)();
|
||||
__ubsan_unreachable();
|
||||
}
|
||||
|
||||
void __ubsan_handle_type_mismatch_abort(struct UbsanTypeMismatchInfo *info,
|
||||
uintptr_t pointer) {
|
||||
__ubsan_handle_type_mismatch(info, pointer);
|
||||
__ubsan_type_mismatch_handler(info, pointer)();
|
||||
__ubsan_unreachable();
|
||||
}
|
||||
|
||||
void __ubsan_handle_type_mismatch_v1(
|
||||
static __ubsan_die_f *__ubsan_type_mismatch_v1_handler(
|
||||
struct UbsanTypeMismatchInfoClang *type_mismatch, uintptr_t pointer) {
|
||||
struct UbsanTypeMismatchInfo mm;
|
||||
mm.location = type_mismatch->location;
|
||||
mm.type = type_mismatch->type;
|
||||
mm.alignment = 1u << type_mismatch->log_alignment;
|
||||
mm.type_check_kind = type_mismatch->type_check_kind;
|
||||
__ubsan_handle_type_mismatch(&mm, pointer);
|
||||
return __ubsan_type_mismatch_handler(&mm, pointer);
|
||||
}
|
||||
|
||||
void __ubsan_handle_type_mismatch_v1(
|
||||
struct UbsanTypeMismatchInfoClang *type_mismatch, uintptr_t pointer) {
|
||||
__ubsan_type_mismatch_v1_handler(type_mismatch, pointer)();
|
||||
__ubsan_unreachable();
|
||||
}
|
||||
|
||||
void __ubsan_handle_type_mismatch_v1_abort(
|
||||
struct UbsanTypeMismatchInfoClang *type_mismatch, uintptr_t pointer) {
|
||||
__ubsan_handle_type_mismatch_v1(type_mismatch, pointer);
|
||||
__ubsan_type_mismatch_v1_handler(type_mismatch, pointer)();
|
||||
__ubsan_unreachable();
|
||||
}
|
||||
|
||||
void __ubsan_handle_float_cast_overflow(void *data_raw, void *from_raw) {
|
||||
struct UbsanFloatCastOverflowData *data =
|
||||
(struct UbsanFloatCastOverflowData *)data_raw;
|
||||
#if __GNUC__ + 0 >= 6
|
||||
__ubsan_abort(&data->location, "float cast overflow");
|
||||
__ubsan_abort(&data->location, "float cast overflow")();
|
||||
__ubsan_unreachable();
|
||||
#else
|
||||
const struct UbsanSourceLocation kUnknownLocation = {
|
||||
"<unknown file>",
|
||||
pushpop(0),
|
||||
pushpop(0),
|
||||
};
|
||||
__ubsan_abort(((void)data, &kUnknownLocation), "float cast overflow");
|
||||
__ubsan_abort(((void)data, &kUnknownLocation), "float cast overflow")();
|
||||
__ubsan_unreachable();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -309,7 +365,8 @@ void __ubsan_handle_float_cast_overflow_abort(void *data_raw, void *from_raw) {
|
|||
}
|
||||
|
||||
void __ubsan_handle_add_overflow(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "add overflow");
|
||||
__ubsan_abort(loc, "add overflow")();
|
||||
__ubsan_unreachable();
|
||||
}
|
||||
|
||||
void __ubsan_handle_add_overflow_abort(const struct UbsanSourceLocation *loc) {
|
||||
|
@ -318,7 +375,8 @@ void __ubsan_handle_add_overflow_abort(const struct UbsanSourceLocation *loc) {
|
|||
|
||||
void __ubsan_handle_alignment_assumption(
|
||||
const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "alignment assumption");
|
||||
__ubsan_abort(loc, "alignment assumption")();
|
||||
__ubsan_unreachable();
|
||||
}
|
||||
|
||||
void __ubsan_handle_alignment_assumption_abort(
|
||||
|
@ -327,7 +385,8 @@ void __ubsan_handle_alignment_assumption_abort(
|
|||
}
|
||||
|
||||
void __ubsan_handle_builtin_unreachable(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "builtin unreachable");
|
||||
__ubsan_abort(loc, "builtin unreachable")();
|
||||
__ubsan_unreachable();
|
||||
}
|
||||
|
||||
void __ubsan_handle_builtin_unreachable_abort(
|
||||
|
@ -336,7 +395,8 @@ void __ubsan_handle_builtin_unreachable_abort(
|
|||
}
|
||||
|
||||
void __ubsan_handle_cfi_bad_type(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "cfi bad type");
|
||||
__ubsan_abort(loc, "cfi bad type")();
|
||||
__ubsan_unreachable();
|
||||
}
|
||||
|
||||
void __ubsan_handle_cfi_bad_type_abort(const struct UbsanSourceLocation *loc) {
|
||||
|
@ -344,7 +404,8 @@ void __ubsan_handle_cfi_bad_type_abort(const struct UbsanSourceLocation *loc) {
|
|||
}
|
||||
|
||||
void __ubsan_handle_cfi_check_fail(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "cfi check fail");
|
||||
__ubsan_abort(loc, "cfi check fail")();
|
||||
__ubsan_unreachable();
|
||||
}
|
||||
|
||||
void __ubsan_handle_cfi_check_fail_abort(
|
||||
|
@ -353,7 +414,8 @@ void __ubsan_handle_cfi_check_fail_abort(
|
|||
}
|
||||
|
||||
void __ubsan_handle_divrem_overflow(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "divrem overflow");
|
||||
__ubsan_abort(loc, "divrem overflow")();
|
||||
__ubsan_unreachable();
|
||||
}
|
||||
|
||||
void __ubsan_handle_divrem_overflow_abort(
|
||||
|
@ -363,7 +425,8 @@ void __ubsan_handle_divrem_overflow_abort(
|
|||
|
||||
void __ubsan_handle_dynamic_type_cache_miss(
|
||||
const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "dynamic type cache miss");
|
||||
__ubsan_abort(loc, "dynamic type cache miss")();
|
||||
__ubsan_unreachable();
|
||||
}
|
||||
|
||||
void __ubsan_handle_dynamic_type_cache_miss_abort(
|
||||
|
@ -373,7 +436,8 @@ void __ubsan_handle_dynamic_type_cache_miss_abort(
|
|||
|
||||
void __ubsan_handle_function_type_mismatch(
|
||||
const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "function type mismatch");
|
||||
__ubsan_abort(loc, "function type mismatch")();
|
||||
__ubsan_unreachable();
|
||||
}
|
||||
|
||||
void __ubsan_handle_function_type_mismatch_abort(
|
||||
|
@ -382,7 +446,8 @@ void __ubsan_handle_function_type_mismatch_abort(
|
|||
}
|
||||
|
||||
void __ubsan_handle_implicit_conversion(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "implicit conversion");
|
||||
__ubsan_abort(loc, "implicit conversion")();
|
||||
__ubsan_unreachable();
|
||||
}
|
||||
|
||||
void __ubsan_handle_implicit_conversion_abort(
|
||||
|
@ -391,7 +456,8 @@ void __ubsan_handle_implicit_conversion_abort(
|
|||
}
|
||||
|
||||
void __ubsan_handle_invalid_builtin(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "invalid builtin");
|
||||
__ubsan_abort(loc, "invalid builtin")();
|
||||
__ubsan_unreachable();
|
||||
}
|
||||
|
||||
void __ubsan_handle_invalid_builtin_abort(
|
||||
|
@ -400,7 +466,8 @@ void __ubsan_handle_invalid_builtin_abort(
|
|||
}
|
||||
|
||||
void __ubsan_handle_load_invalid_value(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "load invalid value (uninitialized? bool∌[01]?)");
|
||||
__ubsan_abort(loc, "load invalid value (uninitialized? bool∌[01]?)")();
|
||||
__ubsan_unreachable();
|
||||
}
|
||||
|
||||
void __ubsan_handle_load_invalid_value_abort(
|
||||
|
@ -409,7 +476,8 @@ void __ubsan_handle_load_invalid_value_abort(
|
|||
}
|
||||
|
||||
void __ubsan_handle_missing_return(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "missing return");
|
||||
__ubsan_abort(loc, "missing return")();
|
||||
__ubsan_unreachable();
|
||||
}
|
||||
|
||||
void __ubsan_handle_missing_return_abort(
|
||||
|
@ -418,7 +486,8 @@ void __ubsan_handle_missing_return_abort(
|
|||
}
|
||||
|
||||
void __ubsan_handle_mul_overflow(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "multiply overflow");
|
||||
__ubsan_abort(loc, "multiply overflow")();
|
||||
__ubsan_unreachable();
|
||||
}
|
||||
|
||||
void __ubsan_handle_mul_overflow_abort(const struct UbsanSourceLocation *loc) {
|
||||
|
@ -426,7 +495,8 @@ void __ubsan_handle_mul_overflow_abort(const struct UbsanSourceLocation *loc) {
|
|||
}
|
||||
|
||||
void __ubsan_handle_negate_overflow(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "negate overflow");
|
||||
__ubsan_abort(loc, "negate overflow")();
|
||||
__ubsan_unreachable();
|
||||
}
|
||||
|
||||
void __ubsan_handle_negate_overflow_abort(
|
||||
|
@ -435,24 +505,28 @@ void __ubsan_handle_negate_overflow_abort(
|
|||
}
|
||||
|
||||
void __ubsan_handle_nonnull_arg(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "nonnull argument");
|
||||
__ubsan_warning(loc, "null argument here");
|
||||
}
|
||||
|
||||
void __ubsan_handle_nonnull_arg_abort(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_handle_nonnull_arg(loc);
|
||||
__ubsan_abort(loc, "nonnull argument")();
|
||||
__ubsan_unreachable();
|
||||
}
|
||||
|
||||
void __ubsan_handle_nonnull_return_v1(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "non-null return (v1)");
|
||||
__ubsan_abort(loc, "non-null return (v1)")();
|
||||
__ubsan_unreachable();
|
||||
}
|
||||
|
||||
void __ubsan_handle_nonnull_return_v1_abort(
|
||||
const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_handle_nonnull_return_v1(loc);
|
||||
__ubsan_abort(loc, "non-null return (v1)")();
|
||||
__ubsan_unreachable();
|
||||
}
|
||||
|
||||
void __ubsan_handle_nullability_arg(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "nullability arg");
|
||||
__ubsan_abort(loc, "nullability arg")();
|
||||
__ubsan_unreachable();
|
||||
}
|
||||
|
||||
void __ubsan_handle_nullability_arg_abort(
|
||||
|
@ -462,7 +536,8 @@ void __ubsan_handle_nullability_arg_abort(
|
|||
|
||||
void __ubsan_handle_nullability_return_v1(
|
||||
const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "nullability return (v1)");
|
||||
__ubsan_abort(loc, "nullability return (v1)")();
|
||||
__ubsan_unreachable();
|
||||
}
|
||||
|
||||
void __ubsan_handle_nullability_return_v1_abort(
|
||||
|
@ -471,7 +546,8 @@ void __ubsan_handle_nullability_return_v1_abort(
|
|||
}
|
||||
|
||||
void __ubsan_handle_pointer_overflow(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "pointer overflow");
|
||||
__ubsan_abort(loc, "pointer overflow")();
|
||||
__ubsan_unreachable();
|
||||
}
|
||||
|
||||
void __ubsan_handle_pointer_overflow_abort(
|
||||
|
@ -480,7 +556,8 @@ void __ubsan_handle_pointer_overflow_abort(
|
|||
}
|
||||
|
||||
void __ubsan_handle_sub_overflow(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "subtract overflow");
|
||||
__ubsan_abort(loc, "subtract overflow")();
|
||||
__ubsan_unreachable();
|
||||
}
|
||||
|
||||
void __ubsan_handle_sub_overflow_abort(const struct UbsanSourceLocation *loc) {
|
||||
|
@ -489,7 +566,8 @@ void __ubsan_handle_sub_overflow_abort(const struct UbsanSourceLocation *loc) {
|
|||
|
||||
void __ubsan_handle_vla_bound_not_positive(
|
||||
const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "vla bound not positive");
|
||||
__ubsan_abort(loc, "vla bound not positive")();
|
||||
__ubsan_unreachable();
|
||||
}
|
||||
|
||||
void __ubsan_handle_vla_bound_not_positive_abort(
|
||||
|
@ -498,7 +576,8 @@ void __ubsan_handle_vla_bound_not_positive_abort(
|
|||
}
|
||||
|
||||
void __ubsan_handle_nonnull_return(const struct UbsanSourceLocation *loc) {
|
||||
__ubsan_abort(loc, "nonnull return");
|
||||
__ubsan_abort(loc, "nonnull return")();
|
||||
__ubsan_unreachable();
|
||||
}
|
||||
|
||||
void __ubsan_handle_nonnull_return_abort(
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
* possible UX for debugging your app, for varying levels of available
|
||||
* information, on most of the various platforms.
|
||||
*
|
||||
* Before calling this function, consider placing showcrashreports() in
|
||||
* Before calling this function, consider placing ShowCrashReports() in
|
||||
* your main function and calling DebugBreak() wherever you want; it's
|
||||
* safer. Also note the "GDB" environment variable can be set to empty
|
||||
* string, as a fail-safe for disabling this behavior.
|
||||
|
|
|
@ -79,7 +79,7 @@ static int PrintBacktraceUsingAddr2line(int fd, const struct StackFrame *bp) {
|
|||
* DWARF is a weak standard. Platforms that use LLVM or old GNU
|
||||
* usually can't be counted upon to print backtraces correctly.
|
||||
*/
|
||||
if (!IsLinux() /* && !IsWindows() */) {
|
||||
if (!IsLinux() && !IsWindows()) {
|
||||
ShowHint("won't print addr2line backtrace because probably llvm");
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -231,7 +231,7 @@ relegated void ShowCrashReport(int err, int sig, struct siginfo *si,
|
|||
? "Stack Overflow"
|
||||
: GetSiCodeName(sig, si->si_code),
|
||||
host, __getpid(), program_invocation_name, names.sysname,
|
||||
names.nodename, names.release, names.version);
|
||||
names.version, names.nodename, names.release);
|
||||
if (ctx) {
|
||||
kprintf("%n");
|
||||
ShowFunctionCalls(ctx);
|
||||
|
|
|
@ -51,7 +51,7 @@ textexit static void __onkill(int sig, struct siginfo *si,
|
|||
|
||||
/**
|
||||
* Installs default handlers for friendly kill signals.
|
||||
* @see showcrashreports()
|
||||
* @see ShowCrashReports()
|
||||
*/
|
||||
void callexitontermination(sigset_t *opt_out_exitsigs) {
|
||||
struct sigaction sa;
|
||||
|
|
|
@ -195,7 +195,7 @@
|
|||
.endm
|
||||
|
||||
.macro .poison name:req kind:req
|
||||
#ifdef __FSANITIZE_ADDRESS__
|
||||
#ifdef __SANITIZE_ADDRESS__
|
||||
2323: .quad 0
|
||||
.init.start 304,"_init_\name\()_poison_\@"
|
||||
push %rdi
|
||||
|
@ -211,13 +211,13 @@
|
|||
.endm
|
||||
|
||||
.macro .underrun
|
||||
#ifdef __FSANITIZE_ADDRESS__
|
||||
#ifdef __SANITIZE_ADDRESS__
|
||||
.poison __BASE_FILE__, kAsanGlobalUnderrun
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro .overrun
|
||||
#ifdef __FSANITIZE_ADDRESS__
|
||||
#ifdef __SANITIZE_ADDRESS__
|
||||
.poison __BASE_FILE__, kAsanGlobalUnderrun
|
||||
#endif
|
||||
.endm
|
||||
|
|
|
@ -16,45 +16,30 @@
|
|||
│ 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/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ntspawn.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/alloca.h"
|
||||
#include "libc/nexgen32e/nt2sysv.h"
|
||||
#include "libc/nt/dll.h"
|
||||
#include "libc/nt/enum/exceptionhandleractions.h"
|
||||
#include "libc/nt/enum/filemapflags.h"
|
||||
#include "libc/nt/enum/memflags.h"
|
||||
#include "libc/nt/enum/pageflags.h"
|
||||
#include "libc/nt/enum/startf.h"
|
||||
#include "libc/nt/enum/wt.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/ipc.h"
|
||||
#include "libc/nt/memory.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/signals.h"
|
||||
#include "libc/nt/struct/context.h"
|
||||
#include "libc/nt/struct/ntexceptionpointers.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/nt/thread.h"
|
||||
#include "libc/runtime/directmap.internal.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
extern int __pid;
|
||||
extern unsigned long long __kbirth;
|
||||
|
|
|
@ -102,15 +102,15 @@ textstartup void __printargs(int argc, char **argv, char **envp,
|
|||
}
|
||||
}
|
||||
STRACE("SPECIALS");
|
||||
STRACE(" ☼ %21s = %#s", "kTmpPath", kTmpPath);
|
||||
STRACE(" ☼ %21s = %#s", "kNtSystemDirectory", kNtSystemDirectory);
|
||||
STRACE(" ☼ %21s = %#s", "kNtWindowsDirectory", kNtWindowsDirectory);
|
||||
STRACE(" ☼ %21s = %#s", "program_executable_name", program_executable_name);
|
||||
STRACE(" ☼ %21s = %#s", "GetInterpreterExecutableName()",
|
||||
STRACE(" ☼ %30s = %#s", "kTmpPath", kTmpPath);
|
||||
STRACE(" ☼ %30s = %#s", "kNtSystemDirectory", kNtSystemDirectory);
|
||||
STRACE(" ☼ %30s = %#s", "kNtWindowsDirectory", kNtWindowsDirectory);
|
||||
STRACE(" ☼ %30s = %#s", "program_executable_name", program_executable_name);
|
||||
STRACE(" ☼ %30s = %#s", "GetInterpreterExecutableName()",
|
||||
GetInterpreterExecutableName(path, sizeof(path)));
|
||||
STRACE(" ☼ %21s = %p", "RSP", __builtin_frame_address(0));
|
||||
STRACE(" ☼ %21s = %p", "GetStackAddr()", GetStackAddr(0));
|
||||
STRACE(" ☼ %21s = %p", "GetStaticStackAddr(0)", GetStaticStackAddr(0));
|
||||
STRACE(" ☼ %21s = %p", "GetStackSize()", GetStackSize());
|
||||
STRACE(" ☼ %30s = %p", "RSP", __builtin_frame_address(0));
|
||||
STRACE(" ☼ %30s = %p", "GetStackAddr()", GetStackAddr(0));
|
||||
STRACE(" ☼ %30s = %p", "GetStaticStackAddr(0)", GetStaticStackAddr(0));
|
||||
STRACE(" ☼ %30s = %p", "GetStackSize()", GetStackSize());
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
// @returnstwice
|
||||
// @vforksafe
|
||||
vfork:
|
||||
#ifdef __FSANITIZE_ADDRESS__
|
||||
#ifdef __SANITIZE_ADDRESS__
|
||||
jmp fork # TODO: asan and vfork don't mix?
|
||||
.endfn vfork,globl
|
||||
#else
|
||||
|
@ -98,4 +98,4 @@ vfork.bsd:
|
|||
.previous
|
||||
#endif /* DEBUGSYS */
|
||||
|
||||
#endif /* __FSANITIZE_ADDRESS__ */
|
||||
#endif /* __SANITIZE_ADDRESS__ */
|
||||
|
|
|
@ -59,7 +59,11 @@ ssize_t appendd(char **b, const void *s, size_t l) {
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
*(char *)mempcpy(p + z.i, s, l) = 0;
|
||||
if (l) {
|
||||
*(char *)mempcpy(p + z.i, s, l) = 0;
|
||||
} else {
|
||||
p[z.i] = 0;
|
||||
}
|
||||
z.i += l;
|
||||
if (!IsTiny() && W == 8) z.i |= (size_t)APPEND_COOKIE << 48;
|
||||
*(size_t *)(p + z.n - W) = z.i;
|
||||
|
|
|
@ -53,7 +53,7 @@ size_t fread(void *buf, size_t stride, size_t count, FILE *f) {
|
|||
p = buf;
|
||||
n = stride * count;
|
||||
m = f->end - f->beg;
|
||||
memcpy(p, f->buf + f->beg, MIN(n, m));
|
||||
if (MIN(n, m)) memcpy(p, f->buf + f->beg, MIN(n, m));
|
||||
if (n < m) {
|
||||
f->beg += n;
|
||||
return count;
|
||||
|
|
|
@ -35,6 +35,9 @@ uint32_t crc32c(uint32_t init, const void *data, size_t size) {
|
|||
pe = p + size;
|
||||
h = init ^ 0xffffffff;
|
||||
if (X86_HAVE(SSE4_2)) {
|
||||
while (p < pe && ((intptr_t)p & 7)) {
|
||||
h = h >> 8 ^ kCrc32cTab[(h & 0xff) ^ *p++];
|
||||
}
|
||||
for (; p + 8 <= pe; p += 8) {
|
||||
asm("crc32q\t%1,%0" : "+r"(h) : "rm"(*(const uint64_t *)p));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue