#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include "base/debug/debugger.h"
#include <errno.h>
#include <fcntl.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <memory>
#include <string_view>
#include "base/check_op.h"
#include "base/notimplemented.h"
#include "base/strings/string_util.h"
#include "base/threading/platform_thread.h"
#include "base/time/time.h"
#include "build/build_config.h"
#if defined(__GLIBCXX__)
#include <cxxabi.h>
#endif
#if BUILDFLAG(IS_APPLE)
#include <AvailabilityMacros.h>
#endif
#if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_BSD)
#include <sys/sysctl.h>
#endif
#if BUILDFLAG(IS_FREEBSD)
#include <sys/user.h>
#endif
#include <ostream>
#include "base/check.h"
#include "base/debug/alias.h"
#include "base/debug/debugging_buildflags.h"
#include "base/environment.h"
#include "base/files/file_util.h"
#include "base/posix/eintr_wrapper.h"
#include "base/process/process.h"
#include "base/strings/string_number_conversions.h"
#if defined(USE_SYMBOLIZE)
#include "base/third_party/symbolize/symbolize.h"
#endif
namespace base {
namespace debug {
#if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_BSD)
bool BeingDebugged() {
static bool is_set = false;
static bool being_debugged = false;
if (is_set)
return being_debugged;
int mib[] = {
CTL_KERN,
KERN_PROC,
KERN_PROC_PID,
getpid()
#if BUILDFLAG(IS_OPENBSD)
,
sizeof(struct kinfo_proc),
0
#endif
};
struct kinfo_proc info;
size_t info_size = sizeof(info);
#if BUILDFLAG(IS_OPENBSD)
if (sysctl(mib, std::size(mib), NULL, &info_size, NULL, 0) < 0)
return -1;
mib[5] = (info_size / sizeof(struct kinfo_proc));
#endif
int sysctl_result = sysctl(mib, std::size(mib), &info, &info_size, NULL, 0);
DCHECK_EQ(sysctl_result, 0);
if (sysctl_result != 0) {
is_set = true;
being_debugged = false;
return being_debugged;
}
is_set = true;
#if BUILDFLAG(IS_FREEBSD)
being_debugged = (info.ki_flag & P_TRACED) != 0;
#elif BUILDFLAG(IS_BSD)
being_debugged = (info.p_flag & P_TRACED) != 0;
#else
being_debugged = (info.kp_proc.p_flag & P_TRACED) != 0;
#endif
return being_debugged;
}
void VerifyDebugger() {
#if BUILDFLAG(ENABLE_LLDBINIT_WARNING)
if (Environment::Create()->HasVar("CHROMIUM_LLDBINIT_SOURCED"))
return;
if (!BeingDebugged())
return;
DCHECK(false)
<< "Detected lldb without sourcing //tools/lldb/lldbinit.py. lldb may "
"not be able to find debug symbols. Please see debug instructions for "
"using //tools/lldb/lldbinit.py:\n"
"https://chromium.googlesource.com/chromium/src/+/main/docs/"
"lldbinit.md\n"
"To continue anyway, type 'continue' in lldb. To always skip this "
"check, define an environment variable CHROMIUM_LLDBINIT_SOURCED=1";
#endif
}
#elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \
BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_AIX)
Process GetDebuggerProcess() { … }
bool BeingDebugged() { … }
void VerifyDebugger() { … }
#else
bool BeingDebugged() {
NOTIMPLEMENTED();
return false;
}
void VerifyDebugger() {}
#endif
#if defined(ARCH_CPU_ARMEL)
#define DEBUG_BREAK_ASM …
#elif defined(ARCH_CPU_ARM64)
#define DEBUG_BREAK_ASM …
#elif defined(ARCH_CPU_MIPS_FAMILY)
#define DEBUG_BREAK_ASM …
#elif defined(ARCH_CPU_X86_FAMILY)
#define DEBUG_BREAK_ASM() …
#endif
#if defined(NDEBUG) && !BUILDFLAG(IS_APPLE) && !BUILDFLAG(IS_ANDROID)
#define DEBUG_BREAK …
#elif BUILDFLAG(IS_NACL)
#define DEBUG_BREAK …
#elif !BUILDFLAG(IS_APPLE)
namespace {
void DebugBreak() { … }
}
#define DEBUG_BREAK() …
#elif defined(DEBUG_BREAK_ASM)
#define DEBUG_BREAK …
#else
#error "Don't know how to debug break on this architecture/OS"
#endif
void BreakDebuggerAsyncSafe() { … }
}
}