mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-25 07:19:02 +00:00
Improve debug binary location detection
This commit is contained in:
parent
68c7c9c1e0
commit
7a9e176ecf
17 changed files with 92 additions and 50 deletions
|
@ -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) \
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
|
@ -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;
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
|
|
|
@ -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){
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue