| // Copyright Catch2 Authors | |
| // Distributed under the Boost Software License, Version 1.0. | |
| // (See accompanying file LICENSE.txt or copy at | |
| // https://www.boost.org/LICENSE_1_0.txt) | |
| // SPDX-License-Identifier: BSL-1.0 | |
| #ifndef CATCH_DEBUGGER_HPP_INCLUDED | |
| #define CATCH_DEBUGGER_HPP_INCLUDED | |
| #include <catch2/internal/catch_platform.hpp> | |
| namespace Catch { | |
| bool isDebuggerActive(); | |
| } | |
| #if !defined( CATCH_TRAP ) && defined( __clang__ ) && defined( __has_builtin ) | |
| # if __has_builtin( __builtin_debugtrap ) | |
| # define CATCH_TRAP() __builtin_debugtrap() | |
| # endif | |
| #endif | |
| #if !defined( CATCH_TRAP ) && defined( _MSC_VER ) | |
| # define CATCH_TRAP() __debugbreak() | |
| #endif | |
| #if !defined(CATCH_TRAP) // If we couldn't use compiler-specific impl from above, we get into platform-specific options | |
| #ifdef CATCH_PLATFORM_MAC | |
| #if defined(__i386__) || defined(__x86_64__) | |
| #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */ | |
| #elif defined(__aarch64__) | |
| #define CATCH_TRAP() __asm__(".inst 0xd43e0000") | |
| #elif defined(__POWERPC__) | |
| #define CATCH_TRAP() __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ | |
| : : : "memory","r0","r3","r4" ) /* NOLINT */ | |
| #endif | |
| #elif defined(CATCH_PLATFORM_IPHONE) | |
| // use inline assembler | |
| #if defined(__i386__) || defined(__x86_64__) | |
| #define CATCH_TRAP() __asm__("int $3") | |
| #elif defined(__aarch64__) | |
| #define CATCH_TRAP() __asm__(".inst 0xd4200000") | |
| #elif defined(__arm__) && !defined(__thumb__) | |
| #define CATCH_TRAP() __asm__(".inst 0xe7f001f0") | |
| #elif defined(__arm__) && defined(__thumb__) | |
| #define CATCH_TRAP() __asm__(".inst 0xde01") | |
| #endif | |
| #elif defined(CATCH_PLATFORM_LINUX) | |
| // If we can use inline assembler, do it because this allows us to break | |
| // directly at the location of the failing check instead of breaking inside | |
| // raise() called from it, i.e. one stack frame below. | |
| #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64)) | |
| #define CATCH_TRAP() asm volatile ("int $3") /* NOLINT */ | |
| #else // Fall back to the generic way. | |
| #include <signal.h> | |
| #define CATCH_TRAP() raise(SIGTRAP) | |
| #endif | |
| #elif defined(__MINGW32__) | |
| extern "C" __declspec(dllimport) void __stdcall DebugBreak(); | |
| #define CATCH_TRAP() DebugBreak() | |
| #endif | |
| #endif // ^^ CATCH_TRAP is not defined yet, so we define it | |
| #if !defined(CATCH_BREAK_INTO_DEBUGGER) | |
| #if defined(CATCH_TRAP) | |
| #define CATCH_BREAK_INTO_DEBUGGER() []{ if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } }() | |
| #else | |
| #define CATCH_BREAK_INTO_DEBUGGER() []{}() | |
| #endif | |
| #endif | |
| #endif // CATCH_DEBUGGER_HPP_INCLUDED |