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