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_
|
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)
|
||||||
|
@ -35,7 +35,7 @@ void __unassert_fail(const char *, const char *, int);
|
||||||
#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(); \
|
||||||
} \
|
} \
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
|
@ -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;
|
|
@ -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,7 +277,7 @@ 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) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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){
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue