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