• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The Android Open Source Project
2 //
3 // This software is licensed under the terms of the GNU General Public
4 // License version 2, as published by the Free Software Foundation, and
5 // may be copied, distributed, and modified under those terms.
6 //
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 // GNU General Public License for more details.
11 
12 #include "aemu/base/Debug.h"
13 
14 #include <chrono>
15 #include <thread>
16 
17 #include "aemu/base/ArraySize.h"
18 #include "aemu/base/files/PathUtils.h"
19 #ifdef _WIN32
20 #include <windows.h>
21 #elif defined(__linux__)
22 #include <fstream>
23 #include <sstream>
24 #include <string>
25 #include <string_view>
26 #elif defined(__APPLE__)
27 #include <sys/sysctl.h>
28 #include <sys/types.h>
29 #ifndef _MSC_VER
30 #include <unistd.h>
31 #endif
32 #endif
33 
34 namespace android {
35 namespace base {
36 
37 #ifdef __linux__
readFile(std::string_view path)38 static std::string readFile(std::string_view path) {
39     std::ifstream is(c_str(path));
40 
41     if (!is) {
42         return {};
43     }
44 
45     std::ostringstream ss;
46     ss << is.rdbuf();
47     return ss.str();
48 }
49 #endif
50 
IsDebuggerAttached()51 bool IsDebuggerAttached() {
52 #ifdef _WIN32
53     return ::IsDebuggerPresent() != 0;
54 #elif defined(__linux__)
55     std::string procStatus = readFile("/proc/self/status");
56 
57     static constexpr std::string_view kTracerPidPrefix = "TracerPid:";
58     const auto tracerPid = procStatus.find(kTracerPidPrefix.data());
59     if (tracerPid == std::string::npos) {
60         return false;
61     }
62 
63     // If the tracer PID is parseable and not 0, there's a debugger attached.
64     const bool debuggerAttached =
65         atoi(procStatus.c_str() + tracerPid + kTracerPidPrefix.size()) != 0;
66     return debuggerAttached;
67 #elif defined(__APPLE__)
68     int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()};
69     struct kinfo_proc procInfo = {};
70     size_t infoSize = sizeof(procInfo);
71     const int res = sysctl(mib, arraySize(mib), &procInfo, &infoSize, nullptr, 0);
72     if (res) {
73         return false;
74     }
75     return (procInfo.kp_proc.p_flag & P_TRACED) != 0;
76 #else
77 #error Unsupported platform
78 #endif
79 }
80 
WaitForDebugger(int64_t timeoutMs)81 bool WaitForDebugger(int64_t timeoutMs) {
82     static const int64_t sleepTimeoutMs = 500;
83 
84     int64_t sleptForMs = 0;
85     while (!IsDebuggerAttached() && (timeoutMs == -1 || sleptForMs < timeoutMs)) {
86         std::this_thread::sleep_for(std::chrono::milliseconds(sleepTimeoutMs));
87         sleptForMs += sleepTimeoutMs;
88     }
89     return IsDebuggerAttached();
90 }
91 
DebugBreak()92 void DebugBreak() {
93 #ifdef _WIN32
94     ::DebugBreak();
95 #else
96 #ifdef __x86_64__
97     asm("int $3");
98 #elif defined(__aarch64)
99     asm("bkpt");
100 #endif
101 #endif
102 }
103 
104 }  // namespace base
105 }  // namespace android