From b634e592dac83edddf724c2e243c674132ddfa8c Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 5 Feb 2016 14:56:20 +0100 Subject: [PATCH] Add support for breaking into debugger for Linux Use Linux-specific /proc/$PID/status file to check whether we're being debugged and a generic raise(SIGTRAP) to actually break into the debugger. --- include/internal/catch_debugger.h | 4 ++++ include/internal/catch_debugger.hpp | 27 +++++++++++++++++++++++++++ include/internal/catch_platform.h | 2 ++ 3 files changed, 33 insertions(+) diff --git a/include/internal/catch_debugger.h b/include/internal/catch_debugger.h index 0dd36aa3..b0588f6a 100644 --- a/include/internal/catch_debugger.h +++ b/include/internal/catch_debugger.h @@ -35,6 +35,10 @@ namespace Catch{ #endif #endif +#elif defined(CATCH_PLATFORM_LINUX) + #include + + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { raise(SIGTRAP); } #elif defined(_MSC_VER) #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); } #elif defined(__MINGW32__) diff --git a/include/internal/catch_debugger.hpp b/include/internal/catch_debugger.hpp index 8c552661..77ab29cc 100644 --- a/include/internal/catch_debugger.hpp +++ b/include/internal/catch_debugger.hpp @@ -61,6 +61,33 @@ } } // namespace Catch +#elif defined(CATCH_PLATFORM_LINUX) + #include + #include + + namespace Catch{ + // The standard POSIX way of detecting a debugger is to attempt to + // ptrace() the process, but this needs to be done from a child and not + // this process itself to still allow attaching to this process later + // if wanted, so is rather heavy. Under Linux we have the PID of the + // "debugger" (which doesn't need to be gdb, of course, it could also + // be strace, for example) in /proc/$PID/status, so just get it from + // there instead. + bool isDebuggerActive(){ + std::ifstream in("/proc/self/status"); + for( std::string line; std::getline(in, line); ) { + static const int PREFIX_LEN = 11; + if( line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0 ) { + // We're traced if the PID is not 0 and no other PID starts + // with 0 digit, so it's enough to check for just a single + // character. + return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0'; + } + } + + return false; + } + } // namespace Catch #elif defined(_MSC_VER) extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); namespace Catch { diff --git a/include/internal/catch_platform.h b/include/internal/catch_platform.h index 0142dc14..120ba599 100644 --- a/include/internal/catch_platform.h +++ b/include/internal/catch_platform.h @@ -15,6 +15,8 @@ #define CATCH_PLATFORM_IPHONE #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) #define CATCH_PLATFORM_WINDOWS +#elif defined(linux) || defined(__linux) || defined(__linux__) +#define CATCH_PLATFORM_LINUX #endif #endif // TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED