diff --git a/libc/assert.h b/libc/assert.h index 96f190671..5ee54351d 100644 --- a/libc/assert.h +++ b/libc/assert.h @@ -15,7 +15,7 @@ COSMOPOLITAN_C_START_ void __assert_fail(const char *, const char *, int); -void __unassert_fail(const char *, const char *, int); +void unassert(const char *, const char *, int); #ifdef NDEBUG #define assert(x) ((void)0) @@ -32,14 +32,14 @@ void __unassert_fail(const char *, const char *, int); #ifndef NDEBUG #define unassert(x) __assert_macro(x, #x) #define npassert(x) __assert_macro(x, #x) -#define __assert_macro(x, s) \ - ({ \ - if (__builtin_expect(!(x), 0)) { \ - __unassert_fail(s, __FILE__, __LINE__); \ - __asm__("nop"); \ - __builtin_unreachable(); \ - } \ - (void)0; \ +#define __assert_macro(x, s) \ + ({ \ + if (__builtin_expect(!(x), 0)) { \ + (unassert)(s, __FILE__, __LINE__); \ + __asm__("nop"); \ + __builtin_unreachable(); \ + } \ + (void)0; \ }) #else #define npassert(x) \ diff --git a/libc/calls/assertfail.c b/libc/calls/assertfail.c index 114ea89e4..508bd1347 100644 --- a/libc/calls/assertfail.c +++ b/libc/calls/assertfail.c @@ -23,6 +23,7 @@ #include "libc/fmt/itoa.h" #include "libc/intrin/describebacktrace.internal.h" #include "libc/runtime/runtime.h" +#include "libc/runtime/symbols.internal.h" /** * Handles assert() failure. @@ -32,7 +33,7 @@ void __assert_fail(const char *expr, const char *file, int line) { sigset_t m = __sig_block(); FormatInt32(ibuf, line); tinyprint(2, file, ":", ibuf, ": \e[31;1massert(", expr, - ") failed\e[0m (cosmoaddr2line ", program_invocation_name, " ", + ") failed\e[0m (cosmoaddr2line ", FindDebugBinary(), " ", DescribeBacktrace(__builtin_frame_address(0)), ")\n", NULL); __sig_unblock(m); abort(); diff --git a/libc/runtime/finddebugbinary.c b/libc/calls/finddebugbinary.c similarity index 68% rename from libc/runtime/finddebugbinary.c rename to libc/calls/finddebugbinary.c index c58e5556d..ff38f51a8 100644 --- a/libc/runtime/finddebugbinary.c +++ b/libc/calls/finddebugbinary.c @@ -20,13 +20,17 @@ #include "libc/atomic.h" #include "libc/calls/blockcancel.internal.h" #include "libc/calls/calls.h" +#include "libc/calls/syscall-sysv.internal.h" #include "libc/cosmo.h" +#include "libc/dce.h" +#include "libc/elf/def.h" #include "libc/elf/tinyelf.internal.h" #include "libc/errno.h" #include "libc/intrin/bits.h" -#include "libc/macros.internal.h" +#include "libc/intrin/directmap.internal.h" +#include "libc/nt/memory.h" +#include "libc/nt/runtime.h" #include "libc/runtime/runtime.h" -#include "libc/runtime/symbols.internal.h" #include "libc/str/str.h" #include "libc/sysv/consts/map.h" #include "libc/sysv/consts/o.h" @@ -38,24 +42,57 @@ static struct { char buf[PATH_MAX]; } g_comdbg; +static const char *kDbgExts[] = { + ".dbg", + ".com.dbg", +#ifdef __aarch64__ + ".aarch64.elf", +#elif defined(__powerpc64__) + ".ppc64.elf", +#endif +}; + +static int GetElfMachine(void) { +#ifdef __x86_64__ + return EM_NEXGEN32E; +#elif defined(__aarch64__) + return EM_AARCH64; +#elif defined(__powerpc64__) + return EM_PPC64; +#elif defined(__riscv) + return EM_RISCV; +#elif defined(__s390x__) + return EM_S390; +#else +#error "unsupported architecture" +#endif +} + static bool IsMyDebugBinary(const char *path) { - void *map; int64_t size; uintptr_t value; bool res = false; int fd, e = errno; + struct DirectMap dm; BLOCK_CANCELATION; if ((fd = open(path, O_RDONLY | O_CLOEXEC, 0)) != -1) { // sanity test that this .com.dbg file (1) is an elf image, and (2) // contains the same number of bytes of code as our .com executable // which is currently running in memory. if ((size = lseek(fd, 0, SEEK_END)) != -1 && - (map = mmap(0, size, PROT_READ, MAP_SHARED, fd, 0)) != MAP_FAILED) { - if (READ32LE((char *)map) == READ32LE("\177ELF") && - GetElfSymbolValue(map, "_etext", &value)) { + (dm = sys_mmap(0, size, PROT_READ, MAP_SHARED, fd, 0)).addr != + MAP_FAILED) { + if (READ32LE((char *)dm.addr) == READ32LE("\177ELF") && + ((Elf64_Ehdr *)dm.addr)->e_machine == GetElfMachine() && + GetElfSymbolValue(dm.addr, "_etext", &value)) { res = !_etext || value == (uintptr_t)_etext; } - munmap(map, size); + if (!IsWindows()) { + sys_munmap(dm.addr, size); + } else { + CloseHandle(dm.maphandle); + UnmapViewOfFile(dm.addr); + } } close(fd); } @@ -65,20 +102,21 @@ static bool IsMyDebugBinary(const char *path) { } static void FindDebugBinaryInit(void) { - char *p = GetProgramExecutableName(); - size_t n = strlen(p); - if ((n > 4 && READ32LE(p + n - 4) == READ32LE(".dbg")) || - IsMyDebugBinary(p)) { - g_comdbg.res = p; - } else if (n + 4 < ARRAYLEN(g_comdbg.buf)) { - mempcpy(mempcpy(g_comdbg.buf, p, n), ".dbg", 5); + const char *comdbg; + if ((comdbg = getenv("COMDBG")) && IsMyDebugBinary(comdbg)) { + g_comdbg.res = comdbg; + return; + } + char *prog = GetProgramExecutableName(); + for (int i = 0; i < ARRAYLEN(kDbgExts); ++i) { + strlcpy(g_comdbg.buf, prog, sizeof(g_comdbg.buf)); + strlcat(g_comdbg.buf, kDbgExts[i], sizeof(g_comdbg.buf)); if (IsMyDebugBinary(g_comdbg.buf)) { g_comdbg.res = g_comdbg.buf; + return; } } - if (!g_comdbg.res) { - g_comdbg.res = getenv("COMDBG"); - } + g_comdbg.res = prog; } /** diff --git a/libc/calls/unassertfail.c b/libc/calls/unassert.c similarity index 93% rename from libc/calls/unassertfail.c rename to libc/calls/unassert.c index bbd24a20b..137d61930 100644 --- a/libc/calls/unassertfail.c +++ b/libc/calls/unassert.c @@ -23,6 +23,7 @@ #include "libc/fmt/itoa.h" #include "libc/intrin/describebacktrace.internal.h" #include "libc/runtime/runtime.h" +#include "libc/runtime/symbols.internal.h" /** * Handles unassert() failure. @@ -32,12 +33,12 @@ * number of things. By doing this instead, we guarantee the backtrace * reported to the signal handler is clean and focused on the problem. */ -void __unassert_fail(const char *expr, const char *file, int line) { +void(unassert)(const char *expr, const char *file, int line) { char ibuf[12]; sigset_t m = __sig_block(); FormatInt32(ibuf, line); tinyprint(2, file, ":", ibuf, ": \e[31;1munassert(", expr, - ") failed\e[0m (cosmoaddr2line ", program_invocation_name, " ", + ") failed\e[0m (cosmoaddr2line ", FindDebugBinary(), " ", DescribeBacktrace(__builtin_frame_address(0)), ")\n", NULL); __sig_unblock(m); notpossible; diff --git a/libc/dlopen/dlopen.c b/libc/dlopen/dlopen.c index 0636ac23d..83a3a7a4a 100644 --- a/libc/dlopen/dlopen.c +++ b/libc/dlopen/dlopen.c @@ -112,7 +112,7 @@ struct Loaded { char *base; char *entry; Elf64_Ehdr eh; - Elf64_Phdr ph[30]; + Elf64_Phdr ph[25]; }; static struct { @@ -277,8 +277,8 @@ static bool elf_slurp(struct Loaded *l, int fd, const char *file) { return true; } -static bool elf_load(struct Loaded *l, const char *file, long pagesz, - char *interp_path, size_t interp_size) { +static dontinline bool elf_load(struct Loaded *l, const char *file, long pagesz, + char *interp_path, size_t interp_size) { int fd; if ((fd = open(file, O_RDONLY | O_CLOEXEC)) == -1) { return false; diff --git a/libc/intrin/unassertfail.c b/libc/intrin/unassert.c similarity index 93% rename from libc/intrin/unassertfail.c rename to libc/intrin/unassert.c index 0c5435a7a..0987615bf 100644 --- a/libc/intrin/unassertfail.c +++ b/libc/intrin/unassert.c @@ -18,7 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ // stub version of unassert() to keep the build a dag -__attribute__((__weak__)) void __unassert_fail(const char *expr, - const char *file, int line) { +__attribute__((__weak__)) void(unassert)(const char *expr, const char *file, + int line) { notpossible; } diff --git a/libc/log/die.c b/libc/log/die.c index 9870c8df9..f1f4fa497 100644 --- a/libc/log/die.c +++ b/libc/log/die.c @@ -22,6 +22,7 @@ #include "libc/intrin/kprintf.h" #include "libc/log/internal.h" #include "libc/runtime/runtime.h" +#include "libc/runtime/symbols.internal.h" #include "libc/str/str.h" /** @@ -46,10 +47,9 @@ relegated wontreturn void __die(void) { strcpy(host, "unknown"); gethostname(host, sizeof(host)); kprintf("%serror: %s on %s pid %d tid %d has perished%s\n" - "cosmoaddr2line %s%s %s\n", + "cosmoaddr2line %s %s\n", __nocolor ? "" : "\e[1;31m", program_invocation_short_name, host, - getpid(), gettid(), __nocolor ? "" : "\e[0m", __argv[0], - endswith(__argv[0], ".com") ? ".dbg" : "", + getpid(), gettid(), __nocolor ? "" : "\e[0m", FindDebugBinary(), DescribeBacktrace(__builtin_frame_address(0))); _Exit(77); } diff --git a/libc/log/minicrash.c b/libc/log/minicrash.c index 585fe5a63..4cf427210 100644 --- a/libc/log/minicrash.c +++ b/libc/log/minicrash.c @@ -26,6 +26,7 @@ #include "libc/log/internal.h" #include "libc/log/log.h" #include "libc/runtime/runtime.h" +#include "libc/runtime/symbols.internal.h" #include "libc/str/str.h" /** @@ -64,12 +65,12 @@ relegated dontinstrument void __minicrash(int sig, siginfo_t *si, void *arg) { gethostname(host, sizeof(host)); kprintf( "%serror: %s on %s pid %d tid %d got %G%s code %d addr %p%s\n" - "cosmoaddr2line %s%s %lx %s\n", + "cosmoaddr2line %s %lx %s\n", __nocolor ? "" : "\e[1;31m", program_invocation_short_name, host, getpid(), gettid(), sig, __is_stack_overflow(si, ctx) ? " (stack overflow)" : "", si->si_code, - si->si_addr, __nocolor ? "" : "\e[0m", __argv[0], - endswith(__argv[0], ".com") ? ".dbg" : "", ctx ? ctx->uc_mcontext.PC : 0, + si->si_addr, __nocolor ? "" : "\e[0m", FindDebugBinary(), + ctx ? ctx->uc_mcontext.PC : 0, DescribeBacktrace(ctx ? (struct StackFrame *)ctx->uc_mcontext.BP : (struct StackFrame *)__builtin_frame_address(0))); } diff --git a/libc/log/oncrash_amd64.c b/libc/log/oncrash_amd64.c index eab3c58a1..05b7aba70 100644 --- a/libc/log/oncrash_amd64.c +++ b/libc/log/oncrash_amd64.c @@ -74,8 +74,8 @@ static const char kFpuExceptions[6] forcealign(1) = "IDZOUP"; relegated static void ShowFunctionCalls(ucontext_t *ctx) { kprintf( - "cosmoaddr2line %s%s %lx %s\n\n", __argv[0], - endswith(__argv[0], ".com") ? ".dbg" : "", ctx ? ctx->uc_mcontext.PC : 0, + "cosmoaddr2line %s %lx %s\n\n", FindDebugBinary(), + ctx ? ctx->uc_mcontext.PC : 0, DescribeBacktrace(ctx ? (struct StackFrame *)ctx->uc_mcontext.BP : (struct StackFrame *)__builtin_frame_address(0))); ShowBacktrace(2, &(struct StackFrame){ diff --git a/libc/log/oncrash_arm64.c b/libc/log/oncrash_arm64.c index eceeb654c..fd9e88e1b 100644 --- a/libc/log/oncrash_arm64.c +++ b/libc/log/oncrash_arm64.c @@ -229,8 +229,8 @@ static relegated void __oncrash_impl(int sig, struct siginfo *si, Append(b, " %s %s %s %s\n", names.sysname, names.version, names.nodename, names.release); Append( - b, " cosmoaddr2line %s%s %lx %s\n", __argv[0], - endswith(__argv[0], ".com") ? ".dbg" : "", ctx ? ctx->uc_mcontext.PC : 0, + b, " cosmoaddr2line %s %lx %s\n", FindDebugBinary(), + ctx ? ctx->uc_mcontext.PC : 0, DescribeBacktrace(ctx ? (struct StackFrame *)ctx->uc_mcontext.BP : (struct StackFrame *)__builtin_frame_address(0))); if (ctx) { diff --git a/libc/log/showcrashreports.c b/libc/log/showcrashreports.c index 6c3e0620b..266d2b1ae 100644 --- a/libc/log/showcrashreports.c +++ b/libc/log/showcrashreports.c @@ -76,6 +76,7 @@ static void InstallCrashHandler(int sig, int flags) { void ShowCrashReports(void) { struct sigaltstack ss; static char crashstack[65536]; + FindDebugBinary(); ss.ss_flags = 0; ss.ss_size = sizeof(crashstack); ss.ss_sp = crashstack; diff --git a/libc/tinymath/__math_oflow.c b/libc/tinymath/__math_oflow.c index c9e56d044..02ea55841 100644 --- a/libc/tinymath/__math_oflow.c +++ b/libc/tinymath/__math_oflow.c @@ -28,7 +28,7 @@ #include "libc/tinymath/internal.h" // clang-format off -double __math_oflow(uint32_t sign) +dontinstrument double __math_oflow(uint32_t sign) { return __math_xflow(sign, 0x1p769); } diff --git a/libc/tinymath/__math_oflowf.c b/libc/tinymath/__math_oflowf.c index af6929dc1..9eff176ee 100644 --- a/libc/tinymath/__math_oflowf.c +++ b/libc/tinymath/__math_oflowf.c @@ -28,7 +28,7 @@ #include "libc/tinymath/internal.h" // clang-format off -float __math_oflowf(uint32_t sign) +dontinstrument float __math_oflowf(uint32_t sign) { return __math_xflowf(sign, 0x1p97f); } diff --git a/libc/tinymath/__math_uflow.c b/libc/tinymath/__math_uflow.c index bfe89b46a..a671044da 100644 --- a/libc/tinymath/__math_uflow.c +++ b/libc/tinymath/__math_uflow.c @@ -28,7 +28,7 @@ #include "libc/tinymath/internal.h" // clang-format off -double __math_uflow(uint32_t sign) +dontinstrument double __math_uflow(uint32_t sign) { return __math_xflow(sign, 0x1p-767); } diff --git a/libc/tinymath/__math_uflowf.c b/libc/tinymath/__math_uflowf.c index 29931ebfd..7f108f6f0 100644 --- a/libc/tinymath/__math_uflowf.c +++ b/libc/tinymath/__math_uflowf.c @@ -28,7 +28,7 @@ #include "libc/tinymath/internal.h" // clang-format off -float __math_uflowf(uint32_t sign) +dontinstrument float __math_uflowf(uint32_t sign) { return __math_xflowf(sign, 0x1p-95f); } diff --git a/libc/tinymath/__math_xflow.c b/libc/tinymath/__math_xflow.c index dd732eee8..145437f50 100644 --- a/libc/tinymath/__math_xflow.c +++ b/libc/tinymath/__math_xflow.c @@ -28,7 +28,7 @@ #include "libc/tinymath/internal.h" // clang-format off -double __math_xflow(uint32_t sign, double y) +dontinstrument double __math_xflow(uint32_t sign, double y) { return eval_as_double(fp_barrier(sign ? -y : y) * y); } diff --git a/libc/tinymath/__math_xflowf.c b/libc/tinymath/__math_xflowf.c index ae3fef854..13d9c7be9 100644 --- a/libc/tinymath/__math_xflowf.c +++ b/libc/tinymath/__math_xflowf.c @@ -28,7 +28,7 @@ #include "libc/tinymath/internal.h" // clang-format off -float __math_xflowf(uint32_t sign, float y) +dontinstrument float __math_xflowf(uint32_t sign, float y) { return eval_as_float(fp_barrierf(sign ? -y : y) * y); }