1605b51b8SPavel Labath //===-- SingleStepCheck.cpp ----------------------------------- -*- C++ -*-===//
2605b51b8SPavel Labath //
3605b51b8SPavel Labath //                     The LLVM Compiler Infrastructure
4605b51b8SPavel Labath //
5605b51b8SPavel Labath // This file is distributed under the University of Illinois Open Source
6605b51b8SPavel Labath // License. See LICENSE.TXT for details.
7605b51b8SPavel Labath //
8605b51b8SPavel Labath //===----------------------------------------------------------------------===//
9605b51b8SPavel Labath 
10605b51b8SPavel Labath #include "SingleStepCheck.h"
11605b51b8SPavel Labath 
12605b51b8SPavel Labath #include <sched.h>
13605b51b8SPavel Labath #include <signal.h>
14605b51b8SPavel Labath #include <sys/wait.h>
15605b51b8SPavel Labath #include <unistd.h>
16605b51b8SPavel Labath 
17605b51b8SPavel Labath #include "NativeProcessLinux.h"
18605b51b8SPavel Labath 
19605b51b8SPavel Labath #include "llvm/Support/Compiler.h"
20605b51b8SPavel Labath 
21605b51b8SPavel Labath #include "lldb/Core/Error.h"
22605b51b8SPavel Labath #include "lldb/Core/Log.h"
23605b51b8SPavel Labath #include "lldb/Host/linux/Ptrace.h"
24605b51b8SPavel Labath 
25605b51b8SPavel Labath using namespace lldb_private::process_linux;
26605b51b8SPavel Labath 
27605b51b8SPavel Labath #if defined(__arm64__) || defined(__aarch64__)
28*b9c1b51eSKate Stone namespace {
29605b51b8SPavel Labath 
30*b9c1b51eSKate Stone void LLVM_ATTRIBUTE_NORETURN Child() {
31605b51b8SPavel Labath   if (ptrace(PTRACE_TRACEME, 0, nullptr, nullptr) == -1)
32605b51b8SPavel Labath     _exit(1);
33605b51b8SPavel Labath 
34*b9c1b51eSKate Stone   // We just do an endless loop SIGSTOPPING ourselves until killed. The tracer
35*b9c1b51eSKate Stone   // will fiddle with our cpu
36605b51b8SPavel Labath   // affinities and monitor the behaviour.
37*b9c1b51eSKate Stone   for (;;) {
38605b51b8SPavel Labath     raise(SIGSTOP);
39605b51b8SPavel Labath 
40*b9c1b51eSKate Stone     // Generate a bunch of instructions here, so that a single-step does not
41*b9c1b51eSKate Stone     // land in the
42*b9c1b51eSKate Stone     // raise() accidentally. If single-stepping works, we will be spinning in
43*b9c1b51eSKate Stone     // this loop. If
44605b51b8SPavel Labath     // it doesn't, we'll land in the raise() call above.
45605b51b8SPavel Labath     for (volatile unsigned i = 0; i < CPU_SETSIZE; ++i)
46605b51b8SPavel Labath       ;
47605b51b8SPavel Labath   }
48605b51b8SPavel Labath }
49605b51b8SPavel Labath 
50*b9c1b51eSKate Stone struct ChildDeleter {
51605b51b8SPavel Labath   ::pid_t pid;
52605b51b8SPavel Labath 
53*b9c1b51eSKate Stone   ~ChildDeleter() {
54605b51b8SPavel Labath     int status;
55605b51b8SPavel Labath     kill(pid, SIGKILL);            // Kill the child.
56605b51b8SPavel Labath     waitpid(pid, &status, __WALL); // Pick up the remains.
57605b51b8SPavel Labath   }
58605b51b8SPavel Labath };
59605b51b8SPavel Labath 
60605b51b8SPavel Labath } // end anonymous namespace
61605b51b8SPavel Labath 
62*b9c1b51eSKate Stone bool impl::SingleStepWorkaroundNeeded() {
63*b9c1b51eSKate Stone   // We shall spawn a child, and use it to verify the debug capabilities of the
64*b9c1b51eSKate Stone   // cpu. We shall
65*b9c1b51eSKate Stone   // iterate through the cpus, bind the child to each one in turn, and verify
66*b9c1b51eSKate Stone   // that
67*b9c1b51eSKate Stone   // single-stepping works on that cpu. A workaround is needed if we find at
68*b9c1b51eSKate Stone   // least one broken
69605b51b8SPavel Labath   // cpu.
70605b51b8SPavel Labath 
71605b51b8SPavel Labath   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
72605b51b8SPavel Labath   Error error;
73605b51b8SPavel Labath   ::pid_t child_pid = fork();
74*b9c1b51eSKate Stone   if (child_pid == -1) {
75*b9c1b51eSKate Stone     if (log) {
76605b51b8SPavel Labath       error.SetErrorToErrno();
77605b51b8SPavel Labath       log->Printf("%s failed to fork(): %s", __FUNCTION__, error.AsCString());
78605b51b8SPavel Labath     }
79605b51b8SPavel Labath     return false;
80605b51b8SPavel Labath   }
81605b51b8SPavel Labath   if (child_pid == 0)
82605b51b8SPavel Labath     Child();
83605b51b8SPavel Labath 
84605b51b8SPavel Labath   ChildDeleter child_deleter{child_pid};
85605b51b8SPavel Labath   cpu_set_t available_cpus;
86*b9c1b51eSKate Stone   if (sched_getaffinity(child_pid, sizeof available_cpus, &available_cpus) ==
87*b9c1b51eSKate Stone       -1) {
88*b9c1b51eSKate Stone     if (log) {
89605b51b8SPavel Labath       error.SetErrorToErrno();
90*b9c1b51eSKate Stone       log->Printf("%s failed to get available cpus: %s", __FUNCTION__,
91*b9c1b51eSKate Stone                   error.AsCString());
92605b51b8SPavel Labath     }
93605b51b8SPavel Labath     return false;
94605b51b8SPavel Labath   }
95605b51b8SPavel Labath 
96605b51b8SPavel Labath   int status;
97605b51b8SPavel Labath   ::pid_t wpid = waitpid(child_pid, &status, __WALL);
98*b9c1b51eSKate Stone   if (wpid != child_pid || !WIFSTOPPED(status)) {
99*b9c1b51eSKate Stone     if (log) {
100605b51b8SPavel Labath       error.SetErrorToErrno();
101*b9c1b51eSKate Stone       log->Printf("%s waitpid() failed (status = %x): %s", __FUNCTION__, status,
102*b9c1b51eSKate Stone                   error.AsCString());
103605b51b8SPavel Labath     }
104605b51b8SPavel Labath     return false;
105605b51b8SPavel Labath   }
106605b51b8SPavel Labath 
107605b51b8SPavel Labath   unsigned cpu;
108*b9c1b51eSKate Stone   for (cpu = 0; cpu < CPU_SETSIZE; ++cpu) {
109605b51b8SPavel Labath     if (!CPU_ISSET(cpu, &available_cpus))
110605b51b8SPavel Labath       continue;
111605b51b8SPavel Labath 
112605b51b8SPavel Labath     cpu_set_t cpus;
113605b51b8SPavel Labath     CPU_ZERO(&cpus);
114605b51b8SPavel Labath     CPU_SET(cpu, &cpus);
115*b9c1b51eSKate Stone     if (sched_setaffinity(child_pid, sizeof cpus, &cpus) == -1) {
116*b9c1b51eSKate Stone       if (log) {
117605b51b8SPavel Labath         error.SetErrorToErrno();
118*b9c1b51eSKate Stone         log->Printf("%s failed to switch to cpu %u: %s", __FUNCTION__, cpu,
119*b9c1b51eSKate Stone                     error.AsCString());
120605b51b8SPavel Labath       }
121605b51b8SPavel Labath       continue;
122605b51b8SPavel Labath     }
123605b51b8SPavel Labath 
124605b51b8SPavel Labath     int status;
125605b51b8SPavel Labath     error = NativeProcessLinux::PtraceWrapper(PTRACE_SINGLESTEP, child_pid);
126*b9c1b51eSKate Stone     if (error.Fail()) {
127605b51b8SPavel Labath       if (log)
128*b9c1b51eSKate Stone         log->Printf("%s single step failed: %s", __FUNCTION__,
129*b9c1b51eSKate Stone                     error.AsCString());
130605b51b8SPavel Labath       break;
131605b51b8SPavel Labath     }
132605b51b8SPavel Labath 
133605b51b8SPavel Labath     wpid = waitpid(child_pid, &status, __WALL);
134*b9c1b51eSKate Stone     if (wpid != child_pid || !WIFSTOPPED(status)) {
135*b9c1b51eSKate Stone       if (log) {
136605b51b8SPavel Labath         error.SetErrorToErrno();
137*b9c1b51eSKate Stone         log->Printf("%s waitpid() failed (status = %x): %s", __FUNCTION__,
138*b9c1b51eSKate Stone                     status, error.AsCString());
139605b51b8SPavel Labath       }
140605b51b8SPavel Labath       break;
141605b51b8SPavel Labath     }
142*b9c1b51eSKate Stone     if (WSTOPSIG(status) != SIGTRAP) {
143605b51b8SPavel Labath       if (log)
144*b9c1b51eSKate Stone         log->Printf("%s single stepping on cpu %d failed with status %x",
145*b9c1b51eSKate Stone                     __FUNCTION__, cpu, status);
146605b51b8SPavel Labath       break;
147605b51b8SPavel Labath     }
148605b51b8SPavel Labath   }
149605b51b8SPavel Labath 
150605b51b8SPavel Labath   // cpu is either the index of the first broken cpu, or CPU_SETSIZE.
151*b9c1b51eSKate Stone   if (cpu == 0) {
152605b51b8SPavel Labath     if (log)
153*b9c1b51eSKate Stone       log->Printf("%s SINGLE STEPPING ON FIRST CPU IS NOT WORKING. DEBUGGING "
154*b9c1b51eSKate Stone                   "LIKELY TO BE UNRELIABLE.",
155605b51b8SPavel Labath                   __FUNCTION__);
156*b9c1b51eSKate Stone     // No point in trying to fiddle with the affinities, just give it our best
157*b9c1b51eSKate Stone     // shot and see how it goes.
158605b51b8SPavel Labath     return false;
159605b51b8SPavel Labath   }
160605b51b8SPavel Labath 
161605b51b8SPavel Labath   return cpu != CPU_SETSIZE;
162605b51b8SPavel Labath }
163605b51b8SPavel Labath 
164605b51b8SPavel Labath #else // !arm64
165*b9c1b51eSKate Stone bool impl::SingleStepWorkaroundNeeded() { return false; }
166605b51b8SPavel Labath #endif
167