You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

143 lines
2.4 KiB
C

// SPDX-License-Identifier: LGPL-3.0-or-later
/**
* \file sys/dbg_unix.c
*
* Implements debugging utilities for Unix platforms.
*
* \copyright The DoubleFourteen Code Forge (C) All Rights Reserved
* \author Lorenzo Cogotti
*/
#include "sys/dbg.h"
#include <sys/stat.h>
#include <fcntl.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifdef __has_include
#if __has_include(<execinfo.h>)
#include <execinfo.h>
#define EXECINFO_AVAILABLE 1
#endif
#endif
Boolean Sys_IsDebuggerPresent(void)
{
#ifdef __linux__
// Read process status file
char buf[4096];
int fd = open("/proc/self/status", O_RDONLY);
if (fd < 0)
return FALSE;
ssize_t n = read(fd, buf, sizeof(buf) - 1);
close(fd);
if (n < 0)
return FALSE;
buf[n] = '\0';
const char *tracer = "TracerPid:\t";
const char *pos = strstr(buf, tracer);
if (!pos)
return FALSE;
pos += strlen(tracer);
pid_t pid = atol(pos);
return pid > 0;
#else
// TODO MacOS, BSD via sysctl()
// http://developer.apple.com/qa/qa2004/qa1361.html
// https://github.com/chromium/chromium/blob/master/base/debug/debugger_posix.cc
return FALSE;
#endif
}
size_t Sys_GetBacktrace(void **dest, size_t n)
{
USED(dest);
USED(n);
#ifdef EXECINFO_AVAILABLE
if (n > (size_t) (INT_MAX - 1))
n = INT_MAX - 1;
void **trace = (void **) alloca(sizeof(*trace) * (n + 1));
int res = backtrace(trace, n + 1);
if (res > 0) {
// Exclude ourselves from the trace
res--;
memcpy(dest, trace + 1, res * sizeof(*dest));
return res;
}
#endif
return 0;
}
void *Sys_GetCaller(void)
{
#ifdef EXECINFO_AVAILABLE
void *trace[3]; // ourselves, caller, caller's caller
int n = backtrace(trace, ARRAY_SIZE(trace));
if (n == ARRAY_SIZE(trace))
return trace[2];
#endif
return NULL;
}
char *Sys_GetSymbolName(void *sym)
{
USED(sym);
#ifdef EXECINFO_AVAILABLE
static THREAD_LOCAL char buf[128];
char **names = backtrace_symbols(&sym, 1);
if (names) {
size_t n = strlen(names[0]);
if (n > sizeof(buf) - 1) {
// Truncate symbol
n = sizeof(buf) - 4;
memcpy(buf, names[0], n);
buf[n+0] = '.'; buf[n+1] = '.'; buf[n+2] = '.';
buf[n+3] = '\0';
} else {
memcpy(buf, names[0], n + 1);
}
free(names);
return buf;
}
#endif
return NULL;
}
void Sys_DumpBacktrace(ConHn hn, void **trace, size_t n)
{
USED(hn);
USED(trace);
USED(n);
#ifdef EXECINFO_AVAILABLE
backtrace_symbols_fd(trace, MIN(n, (size_t) INT_MAX), hn);
#endif
}