// Copyright 2016 The Android Open Source Project // // This software is licensed under the terms of the GNU General Public // License version 2, as published by the Free Software Foundation, and // may be copied, distributed, and modified under those terms. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. #include "aemu/base/Debug.h" #include #include #include "aemu/base/ArraySize.h" #include "aemu/base/files/PathUtils.h" #ifdef _WIN32 #include #elif defined(__linux__) #include #include #include #include #elif defined(__APPLE__) #include #include #ifndef _MSC_VER #include #endif #endif namespace android { namespace base { #ifdef __linux__ static std::string readFile(std::string_view path) { std::ifstream is(c_str(path)); if (!is) { return {}; } std::ostringstream ss; ss << is.rdbuf(); return ss.str(); } #endif bool IsDebuggerAttached() { #ifdef _WIN32 return ::IsDebuggerPresent() != 0; #elif defined(__linux__) std::string procStatus = readFile("/proc/self/status"); static constexpr std::string_view kTracerPidPrefix = "TracerPid:"; const auto tracerPid = procStatus.find(kTracerPidPrefix.data()); if (tracerPid == std::string::npos) { return false; } // If the tracer PID is parseable and not 0, there's a debugger attached. const bool debuggerAttached = atoi(procStatus.c_str() + tracerPid + kTracerPidPrefix.size()) != 0; return debuggerAttached; #elif defined(__APPLE__) int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()}; struct kinfo_proc procInfo = {}; size_t infoSize = sizeof(procInfo); const int res = sysctl(mib, arraySize(mib), &procInfo, &infoSize, nullptr, 0); if (res) { return false; } return (procInfo.kp_proc.p_flag & P_TRACED) != 0; #else #error Unsupported platform #endif } bool WaitForDebugger(int64_t timeoutMs) { static const int64_t sleepTimeoutMs = 500; int64_t sleptForMs = 0; while (!IsDebuggerAttached() && (timeoutMs == -1 || sleptForMs < timeoutMs)) { std::this_thread::sleep_for(std::chrono::milliseconds(sleepTimeoutMs)); sleptForMs += sleepTimeoutMs; } return IsDebuggerAttached(); } void DebugBreak() { #ifdef _WIN32 ::DebugBreak(); #else #ifdef __x86_64__ asm("int $3"); #elif defined(__aarch64) asm("bkpt"); #endif #endif } } // namespace base } // namespace android