Files
clang-p2996/lldb/source/Plugins/Process/Linux/SingleStepCheck.cpp
Raphael Isemann 808142876c [lldb][NFC] Fix all formatting errors in .cpp file headers
Summary:
A *.cpp file header in LLDB (and in LLDB) should like this:
```
//===-- TestUtilities.cpp -------------------------------------------------===//
```
However in LLDB most of our source files have arbitrary changes to this format and
these changes are spreading through LLDB as folks usually just use the existing
source files as templates for their new files (most notably the unnecessary
editor language indicator `-*- C++ -*-` is spreading and in every review
someone is pointing out that this is wrong, resulting in people pointing out that this
is done in the same way in other files).

This patch removes most of these inconsistencies including the editor language indicators,
all the different missing/additional '-' characters, files that center the file name, missing
trailing `===//` (mostly caused by clang-format breaking the line).

Reviewers: aprantl, espindola, jfb, shafik, JDevlieghere

Reviewed By: JDevlieghere

Subscribers: dexonsmith, wuzish, emaste, sdardis, nemanjai, kbarton, MaskRay, atanasyan, arphaman, jfb, abidh, jsji, JDevlieghere, usaxena95, lldb-commits

Tags: #lldb

Differential Revision: https://reviews.llvm.org/D73258
2020-01-24 08:52:55 +01:00

187 lines
5.7 KiB
C++

//===-- SingleStepCheck.cpp -----------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "SingleStepCheck.h"
#include <sched.h>
#include <signal.h>
#include <sys/wait.h>
#include <unistd.h>
#include "NativeProcessLinux.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Errno.h"
#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
#include "lldb/Host/linux/Ptrace.h"
#include "lldb/Utility/Status.h"
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::process_linux;
#if defined(__arm64__) || defined(__aarch64__)
namespace {
void LLVM_ATTRIBUTE_NORETURN Child() {
if (ptrace(PTRACE_TRACEME, 0, nullptr, nullptr) == -1)
_exit(1);
// We just do an endless loop SIGSTOPPING ourselves until killed. The tracer
// will fiddle with our cpu affinities and monitor the behaviour.
for (;;) {
raise(SIGSTOP);
// Generate a bunch of instructions here, so that a single-step does not
// land in the raise() accidentally. If single-stepping works, we will be
// spinning in this loop. If it doesn't, we'll land in the raise() call
// above.
for (volatile unsigned i = 0; i < CPU_SETSIZE; ++i)
;
}
}
struct ChildDeleter {
::pid_t pid;
~ChildDeleter() {
int status;
// Kill the child.
kill(pid, SIGKILL);
// Pick up the remains.
llvm::sys::RetryAfterSignal(-1, waitpid, pid, &status, __WALL);
}
};
bool WorkaroundNeeded() {
// We shall spawn a child, and use it to verify the debug capabilities of the
// cpu. We shall iterate through the cpus, bind the child to each one in
// turn, and verify that single-stepping works on that cpu. A workaround is
// needed if we find at least one broken cpu.
Log *log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD);
::pid_t child_pid = fork();
if (child_pid == -1) {
LLDB_LOG(log, "failed to fork(): {0}", Status(errno, eErrorTypePOSIX));
return false;
}
if (child_pid == 0)
Child();
ChildDeleter child_deleter{child_pid};
cpu_set_t available_cpus;
if (sched_getaffinity(child_pid, sizeof available_cpus, &available_cpus) ==
-1) {
LLDB_LOG(log, "failed to get available cpus: {0}",
Status(errno, eErrorTypePOSIX));
return false;
}
int status;
::pid_t wpid = llvm::sys::RetryAfterSignal(-1, waitpid,
child_pid, &status, __WALL);
if (wpid != child_pid || !WIFSTOPPED(status)) {
LLDB_LOG(log, "waitpid() failed (status = {0:x}): {1}", status,
Status(errno, eErrorTypePOSIX));
return false;
}
unsigned cpu;
for (cpu = 0; cpu < CPU_SETSIZE; ++cpu) {
if (!CPU_ISSET(cpu, &available_cpus))
continue;
cpu_set_t cpus;
CPU_ZERO(&cpus);
CPU_SET(cpu, &cpus);
if (sched_setaffinity(child_pid, sizeof cpus, &cpus) == -1) {
LLDB_LOG(log, "failed to switch to cpu {0}: {1}", cpu,
Status(errno, eErrorTypePOSIX));
continue;
}
int status;
Status error =
NativeProcessLinux::PtraceWrapper(PTRACE_SINGLESTEP, child_pid);
if (error.Fail()) {
LLDB_LOG(log, "single step failed: {0}", error);
break;
}
wpid = llvm::sys::RetryAfterSignal(-1, waitpid,
child_pid, &status, __WALL);
if (wpid != child_pid || !WIFSTOPPED(status)) {
LLDB_LOG(log, "waitpid() failed (status = {0:x}): {1}", status,
Status(errno, eErrorTypePOSIX));
break;
}
if (WSTOPSIG(status) != SIGTRAP) {
LLDB_LOG(log, "single stepping on cpu {0} failed with status {1:x}", cpu,
status);
break;
}
}
// cpu is either the index of the first broken cpu, or CPU_SETSIZE.
if (cpu == 0) {
LLDB_LOG(log,
"SINGLE STEPPING ON FIRST CPU IS NOT WORKING. DEBUGGING "
"LIKELY TO BE UNRELIABLE.");
// No point in trying to fiddle with the affinities, just give it our best
// shot and see how it goes.
return false;
}
return cpu != CPU_SETSIZE;
}
} // end anonymous namespace
std::unique_ptr<SingleStepWorkaround> SingleStepWorkaround::Get(::pid_t tid) {
Log *log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD);
static bool workaround_needed = WorkaroundNeeded();
if (!workaround_needed) {
LLDB_LOG(log, "workaround for thread {0} not needed", tid);
return nullptr;
}
cpu_set_t original_set;
if (sched_getaffinity(tid, sizeof original_set, &original_set) != 0) {
// This should really not fail. But, just in case...
LLDB_LOG(log, "Unable to get cpu affinity for thread {0}: {1}", tid,
Status(errno, eErrorTypePOSIX));
return nullptr;
}
cpu_set_t set;
CPU_ZERO(&set);
CPU_SET(0, &set);
if (sched_setaffinity(tid, sizeof set, &set) != 0) {
// This may fail in very locked down systems, if the thread is not allowed
// to run on cpu 0. If that happens, only thing we can do is it log it and
// continue...
LLDB_LOG(log, "Unable to set cpu affinity for thread {0}: {1}", tid,
Status(errno, eErrorTypePOSIX));
}
LLDB_LOG(log, "workaround for thread {0} prepared", tid);
return std::make_unique<SingleStepWorkaround>(tid, original_set);
}
SingleStepWorkaround::~SingleStepWorkaround() {
Log *log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD);
LLDB_LOG(log, "Removing workaround");
if (sched_setaffinity(m_tid, sizeof m_original_set, &m_original_set) != 0) {
LLDB_LOG(log, "Unable to reset cpu affinity for thread {0}: {1}", m_tid,
Status(errno, eErrorTypePOSIX));
}
}
#endif