debug: make DEBUG_WAIT support more robust
PTRACE_ME doesn't work as we thought, instead just deliver a suitable signal depending on if we're currently under a debugger.
This commit is contained in:
parent
eacd2f6072
commit
c15794d4b3
10
debug.cpp
10
debug.cpp
@ -85,3 +85,13 @@ util::debug::init (void)
|
|||||||
if (getenv ("DEBUG_WAIT"))
|
if (getenv ("DEBUG_WAIT"))
|
||||||
await_debugger ();
|
await_debugger ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
static void
|
||||||
|
debug_wait [[gnu::constructor]] (void) {
|
||||||
|
if (auto val = getenv ("DEBUG_WAIT")) {
|
||||||
|
if (std::string ("0") != val)
|
||||||
|
await_debugger ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -21,18 +21,53 @@
|
|||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/ptrace.h>
|
#include <sys/ptrace.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Will return true if it is known we are under a debugger. This isn't
|
||||||
|
// designed to exhaustively check for debuggers, only to offer conveniences.
|
||||||
|
// Specifically: errors will return false.
|
||||||
|
static
|
||||||
|
bool
|
||||||
|
is_debugged (void)
|
||||||
|
{
|
||||||
|
auto pid = fork ();
|
||||||
|
if (pid == -1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// We are the child
|
||||||
|
if (pid == 0) {
|
||||||
|
auto ppid = getppid ();
|
||||||
|
int res;
|
||||||
|
|
||||||
|
// attempt to trace our parent. this will fail if we're being debugged.
|
||||||
|
if (ptrace (PTRACE_ATTACH, ppid, nullptr, nullptr) == 0) {
|
||||||
|
waitpid (ppid, nullptr, 0);
|
||||||
|
ptrace (PTRACE_DETACH, ppid, nullptr, nullptr);
|
||||||
|
|
||||||
|
res = 0;
|
||||||
|
} else {
|
||||||
|
res = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
_exit (res);
|
||||||
|
// We are the parent. Wait for our child to tell us the result.
|
||||||
|
} else {
|
||||||
|
int status;
|
||||||
|
waitpid (pid, &status, 0);
|
||||||
|
return WEXITSTATUS (status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
void
|
void
|
||||||
breakpoint (void)
|
breakpoint (void)
|
||||||
{
|
{
|
||||||
#if defined (__x86_64) || defined (__i386)
|
raise (SIGTRAP);
|
||||||
__asm__ ("int $3;");
|
|
||||||
#else
|
|
||||||
raise (SIGINT);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -48,8 +83,11 @@ prepare_debugger (void)
|
|||||||
void
|
void
|
||||||
await_debugger (void)
|
await_debugger (void)
|
||||||
{
|
{
|
||||||
if (ptrace (PTRACE_TRACEME))
|
if (is_debugged ())
|
||||||
LOG_CRITICAL ("unable to wait for debugger");
|
breakpoint ();
|
||||||
|
else
|
||||||
|
raise (SIGSTOP);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user