1*605b51b8SPavel Labath //===-- SingleStepCheck.cpp ----------------------------------- -*- C++ -*-===//
2*605b51b8SPavel Labath //
3*605b51b8SPavel Labath //                     The LLVM Compiler Infrastructure
4*605b51b8SPavel Labath //
5*605b51b8SPavel Labath // This file is distributed under the University of Illinois Open Source
6*605b51b8SPavel Labath // License. See LICENSE.TXT for details.
7*605b51b8SPavel Labath //
8*605b51b8SPavel Labath //===----------------------------------------------------------------------===//
9*605b51b8SPavel Labath 
10*605b51b8SPavel Labath #include "SingleStepCheck.h"
11*605b51b8SPavel Labath 
12*605b51b8SPavel Labath #include <sched.h>
13*605b51b8SPavel Labath #include <signal.h>
14*605b51b8SPavel Labath #include <sys/wait.h>
15*605b51b8SPavel Labath #include <unistd.h>
16*605b51b8SPavel Labath 
17*605b51b8SPavel Labath #include "NativeProcessLinux.h"
18*605b51b8SPavel Labath 
19*605b51b8SPavel Labath #include "llvm/Support/Compiler.h"
20*605b51b8SPavel Labath 
21*605b51b8SPavel Labath #include "lldb/Core/Error.h"
22*605b51b8SPavel Labath #include "lldb/Core/Log.h"
23*605b51b8SPavel Labath #include "lldb/Host/linux/Ptrace.h"
24*605b51b8SPavel Labath 
25*605b51b8SPavel Labath using namespace lldb_private::process_linux;
26*605b51b8SPavel Labath 
27*605b51b8SPavel Labath #if defined(__arm64__) || defined(__aarch64__)
28*605b51b8SPavel Labath namespace
29*605b51b8SPavel Labath {
30*605b51b8SPavel Labath 
31*605b51b8SPavel Labath void LLVM_ATTRIBUTE_NORETURN
32*605b51b8SPavel Labath Child()
33*605b51b8SPavel Labath {
34*605b51b8SPavel Labath     if (ptrace(PTRACE_TRACEME, 0, nullptr, nullptr) == -1)
35*605b51b8SPavel Labath         _exit(1);
36*605b51b8SPavel Labath 
37*605b51b8SPavel Labath     // We just do an endless loop SIGSTOPPING ourselves until killed. The tracer will fiddle with our cpu
38*605b51b8SPavel Labath     // affinities and monitor the behaviour.
39*605b51b8SPavel Labath     for (;;)
40*605b51b8SPavel Labath     {
41*605b51b8SPavel Labath         raise(SIGSTOP);
42*605b51b8SPavel Labath 
43*605b51b8SPavel Labath         // Generate a bunch of instructions here, so that a single-step does not land in the
44*605b51b8SPavel Labath         // raise() accidentally. If single-stepping works, we will be spinning in this loop. If
45*605b51b8SPavel Labath         // it doesn't, we'll land in the raise() call above.
46*605b51b8SPavel Labath         for (volatile unsigned i = 0; i < CPU_SETSIZE; ++i)
47*605b51b8SPavel Labath             ;
48*605b51b8SPavel Labath     }
49*605b51b8SPavel Labath }
50*605b51b8SPavel Labath 
51*605b51b8SPavel Labath struct ChildDeleter
52*605b51b8SPavel Labath {
53*605b51b8SPavel Labath     ::pid_t pid;
54*605b51b8SPavel Labath 
55*605b51b8SPavel Labath     ~ChildDeleter()
56*605b51b8SPavel Labath     {
57*605b51b8SPavel Labath         int status;
58*605b51b8SPavel Labath         kill(pid, SIGKILL);            // Kill the child.
59*605b51b8SPavel Labath         waitpid(pid, &status, __WALL); // Pick up the remains.
60*605b51b8SPavel Labath     }
61*605b51b8SPavel Labath };
62*605b51b8SPavel Labath 
63*605b51b8SPavel Labath } // end anonymous namespace
64*605b51b8SPavel Labath 
65*605b51b8SPavel Labath bool
66*605b51b8SPavel Labath impl::SingleStepWorkaroundNeeded()
67*605b51b8SPavel Labath {
68*605b51b8SPavel Labath     // We shall spawn a child, and use it to verify the debug capabilities of the cpu. We shall
69*605b51b8SPavel Labath     // iterate through the cpus, bind the child to each one in turn, and verify that
70*605b51b8SPavel Labath     // single-stepping works on that cpu. A workaround is needed if we find at least one broken
71*605b51b8SPavel Labath     // cpu.
72*605b51b8SPavel Labath 
73*605b51b8SPavel Labath     Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
74*605b51b8SPavel Labath     Error error;
75*605b51b8SPavel Labath     ::pid_t child_pid = fork();
76*605b51b8SPavel Labath     if (child_pid == -1)
77*605b51b8SPavel Labath     {
78*605b51b8SPavel Labath         if (log)
79*605b51b8SPavel Labath         {
80*605b51b8SPavel Labath             error.SetErrorToErrno();
81*605b51b8SPavel Labath             log->Printf("%s failed to fork(): %s", __FUNCTION__, error.AsCString());
82*605b51b8SPavel Labath         }
83*605b51b8SPavel Labath         return false;
84*605b51b8SPavel Labath     }
85*605b51b8SPavel Labath     if (child_pid == 0)
86*605b51b8SPavel Labath         Child();
87*605b51b8SPavel Labath 
88*605b51b8SPavel Labath     ChildDeleter child_deleter{child_pid};
89*605b51b8SPavel Labath     cpu_set_t available_cpus;
90*605b51b8SPavel Labath     if (sched_getaffinity(child_pid, sizeof available_cpus, &available_cpus) == -1)
91*605b51b8SPavel Labath     {
92*605b51b8SPavel Labath         if (log)
93*605b51b8SPavel Labath         {
94*605b51b8SPavel Labath             error.SetErrorToErrno();
95*605b51b8SPavel Labath             log->Printf("%s failed to get available cpus: %s", __FUNCTION__, error.AsCString());
96*605b51b8SPavel Labath         }
97*605b51b8SPavel Labath         return false;
98*605b51b8SPavel Labath     }
99*605b51b8SPavel Labath 
100*605b51b8SPavel Labath     int status;
101*605b51b8SPavel Labath     ::pid_t wpid = waitpid(child_pid, &status, __WALL);
102*605b51b8SPavel Labath     if (wpid != child_pid || !WIFSTOPPED(status))
103*605b51b8SPavel Labath     {
104*605b51b8SPavel Labath         if (log)
105*605b51b8SPavel Labath         {
106*605b51b8SPavel Labath             error.SetErrorToErrno();
107*605b51b8SPavel Labath             log->Printf("%s waitpid() failed (status = %x): %s", __FUNCTION__, status, error.AsCString());
108*605b51b8SPavel Labath         }
109*605b51b8SPavel Labath         return false;
110*605b51b8SPavel Labath     }
111*605b51b8SPavel Labath 
112*605b51b8SPavel Labath     unsigned cpu;
113*605b51b8SPavel Labath     for (cpu = 0; cpu < CPU_SETSIZE; ++cpu)
114*605b51b8SPavel Labath     {
115*605b51b8SPavel Labath         if (!CPU_ISSET(cpu, &available_cpus))
116*605b51b8SPavel Labath             continue;
117*605b51b8SPavel Labath 
118*605b51b8SPavel Labath         cpu_set_t cpus;
119*605b51b8SPavel Labath         CPU_ZERO(&cpus);
120*605b51b8SPavel Labath         CPU_SET(cpu, &cpus);
121*605b51b8SPavel Labath         if (sched_setaffinity(child_pid, sizeof cpus, &cpus) == -1)
122*605b51b8SPavel Labath         {
123*605b51b8SPavel Labath             if (log)
124*605b51b8SPavel Labath             {
125*605b51b8SPavel Labath                 error.SetErrorToErrno();
126*605b51b8SPavel Labath                 log->Printf("%s failed to switch to cpu %u: %s", __FUNCTION__, cpu, error.AsCString());
127*605b51b8SPavel Labath             }
128*605b51b8SPavel Labath             continue;
129*605b51b8SPavel Labath         }
130*605b51b8SPavel Labath 
131*605b51b8SPavel Labath         int status;
132*605b51b8SPavel Labath         error = NativeProcessLinux::PtraceWrapper(PTRACE_SINGLESTEP, child_pid);
133*605b51b8SPavel Labath         if (error.Fail())
134*605b51b8SPavel Labath         {
135*605b51b8SPavel Labath             if (log)
136*605b51b8SPavel Labath                 log->Printf("%s single step failed: %s", __FUNCTION__, error.AsCString());
137*605b51b8SPavel Labath             break;
138*605b51b8SPavel Labath         }
139*605b51b8SPavel Labath 
140*605b51b8SPavel Labath         wpid = waitpid(child_pid, &status, __WALL);
141*605b51b8SPavel Labath         if (wpid != child_pid || !WIFSTOPPED(status))
142*605b51b8SPavel Labath         {
143*605b51b8SPavel Labath             if (log)
144*605b51b8SPavel Labath             {
145*605b51b8SPavel Labath                 error.SetErrorToErrno();
146*605b51b8SPavel Labath                 log->Printf("%s waitpid() failed (status = %x): %s", __FUNCTION__, status, error.AsCString());
147*605b51b8SPavel Labath             }
148*605b51b8SPavel Labath             break;
149*605b51b8SPavel Labath         }
150*605b51b8SPavel Labath         if (WSTOPSIG(status) != SIGTRAP)
151*605b51b8SPavel Labath         {
152*605b51b8SPavel Labath             if (log)
153*605b51b8SPavel Labath                 log->Printf("%s single stepping on cpu %d failed with status %x", __FUNCTION__, cpu, status);
154*605b51b8SPavel Labath             break;
155*605b51b8SPavel Labath         }
156*605b51b8SPavel Labath     }
157*605b51b8SPavel Labath 
158*605b51b8SPavel Labath     // cpu is either the index of the first broken cpu, or CPU_SETSIZE.
159*605b51b8SPavel Labath     if (cpu == 0)
160*605b51b8SPavel Labath     {
161*605b51b8SPavel Labath         if (log)
162*605b51b8SPavel Labath             log->Printf("%s SINGLE STEPPING ON FIRST CPU IS NOT WORKING. DEBUGGING LIKELY TO BE UNRELIABLE.",
163*605b51b8SPavel Labath                         __FUNCTION__);
164*605b51b8SPavel Labath         // No point in trying to fiddle with the affinities, just give it our best shot and see how it goes.
165*605b51b8SPavel Labath         return false;
166*605b51b8SPavel Labath     }
167*605b51b8SPavel Labath 
168*605b51b8SPavel Labath     return cpu != CPU_SETSIZE;
169*605b51b8SPavel Labath }
170*605b51b8SPavel Labath 
171*605b51b8SPavel Labath #else // !arm64
172*605b51b8SPavel Labath bool
173*605b51b8SPavel Labath impl::SingleStepWorkaroundNeeded()
174*605b51b8SPavel Labath {
175*605b51b8SPavel Labath     return false;
176*605b51b8SPavel Labath }
177*605b51b8SPavel Labath #endif
178