Improve debug binary location detection

This commit is contained in:
Justine Tunney 2023-11-16 23:26:05 -08:00
parent 68c7c9c1e0
commit 7a9e176ecf
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
17 changed files with 92 additions and 50 deletions

View file

@ -15,7 +15,7 @@
COSMOPOLITAN_C_START_ COSMOPOLITAN_C_START_
void __assert_fail(const char *, const char *, int); 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 #ifdef NDEBUG
#define assert(x) ((void)0) #define assert(x) ((void)0)
@ -32,14 +32,14 @@ void __unassert_fail(const char *, const char *, int);
#ifndef NDEBUG #ifndef NDEBUG
#define unassert(x) __assert_macro(x, #x) #define unassert(x) __assert_macro(x, #x)
#define npassert(x) __assert_macro(x, #x) #define npassert(x) __assert_macro(x, #x)
#define __assert_macro(x, s) \ #define __assert_macro(x, s) \
({ \ ({ \
if (__builtin_expect(!(x), 0)) { \ if (__builtin_expect(!(x), 0)) { \
__unassert_fail(s, __FILE__, __LINE__); \ (unassert)(s, __FILE__, __LINE__); \
__asm__("nop"); \ __asm__("nop"); \
__builtin_unreachable(); \ __builtin_unreachable(); \
} \ } \
(void)0; \ (void)0; \
}) })
#else #else
#define npassert(x) \ #define npassert(x) \

View file

@ -23,6 +23,7 @@
#include "libc/fmt/itoa.h" #include "libc/fmt/itoa.h"
#include "libc/intrin/describebacktrace.internal.h" #include "libc/intrin/describebacktrace.internal.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/runtime/symbols.internal.h"
/** /**
* Handles assert() failure. * Handles assert() failure.
@ -32,7 +33,7 @@ void __assert_fail(const char *expr, const char *file, int line) {
sigset_t m = __sig_block(); sigset_t m = __sig_block();
FormatInt32(ibuf, line); FormatInt32(ibuf, line);
tinyprint(2, file, ":", ibuf, ": \e[31;1massert(", expr, 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); DescribeBacktrace(__builtin_frame_address(0)), ")\n", NULL);
__sig_unblock(m); __sig_unblock(m);
abort(); abort();

View file

@ -20,13 +20,17 @@
#include "libc/atomic.h" #include "libc/atomic.h"
#include "libc/calls/blockcancel.internal.h" #include "libc/calls/blockcancel.internal.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/cosmo.h" #include "libc/cosmo.h"
#include "libc/dce.h"
#include "libc/elf/def.h"
#include "libc/elf/tinyelf.internal.h" #include "libc/elf/tinyelf.internal.h"
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/intrin/bits.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/runtime.h"
#include "libc/runtime/symbols.internal.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "libc/sysv/consts/map.h" #include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h" #include "libc/sysv/consts/o.h"
@ -38,24 +42,57 @@ static struct {
char buf[PATH_MAX]; char buf[PATH_MAX];
} g_comdbg; } 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) { static bool IsMyDebugBinary(const char *path) {
void *map;
int64_t size; int64_t size;
uintptr_t value; uintptr_t value;
bool res = false; bool res = false;
int fd, e = errno; int fd, e = errno;
struct DirectMap dm;
BLOCK_CANCELATION; BLOCK_CANCELATION;
if ((fd = open(path, O_RDONLY | O_CLOEXEC, 0)) != -1) { if ((fd = open(path, O_RDONLY | O_CLOEXEC, 0)) != -1) {
// sanity test that this .com.dbg file (1) is an elf image, and (2) // 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 // contains the same number of bytes of code as our .com executable
// which is currently running in memory. // which is currently running in memory.
if ((size = lseek(fd, 0, SEEK_END)) != -1 && if ((size = lseek(fd, 0, SEEK_END)) != -1 &&
(map = mmap(0, size, PROT_READ, MAP_SHARED, fd, 0)) != MAP_FAILED) { (dm = sys_mmap(0, size, PROT_READ, MAP_SHARED, fd, 0)).addr !=
if (READ32LE((char *)map) == READ32LE("\177ELF") && MAP_FAILED) {
GetElfSymbolValue(map, "_etext", &value)) { 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; 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); close(fd);
} }
@ -65,20 +102,21 @@ static bool IsMyDebugBinary(const char *path) {
} }
static void FindDebugBinaryInit(void) { static void FindDebugBinaryInit(void) {
char *p = GetProgramExecutableName(); const char *comdbg;
size_t n = strlen(p); if ((comdbg = getenv("COMDBG")) && IsMyDebugBinary(comdbg)) {
if ((n > 4 && READ32LE(p + n - 4) == READ32LE(".dbg")) || g_comdbg.res = comdbg;
IsMyDebugBinary(p)) { return;
g_comdbg.res = p; }
} else if (n + 4 < ARRAYLEN(g_comdbg.buf)) { char *prog = GetProgramExecutableName();
mempcpy(mempcpy(g_comdbg.buf, p, n), ".dbg", 5); 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)) { if (IsMyDebugBinary(g_comdbg.buf)) {
g_comdbg.res = g_comdbg.buf; g_comdbg.res = g_comdbg.buf;
return;
} }
} }
if (!g_comdbg.res) { g_comdbg.res = prog;
g_comdbg.res = getenv("COMDBG");
}
} }
/** /**

View file

@ -23,6 +23,7 @@
#include "libc/fmt/itoa.h" #include "libc/fmt/itoa.h"
#include "libc/intrin/describebacktrace.internal.h" #include "libc/intrin/describebacktrace.internal.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/runtime/symbols.internal.h"
/** /**
* Handles unassert() failure. * Handles unassert() failure.
@ -32,12 +33,12 @@
* number of things. By doing this instead, we guarantee the backtrace * number of things. By doing this instead, we guarantee the backtrace
* reported to the signal handler is clean and focused on the problem. * 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]; char ibuf[12];
sigset_t m = __sig_block(); sigset_t m = __sig_block();
FormatInt32(ibuf, line); FormatInt32(ibuf, line);
tinyprint(2, file, ":", ibuf, ": \e[31;1munassert(", expr, 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); DescribeBacktrace(__builtin_frame_address(0)), ")\n", NULL);
__sig_unblock(m); __sig_unblock(m);
notpossible; notpossible;

View file

@ -112,7 +112,7 @@ struct Loaded {
char *base; char *base;
char *entry; char *entry;
Elf64_Ehdr eh; Elf64_Ehdr eh;
Elf64_Phdr ph[30]; Elf64_Phdr ph[25];
}; };
static struct { static struct {
@ -277,8 +277,8 @@ static bool elf_slurp(struct Loaded *l, int fd, const char *file) {
return true; return true;
} }
static bool elf_load(struct Loaded *l, const char *file, long pagesz, static dontinline bool elf_load(struct Loaded *l, const char *file, long pagesz,
char *interp_path, size_t interp_size) { char *interp_path, size_t interp_size) {
int fd; int fd;
if ((fd = open(file, O_RDONLY | O_CLOEXEC)) == -1) { if ((fd = open(file, O_RDONLY | O_CLOEXEC)) == -1) {
return false; return false;

View file

@ -18,7 +18,7 @@
*/ */
// stub version of unassert() to keep the build a dag // stub version of unassert() to keep the build a dag
__attribute__((__weak__)) void __unassert_fail(const char *expr, __attribute__((__weak__)) void(unassert)(const char *expr, const char *file,
const char *file, int line) { int line) {
notpossible; notpossible;
} }

View file

@ -22,6 +22,7 @@
#include "libc/intrin/kprintf.h" #include "libc/intrin/kprintf.h"
#include "libc/log/internal.h" #include "libc/log/internal.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/runtime/symbols.internal.h"
#include "libc/str/str.h" #include "libc/str/str.h"
/** /**
@ -46,10 +47,9 @@ relegated wontreturn void __die(void) {
strcpy(host, "unknown"); strcpy(host, "unknown");
gethostname(host, sizeof(host)); gethostname(host, sizeof(host));
kprintf("%serror: %s on %s pid %d tid %d has perished%s\n" 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, __nocolor ? "" : "\e[1;31m", program_invocation_short_name, host,
getpid(), gettid(), __nocolor ? "" : "\e[0m", __argv[0], getpid(), gettid(), __nocolor ? "" : "\e[0m", FindDebugBinary(),
endswith(__argv[0], ".com") ? ".dbg" : "",
DescribeBacktrace(__builtin_frame_address(0))); DescribeBacktrace(__builtin_frame_address(0)));
_Exit(77); _Exit(77);
} }

View file

@ -26,6 +26,7 @@
#include "libc/log/internal.h" #include "libc/log/internal.h"
#include "libc/log/log.h" #include "libc/log/log.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/runtime/symbols.internal.h"
#include "libc/str/str.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)); gethostname(host, sizeof(host));
kprintf( kprintf(
"%serror: %s on %s pid %d tid %d got %G%s code %d addr %p%s\n" "%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, __nocolor ? "" : "\e[1;31m", program_invocation_short_name, host,
getpid(), gettid(), sig, getpid(), gettid(), sig,
__is_stack_overflow(si, ctx) ? " (stack overflow)" : "", si->si_code, __is_stack_overflow(si, ctx) ? " (stack overflow)" : "", si->si_code,
si->si_addr, __nocolor ? "" : "\e[0m", __argv[0], si->si_addr, __nocolor ? "" : "\e[0m", FindDebugBinary(),
endswith(__argv[0], ".com") ? ".dbg" : "", ctx ? ctx->uc_mcontext.PC : 0, ctx ? ctx->uc_mcontext.PC : 0,
DescribeBacktrace(ctx ? (struct StackFrame *)ctx->uc_mcontext.BP DescribeBacktrace(ctx ? (struct StackFrame *)ctx->uc_mcontext.BP
: (struct StackFrame *)__builtin_frame_address(0))); : (struct StackFrame *)__builtin_frame_address(0)));
} }

View file

@ -74,8 +74,8 @@ static const char kFpuExceptions[6] forcealign(1) = "IDZOUP";
relegated static void ShowFunctionCalls(ucontext_t *ctx) { relegated static void ShowFunctionCalls(ucontext_t *ctx) {
kprintf( kprintf(
"cosmoaddr2line %s%s %lx %s\n\n", __argv[0], "cosmoaddr2line %s %lx %s\n\n", FindDebugBinary(),
endswith(__argv[0], ".com") ? ".dbg" : "", ctx ? ctx->uc_mcontext.PC : 0, ctx ? ctx->uc_mcontext.PC : 0,
DescribeBacktrace(ctx ? (struct StackFrame *)ctx->uc_mcontext.BP DescribeBacktrace(ctx ? (struct StackFrame *)ctx->uc_mcontext.BP
: (struct StackFrame *)__builtin_frame_address(0))); : (struct StackFrame *)__builtin_frame_address(0)));
ShowBacktrace(2, &(struct StackFrame){ ShowBacktrace(2, &(struct StackFrame){

View file

@ -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, Append(b, " %s %s %s %s\n", names.sysname, names.version, names.nodename,
names.release); names.release);
Append( Append(
b, " cosmoaddr2line %s%s %lx %s\n", __argv[0], b, " cosmoaddr2line %s %lx %s\n", FindDebugBinary(),
endswith(__argv[0], ".com") ? ".dbg" : "", ctx ? ctx->uc_mcontext.PC : 0, ctx ? ctx->uc_mcontext.PC : 0,
DescribeBacktrace(ctx ? (struct StackFrame *)ctx->uc_mcontext.BP DescribeBacktrace(ctx ? (struct StackFrame *)ctx->uc_mcontext.BP
: (struct StackFrame *)__builtin_frame_address(0))); : (struct StackFrame *)__builtin_frame_address(0)));
if (ctx) { if (ctx) {

View file

@ -76,6 +76,7 @@ static void InstallCrashHandler(int sig, int flags) {
void ShowCrashReports(void) { void ShowCrashReports(void) {
struct sigaltstack ss; struct sigaltstack ss;
static char crashstack[65536]; static char crashstack[65536];
FindDebugBinary();
ss.ss_flags = 0; ss.ss_flags = 0;
ss.ss_size = sizeof(crashstack); ss.ss_size = sizeof(crashstack);
ss.ss_sp = crashstack; ss.ss_sp = crashstack;

View file

@ -28,7 +28,7 @@
#include "libc/tinymath/internal.h" #include "libc/tinymath/internal.h"
// clang-format off // clang-format off
double __math_oflow(uint32_t sign) dontinstrument double __math_oflow(uint32_t sign)
{ {
return __math_xflow(sign, 0x1p769); return __math_xflow(sign, 0x1p769);
} }

View file

@ -28,7 +28,7 @@
#include "libc/tinymath/internal.h" #include "libc/tinymath/internal.h"
// clang-format off // clang-format off
float __math_oflowf(uint32_t sign) dontinstrument float __math_oflowf(uint32_t sign)
{ {
return __math_xflowf(sign, 0x1p97f); return __math_xflowf(sign, 0x1p97f);
} }

View file

@ -28,7 +28,7 @@
#include "libc/tinymath/internal.h" #include "libc/tinymath/internal.h"
// clang-format off // clang-format off
double __math_uflow(uint32_t sign) dontinstrument double __math_uflow(uint32_t sign)
{ {
return __math_xflow(sign, 0x1p-767); return __math_xflow(sign, 0x1p-767);
} }

View file

@ -28,7 +28,7 @@
#include "libc/tinymath/internal.h" #include "libc/tinymath/internal.h"
// clang-format off // clang-format off
float __math_uflowf(uint32_t sign) dontinstrument float __math_uflowf(uint32_t sign)
{ {
return __math_xflowf(sign, 0x1p-95f); return __math_xflowf(sign, 0x1p-95f);
} }

View file

@ -28,7 +28,7 @@
#include "libc/tinymath/internal.h" #include "libc/tinymath/internal.h"
// clang-format off // 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); return eval_as_double(fp_barrier(sign ? -y : y) * y);
} }

View file

@ -28,7 +28,7 @@
#include "libc/tinymath/internal.h" #include "libc/tinymath/internal.h"
// clang-format off // 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); return eval_as_float(fp_barrierf(sign ? -y : y) * y);
} }