14#include "llvm/Support/Compiler.h"
15#include "llvm/Support/Errno.h"
22#include <sys/ptrace.h>
30#if defined(__arm64__) || defined(__aarch64__)
33[[noreturn]]
void Child() {
34 if (ptrace(PTRACE_TRACEME, 0,
nullptr,
nullptr) == -1)
46 for (
volatile unsigned i = 0; i < CPU_SETSIZE; ++i)
59 llvm::sys::RetryAfterSignal(-1, waitpid, pid, &status, __WALL);
63bool WorkaroundNeeded() {
71 if (child_pid == -1) {
78 ChildDeleter child_deleter{child_pid};
79 cpu_set_t available_cpus;
80 if (sched_getaffinity(child_pid,
sizeof available_cpus, &available_cpus) ==
82 LLDB_LOG(log,
"failed to get available cpus: {0}",
88 ::pid_t wpid = llvm::sys::RetryAfterSignal(-1, waitpid,
89 child_pid, &status, __WALL);
90 if (wpid != child_pid || !WIFSTOPPED(status)) {
91 LLDB_LOG(log,
"waitpid() failed (status = {0:x}): {1}", status,
97 for (cpu = 0; cpu < CPU_SETSIZE; ++cpu) {
98 if (!CPU_ISSET(cpu, &available_cpus))
104 if (sched_setaffinity(child_pid,
sizeof cpus, &cpus) == -1) {
105 LLDB_LOG(log,
"failed to switch to cpu {0}: {1}", cpu,
118 wpid = llvm::sys::RetryAfterSignal(-1, waitpid,
119 child_pid, &status, __WALL);
120 if (wpid != child_pid || !WIFSTOPPED(status)) {
121 LLDB_LOG(log,
"waitpid() failed (status = {0:x}): {1}", status,
125 if (WSTOPSIG(status) !=
SIGTRAP) {
126 LLDB_LOG(log,
"single stepping on cpu {0} failed with status {1:x}", cpu,
135 "SINGLE STEPPING ON FIRST CPU IS NOT WORKING. DEBUGGING "
136 "LIKELY TO BE UNRELIABLE.");
142 return cpu != CPU_SETSIZE;
150 static bool workaround_needed = WorkaroundNeeded();
151 if (!workaround_needed) {
152 LLDB_LOG(log,
"workaround for thread {0} not needed", tid);
156 cpu_set_t original_set;
157 if (sched_getaffinity(tid,
sizeof original_set, &original_set) != 0) {
159 LLDB_LOG(log,
"Unable to get cpu affinity for thread {0}: {1}", tid,
167 if (sched_setaffinity(tid,
sizeof set, &set) != 0) {
171 LLDB_LOG(log,
"Unable to set cpu affinity for thread {0}: {1}", tid,
175 LLDB_LOG(log,
"workaround for thread {0} prepared", tid);
176 return std::make_unique<SingleStepWorkaround>(tid, original_set);
179SingleStepWorkaround::~SingleStepWorkaround() {
181 LLDB_LOG(log,
"Removing workaround");
182 if (sched_setaffinity(m_tid,
sizeof m_original_set, &m_original_set) != 0) {
183 LLDB_LOG(log,
"Unable to reset cpu affinity for thread {0}: {1}", m_tid,
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
static Status PtraceWrapper(int req, lldb::pid_t pid, void *addr=nullptr, void *data=nullptr, size_t data_size=0, long *result=nullptr)
}
static std::unique_ptr< SingleStepWorkaround > Get(::pid_t tid)
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
@ eErrorTypePOSIX
POSIX error codes.