5#if PLUGIFY_STACKTRACE_SUPPORT
11#if PLUGIFY_PLATFORM_WINDOWS
14#elif PLUGIFY_PLATFORM_SWITCH
15#include <nn/diag/diag_Debugger.h>
16#elif PLUGIFY_PLATFORM_ORBIS || PLUGIFY_PLATFORM_PROSPERO
18#elif PLUGIFY_PLATFORM_APPLE
19#include <mach/mach_init.h>
21#elif PLUGIFY_PLATFORM_LINUX
31#if PLUGIFY_STACKTRACE_SUPPORT
33 using std::breakpoint;
34 using std::breakpoint_if_debugging;
35 using std::is_debugger_present;
39#if PLUGIFY_PLATFORM_WINDOWS
41 inline bool is_debugger_present() noexcept {
42 return (IsDebuggerPresent() != FALSE);
45#elif PLUGIFY_PLATFORM_SWITCH
47 inline bool is_debugger_present() noexcept {
48 return nn::diag::IsDebuggerAttached();
51#elif PLUGIFY_PLATFORM_ORBIS || PLUGIFY_PLATFORM_PROSPERO
53 inline bool is_debugger_present() noexcept {
54 return sceDbgIsDebuggerAttached() != 0;
57#elif PLUGIFY_PLATFORM_APPLE
59 inline bool is_debugger_present() noexcept {
60 mach_msg_type_number_t count = 0;
61 exception_mask_t masks[EXC_TYPES_COUNT];
62 mach_port_t ports[EXC_TYPES_COUNT];
63 exception_behavior_t behaviors[EXC_TYPES_COUNT];
64 thread_state_flavor_t flavors[EXC_TYPES_COUNT];
65 exception_mask_t mask = EXC_MASK_ALL & ~(EXC_MASK_RESOURCE | EXC_MASK_GUARD);
67 kern_return_t result = task_get_exception_ports(mach_task_self(), mask, masks, &count, ports, behaviors, flavors);
68 if (result != KERN_SUCCESS)
71 for (mach_msg_type_number_t i = 0; i < count; ++i)
72 if (MACH_PORT_VALID(ports[i]))
78#elif PLUGIFY_PLATFORM_LINUX
82 inline bool parse_proc_status_line(
char* buf,
size_t size)
noexcept {
83 if (std::strncmp(buf,
"TracerPid:\t", 11) != 0) {
86 unsigned long long pid = 0;
89 auto byte =
static_cast<unsigned char>(buf[pos]);
90 if (!(
static_cast<unsigned char>(
'0') <=
byte &&
byte <=
static_cast<unsigned char>(
'9'))) {
93 uint8_t digit =
static_cast<uint8_t
>(
byte -
static_cast<unsigned char>(
'0'));
94 pid = (pid * 10) + digit;
100 inline bool parse_proc_status() noexcept {
101 int olderrno = errno;
102 bool detected_debugger =
false;
105 bool open_done =
false;
107 int res = open(
"/proc/self/status", O_RDONLY);
111 }
else if (errno != EINTR) {
126 size_t iobuf_size = 0;
128 size_t linebuf_size = 0;
130 ssize_t bytes_read = read(fd, iobuf,
sizeof(iobuf));
131 if (bytes_read == -1) {
132 if (errno == EINTR) {
135 }
else if (bytes_read == 0) {
138 iobuf_size =
static_cast<size_t>(bytes_read);
139 for (
size_t i = 0; i < iobuf_size; ++i) {
140 if (iobuf[i] ==
static_cast<unsigned char>(
'\n')) {
141 if (parse_proc_status_line(linebuf, linebuf_size)) {
142 detected_debugger =
true;
146 if (linebuf_size <
sizeof(linebuf)) {
147 linebuf[linebuf_size] =
static_cast<char>(iobuf[i]);
152 if (linebuf_size > 0) {
153 if (parse_proc_status_line(linebuf, linebuf_size)) {
154 detected_debugger =
true;
159 bool close_done =
false;
160 while (!close_done) {
165 }
else if (errno != EINTR) {
175 return detected_debugger;
181 PLUGIFY_NOINLINE
inline bool is_debugger_present() noexcept {
182 return plg::detail::debugging::parse_proc_status();
187 inline bool is_debugger_present() noexcept {
193 PLUGIFY_FORCE_INLINE
void breakpoint() noexcept {
194#if PLUGIFY_COMPILER_MSVC
196#elif PLUGIFY_COMPILER_CLANG
197 __builtin_debugtrap();
198#elif PLUGIFY_COMPILER_GCC
201# error "Unsupported platform for breakpoint"
205 PLUGIFY_FORCE_INLINE
void breakpoint_if_debugging() noexcept {
206 if (plg::is_debugger_present()) {