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_
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) \

View file

@ -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();

View file

@ -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;
}
/**

View file

@ -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;

View file

@ -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;

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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)));
}

View file

@ -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){

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,
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) {

View file

@ -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;

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);
}