From c15794d4b399032af76d32cd6d8396bba0537ad8 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Mon, 21 Mar 2016 14:19:08 +1100 Subject: [PATCH] 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. --- debug.cpp | 10 ++++++++++ debug_posix.cpp | 52 ++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 55 insertions(+), 7 deletions(-) diff --git a/debug.cpp b/debug.cpp index 91a01b72..5a6eea98 100644 --- a/debug.cpp +++ b/debug.cpp @@ -85,3 +85,13 @@ util::debug::init (void) if (getenv ("DEBUG_WAIT")) await_debugger (); } + + +/////////////////////////////////////////////////////////////////////////////// +static void +debug_wait [[gnu::constructor]] (void) { + if (auto val = getenv ("DEBUG_WAIT")) { + if (std::string ("0") != val) + await_debugger (); + } +} diff --git a/debug_posix.cpp b/debug_posix.cpp index b1e2ab7f..8ed67e64 100644 --- a/debug_posix.cpp +++ b/debug_posix.cpp @@ -21,18 +21,53 @@ #include #include +#include +#include #include +/////////////////////////////////////////////////////////////////////////////// +// 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 breakpoint (void) { -#if defined (__x86_64) || defined (__i386) - __asm__ ("int $3;"); -#else - raise (SIGINT); -#endif + raise (SIGTRAP); } @@ -48,8 +83,11 @@ prepare_debugger (void) void await_debugger (void) { - if (ptrace (PTRACE_TRACEME)) - LOG_CRITICAL ("unable to wait for debugger"); + if (is_debugged ()) + breakpoint (); + else + raise (SIGSTOP); + }