aboutsummaryrefslogtreecommitdiff
path: root/source/Plugins/Process/Linux
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-04-16 16:04:10 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-04-16 16:04:10 +0000
commit74a628f776edb588bff8f8f5cc16eac947c9d631 (patch)
treedc32e010ac4902621e5a279bfeb48628f7f0e166 /source/Plugins/Process/Linux
parentafed7be32164a598f8172282c249af7266c48b46 (diff)
downloadsrc-74a628f776edb588bff8f8f5cc16eac947c9d631.tar.gz
src-74a628f776edb588bff8f8f5cc16eac947c9d631.zip
Vendor import of lldb trunk r300422:vendor/lldb/lldb-trunk-r300422
Notes
Notes: svn path=/vendor/lldb/dist/; revision=317027 svn path=/vendor/lldb/lldb-trunk-r300422/; revision=317028; tag=vendor/lldb/lldb-trunk-r300422
Diffstat (limited to 'source/Plugins/Process/Linux')
-rw-r--r--source/Plugins/Process/Linux/CMakeLists.txt14
-rw-r--r--source/Plugins/Process/Linux/NativeProcessLinux.cpp1061
-rw-r--r--source/Plugins/Process/Linux/NativeProcessLinux.h10
-rw-r--r--source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp10
-rw-r--r--source/Plugins/Process/Linux/NativeRegisterContextLinux.h2
-rw-r--r--source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp270
-rw-r--r--source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h7
-rw-r--r--source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp239
-rw-r--r--source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h7
-rw-r--r--source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp260
-rw-r--r--source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp6
-rwxr-xr-xsource/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp6
-rw-r--r--source/Plugins/Process/Linux/NativeThreadLinux.cpp121
-rw-r--r--source/Plugins/Process/Linux/NativeThreadLinux.h14
-rw-r--r--source/Plugins/Process/Linux/ProcFileReader.cpp103
-rw-r--r--source/Plugins/Process/Linux/ProcFileReader.h37
-rw-r--r--source/Plugins/Process/Linux/SingleStepCheck.cpp130
-rw-r--r--source/Plugins/Process/Linux/SingleStepCheck.h51
18 files changed, 937 insertions, 1411 deletions
diff --git a/source/Plugins/Process/Linux/CMakeLists.txt b/source/Plugins/Process/Linux/CMakeLists.txt
index 8291fef467e3..8a46d730caff 100644
--- a/source/Plugins/Process/Linux/CMakeLists.txt
+++ b/source/Plugins/Process/Linux/CMakeLists.txt
@@ -2,7 +2,7 @@ include_directories(.)
include_directories(../POSIX)
include_directories(../Utility)
-add_lldb_library(lldbPluginProcessLinux
+add_lldb_library(lldbPluginProcessLinux PLUGIN
NativeProcessLinux.cpp
NativeRegisterContextLinux.cpp
NativeRegisterContextLinux_arm.cpp
@@ -11,6 +11,16 @@ add_lldb_library(lldbPluginProcessLinux
NativeRegisterContextLinux_mips64.cpp
NativeRegisterContextLinux_s390x.cpp
NativeThreadLinux.cpp
- ProcFileReader.cpp
SingleStepCheck.cpp
+
+ LINK_LIBS
+ lldbCore
+ lldbHost
+ lldbSymbol
+ lldbTarget
+ lldbUtility
+ lldbPluginProcessPOSIX
+ lldbPluginProcessUtility
+ LINK_COMPONENTS
+ Support
)
diff --git a/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/source/Plugins/Process/Linux/NativeProcessLinux.cpp
index fb84729dd5f4..914d690ad88c 100644
--- a/source/Plugins/Process/Linux/NativeProcessLinux.cpp
+++ b/source/Plugins/Process/Linux/NativeProcessLinux.cpp
@@ -24,43 +24,40 @@
// Other libraries and framework includes
#include "lldb/Core/EmulateInstruction.h"
-#include "lldb/Core/Error.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/State.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostProcess.h"
+#include "lldb/Host/PseudoTerminal.h"
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Host/common/NativeBreakpoint.h"
#include "lldb/Host/common/NativeRegisterContext.h"
-#include "lldb/Host/linux/ProcessLauncherLinux.h"
+#include "lldb/Host/linux/Ptrace.h"
+#include "lldb/Host/linux/Uio.h"
+#include "lldb/Host/posix/ProcessLauncherPosixFork.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/ProcessLaunchInfo.h"
#include "lldb/Target/Target.h"
+#include "lldb/Utility/Error.h"
#include "lldb/Utility/LLDBAssert.h"
-#include "lldb/Utility/PseudoTerminal.h"
#include "lldb/Utility/StringExtractor.h"
#include "NativeThreadLinux.h"
#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
-#include "ProcFileReader.h"
#include "Procfs.h"
-// System includes - They have to be included after framework includes because
-// they define some
-// macros which collide with variable names in other modules
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Threading.h"
+
#include <linux/unistd.h>
#include <sys/socket.h>
-
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/user.h>
#include <sys/wait.h>
-#include "lldb/Host/linux/Ptrace.h"
-#include "lldb/Host/linux/Uio.h"
-
// Support hardware breakpoints in case it has not been defined
#ifndef TRAP_HWBKPT
#define TRAP_HWBKPT 4
@@ -75,10 +72,10 @@ using namespace llvm;
static bool ProcessVmReadvSupported() {
static bool is_supported;
- static std::once_flag flag;
+ static llvm::once_flag flag;
- std::call_once(flag, [] {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ llvm::call_once(flag, [] {
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
uint32_t source = 0x47424742;
uint32_t dest = 0;
@@ -92,16 +89,15 @@ static bool ProcessVmReadvSupported() {
// value from our own process.
ssize_t res = process_vm_readv(getpid(), &local, 1, &remote, 1, 0);
is_supported = (res == sizeof(source) && source == dest);
- if (log) {
- if (is_supported)
- log->Printf("%s: Detected kernel support for process_vm_readv syscall. "
- "Fast memory reads enabled.",
- __FUNCTION__);
- else
- log->Printf("%s: syscall process_vm_readv failed (error: %s). Fast "
- "memory reads disabled.",
- __FUNCTION__, strerror(errno));
- }
+ if (is_supported)
+ LLDB_LOG(log,
+ "Detected kernel support for process_vm_readv syscall. "
+ "Fast memory reads enabled.");
+ else
+ LLDB_LOG(log,
+ "syscall process_vm_readv failed (error: {0}). Fast memory "
+ "reads disabled.",
+ strerror(errno));
});
return is_supported;
@@ -109,33 +105,29 @@ static bool ProcessVmReadvSupported() {
namespace {
void MaybeLogLaunchInfo(const ProcessLaunchInfo &info) {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
if (!log)
return;
if (const FileAction *action = info.GetFileActionForFD(STDIN_FILENO))
- log->Printf("%s: setting STDIN to '%s'", __FUNCTION__,
- action->GetFileSpec().GetCString());
+ LLDB_LOG(log, "setting STDIN to '{0}'", action->GetFileSpec());
else
- log->Printf("%s leaving STDIN as is", __FUNCTION__);
+ LLDB_LOG(log, "leaving STDIN as is");
if (const FileAction *action = info.GetFileActionForFD(STDOUT_FILENO))
- log->Printf("%s setting STDOUT to '%s'", __FUNCTION__,
- action->GetFileSpec().GetCString());
+ LLDB_LOG(log, "setting STDOUT to '{0}'", action->GetFileSpec());
else
- log->Printf("%s leaving STDOUT as is", __FUNCTION__);
+ LLDB_LOG(log, "leaving STDOUT as is");
if (const FileAction *action = info.GetFileActionForFD(STDERR_FILENO))
- log->Printf("%s setting STDERR to '%s'", __FUNCTION__,
- action->GetFileSpec().GetCString());
+ LLDB_LOG(log, "setting STDERR to '{0}'", action->GetFileSpec());
else
- log->Printf("%s leaving STDERR as is", __FUNCTION__);
+ LLDB_LOG(log, "leaving STDERR as is");
int i = 0;
for (const char **args = info.GetArguments().GetConstArgumentVector(); *args;
++args, ++i)
- log->Printf("%s arg %d: \"%s\"", __FUNCTION__, i,
- *args ? *args : "nullptr");
+ LLDB_LOG(log, "arg {0}: '{1}'", i, *args);
}
void DisplayBytes(StreamString &s, void *bytes, uint32_t count) {
@@ -148,50 +140,49 @@ void DisplayBytes(StreamString &s, void *bytes, uint32_t count) {
}
void PtraceDisplayBytes(int &req, void *data, size_t data_size) {
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
+ if (!log)
+ return;
StreamString buf;
- Log *verbose_log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(
- POSIX_LOG_PTRACE | POSIX_LOG_VERBOSE));
-
- if (verbose_log) {
- switch (req) {
- case PTRACE_POKETEXT: {
- DisplayBytes(buf, &data, 8);
- verbose_log->Printf("PTRACE_POKETEXT %s", buf.GetData());
- break;
- }
- case PTRACE_POKEDATA: {
- DisplayBytes(buf, &data, 8);
- verbose_log->Printf("PTRACE_POKEDATA %s", buf.GetData());
- break;
- }
- case PTRACE_POKEUSER: {
- DisplayBytes(buf, &data, 8);
- verbose_log->Printf("PTRACE_POKEUSER %s", buf.GetData());
- break;
- }
- case PTRACE_SETREGS: {
- DisplayBytes(buf, data, data_size);
- verbose_log->Printf("PTRACE_SETREGS %s", buf.GetData());
- break;
- }
- case PTRACE_SETFPREGS: {
- DisplayBytes(buf, data, data_size);
- verbose_log->Printf("PTRACE_SETFPREGS %s", buf.GetData());
- break;
- }
- case PTRACE_SETSIGINFO: {
- DisplayBytes(buf, data, sizeof(siginfo_t));
- verbose_log->Printf("PTRACE_SETSIGINFO %s", buf.GetData());
- break;
- }
- case PTRACE_SETREGSET: {
- // Extract iov_base from data, which is a pointer to the struct IOVEC
- DisplayBytes(buf, *(void **)data, data_size);
- verbose_log->Printf("PTRACE_SETREGSET %s", buf.GetData());
- break;
- }
- default: {}
- }
+
+ switch (req) {
+ case PTRACE_POKETEXT: {
+ DisplayBytes(buf, &data, 8);
+ LLDB_LOGV(log, "PTRACE_POKETEXT {0}", buf.GetData());
+ break;
+ }
+ case PTRACE_POKEDATA: {
+ DisplayBytes(buf, &data, 8);
+ LLDB_LOGV(log, "PTRACE_POKEDATA {0}", buf.GetData());
+ break;
+ }
+ case PTRACE_POKEUSER: {
+ DisplayBytes(buf, &data, 8);
+ LLDB_LOGV(log, "PTRACE_POKEUSER {0}", buf.GetData());
+ break;
+ }
+ case PTRACE_SETREGS: {
+ DisplayBytes(buf, data, data_size);
+ LLDB_LOGV(log, "PTRACE_SETREGS {0}", buf.GetData());
+ break;
+ }
+ case PTRACE_SETFPREGS: {
+ DisplayBytes(buf, data, data_size);
+ LLDB_LOGV(log, "PTRACE_SETFPREGS {0}", buf.GetData());
+ break;
+ }
+ case PTRACE_SETSIGINFO: {
+ DisplayBytes(buf, data, sizeof(siginfo_t));
+ LLDB_LOGV(log, "PTRACE_SETSIGINFO {0}", buf.GetData());
+ break;
+ }
+ case PTRACE_SETREGSET: {
+ // Extract iov_base from data, which is a pointer to the struct IOVEC
+ DisplayBytes(buf, *(void **)data, data_size);
+ LLDB_LOGV(log, "PTRACE_SETREGSET {0}", buf.GetData());
+ break;
+ }
+ default: {}
}
}
@@ -227,15 +218,14 @@ Error NativeProcessProtocol::Launch(
ProcessLaunchInfo &launch_info,
NativeProcessProtocol::NativeDelegate &native_delegate, MainLoop &mainloop,
NativeProcessProtocolSP &native_process_sp) {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
Error error;
// Verify the working directory is valid if one was specified.
FileSpec working_dir{launch_info.GetWorkingDirectory()};
- if (working_dir &&
- (!working_dir.ResolvePath() ||
- working_dir.GetFileType() != FileSpec::eFileTypeDirectory)) {
+ if (working_dir && (!working_dir.ResolvePath() ||
+ !llvm::sys::fs::is_directory(working_dir.GetPath()))) {
error.SetErrorStringWithFormat("No such file or directory: %s",
working_dir.GetCString());
return error;
@@ -255,9 +245,7 @@ Error NativeProcessProtocol::Launch(
if (error.Fail()) {
native_process_sp.reset();
- if (log)
- log->Printf("NativeProcessLinux::%s failed to launch process: %s",
- __FUNCTION__, error.AsCString());
+ LLDB_LOG(log, "failed to launch process: {0}", error);
return error;
}
@@ -269,9 +257,8 @@ Error NativeProcessProtocol::Launch(
Error NativeProcessProtocol::Attach(
lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate,
MainLoop &mainloop, NativeProcessProtocolSP &native_process_sp) {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
- log->Printf("NativeProcessLinux::%s(pid = %" PRIi64 ")", __FUNCTION__, pid);
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+ LLDB_LOG(log, "pid = {0:x}", pid);
// Retrieve the architecture for the running process.
ArchSpec process_arch;
@@ -306,10 +293,8 @@ NativeProcessLinux::NativeProcessLinux()
void NativeProcessLinux::AttachToInferior(MainLoop &mainloop, lldb::pid_t pid,
Error &error) {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (log)
- log->Printf("NativeProcessLinux::%s (pid = %" PRIi64 ")", __FUNCTION__,
- pid);
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+ LLDB_LOG(log, "pid = {0:x}", pid);
m_sigchld_handle = mainloop.RegisterSignal(
SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, error);
@@ -321,11 +306,8 @@ void NativeProcessLinux::AttachToInferior(MainLoop &mainloop, lldb::pid_t pid,
return;
// Set the architecture to the exe architecture.
- if (log)
- log->Printf("NativeProcessLinux::%s (pid = %" PRIi64
- ") detected architecture %s",
- __FUNCTION__, pid, m_arch.GetArchitectureName());
-
+ LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid,
+ m_arch.GetArchitectureName());
m_pid = pid;
SetState(eStateAttaching);
@@ -345,20 +327,18 @@ Error NativeProcessLinux::LaunchInferior(MainLoop &mainloop,
MaybeLogLaunchInfo(launch_info);
::pid_t pid =
- ProcessLauncherLinux().LaunchProcess(launch_info, error).GetProcessId();
+ ProcessLauncherPosixFork().LaunchProcess(launch_info, error).GetProcessId();
if (error.Fail())
return error;
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
// Wait for the child process to trap on its call to execve.
::pid_t wpid;
int status;
if ((wpid = waitpid(pid, &status, 0)) < 0) {
error.SetErrorToErrno();
- if (log)
- log->Printf("NativeProcessLinux::%s waitpid for inferior failed with %s",
- __FUNCTION__, error.AsCString());
+ LLDB_LOG(log, "waitpid for inferior failed with %s", error);
// Mark the inferior as invalid.
// FIXME this could really use a new state - eStateLaunchFailure. For now,
@@ -370,16 +350,10 @@ Error NativeProcessLinux::LaunchInferior(MainLoop &mainloop,
assert(WIFSTOPPED(status) && (wpid == static_cast<::pid_t>(pid)) &&
"Could not sync with inferior process.");
- if (log)
- log->Printf("NativeProcessLinux::%s inferior started, now in stopped state",
- __FUNCTION__);
-
+ LLDB_LOG(log, "inferior started, now in stopped state");
error = SetDefaultPtraceOpts(pid);
if (error.Fail()) {
- if (log)
- log->Printf("NativeProcessLinux::%s inferior failed to set default "
- "ptrace options: %s",
- __FUNCTION__, error.AsCString());
+ LLDB_LOG(log, "failed to set default ptrace options: {0}", error);
// Mark the inferior as invalid.
// FIXME this could really use a new state - eStateLaunchFailure. For now,
@@ -398,10 +372,10 @@ Error NativeProcessLinux::LaunchInferior(MainLoop &mainloop,
if (m_terminal_fd != -1) {
error = EnsureFDFlags(m_terminal_fd, O_NONBLOCK);
if (error.Fail()) {
- if (log)
- log->Printf("NativeProcessLinux::%s inferior EnsureFDFlags failed for "
- "ensuring terminal O_NONBLOCK setting: %s",
- __FUNCTION__, error.AsCString());
+ LLDB_LOG(log,
+ "inferior EnsureFDFlags failed for ensuring terminal "
+ "O_NONBLOCK setting: {0}",
+ error);
// Mark the inferior as invalid.
// FIXME this could really use a new state - eStateLaunchFailure. For
@@ -412,10 +386,7 @@ Error NativeProcessLinux::LaunchInferior(MainLoop &mainloop,
}
}
- if (log)
- log->Printf("NativeProcessLinux::%s() adding pid = %" PRIu64, __FUNCTION__,
- uint64_t(pid));
-
+ LLDB_LOG(log, "adding pid = {0}", pid);
ResolveProcessArchitecture(m_pid, m_arch);
NativeThreadLinuxSP thread_sp = AddThread(pid);
assert(thread_sp && "AddThread() returned a nullptr thread");
@@ -426,19 +397,13 @@ Error NativeProcessLinux::LaunchInferior(MainLoop &mainloop,
SetCurrentThreadID(thread_sp->GetID());
SetState(StateType::eStateStopped);
- if (log) {
- if (error.Success())
- log->Printf("NativeProcessLinux::%s inferior launching succeeded",
- __FUNCTION__);
- else
- log->Printf("NativeProcessLinux::%s inferior launching failed: %s",
- __FUNCTION__, error.AsCString());
- }
+ if (error.Fail())
+ LLDB_LOG(log, "inferior launching failed {0}", error);
return error;
}
::pid_t NativeProcessLinux::Attach(lldb::pid_t pid, Error &error) {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
// Use a map to keep track of the threads which we have attached/need to
// attach.
@@ -487,10 +452,7 @@ Error NativeProcessLinux::LaunchInferior(MainLoop &mainloop,
if (error.Fail())
return -1;
- if (log)
- log->Printf("NativeProcessLinux::%s() adding tid = %" PRIu64,
- __FUNCTION__, tid);
-
+ LLDB_LOG(log, "adding tid = {0}", tid);
it->second = true;
// Create the thread, mark it as stopped.
@@ -578,11 +540,8 @@ void NativeProcessLinux::MonitorCallback(lldb::pid_t pid, bool exited,
// Handle when the thread exits.
if (exited) {
- if (log)
- log->Printf(
- "NativeProcessLinux::%s() got exit signal(%d) , tid = %" PRIu64
- " (%s main thread)",
- __FUNCTION__, signal, pid, is_main_thread ? "is" : "is not");
+ LLDB_LOG(log, "got exit signal({0}) , tid = {1} ({2} main thread)", signal,
+ pid, is_main_thread ? "is" : "is not");
// This is a thread that exited. Ensure we're not tracking it anymore.
const bool thread_found = StopTrackingThread(pid);
@@ -596,41 +555,32 @@ void NativeProcessLinux::MonitorCallback(lldb::pid_t pid, bool exited,
const bool already_notified = (GetState() == StateType::eStateExited) ||
(GetState() == StateType::eStateCrashed);
if (!already_notified) {
- if (log)
- log->Printf("NativeProcessLinux::%s() tid = %" PRIu64
- " handling main thread exit (%s), expected exit state "
- "already set but state was %s instead, setting exit "
- "state now",
- __FUNCTION__, pid,
- thread_found ? "stopped tracking thread metadata"
- : "thread metadata not found",
- StateAsCString(GetState()));
+ LLDB_LOG(
+ log,
+ "tid = {0} handling main thread exit ({1}), expected exit state "
+ "already set but state was {2} instead, setting exit state now",
+ pid,
+ thread_found ? "stopped tracking thread metadata"
+ : "thread metadata not found",
+ GetState());
// The main thread exited. We're done monitoring. Report to delegate.
SetExitStatus(convert_pid_status_to_exit_type(status),
convert_pid_status_to_return_code(status), nullptr, true);
// Notify delegate that our process has exited.
SetState(StateType::eStateExited, true);
- } else {
- if (log)
- log->Printf("NativeProcessLinux::%s() tid = %" PRIu64
- " main thread now exited (%s)",
- __FUNCTION__, pid,
- thread_found ? "stopped tracking thread metadata"
- : "thread metadata not found");
- }
+ } else
+ LLDB_LOG(log, "tid = {0} main thread now exited (%s)", pid,
+ thread_found ? "stopped tracking thread metadata"
+ : "thread metadata not found");
} else {
// Do we want to report to the delegate in this case? I think not. If
- // this was an orderly
- // thread exit, we would already have received the SIGTRAP |
- // (PTRACE_EVENT_EXIT << 8) signal,
- // and we would have done an all-stop then.
- if (log)
- log->Printf("NativeProcessLinux::%s() tid = %" PRIu64
- " handling non-main thread exit (%s)",
- __FUNCTION__, pid,
- thread_found ? "stopped tracking thread metadata"
- : "thread metadata not found");
+ // this was an orderly thread exit, we would already have received the
+ // SIGTRAP | (PTRACE_EVENT_EXIT << 8) signal, and we would have done an
+ // all-stop then.
+ LLDB_LOG(log, "tid = {0} handling non-main thread exit (%s)", pid,
+ thread_found ? "stopped tracking thread metadata"
+ : "thread metadata not found");
}
return;
}
@@ -641,28 +591,20 @@ void NativeProcessLinux::MonitorCallback(lldb::pid_t pid, bool exited,
if (!thread_sp) {
// Normally, the only situation when we cannot find the thread is if we have
- // just
- // received a new thread notification. This is indicated by GetSignalInfo()
- // returning
- // si_code == SI_USER and si_pid == 0
- if (log)
- log->Printf("NativeProcessLinux::%s received notification about an "
- "unknown tid %" PRIu64 ".",
- __FUNCTION__, pid);
+ // just received a new thread notification. This is indicated by
+ // GetSignalInfo() returning si_code == SI_USER and si_pid == 0
+ LLDB_LOG(log, "received notification about an unknown tid {0}.", pid);
if (info_err.Fail()) {
- if (log)
- log->Printf("NativeProcessLinux::%s (tid %" PRIu64
- ") GetSignalInfo failed (%s). Ingoring this notification.",
- __FUNCTION__, pid, info_err.AsCString());
+ LLDB_LOG(log,
+ "(tid {0}) GetSignalInfo failed ({1}). "
+ "Ingoring this notification.",
+ pid, info_err);
return;
}
- if (log && (info.si_code != SI_USER || info.si_pid != 0))
- log->Printf("NativeProcessLinux::%s (tid %" PRIu64
- ") unexpected signal info (si_code: %d, si_pid: %d). "
- "Treating as a new thread notification anyway.",
- __FUNCTION__, pid, info.si_code, info.si_pid);
+ LLDB_LOG(log, "tid {0}, si_code: {1}, si_pid: {2}", pid, info.si_code,
+ info.si_pid);
auto thread_sp = AddThread(pid);
// Resume the newly created thread.
@@ -682,49 +624,35 @@ void NativeProcessLinux::MonitorCallback(lldb::pid_t pid, bool exited,
if (info_err.GetError() == EINVAL) {
// This is a group stop reception for this tid.
// We can reach here if we reinject SIGSTOP, SIGSTP, SIGTTIN or SIGTTOU
- // into the
- // tracee, triggering the group-stop mechanism. Normally receiving these
- // would stop
- // the process, pending a SIGCONT. Simulating this state in a debugger is
- // hard and is
- // generally not needed (one use case is debugging background task being
- // managed by a
- // shell). For general use, it is sufficient to stop the process in a
- // signal-delivery
+ // into the tracee, triggering the group-stop mechanism. Normally
+ // receiving these would stop the process, pending a SIGCONT. Simulating
+ // this state in a debugger is hard and is generally not needed (one use
+ // case is debugging background task being managed by a shell). For
+ // general use, it is sufficient to stop the process in a signal-delivery
// stop which happens before the group stop. This done by MonitorSignal
- // and works
- // correctly for all signals.
- if (log)
- log->Printf(
- "NativeProcessLinux::%s received a group stop for pid %" PRIu64
- " tid %" PRIu64 ". Transparent handling of group stops not "
- "supported, resuming the thread.",
- __FUNCTION__, GetID(), pid);
+ // and works correctly for all signals.
+ LLDB_LOG(log,
+ "received a group stop for pid {0} tid {1}. Transparent "
+ "handling of group stops not supported, resuming the "
+ "thread.",
+ GetID(), pid);
ResumeThread(*thread_sp, thread_sp->GetState(),
LLDB_INVALID_SIGNAL_NUMBER);
} else {
// ptrace(GETSIGINFO) failed (but not due to group-stop).
// A return value of ESRCH means the thread/process is no longer on the
- // system,
- // so it was killed somehow outside of our control. Either way, we can't
- // do anything
- // with it anymore.
+ // system, so it was killed somehow outside of our control. Either way,
+ // we can't do anything with it anymore.
// Stop tracking the metadata for the thread since it's entirely off the
// system now.
const bool thread_found = StopTrackingThread(pid);
- if (log)
- log->Printf(
- "NativeProcessLinux::%s GetSignalInfo failed: %s, tid = %" PRIu64
- ", signal = %d, status = %d (%s, %s, %s)",
- __FUNCTION__, info_err.AsCString(), pid, signal, status,
- info_err.GetError() == ESRCH ? "thread/process killed"
- : "unknown reason",
- is_main_thread ? "is main thread" : "is not main thread",
- thread_found ? "thread metadata removed"
- : "thread metadata not found");
+ LLDB_LOG(log,
+ "GetSignalInfo failed: {0}, tid = {1}, signal = {2}, "
+ "status = {3}, main_thread = {4}, thread_found: {5}",
+ info_err, pid, signal, status, is_main_thread, thread_found);
if (is_main_thread) {
// Notify the delegate - our process is not available but appears to
@@ -736,19 +664,18 @@ void NativeProcessLinux::MonitorCallback(lldb::pid_t pid, bool exited,
} else {
// This thread was pulled out from underneath us. Anything to do here?
// Do we want to do an all stop?
- if (log)
- log->Printf("NativeProcessLinux::%s pid %" PRIu64 " tid %" PRIu64
- " non-main thread exit occurred, didn't tell delegate "
- "anything since thread disappeared out from underneath "
- "us",
- __FUNCTION__, GetID(), pid);
+ LLDB_LOG(log,
+ "pid {0} tid {1} non-main thread exit occurred, didn't "
+ "tell delegate anything since thread disappeared out "
+ "from underneath us",
+ GetID(), pid);
}
}
}
}
void NativeProcessLinux::WaitForNewThread(::pid_t tid) {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
NativeThreadLinuxSP new_thread_sp = GetThreadByID(tid);
@@ -763,65 +690,34 @@ void NativeProcessLinux::WaitForNewThread(::pid_t tid) {
int status = -1;
::pid_t wait_pid;
do {
- if (log)
- log->Printf("NativeProcessLinux::%s() received thread creation event for "
- "tid %" PRIu32
- ". tid not tracked yet, waiting for thread to appear...",
- __FUNCTION__, tid);
+ LLDB_LOG(log,
+ "received thread creation event for tid {0}. tid not tracked "
+ "yet, waiting for thread to appear...",
+ tid);
wait_pid = waitpid(tid, &status, __WALL);
} while (wait_pid == -1 && errno == EINTR);
// Since we are waiting on a specific tid, this must be the creation event.
- // But let's do
- // some checks just in case.
+ // But let's do some checks just in case.
if (wait_pid != tid) {
- if (log)
- log->Printf(
- "NativeProcessLinux::%s() waiting for tid %" PRIu32
- " failed. Assuming the thread has disappeared in the meantime",
- __FUNCTION__, tid);
+ LLDB_LOG(log,
+ "waiting for tid {0} failed. Assuming the thread has "
+ "disappeared in the meantime",
+ tid);
// The only way I know of this could happen is if the whole process was
// SIGKILLed in the mean time. In any case, we can't do anything about that
// now.
return;
}
if (WIFEXITED(status)) {
- if (log)
- log->Printf("NativeProcessLinux::%s() waiting for tid %" PRIu32
- " returned an 'exited' event. Not tracking the thread.",
- __FUNCTION__, tid);
+ LLDB_LOG(log,
+ "waiting for tid {0} returned an 'exited' event. Not "
+ "tracking the thread.",
+ tid);
// Also a very improbable event.
return;
}
- siginfo_t info;
- Error error = GetSignalInfo(tid, &info);
- if (error.Fail()) {
- if (log)
- log->Printf(
- "NativeProcessLinux::%s() GetSignalInfo for tid %" PRIu32
- " failed. Assuming the thread has disappeared in the meantime.",
- __FUNCTION__, tid);
- return;
- }
-
- if (((info.si_pid != 0) || (info.si_code != SI_USER)) && log) {
- // We should be getting a thread creation signal here, but we received
- // something
- // else. There isn't much we can do about it now, so we will just log that.
- // Since the
- // thread is alive and we are receiving events from it, we shall pretend
- // that it was
- // created properly.
- log->Printf("NativeProcessLinux::%s() GetSignalInfo for tid %" PRIu32
- " received unexpected signal with code %d from pid %d.",
- __FUNCTION__, tid, info.si_code, info.si_pid);
- }
-
- if (log)
- log->Printf("NativeProcessLinux::%s() pid = %" PRIu64
- ": tracking new thread tid %" PRIu32,
- __FUNCTION__, GetID(), tid);
-
+ LLDB_LOG(log, "pid = {0}: tracking new thread tid {1}", GetID(), tid);
new_thread_sp = AddThread(tid);
ResumeThread(*new_thread_sp, eStateRunning, LLDB_INVALID_SIGNAL_NUMBER);
ThreadWasCreated(*new_thread_sp);
@@ -829,7 +725,7 @@ void NativeProcessLinux::WaitForNewThread(::pid_t tid) {
void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info,
NativeThreadLinux &thread) {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
const bool is_main_thread = (thread.GetID() == GetID());
assert(info.si_signo == SIGTRAP && "Unexpected child signal!");
@@ -852,11 +748,10 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info,
unsigned long event_message = 0;
if (GetEventMessage(thread.GetID(), &event_message).Fail()) {
- if (log)
- log->Printf("NativeProcessLinux::%s() pid %" PRIu64
- " received thread creation event but GetEventMessage "
- "failed so we don't know the new tid",
- __FUNCTION__, thread.GetID());
+ LLDB_LOG(log,
+ "pid {0} received thread creation event but "
+ "GetEventMessage failed so we don't know the new tid",
+ thread.GetID());
} else
WaitForNewThread(event_message);
@@ -866,35 +761,24 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info,
case (SIGTRAP | (PTRACE_EVENT_EXEC << 8)): {
NativeThreadLinuxSP main_thread_sp;
- if (log)
- log->Printf("NativeProcessLinux::%s() received exec event, code = %d",
- __FUNCTION__, info.si_code ^ SIGTRAP);
+ LLDB_LOG(log, "received exec event, code = {0}", info.si_code ^ SIGTRAP);
// Exec clears any pending notifications.
m_pending_notification_tid = LLDB_INVALID_THREAD_ID;
// Remove all but the main thread here. Linux fork creates a new process
// which only copies the main thread.
- if (log)
- log->Printf("NativeProcessLinux::%s exec received, stop tracking all but "
- "main thread",
- __FUNCTION__);
+ LLDB_LOG(log, "exec received, stop tracking all but main thread");
for (auto thread_sp : m_threads) {
const bool is_main_thread = thread_sp && thread_sp->GetID() == GetID();
if (is_main_thread) {
main_thread_sp = std::static_pointer_cast<NativeThreadLinux>(thread_sp);
- if (log)
- log->Printf(
- "NativeProcessLinux::%s found main thread with tid %" PRIu64
- ", keeping",
- __FUNCTION__, main_thread_sp->GetID());
+ LLDB_LOG(log, "found main thread with tid {0}, keeping",
+ main_thread_sp->GetID());
} else {
- if (log)
- log->Printf(
- "NativeProcessLinux::%s discarding non-main-thread tid %" PRIu64
- " due to exec",
- __FUNCTION__, thread_sp->GetID());
+ LLDB_LOG(log, "discarding non-main-thread tid {0} due to exec",
+ thread_sp->GetID());
}
}
@@ -906,11 +790,10 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info,
main_thread_sp->SetStoppedByExec();
} else {
SetCurrentThreadID(LLDB_INVALID_THREAD_ID);
- if (log)
- log->Printf("NativeProcessLinux::%s pid %" PRIu64
- "no main thread found, discarded all threads, we're in a "
- "no-thread state!",
- __FUNCTION__, GetID());
+ LLDB_LOG(log,
+ "pid {0} no main thread found, discarded all threads, "
+ "we're in a no-thread state!",
+ GetID());
}
// Tell coordinator about about the "new" (since exec) stopped main thread.
@@ -941,13 +824,11 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info,
if (GetEventMessage(thread.GetID(), &data).Fail())
data = -1;
- if (log) {
- log->Printf("NativeProcessLinux::%s() received PTRACE_EVENT_EXIT, data = "
- "%lx (WIFEXITED=%s,WIFSIGNALED=%s), pid = %" PRIu64 " (%s)",
- __FUNCTION__, data, WIFEXITED(data) ? "true" : "false",
- WIFSIGNALED(data) ? "true" : "false", thread.GetID(),
- is_main_thread ? "is main thread" : "not main thread");
- }
+ LLDB_LOG(log,
+ "received PTRACE_EVENT_EXIT, data = {0:x}, WIFEXITED={1}, "
+ "WIFSIGNALED={2}, pid = {3}, main_thread = {4}",
+ data, WIFEXITED(data), WIFSIGNALED(data), thread.GetID(),
+ is_main_thread);
if (is_main_thread) {
SetExitStatus(convert_pid_status_to_exit_type(data),
@@ -978,16 +859,29 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info,
uint32_t wp_index;
Error error = thread.GetRegisterContext()->GetWatchpointHitIndex(
wp_index, (uintptr_t)info.si_addr);
- if (error.Fail() && log)
- log->Printf("NativeProcessLinux::%s() "
- "received error while checking for watchpoint hits, "
- "pid = %" PRIu64 " error = %s",
- __FUNCTION__, thread.GetID(), error.AsCString());
+ if (error.Fail())
+ LLDB_LOG(log,
+ "received error while checking for watchpoint hits, pid = "
+ "{0}, error = {1}",
+ thread.GetID(), error);
if (wp_index != LLDB_INVALID_INDEX32) {
MonitorWatchpoint(thread, wp_index);
break;
}
+ // If a breakpoint was hit, report it
+ uint32_t bp_index;
+ error = thread.GetRegisterContext()->GetHardwareBreakHitIndex(
+ bp_index, (uintptr_t)info.si_addr);
+ if (error.Fail())
+ LLDB_LOG(log, "received error while checking for hardware "
+ "breakpoint hits, pid = {0}, error = {1}",
+ thread.GetID(), error);
+ if (bp_index != LLDB_INVALID_INDEX32) {
+ MonitorBreakpoint(thread);
+ break;
+ }
+
// Otherwise, report step over
MonitorTrace(thread);
break;
@@ -1002,11 +896,11 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info,
uint32_t wp_index;
Error error = thread.GetRegisterContext()->GetWatchpointHitIndex(
wp_index, LLDB_INVALID_ADDRESS);
- if (error.Fail() && log)
- log->Printf("NativeProcessLinux::%s() "
- "received error while checking for watchpoint hits, "
- "pid = %" PRIu64 " error = %s",
- __FUNCTION__, thread.GetID(), error.AsCString());
+ if (error.Fail())
+ LLDB_LOG(log,
+ "received error while checking for watchpoint hits, pid = "
+ "{0}, error = {1}",
+ thread.GetID(), error);
if (wp_index != LLDB_INVALID_INDEX32) {
MonitorWatchpoint(thread, wp_index);
break;
@@ -1020,31 +914,28 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info,
case SIGTRAP:
case (SIGTRAP | 0x80):
- if (log)
- log->Printf("NativeProcessLinux::%s() received unknown SIGTRAP system "
- "call stop event, pid %" PRIu64 "tid %" PRIu64 ", resuming",
- __FUNCTION__, GetID(), thread.GetID());
+ LLDB_LOG(
+ log,
+ "received unknown SIGTRAP stop event ({0}, pid {1} tid {2}, resuming",
+ info.si_code, GetID(), thread.GetID());
// Ignore these signals until we know more about them.
ResumeThread(thread, thread.GetState(), LLDB_INVALID_SIGNAL_NUMBER);
break;
default:
- assert(false && "Unexpected SIGTRAP code!");
- if (log)
- log->Printf("NativeProcessLinux::%s() pid %" PRIu64 "tid %" PRIu64
- " received unhandled SIGTRAP code: 0x%d",
- __FUNCTION__, GetID(), thread.GetID(), info.si_code);
+ LLDB_LOG(
+ log,
+ "received unknown SIGTRAP stop event ({0}, pid {1} tid {2}, resuming",
+ info.si_code, GetID(), thread.GetID());
+ llvm_unreachable("Unexpected SIGTRAP code!");
break;
}
}
void NativeProcessLinux::MonitorTrace(NativeThreadLinux &thread) {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (log)
- log->Printf("NativeProcessLinux::%s() received trace event, pid = %" PRIu64
- " (single stepping)",
- __FUNCTION__, thread.GetID());
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+ LLDB_LOG(log, "received trace event, pid = {0}", thread.GetID());
// This thread is currently stopped.
thread.SetStoppedByTrace();
@@ -1055,18 +946,13 @@ void NativeProcessLinux::MonitorTrace(NativeThreadLinux &thread) {
void NativeProcessLinux::MonitorBreakpoint(NativeThreadLinux &thread) {
Log *log(
GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_BREAKPOINTS));
- if (log)
- log->Printf(
- "NativeProcessLinux::%s() received breakpoint event, pid = %" PRIu64,
- __FUNCTION__, thread.GetID());
+ LLDB_LOG(log, "received breakpoint event, pid = {0}", thread.GetID());
// Mark the thread as stopped at breakpoint.
thread.SetStoppedByBreakpoint();
Error error = FixupBreakpointPCAsNeeded(thread);
if (error.Fail())
- if (log)
- log->Printf("NativeProcessLinux::%s() pid = %" PRIu64 " fixup: %s",
- __FUNCTION__, thread.GetID(), error.AsCString());
+ LLDB_LOG(log, "pid = {0} fixup: {1}", thread.GetID(), error);
if (m_threads_stepping_with_breakpoint.find(thread.GetID()) !=
m_threads_stepping_with_breakpoint.end())
@@ -1079,10 +965,8 @@ void NativeProcessLinux::MonitorWatchpoint(NativeThreadLinux &thread,
uint32_t wp_index) {
Log *log(
GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_WATCHPOINTS));
- if (log)
- log->Printf("NativeProcessLinux::%s() received watchpoint event, "
- "pid = %" PRIu64 ", wp_index = %" PRIu32,
- __FUNCTION__, thread.GetID(), wp_index);
+ LLDB_LOG(log, "received watchpoint event, pid = {0}, wp_index = {1}",
+ thread.GetID(), wp_index);
// Mark the thread as stopped at watchpoint.
// The address is at (lldb::addr_t)info->si_addr if we need it.
@@ -1098,7 +982,7 @@ void NativeProcessLinux::MonitorSignal(const siginfo_t &info,
const int signo = info.si_signo;
const bool is_from_llgs = info.si_pid == getpid();
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
// POSIX says that process behaviour is undefined after it ignores a SIGFPE,
// SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a
@@ -1110,47 +994,33 @@ void NativeProcessLinux::MonitorSignal(const siginfo_t &info,
// Similarly, ACK signals generated by this monitor.
// Handle the signal.
- if (info.si_code == SI_TKILL || info.si_code == SI_USER) {
- if (log)
- log->Printf("NativeProcessLinux::%s() received signal %s (%d) with code "
- "%s, (siginfo pid = %d (%s), waitpid pid = %" PRIu64 ")",
- __FUNCTION__, Host::GetSignalAsCString(signo), signo,
- (info.si_code == SI_TKILL ? "SI_TKILL" : "SI_USER"),
- info.si_pid, is_from_llgs ? "from llgs" : "not from llgs",
- thread.GetID());
- }
+ LLDB_LOG(log,
+ "received signal {0} ({1}) with code {2}, (siginfo pid = {3}, "
+ "waitpid pid = {4})",
+ Host::GetSignalAsCString(signo), signo, info.si_code,
+ thread.GetID());
// Check for thread stop notification.
if (is_from_llgs && (info.si_code == SI_TKILL) && (signo == SIGSTOP)) {
// This is a tgkill()-based stop.
- if (log)
- log->Printf("NativeProcessLinux::%s() pid %" PRIu64 " tid %" PRIu64
- ", thread stopped",
- __FUNCTION__, GetID(), thread.GetID());
+ LLDB_LOG(log, "pid {0} tid {1}, thread stopped", GetID(), thread.GetID());
// Check that we're not already marked with a stop reason.
// Note this thread really shouldn't already be marked as stopped - if we
- // were, that would imply that
- // the kernel signaled us with the thread stopping which we handled and
- // marked as stopped,
- // and that, without an intervening resume, we received another stop. It is
- // more likely
- // that we are missing the marking of a run state somewhere if we find that
- // the thread was
- // marked as stopped.
+ // were, that would imply that the kernel signaled us with the thread
+ // stopping which we handled and marked as stopped, and that, without an
+ // intervening resume, we received another stop. It is more likely that we
+ // are missing the marking of a run state somewhere if we find that the
+ // thread was marked as stopped.
const StateType thread_state = thread.GetState();
if (!StateIsStoppedState(thread_state, false)) {
// An inferior thread has stopped because of a SIGSTOP we have sent it.
// Generally, these are not important stops and we don't want to report
- // them as
- // they are just used to stop other threads when one thread (the one with
- // the
- // *real* stop reason) hits a breakpoint (watchpoint, etc...). However, in
- // the
- // case of an asynchronous Interrupt(), this *is* the real stop reason, so
- // we
- // leave the signal intact if this is the thread that was chosen as the
- // triggering thread.
+ // them as they are just used to stop other threads when one thread (the
+ // one with the *real* stop reason) hits a breakpoint (watchpoint,
+ // etc...). However, in the case of an asynchronous Interrupt(), this *is*
+ // the real stop reason, so we leave the signal intact if this is the
+ // thread that was chosen as the triggering thread.
if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID) {
if (m_pending_notification_tid == thread.GetID())
thread.SetStoppedBySignal(SIGSTOP, &info);
@@ -1163,30 +1033,15 @@ void NativeProcessLinux::MonitorSignal(const siginfo_t &info,
// We can end up here if stop was initiated by LLGS but by this time a
// thread stop has occurred - maybe initiated by another event.
Error error = ResumeThread(thread, thread.GetState(), 0);
- if (error.Fail() && log) {
- log->Printf(
- "NativeProcessLinux::%s failed to resume thread tid %" PRIu64
- ": %s",
- __FUNCTION__, thread.GetID(), error.AsCString());
- }
+ if (error.Fail())
+ LLDB_LOG(log, "failed to resume thread {0}: {1}", thread.GetID(),
+ error);
}
} else {
- if (log) {
- // Retrieve the signal name if the thread was stopped by a signal.
- int stop_signo = 0;
- const bool stopped_by_signal = thread.IsStopped(&stop_signo);
- const char *signal_name = stopped_by_signal
- ? Host::GetSignalAsCString(stop_signo)
- : "<not stopped by signal>";
- if (!signal_name)
- signal_name = "<no-signal-name>";
-
- log->Printf("NativeProcessLinux::%s() pid %" PRIu64 " tid %" PRIu64
- ", thread was already marked as a stopped state (state=%s, "
- "signal=%d (%s)), leaving stop signal as is",
- __FUNCTION__, GetID(), thread.GetID(),
- StateAsCString(thread_state), stop_signo, signal_name);
- }
+ LLDB_LOG(log,
+ "pid {0} tid {1}, thread was already marked as a stopped "
+ "state (state={2}), leaving stop signal as is",
+ GetID(), thread.GetID(), thread_state);
SignalIfAllThreadsStopped();
}
@@ -1194,11 +1049,15 @@ void NativeProcessLinux::MonitorSignal(const siginfo_t &info,
return;
}
- if (log)
- log->Printf("NativeProcessLinux::%s() received signal %s", __FUNCTION__,
- Host::GetSignalAsCString(signo));
+ // Check if debugger should stop at this signal or just ignore it
+ // and resume the inferior.
+ if (m_signals_to_ignore.find(signo) != m_signals_to_ignore.end()) {
+ ResumeThread(thread, thread.GetState(), signo);
+ return;
+ }
// This thread is stopped.
+ LLDB_LOG(log, "received signal {0}", Host::GetSignalAsCString(signo));
thread.SetStoppedBySignal(signo, &info);
// Send a stop to the debugger after we get all other threads to stop.
@@ -1383,10 +1242,8 @@ bool NativeProcessLinux::SupportHardwareSingleStepping() const {
}
Error NativeProcessLinux::Resume(const ResumeActionList &resume_actions) {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
- if (log)
- log->Printf("NativeProcessLinux::%s called: pid %" PRIu64, __FUNCTION__,
- GetID());
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+ LLDB_LOG(log, "pid {0}", GetID());
bool software_single_step = !SupportHardwareSingleStepping();
@@ -1415,20 +1272,13 @@ Error NativeProcessLinux::Resume(const ResumeActionList &resume_actions) {
resume_actions.GetActionForThread(thread_sp->GetID(), true);
if (action == nullptr) {
- if (log)
- log->Printf(
- "NativeProcessLinux::%s no action specified for pid %" PRIu64
- " tid %" PRIu64,
- __FUNCTION__, GetID(), thread_sp->GetID());
+ LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(),
+ thread_sp->GetID());
continue;
}
- if (log) {
- log->Printf("NativeProcessLinux::%s processing resume action state %s "
- "for pid %" PRIu64 " tid %" PRIu64,
- __FUNCTION__, StateAsCString(action->state), GetID(),
- thread_sp->GetID());
- }
+ LLDB_LOG(log, "processing resume action state {0} for pid {1} tid {2}",
+ action->state, GetID(), thread_sp->GetID());
switch (action->state) {
case eStateRunning:
@@ -1442,7 +1292,7 @@ Error NativeProcessLinux::Resume(const ResumeActionList &resume_actions) {
case eStateSuspended:
case eStateStopped:
- lldbassert(0 && "Unexpected state");
+ llvm_unreachable("Unexpected state");
default:
return Error("NativeProcessLinux::%s (): unexpected state %s specified "
@@ -1487,11 +1337,9 @@ Error NativeProcessLinux::Detach() {
Error NativeProcessLinux::Signal(int signo) {
Error error;
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (log)
- log->Printf(
- "NativeProcessLinux::%s: sending signal %d (%s) to pid %" PRIu64,
- __FUNCTION__, signo, Host::GetSignalAsCString(signo), GetID());
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+ LLDB_LOG(log, "sending signal {0} ({1}) to pid {1}", signo,
+ Host::GetSignalAsCString(signo), GetID());
if (kill(GetID(), signo))
error.SetErrorToErrno();
@@ -1502,16 +1350,12 @@ Error NativeProcessLinux::Signal(int signo) {
Error NativeProcessLinux::Interrupt() {
// Pick a running thread (or if none, a not-dead stopped thread) as
// the chosen thread that will be the stop-reason thread.
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
NativeThreadProtocolSP running_thread_sp;
NativeThreadProtocolSP stopped_thread_sp;
- if (log)
- log->Printf(
- "NativeProcessLinux::%s selecting running thread for interrupt target",
- __FUNCTION__);
-
+ LLDB_LOG(log, "selecting running thread for interrupt target");
for (auto thread_sp : m_threads) {
// The thread shouldn't be null but lets just cover that here.
if (!thread_sp)
@@ -1533,9 +1377,7 @@ Error NativeProcessLinux::Interrupt() {
if (!running_thread_sp && !stopped_thread_sp) {
Error error("found no running/stepping or live stopped threads as target "
"for interrupt");
- if (log)
- log->Printf("NativeProcessLinux::%s skipping due to error: %s",
- __FUNCTION__, error.AsCString());
+ LLDB_LOG(log, "skipping due to error: {0}", error);
return error;
}
@@ -1543,12 +1385,9 @@ Error NativeProcessLinux::Interrupt() {
NativeThreadProtocolSP deferred_signal_thread_sp =
running_thread_sp ? running_thread_sp : stopped_thread_sp;
- if (log)
- log->Printf("NativeProcessLinux::%s pid %" PRIu64 " %s tid %" PRIu64
- " chosen for interrupt target",
- __FUNCTION__, GetID(),
- running_thread_sp ? "running" : "stopped",
- deferred_signal_thread_sp->GetID());
+ LLDB_LOG(log, "pid {0} {1} tid {2} chosen for interrupt target", GetID(),
+ running_thread_sp ? "running" : "stopped",
+ deferred_signal_thread_sp->GetID());
StopRunningThreads(deferred_signal_thread_sp->GetID());
@@ -1556,10 +1395,8 @@ Error NativeProcessLinux::Interrupt() {
}
Error NativeProcessLinux::Kill() {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (log)
- log->Printf("NativeProcessLinux::%s called for PID %" PRIu64, __FUNCTION__,
- GetID());
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+ LLDB_LOG(log, "pid {0}", GetID());
Error error;
@@ -1570,10 +1407,8 @@ Error NativeProcessLinux::Kill() {
case StateType::eStateDetached:
case StateType::eStateUnloaded:
// Nothing to do - the process is already dead.
- if (log)
- log->Printf("NativeProcessLinux::%s ignored for PID %" PRIu64
- " due to current state: %s",
- __FUNCTION__, GetID(), StateAsCString(m_state));
+ LLDB_LOG(log, "ignored for PID {0} due to current state: {1}", GetID(),
+ m_state);
return error;
case StateType::eStateConnected:
@@ -1596,11 +1431,11 @@ Error NativeProcessLinux::Kill() {
}
static Error
-ParseMemoryRegionInfoFromProcMapsLine(const std::string &maps_line,
+ParseMemoryRegionInfoFromProcMapsLine(llvm::StringRef &maps_line,
MemoryRegionInfo &memory_region_info) {
memory_region_info.Clear();
- StringExtractor line_extractor(maps_line.c_str());
+ StringExtractor line_extractor(maps_line);
// Format: {address_start_hex}-{address_end_hex} perms offset dev inode
// pathname
@@ -1712,6 +1547,7 @@ Error NativeProcessLinux::GetMemoryRegionInfo(lldb::addr_t load_addr,
assert((proc_entry_info.GetRange().GetRangeBase() >= prev_base_address) &&
"descending /proc/pid/maps entries detected, unexpected");
prev_base_address = proc_entry_info.GetRange().GetRangeBase();
+ UNUSED_IF_ASSERT_DISABLED(prev_base_address);
// If the target address comes before this entry, indicate distance to next
// region.
@@ -1750,60 +1586,50 @@ Error NativeProcessLinux::GetMemoryRegionInfo(lldb::addr_t load_addr,
}
Error NativeProcessLinux::PopulateMemoryRegionCache() {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
// If our cache is empty, pull the latest. There should always be at least
// one memory region if memory region handling is supported.
if (!m_mem_region_cache.empty()) {
- if (log)
- log->Printf("NativeProcessLinux::%s reusing %" PRIu64
- " cached memory region entries",
- __FUNCTION__,
- static_cast<uint64_t>(m_mem_region_cache.size()));
+ LLDB_LOG(log, "reusing {0} cached memory region entries",
+ m_mem_region_cache.size());
return Error();
}
- Error error = ProcFileReader::ProcessLineByLine(
- GetID(), "maps", [&](const std::string &line) -> bool {
- MemoryRegionInfo info;
- const Error parse_error =
- ParseMemoryRegionInfoFromProcMapsLine(line, info);
- if (parse_error.Success()) {
- m_mem_region_cache.emplace_back(
- info, FileSpec(info.GetName().GetCString(), true));
- return true;
- } else {
- if (log)
- log->Printf("NativeProcessLinux::%s failed to parse proc maps "
- "line '%s': %s",
- __FUNCTION__, line.c_str(), parse_error.AsCString());
- return false;
- }
- });
-
- // If we had an error, we'll mark unsupported.
- if (error.Fail()) {
+ auto BufferOrError = getProcFile(GetID(), "maps");
+ if (!BufferOrError) {
m_supports_mem_region = LazyBool::eLazyBoolNo;
- return error;
- } else if (m_mem_region_cache.empty()) {
+ return BufferOrError.getError();
+ }
+ StringRef Rest = BufferOrError.get()->getBuffer();
+ while (! Rest.empty()) {
+ StringRef Line;
+ std::tie(Line, Rest) = Rest.split('\n');
+ MemoryRegionInfo info;
+ const Error parse_error = ParseMemoryRegionInfoFromProcMapsLine(Line, info);
+ if (parse_error.Fail()) {
+ LLDB_LOG(log, "failed to parse proc maps line '{0}': {1}", Line,
+ parse_error);
+ m_supports_mem_region = LazyBool::eLazyBoolNo;
+ return parse_error;
+ }
+ m_mem_region_cache.emplace_back(
+ info, FileSpec(info.GetName().GetCString(), true));
+ }
+
+ if (m_mem_region_cache.empty()) {
// No entries after attempting to read them. This shouldn't happen if
// /proc/{pid}/maps is supported. Assume we don't support map entries
// via procfs.
- if (log)
- log->Printf("NativeProcessLinux::%s failed to find any procfs maps "
- "entries, assuming no support for memory region metadata "
- "retrieval",
- __FUNCTION__);
m_supports_mem_region = LazyBool::eLazyBoolNo;
- error.SetErrorString("not supported");
- return error;
+ LLDB_LOG(log,
+ "failed to find any procfs maps entries, assuming no support "
+ "for memory region metadata retrieval");
+ return Error("not supported");
}
- if (log)
- log->Printf("NativeProcessLinux::%s read %" PRIu64
- " memory region entries from /proc/%" PRIu64 "/maps",
- __FUNCTION__, static_cast<uint64_t>(m_mem_region_cache.size()),
- GetID());
+ LLDB_LOG(log, "read {0} memory region entries from /proc/{1}/maps",
+ m_mem_region_cache.size(), GetID());
// We support memory retrieval, remember that.
m_supports_mem_region = LazyBool::eLazyBoolYes;
@@ -1811,15 +1637,10 @@ Error NativeProcessLinux::PopulateMemoryRegionCache() {
}
void NativeProcessLinux::DoStopIDBumped(uint32_t newBumpId) {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (log)
- log->Printf("NativeProcessLinux::%s(newBumpId=%" PRIu32 ") called",
- __FUNCTION__, newBumpId);
-
- if (log)
- log->Printf("NativeProcessLinux::%s clearing %" PRIu64
- " entries from the cache",
- __FUNCTION__, static_cast<uint64_t>(m_mem_region_cache.size()));
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+ LLDB_LOG(log, "newBumpId={0}", newBumpId);
+ LLDB_LOG(log, "clearing {0} entries from memory region cache",
+ m_mem_region_cache.size());
m_mem_region_cache.clear();
}
@@ -1917,11 +1738,18 @@ Error NativeProcessLinux::GetSoftwareBreakpointPCOffset(
Error NativeProcessLinux::SetBreakpoint(lldb::addr_t addr, uint32_t size,
bool hardware) {
if (hardware)
- return Error("NativeProcessLinux does not support hardware breakpoints");
+ return SetHardwareBreakpoint(addr, size);
else
return SetSoftwareBreakpoint(addr, size);
}
+Error NativeProcessLinux::RemoveBreakpoint(lldb::addr_t addr, bool hardware) {
+ if (hardware)
+ return RemoveHardwareBreakpoint(addr);
+ else
+ return NativeProcessProtocol::RemoveBreakpoint(addr);
+}
+
Error NativeProcessLinux::GetSoftwareBreakpointTrapOpcode(
size_t trap_opcode_size_hint, size_t &actual_opcode_size,
const uint8_t *&trap_opcode_bytes) {
@@ -2154,40 +1982,30 @@ Error NativeProcessLinux::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
bytes_read = process_vm_readv(pid, &local_iov, 1, &remote_iov, 1, 0);
const bool success = bytes_read == size;
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (log)
- log->Printf("NativeProcessLinux::%s using process_vm_readv to read %zd "
- "bytes from inferior address 0x%" PRIx64 ": %s",
- __FUNCTION__, size, addr,
- success ? "Success" : strerror(errno));
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+ LLDB_LOG(log,
+ "using process_vm_readv to read {0} bytes from inferior "
+ "address {1:x}: {2}",
+ size, addr, success ? "Success" : strerror(errno));
if (success)
return Error();
- // else
- // the call failed for some reason, let's retry the read using ptrace
- // api.
+ // else the call failed for some reason, let's retry the read using ptrace
+ // api.
}
unsigned char *dst = static_cast<unsigned char *>(buf);
size_t remainder;
long data;
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_ALL));
- if (log)
- ProcessPOSIXLog::IncNestLevel();
- if (log && ProcessPOSIXLog::AtTopNestLevel() &&
- log->GetMask().Test(POSIX_LOG_MEMORY))
- log->Printf("NativeProcessLinux::%s(%p, %p, %zd, _)", __FUNCTION__,
- (void *)addr, buf, size);
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY));
+ LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size);
for (bytes_read = 0; bytes_read < size; bytes_read += remainder) {
Error error = NativeProcessLinux::PtraceWrapper(
PTRACE_PEEKDATA, GetID(), (void *)addr, nullptr, 0, &data);
- if (error.Fail()) {
- if (log)
- ProcessPOSIXLog::DecNestLevel();
+ if (error.Fail())
return error;
- }
remainder = size - bytes_read;
remainder = remainder > k_ptrace_word_size ? k_ptrace_word_size : remainder;
@@ -2195,24 +2013,10 @@ Error NativeProcessLinux::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
// Copy the data into our buffer
memcpy(dst, &data, remainder);
- if (log && ProcessPOSIXLog::AtTopNestLevel() &&
- (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) ||
- (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) &&
- size <= POSIX_LOG_MEMORY_SHORT_BYTES))) {
- uintptr_t print_dst = 0;
- // Format bytes from data by moving into print_dst for log output
- for (unsigned i = 0; i < remainder; ++i)
- print_dst |= (((data >> i * 8) & 0xFF) << i * 8);
- log->Printf("NativeProcessLinux::%s() [0x%" PRIx64 "]:0x%" PRIx64
- " (0x%" PRIx64 ")",
- __FUNCTION__, addr, uint64_t(print_dst), uint64_t(data));
- }
+ LLDB_LOG(log, "[{0:x}]:{1:x}", addr, data);
addr += k_ptrace_word_size;
dst += k_ptrace_word_size;
}
-
- if (log)
- ProcessPOSIXLog::DecNestLevel();
return Error();
}
@@ -2231,13 +2035,8 @@ Error NativeProcessLinux::WriteMemory(lldb::addr_t addr, const void *buf,
size_t remainder;
Error error;
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_ALL));
- if (log)
- ProcessPOSIXLog::IncNestLevel();
- if (log && ProcessPOSIXLog::AtTopNestLevel() &&
- log->GetMask().Test(POSIX_LOG_MEMORY))
- log->Printf("NativeProcessLinux::%s(0x%" PRIx64 ", %p, %zu)", __FUNCTION__,
- addr, buf, size);
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY));
+ LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size);
for (bytes_written = 0; bytes_written < size; bytes_written += remainder) {
remainder = size - bytes_written;
@@ -2247,54 +2046,32 @@ Error NativeProcessLinux::WriteMemory(lldb::addr_t addr, const void *buf,
unsigned long data = 0;
memcpy(&data, src, k_ptrace_word_size);
- if (log && ProcessPOSIXLog::AtTopNestLevel() &&
- (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) ||
- (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) &&
- size <= POSIX_LOG_MEMORY_SHORT_BYTES)))
- log->Printf("NativeProcessLinux::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__,
- (void *)addr, *(const unsigned long *)src, data);
-
+ LLDB_LOG(log, "[{0:x}]:{1:x}", addr, data);
error = NativeProcessLinux::PtraceWrapper(PTRACE_POKEDATA, GetID(),
(void *)addr, (void *)data);
- if (error.Fail()) {
- if (log)
- ProcessPOSIXLog::DecNestLevel();
+ if (error.Fail())
return error;
- }
} else {
unsigned char buff[8];
size_t bytes_read;
error = ReadMemory(addr, buff, k_ptrace_word_size, bytes_read);
- if (error.Fail()) {
- if (log)
- ProcessPOSIXLog::DecNestLevel();
+ if (error.Fail())
return error;
- }
memcpy(buff, src, remainder);
size_t bytes_written_rec;
error = WriteMemory(addr, buff, k_ptrace_word_size, bytes_written_rec);
- if (error.Fail()) {
- if (log)
- ProcessPOSIXLog::DecNestLevel();
+ if (error.Fail())
return error;
- }
- if (log && ProcessPOSIXLog::AtTopNestLevel() &&
- (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) ||
- (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) &&
- size <= POSIX_LOG_MEMORY_SHORT_BYTES)))
- log->Printf("NativeProcessLinux::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__,
- (void *)addr, *(const unsigned long *)src,
- *(unsigned long *)buff);
+ LLDB_LOG(log, "[{0:x}]:{1:x} ({2:x})", addr, *(const unsigned long *)src,
+ *(unsigned long *)buff);
}
addr += k_ptrace_word_size;
src += k_ptrace_word_size;
}
- if (log)
- ProcessPOSIXLog::DecNestLevel();
return error;
}
@@ -2328,14 +2105,10 @@ bool NativeProcessLinux::HasThreadNoLock(lldb::tid_t thread_id) {
}
bool NativeProcessLinux::StopTrackingThread(lldb::tid_t thread_id) {
- Log *const log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD);
-
- if (log)
- log->Printf("NativeProcessLinux::%s (tid: %" PRIu64 ")", __FUNCTION__,
- thread_id);
+ Log *const log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD);
+ LLDB_LOG(log, "tid: {0})", thread_id);
bool found = false;
-
for (auto it = m_threads.begin(); it != m_threads.end(); ++it) {
if (*it && ((*it)->GetID() == thread_id)) {
m_threads.erase(it);
@@ -2345,18 +2118,12 @@ bool NativeProcessLinux::StopTrackingThread(lldb::tid_t thread_id) {
}
SignalIfAllThreadsStopped();
-
return found;
}
NativeThreadLinuxSP NativeProcessLinux::AddThread(lldb::tid_t thread_id) {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
-
- if (log) {
- log->Printf("NativeProcessLinux::%s pid %" PRIu64
- " adding thread with tid %" PRIu64,
- __FUNCTION__, GetID(), thread_id);
- }
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
+ LLDB_LOG(log, "pid {0} adding thread with tid {1}", GetID(), thread_id);
assert(!HasThreadNoLock(thread_id) &&
"attempted to add a thread by id that already exists");
@@ -2371,7 +2138,7 @@ NativeThreadLinuxSP NativeProcessLinux::AddThread(lldb::tid_t thread_id) {
}
Error NativeProcessLinux::FixupBreakpointPCAsNeeded(NativeThreadLinux &thread) {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS));
Error error;
@@ -2380,24 +2147,17 @@ Error NativeProcessLinux::FixupBreakpointPCAsNeeded(NativeThreadLinux &thread) {
NativeRegisterContextSP context_sp = thread.GetRegisterContext();
if (!context_sp) {
error.SetErrorString("cannot get a NativeRegisterContext for the thread");
- if (log)
- log->Printf("NativeProcessLinux::%s failed: %s", __FUNCTION__,
- error.AsCString());
+ LLDB_LOG(log, "failed: {0}", error);
return error;
}
uint32_t breakpoint_size = 0;
error = GetSoftwareBreakpointPCOffset(breakpoint_size);
if (error.Fail()) {
- if (log)
- log->Printf("NativeProcessLinux::%s GetBreakpointSize() failed: %s",
- __FUNCTION__, error.AsCString());
+ LLDB_LOG(log, "GetBreakpointSize() failed: {0}", error);
return error;
- } else {
- if (log)
- log->Printf("NativeProcessLinux::%s breakpoint size: %" PRIu32,
- __FUNCTION__, breakpoint_size);
- }
+ } else
+ LLDB_LOG(log, "breakpoint size: {0}", breakpoint_size);
// First try probing for a breakpoint at a software breakpoint location: PC -
// breakpoint size.
@@ -2415,21 +2175,19 @@ Error NativeProcessLinux::FixupBreakpointPCAsNeeded(NativeThreadLinux &thread) {
error = m_breakpoint_list.GetBreakpoint(breakpoint_addr, breakpoint_sp);
if (!error.Success() || !breakpoint_sp) {
// We didn't find one at a software probe location. Nothing to do.
- if (log)
- log->Printf(
- "NativeProcessLinux::%s pid %" PRIu64
- " no lldb breakpoint found at current pc with adjustment: 0x%" PRIx64,
- __FUNCTION__, GetID(), breakpoint_addr);
+ LLDB_LOG(log,
+ "pid {0} no lldb breakpoint found at current pc with "
+ "adjustment: {1}",
+ GetID(), breakpoint_addr);
return Error();
}
// If the breakpoint is not a software breakpoint, nothing to do.
if (!breakpoint_sp->IsSoftwareBreakpoint()) {
- if (log)
- log->Printf("NativeProcessLinux::%s pid %" PRIu64
- " breakpoint found at 0x%" PRIx64
- ", not software, nothing to adjust",
- __FUNCTION__, GetID(), breakpoint_addr);
+ LLDB_LOG(
+ log,
+ "pid {0} breakpoint found at {1:x}, not software, nothing to adjust",
+ GetID(), breakpoint_addr);
return Error();
}
@@ -2440,28 +2198,21 @@ Error NativeProcessLinux::FixupBreakpointPCAsNeeded(NativeThreadLinux &thread) {
// Sanity check.
if (breakpoint_size == 0) {
// Nothing to do! How did we get here?
- if (log)
- log->Printf(
- "NativeProcessLinux::%s pid %" PRIu64
- " breakpoint found at 0x%" PRIx64
- ", it is software, but the size is zero, nothing to do (unexpected)",
- __FUNCTION__, GetID(), breakpoint_addr);
+ LLDB_LOG(log,
+ "pid {0} breakpoint found at {1:x}, it is software, but the "
+ "size is zero, nothing to do (unexpected)",
+ GetID(), breakpoint_addr);
return Error();
}
// Change the program counter.
- if (log)
- log->Printf("NativeProcessLinux::%s pid %" PRIu64 " tid %" PRIu64
- ": changing PC from 0x%" PRIx64 " to 0x%" PRIx64,
- __FUNCTION__, GetID(), thread.GetID(), initial_pc_addr,
- breakpoint_addr);
+ LLDB_LOG(log, "pid {0} tid {1}: changing PC from {2:x} to {3:x}", GetID(),
+ thread.GetID(), initial_pc_addr, breakpoint_addr);
error = context_sp->SetPC(breakpoint_addr);
if (error.Fail()) {
- if (log)
- log->Printf("NativeProcessLinux::%s pid %" PRIu64 " tid %" PRIu64
- ": failed to set PC: %s",
- __FUNCTION__, GetID(), thread.GetID(), error.AsCString());
+ LLDB_LOG(log, "pid {0} tid {1}: failed to set PC: {2}", GetID(),
+ thread.GetID(), error);
return error;
}
@@ -2511,11 +2262,8 @@ NativeThreadLinuxSP NativeProcessLinux::GetThreadByID(lldb::tid_t tid) {
Error NativeProcessLinux::ResumeThread(NativeThreadLinux &thread,
lldb::StateType state, int signo) {
- Log *const log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD);
-
- if (log)
- log->Printf("NativeProcessLinux::%s (tid: %" PRIu64 ")", __FUNCTION__,
- thread.GetID());
+ Log *const log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD);
+ LLDB_LOG(log, "tid: {0}", thread.GetID());
// Before we do the resume below, first check if we have a pending
// stop notification that is currently waiting for
@@ -2523,12 +2271,12 @@ Error NativeProcessLinux::ResumeThread(NativeThreadLinux &thread,
// we're ostensibly waiting for threads to stop before we send out the
// pending notification, and here we are resuming one before we send
// out the pending stop notification.
- if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID && log) {
- log->Printf("NativeProcessLinux::%s about to resume tid %" PRIu64
- " per explicit request but we have a pending stop notification "
- "(tid %" PRIu64 ") that is actively waiting for this thread to "
- "stop. Valid sequence of events?",
- __FUNCTION__, thread.GetID(), m_pending_notification_tid);
+ if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID) {
+ LLDB_LOG(log,
+ "about to resume tid {0} per explicit request but we have a "
+ "pending stop notification (tid {1}) that is actively "
+ "waiting for this thread to stop. Valid sequence of events?",
+ thread.GetID(), m_pending_notification_tid);
}
// Request a resume. We expect this to be synchronous and the system
@@ -2547,9 +2295,7 @@ Error NativeProcessLinux::ResumeThread(NativeThreadLinux &thread,
return step_result;
}
default:
- if (log)
- log->Printf("NativeProcessLinux::%s Unhandled state %s.", __FUNCTION__,
- StateAsCString(state));
+ LLDB_LOG(log, "Unhandled state {0}.", state);
llvm_unreachable("Unhandled state for resume");
}
}
@@ -2557,13 +2303,9 @@ Error NativeProcessLinux::ResumeThread(NativeThreadLinux &thread,
//===----------------------------------------------------------------------===//
void NativeProcessLinux::StopRunningThreads(const lldb::tid_t triggering_tid) {
- Log *const log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD);
-
- if (log) {
- log->Printf("NativeProcessLinux::%s about to process event: "
- "(triggering_tid: %" PRIu64 ")",
- __FUNCTION__, triggering_tid);
- }
+ Log *const log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD);
+ LLDB_LOG(log, "about to process event: (triggering_tid: {0})",
+ triggering_tid);
m_pending_notification_tid = triggering_tid;
@@ -2575,10 +2317,7 @@ void NativeProcessLinux::StopRunningThreads(const lldb::tid_t triggering_tid) {
}
SignalIfAllThreadsStopped();
-
- if (log) {
- log->Printf("NativeProcessLinux::%s event processing done", __FUNCTION__);
- }
+ LLDB_LOG(log, "event processing done");
}
void NativeProcessLinux::SignalIfAllThreadsStopped() {
@@ -2599,10 +2338,8 @@ void NativeProcessLinux::SignalIfAllThreadsStopped() {
for (const auto &thread_info : m_threads_stepping_with_breakpoint) {
Error error = RemoveBreakpoint(thread_info.second);
if (error.Fail())
- if (log)
- log->Printf("NativeProcessLinux::%s() pid = %" PRIu64
- " remove stepping breakpoint: %s",
- __FUNCTION__, thread_info.first, error.AsCString());
+ LLDB_LOG(log, "pid = {0} remove stepping breakpoint: {1}",
+ thread_info.first, error);
}
m_threads_stepping_with_breakpoint.clear();
@@ -2613,11 +2350,8 @@ void NativeProcessLinux::SignalIfAllThreadsStopped() {
}
void NativeProcessLinux::ThreadWasCreated(NativeThreadLinux &thread) {
- Log *const log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD);
-
- if (log)
- log->Printf("NativeProcessLinux::%s (tid: %" PRIu64 ")", __FUNCTION__,
- thread.GetID());
+ Log *const log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD);
+ LLDB_LOG(log, "tid: {0}", thread.GetID());
if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID &&
StateIsRunningState(thread.GetState())) {
@@ -2629,7 +2363,7 @@ void NativeProcessLinux::ThreadWasCreated(NativeThreadLinux &thread) {
}
void NativeProcessLinux::SigchldHandler() {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
// Process all pending waitpid notifications.
while (true) {
int status = -1;
@@ -2643,10 +2377,7 @@ void NativeProcessLinux::SigchldHandler() {
continue;
Error error(errno, eErrorTypePOSIX);
- if (log)
- log->Printf("NativeProcessLinux::%s waitpid (-1, &status, __WALL | "
- "__WNOTHREAD | WNOHANG) failed: %s",
- __FUNCTION__, error.AsCString());
+ LLDB_LOG(log, "waitpid (-1, &status, _) failed: {0}", error);
break;
}
@@ -2671,13 +2402,10 @@ void NativeProcessLinux::SigchldHandler() {
} else
status_cstr = "(\?\?\?)";
- if (log)
- log->Printf("NativeProcessLinux::%s: waitpid (-1, &status, __WALL | "
- "__WNOTHREAD | WNOHANG)"
- "=> pid = %" PRIi32
- ", status = 0x%8.8x (%s), signal = %i, exit_state = %i",
- __FUNCTION__, wait_pid, status, status_cstr, signal,
- exit_status);
+ LLDB_LOG(log,
+ "waitpid (-1, &status, _) => pid = {0}, status = {1:x} "
+ "({2}), signal = {3}, exit_state = {4}",
+ wait_pid, status, status_cstr, signal, exit_status);
MonitorCallback(wait_pid, exited, signal, exit_status);
}
@@ -2710,32 +2438,13 @@ Error NativeProcessLinux::PtraceWrapper(int req, lldb::pid_t pid, void *addr,
if (result)
*result = ret;
- if (log)
- log->Printf("ptrace(%d, %" PRIu64 ", %p, %p, %zu)=%lX", req, pid, addr,
- data, data_size, ret);
+ LLDB_LOG(log, "ptrace({0}, {1}, {2}, {3}, {4})={5:x}", req, pid, addr, data,
+ data_size, ret);
PtraceDisplayBytes(req, data, data_size);
- if (log && error.GetError() != 0) {
- const char *str;
- switch (error.GetError()) {
- case ESRCH:
- str = "ESRCH";
- break;
- case EINVAL:
- str = "EINVAL";
- break;
- case EBUSY:
- str = "EBUSY";
- break;
- case EPERM:
- str = "EPERM";
- break;
- default:
- str = error.AsCString();
- }
- log->Printf("ptrace() failed; errno=%d (%s)", error.GetError(), str);
- }
+ if (error.Fail())
+ LLDB_LOG(log, "ptrace() failed: {0}", error);
return error;
}
diff --git a/source/Plugins/Process/Linux/NativeProcessLinux.h b/source/Plugins/Process/Linux/NativeProcessLinux.h
index 5f51a6bc138e..e4809d082b50 100644
--- a/source/Plugins/Process/Linux/NativeProcessLinux.h
+++ b/source/Plugins/Process/Linux/NativeProcessLinux.h
@@ -16,9 +16,10 @@
// Other libraries and framework includes
#include "lldb/Core/ArchSpec.h"
#include "lldb/Host/Debug.h"
-#include "lldb/Host/FileSpec.h"
#include "lldb/Host/HostThread.h"
+#include "lldb/Host/linux/Support.h"
#include "lldb/Target/MemoryRegionInfo.h"
+#include "lldb/Utility/FileSpec.h"
#include "lldb/lldb-types.h"
#include "NativeThreadLinux.h"
@@ -86,6 +87,8 @@ public:
Error SetBreakpoint(lldb::addr_t addr, uint32_t size, bool hardware) override;
+ Error RemoveBreakpoint(lldb::addr_t addr, bool hardware = false) override;
+
void DoStopIDBumped(uint32_t newBumpId) override;
Error GetLoadedModuleFileSpec(const char *module_path,
@@ -96,6 +99,11 @@ public:
NativeThreadLinuxSP GetThreadByID(lldb::tid_t id);
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+ GetAuxvData() const override {
+ return getProcFile(GetID(), "auxv");
+ }
+
// ---------------------------------------------------------------------
// Interface used by NativeRegisterContext-derived classes.
// ---------------------------------------------------------------------
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp
index 580d2f952ad1..be256e972215 100644
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp
@@ -171,10 +171,7 @@ Error NativeRegisterContextLinux::DoReadRegisterValue(uint32_t offset,
// First cast to an unsigned of the same size to avoid sign extension.
value.SetUInt(static_cast<unsigned long>(data), size);
- if (log)
- log->Printf("NativeRegisterContextLinux::%s() reg %s: 0x%lx", __FUNCTION__,
- reg_name, data);
-
+ LLDB_LOG(log, "{0}: {1:x}", reg_name, data);
return error;
}
@@ -183,10 +180,7 @@ Error NativeRegisterContextLinux::DoWriteRegisterValue(
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_REGISTERS));
void *buf = reinterpret_cast<void *>(value.GetAsUInt64());
-
- if (log)
- log->Printf("NativeRegisterContextLinux::%s() reg %s: %p", __FUNCTION__,
- reg_name, buf);
+ LLDB_LOG(log, "{0}: {1}", reg_name, buf);
return NativeProcessLinux::PtraceWrapper(
PTRACE_POKEUSER, m_thread.GetID(), reinterpret_cast<void *>(offset), buf);
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux.h b/source/Plugins/Process/Linux/NativeRegisterContextLinux.h
index a16c65b64a07..4dfc5365f357 100644
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux.h
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux.h
@@ -10,10 +10,10 @@
#ifndef lldb_NativeRegisterContextLinux_h
#define lldb_NativeRegisterContextLinux_h
-#include "lldb/Host/common/NativeRegisterContextRegisterInfo.h"
#include "lldb/Host/common/NativeThreadProtocol.h"
#include "Plugins/Process/Linux/NativeProcessLinux.h"
+#include "Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h"
namespace lldb_private {
namespace process_linux {
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
index 9e857139cfca..2dd23ad75a03 100644
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
@@ -11,13 +11,14 @@
#include "NativeRegisterContextLinux_arm.h"
-#include "lldb/Core/DataBufferHeap.h"
-#include "lldb/Core/Error.h"
-#include "lldb/Core/Log.h"
#include "lldb/Core/RegisterValue.h"
+#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/Error.h"
+#include "lldb/Utility/Log.h"
#include "Plugins/Process/Linux/Procfs.h"
-#include "Plugins/Process/Utility/RegisterContextLinux_arm.h"
+#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
+#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h"
#include <elf.h>
#include <sys/socket.h>
@@ -108,7 +109,7 @@ NativeRegisterContextLinux_arm::NativeRegisterContextLinux_arm(
const ArchSpec &target_arch, NativeThreadProtocol &native_thread,
uint32_t concrete_frame_idx)
: NativeRegisterContextLinux(native_thread, concrete_frame_idx,
- new RegisterContextLinux_arm(target_arch)) {
+ new RegisterInfoPOSIX_arm(target_arch)) {
switch (target_arch.GetMachine()) {
case llvm::Triple::arm:
m_reg_info.num_registers = k_num_registers_arm;
@@ -129,6 +130,7 @@ NativeRegisterContextLinux_arm::NativeRegisterContextLinux_arm(
::memset(&m_fpr, 0, sizeof(m_fpr));
::memset(&m_gpr_arm, 0, sizeof(m_gpr_arm));
::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs));
+ ::memset(&m_hbr_regs, 0, sizeof(m_hbr_regs));
// 16 is just a maximum value, query hardware for actual watchpoint count
m_max_hwp_supported = 16;
@@ -353,10 +355,8 @@ bool NativeRegisterContextLinux_arm::IsFPR(unsigned reg) const {
return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr);
}
-uint32_t
-NativeRegisterContextLinux_arm::SetHardwareBreakpoint(lldb::addr_t addr,
- size_t size) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+uint32_t NativeRegisterContextLinux_arm::NumSupportedHardwareBreakpoints() {
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS));
if (log)
log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
@@ -367,77 +367,78 @@ NativeRegisterContextLinux_arm::SetHardwareBreakpoint(lldb::addr_t addr,
error = ReadHardwareDebugInfo();
if (error.Fail())
- return LLDB_INVALID_INDEX32;
+ return 0;
- uint32_t control_value = 0, bp_index = 0;
+ LLDB_LOG(log, "{0}", m_max_hbp_supported);
+ return m_max_hbp_supported;
+}
- // Check if size has a valid hardware breakpoint length.
- // Thumb instructions are 2-bytes but we have no way here to determine
- // if target address is a thumb or arm instruction.
- // TODO: Add support for setting thumb mode hardware breakpoints
- if (size != 4 && size != 2)
- return LLDB_INVALID_INDEX32;
+uint32_t
+NativeRegisterContextLinux_arm::SetHardwareBreakpoint(lldb::addr_t addr,
+ size_t size) {
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS));
+ LLDB_LOG(log, "addr: {0:x}, size: {1:x}", addr, size);
- // Setup control value
- // Make the byte_mask into a valid Byte Address Select mask
- control_value = 0xfu << 5;
+ // Read hardware breakpoint and watchpoint information.
+ Error error = ReadHardwareDebugInfo();
- // Enable this breakpoint and make it stop in privileged or user mode;
- control_value |= 7;
+ if (error.Fail())
+ return LLDB_INVALID_INDEX32;
- // Make sure bits 1:0 are clear in our address
- // This should be different once we support thumb here.
- addr &= ~((lldb::addr_t)3);
+ uint32_t control_value = 0, bp_index = 0;
- // Iterate over stored hardware breakpoints
- // Find a free bp_index or update reference count if duplicate.
- bp_index = LLDB_INVALID_INDEX32;
+ // Setup address and control values.
+ // Use size to get a hint of arm vs thumb modes.
+ switch (size) {
+ case 2:
+ control_value = (0x3 << 5) | 7;
+ addr &= ~1;
+ break;
+ case 4:
+ control_value = (0xfu << 5) | 7;
+ addr &= ~3;
+ break;
+ default:
+ return LLDB_INVALID_INDEX32;
+ }
+ // Iterate over stored breakpoints and find a free bp_index
+ bp_index = LLDB_INVALID_INDEX32;
for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
if ((m_hbr_regs[i].control & 1) == 0) {
bp_index = i; // Mark last free slot
- } else if (m_hbr_regs[i].address == addr &&
- m_hbr_regs[i].control == control_value) {
- bp_index = i; // Mark duplicate index
- break; // Stop searching here
+ } else if (m_hbr_regs[i].address == addr) {
+ return LLDB_INVALID_INDEX32; // We do not support duplicate breakpoints.
}
}
if (bp_index == LLDB_INVALID_INDEX32)
return LLDB_INVALID_INDEX32;
- // Add new or update existing breakpoint
- if ((m_hbr_regs[bp_index].control & 1) == 0) {
- m_hbr_regs[bp_index].address = addr;
- m_hbr_regs[bp_index].control = control_value;
- m_hbr_regs[bp_index].refcount = 1;
+ // Update breakpoint in local cache
+ m_hbr_regs[bp_index].real_addr = addr;
+ m_hbr_regs[bp_index].address = addr;
+ m_hbr_regs[bp_index].control = control_value;
- // PTRACE call to set corresponding hardware breakpoint register.
- error = WriteHardwareDebugRegs(eDREGTypeBREAK, bp_index);
+ // PTRACE call to set corresponding hardware breakpoint register.
+ error = WriteHardwareDebugRegs(eDREGTypeBREAK, bp_index);
- if (error.Fail()) {
- m_hbr_regs[bp_index].address = 0;
- m_hbr_regs[bp_index].control &= ~1;
- m_hbr_regs[bp_index].refcount = 0;
+ if (error.Fail()) {
+ m_hbr_regs[bp_index].address = 0;
+ m_hbr_regs[bp_index].control &= ~1;
- return LLDB_INVALID_INDEX32;
- }
- } else
- m_hbr_regs[bp_index].refcount++;
+ return LLDB_INVALID_INDEX32;
+ }
return bp_index;
}
bool NativeRegisterContextLinux_arm::ClearHardwareBreakpoint(uint32_t hw_idx) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
-
- if (log)
- log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
-
- Error error;
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS));
+ LLDB_LOG(log, "hw_idx: {0}", hw_idx);
// Read hardware breakpoint and watchpoint information.
- error = ReadHardwareDebugInfo();
+ Error error = ReadHardwareDebugInfo();
if (error.Fail())
return false;
@@ -445,39 +446,50 @@ bool NativeRegisterContextLinux_arm::ClearHardwareBreakpoint(uint32_t hw_idx) {
if (hw_idx >= m_max_hbp_supported)
return false;
- // Update reference count if multiple references.
- if (m_hbr_regs[hw_idx].refcount > 1) {
- m_hbr_regs[hw_idx].refcount--;
- return true;
- } else if (m_hbr_regs[hw_idx].refcount == 1) {
- // Create a backup we can revert to in case of failure.
- lldb::addr_t tempAddr = m_hbr_regs[hw_idx].address;
- uint32_t tempControl = m_hbr_regs[hw_idx].control;
- uint32_t tempRefCount = m_hbr_regs[hw_idx].refcount;
+ // Create a backup we can revert to in case of failure.
+ lldb::addr_t tempAddr = m_hbr_regs[hw_idx].address;
+ uint32_t tempControl = m_hbr_regs[hw_idx].control;
- m_hbr_regs[hw_idx].control &= ~1;
- m_hbr_regs[hw_idx].address = 0;
- m_hbr_regs[hw_idx].refcount = 0;
+ m_hbr_regs[hw_idx].control &= ~1;
+ m_hbr_regs[hw_idx].address = 0;
- // PTRACE call to clear corresponding hardware breakpoint register.
- WriteHardwareDebugRegs(eDREGTypeBREAK, hw_idx);
+ // PTRACE call to clear corresponding hardware breakpoint register.
+ error = WriteHardwareDebugRegs(eDREGTypeBREAK, hw_idx);
- if (error.Fail()) {
- m_hbr_regs[hw_idx].control = tempControl;
- m_hbr_regs[hw_idx].address = tempAddr;
- m_hbr_regs[hw_idx].refcount = tempRefCount;
+ if (error.Fail()) {
+ m_hbr_regs[hw_idx].control = tempControl;
+ m_hbr_regs[hw_idx].address = tempAddr;
- return false;
- }
+ return false;
+ }
- return true;
+ return true;
+}
+
+Error NativeRegisterContextLinux_arm::GetHardwareBreakHitIndex(
+ uint32_t &bp_index, lldb::addr_t trap_addr) {
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS));
+
+ if (log)
+ log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
+
+ lldb::addr_t break_addr;
+
+ for (bp_index = 0; bp_index < m_max_hbp_supported; ++bp_index) {
+ break_addr = m_hbr_regs[bp_index].address;
+
+ if ((m_hbr_regs[bp_index].control & 0x1) && (trap_addr == break_addr)) {
+ m_hbr_regs[bp_index].hit_addr = trap_addr;
+ return Error();
+ }
}
- return false;
+ bp_index = LLDB_INVALID_INDEX32;
+ return Error();
}
-uint32_t NativeRegisterContextLinux_arm::NumSupportedHardwareWatchpoints() {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+Error NativeRegisterContextLinux_arm::ClearAllHardwareBreakpoints() {
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS));
if (log)
log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
@@ -488,22 +500,57 @@ uint32_t NativeRegisterContextLinux_arm::NumSupportedHardwareWatchpoints() {
error = ReadHardwareDebugInfo();
if (error.Fail())
+ return error;
+
+ lldb::addr_t tempAddr = 0;
+ uint32_t tempControl = 0;
+
+ for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
+ if (m_hbr_regs[i].control & 0x01) {
+ // Create a backup we can revert to in case of failure.
+ tempAddr = m_hbr_regs[i].address;
+ tempControl = m_hbr_regs[i].control;
+
+ // Clear breakpoints in local cache
+ m_hbr_regs[i].control &= ~1;
+ m_hbr_regs[i].address = 0;
+
+ // Ptrace call to update hardware debug registers
+ error = WriteHardwareDebugRegs(eDREGTypeBREAK, i);
+
+ if (error.Fail()) {
+ m_hbr_regs[i].control = tempControl;
+ m_hbr_regs[i].address = tempAddr;
+
+ return error;
+ }
+ }
+ }
+
+ return Error();
+}
+
+uint32_t NativeRegisterContextLinux_arm::NumSupportedHardwareWatchpoints() {
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
+
+ // Read hardware breakpoint and watchpoint information.
+ Error error = ReadHardwareDebugInfo();
+
+ if (error.Fail())
return 0;
+ LLDB_LOG(log, "{0}", m_max_hwp_supported);
return m_max_hwp_supported;
}
uint32_t NativeRegisterContextLinux_arm::SetHardwareWatchpoint(
lldb::addr_t addr, size_t size, uint32_t watch_flags) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
-
- if (log)
- log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
-
- Error error;
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
+ LLDB_LOG(log, "addr: {0:x}, size: {1:x} watch_flags: {2:x}", addr, size,
+ watch_flags);
// Read hardware breakpoint and watchpoint information.
- error = ReadHardwareDebugInfo();
+ Error error = ReadHardwareDebugInfo();
if (error.Fail())
return LLDB_INVALID_INDEX32;
@@ -603,15 +650,11 @@ uint32_t NativeRegisterContextLinux_arm::SetHardwareWatchpoint(
bool NativeRegisterContextLinux_arm::ClearHardwareWatchpoint(
uint32_t wp_index) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
-
- if (log)
- log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
-
- Error error;
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
+ LLDB_LOG(log, "wp_index: {0}", wp_index);
// Read hardware breakpoint and watchpoint information.
- error = ReadHardwareDebugInfo();
+ Error error = ReadHardwareDebugInfo();
if (error.Fail())
return false;
@@ -641,15 +684,8 @@ bool NativeRegisterContextLinux_arm::ClearHardwareWatchpoint(
}
Error NativeRegisterContextLinux_arm::ClearAllHardwareWatchpoints() {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
-
- if (log)
- log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
-
- Error error;
-
// Read hardware breakpoint and watchpoint information.
- error = ReadHardwareDebugInfo();
+ Error error = ReadHardwareDebugInfo();
if (error.Fail())
return error;
@@ -683,10 +719,8 @@ Error NativeRegisterContextLinux_arm::ClearAllHardwareWatchpoints() {
}
uint32_t NativeRegisterContextLinux_arm::GetWatchpointSize(uint32_t wp_index) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
-
- if (log)
- log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
+ LLDB_LOG(log, "wp_index: {0}", wp_index);
switch ((m_hwp_regs[wp_index].control >> 5) & 0x0f) {
case 0x01:
@@ -702,10 +736,8 @@ uint32_t NativeRegisterContextLinux_arm::GetWatchpointSize(uint32_t wp_index) {
}
}
bool NativeRegisterContextLinux_arm::WatchpointIsEnabled(uint32_t wp_index) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
-
- if (log)
- log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
+ LLDB_LOG(log, "wp_index: {0}", wp_index);
if ((m_hwp_regs[wp_index].control & 0x1) == 0x1)
return true;
@@ -715,10 +747,8 @@ bool NativeRegisterContextLinux_arm::WatchpointIsEnabled(uint32_t wp_index) {
Error NativeRegisterContextLinux_arm::GetWatchpointHitIndex(
uint32_t &wp_index, lldb::addr_t trap_addr) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
-
- if (log)
- log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
+ LLDB_LOG(log, "wp_index: {0}, trap_addr: {1:x}", wp_index, trap_addr);
uint32_t watch_size;
lldb::addr_t watch_addr;
@@ -740,10 +770,8 @@ Error NativeRegisterContextLinux_arm::GetWatchpointHitIndex(
lldb::addr_t
NativeRegisterContextLinux_arm::GetWatchpointAddress(uint32_t wp_index) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
-
- if (log)
- log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
+ LLDB_LOG(log, "wp_index: {0}", wp_index);
if (wp_index >= m_max_hwp_supported)
return LLDB_INVALID_ADDRESS;
@@ -756,10 +784,8 @@ NativeRegisterContextLinux_arm::GetWatchpointAddress(uint32_t wp_index) {
lldb::addr_t
NativeRegisterContextLinux_arm::GetWatchpointHitAddress(uint32_t wp_index) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
-
- if (log)
- log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
+ LLDB_LOG(log, "wp_index: {0}", wp_index);
if (wp_index >= m_max_hwp_supported)
return LLDB_INVALID_ADDRESS;
@@ -817,8 +843,8 @@ Error NativeRegisterContextLinux_arm::WriteHardwareDebugRegs(int hwbType,
(PTRACE_TYPE_ARG3)(intptr_t) - ((hwb_index << 1) + 2), ctrl_buf,
sizeof(unsigned int));
} else {
- addr_buf = &m_hwp_regs[hwb_index].address;
- ctrl_buf = &m_hwp_regs[hwb_index].control;
+ addr_buf = &m_hbr_regs[hwb_index].address;
+ ctrl_buf = &m_hbr_regs[hwb_index].control;
error = NativeProcessLinux::PtraceWrapper(
PTRACE_SETHBPREGS, m_thread.GetID(),
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h
index f979811216dc..824ac88ad9ef 100644
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h
@@ -46,10 +46,17 @@ public:
// Hardware breakpoints/watchpoint mangement functions
//------------------------------------------------------------------
+ uint32_t NumSupportedHardwareBreakpoints() override;
+
uint32_t SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override;
bool ClearHardwareBreakpoint(uint32_t hw_idx) override;
+ Error ClearAllHardwareBreakpoints() override;
+
+ Error GetHardwareBreakHitIndex(uint32_t &bp_index,
+ lldb::addr_t trap_addr) override;
+
uint32_t NumSupportedHardwareWatchpoints() override;
uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size,
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
index 786778e25a24..f3715147fa3e 100644
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
@@ -16,11 +16,11 @@
// C++ Includes
// Other libraries and framework includes
-#include "lldb/Core/DataBufferHeap.h"
-#include "lldb/Core/Error.h"
-#include "lldb/Core/Log.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Host/common/NativeProcessProtocol.h"
+#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/Error.h"
+#include "lldb/Utility/Log.h"
#include "Plugins/Process/Linux/NativeProcessLinux.h"
#include "Plugins/Process/Linux/Procfs.h"
@@ -116,7 +116,6 @@ NativeRegisterContextLinux *
NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
const ArchSpec &target_arch, NativeThreadProtocol &native_thread,
uint32_t concrete_frame_idx) {
- Log *log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_REGISTERS);
switch (target_arch.GetMachine()) {
case llvm::Triple::arm:
return new NativeRegisterContextLinux_arm(target_arch, native_thread,
@@ -125,12 +124,7 @@ NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
return new NativeRegisterContextLinux_arm64(target_arch, native_thread,
concrete_frame_idx);
default:
- if (log)
- log->Printf("NativeRegisterContextLinux::%s() have no register context "
- "for architecture: %s\n",
- __FUNCTION__,
- target_arch.GetTriple().getArchName().str().c_str());
- return nullptr;
+ llvm_unreachable("have no register context for architecture");
}
}
@@ -152,13 +146,14 @@ NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64(
m_reg_info.gpr_flags = gpr_cpsr_arm64;
break;
default:
- assert(false && "Unhandled target architecture.");
+ llvm_unreachable("Unhandled target architecture.");
break;
}
::memset(&m_fpr, 0, sizeof(m_fpr));
::memset(&m_gpr_arm64, 0, sizeof(m_gpr_arm64));
::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs));
+ ::memset(&m_hbr_regs, 0, sizeof(m_hbr_regs));
// 16 is just a maximum value, query hardware for actual watchpoint count
m_max_hwp_supported = 16;
@@ -366,10 +361,8 @@ bool NativeRegisterContextLinux_arm64::IsFPR(unsigned reg) const {
return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr);
}
-uint32_t
-NativeRegisterContextLinux_arm64::SetHardwareBreakpoint(lldb::addr_t addr,
- size_t size) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+uint32_t NativeRegisterContextLinux_arm64::NumSupportedHardwareBreakpoints() {
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS));
if (log)
log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
@@ -380,6 +373,21 @@ NativeRegisterContextLinux_arm64::SetHardwareBreakpoint(lldb::addr_t addr,
error = ReadHardwareDebugInfo();
if (error.Fail())
+ return 0;
+
+ return m_max_hbp_supported;
+}
+
+uint32_t
+NativeRegisterContextLinux_arm64::SetHardwareBreakpoint(lldb::addr_t addr,
+ size_t size) {
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS));
+ LLDB_LOG(log, "addr: {0:x}, size: {1:x}", addr, size);
+
+ // Read hardware breakpoint and watchpoint information.
+ Error error = ReadHardwareDebugInfo();
+
+ if (error.Fail())
return LLDB_INVALID_INDEX32;
uint32_t control_value = 0, bp_index = 0;
@@ -398,55 +406,44 @@ NativeRegisterContextLinux_arm64::SetHardwareBreakpoint(lldb::addr_t addr,
control_value |= ((1 << size) - 1) << 5;
control_value |= (2 << 1) | 1;
- // Iterate over stored hardware breakpoints
- // Find a free bp_index or update reference count if duplicate.
+ // Iterate over stored breakpoints and find a free bp_index
bp_index = LLDB_INVALID_INDEX32;
for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
if ((m_hbr_regs[i].control & 1) == 0) {
bp_index = i; // Mark last free slot
- } else if (m_hbr_regs[i].address == addr &&
- m_hbr_regs[i].control == control_value) {
- bp_index = i; // Mark duplicate index
- break; // Stop searching here
+ } else if (m_hbr_regs[i].address == addr) {
+ return LLDB_INVALID_INDEX32; // We do not support duplicate breakpoints.
}
}
if (bp_index == LLDB_INVALID_INDEX32)
return LLDB_INVALID_INDEX32;
- // Add new or update existing breakpoint
- if ((m_hbr_regs[bp_index].control & 1) == 0) {
- m_hbr_regs[bp_index].address = addr;
- m_hbr_regs[bp_index].control = control_value;
- m_hbr_regs[bp_index].refcount = 1;
+ // Update breakpoint in local cache
+ m_hbr_regs[bp_index].real_addr = addr;
+ m_hbr_regs[bp_index].address = addr;
+ m_hbr_regs[bp_index].control = control_value;
- // PTRACE call to set corresponding hardware breakpoint register.
- error = WriteHardwareDebugRegs(eDREGTypeBREAK);
+ // PTRACE call to set corresponding hardware breakpoint register.
+ error = WriteHardwareDebugRegs(eDREGTypeBREAK);
- if (error.Fail()) {
- m_hbr_regs[bp_index].address = 0;
- m_hbr_regs[bp_index].control &= ~1;
- m_hbr_regs[bp_index].refcount = 0;
+ if (error.Fail()) {
+ m_hbr_regs[bp_index].address = 0;
+ m_hbr_regs[bp_index].control &= ~1;
- return LLDB_INVALID_INDEX32;
- }
- } else
- m_hbr_regs[bp_index].refcount++;
+ return LLDB_INVALID_INDEX32;
+ }
return bp_index;
}
bool NativeRegisterContextLinux_arm64::ClearHardwareBreakpoint(
uint32_t hw_idx) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
-
- if (log)
- log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
-
- Error error;
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS));
+ LLDB_LOG(log, "hw_idx: {0}", hw_idx);
// Read hardware breakpoint and watchpoint information.
- error = ReadHardwareDebugInfo();
+ Error error = ReadHardwareDebugInfo();
if (error.Fail())
return false;
@@ -454,39 +451,50 @@ bool NativeRegisterContextLinux_arm64::ClearHardwareBreakpoint(
if (hw_idx >= m_max_hbp_supported)
return false;
- // Update reference count if multiple references.
- if (m_hbr_regs[hw_idx].refcount > 1) {
- m_hbr_regs[hw_idx].refcount--;
- return true;
- } else if (m_hbr_regs[hw_idx].refcount == 1) {
- // Create a backup we can revert to in case of failure.
- lldb::addr_t tempAddr = m_hbr_regs[hw_idx].address;
- uint32_t tempControl = m_hbr_regs[hw_idx].control;
- uint32_t tempRefCount = m_hbr_regs[hw_idx].refcount;
+ // Create a backup we can revert to in case of failure.
+ lldb::addr_t tempAddr = m_hbr_regs[hw_idx].address;
+ uint32_t tempControl = m_hbr_regs[hw_idx].control;
- m_hbr_regs[hw_idx].control &= ~1;
- m_hbr_regs[hw_idx].address = 0;
- m_hbr_regs[hw_idx].refcount = 0;
+ m_hbr_regs[hw_idx].control &= ~1;
+ m_hbr_regs[hw_idx].address = 0;
- // PTRACE call to clear corresponding hardware breakpoint register.
- WriteHardwareDebugRegs(eDREGTypeBREAK);
+ // PTRACE call to clear corresponding hardware breakpoint register.
+ error = WriteHardwareDebugRegs(eDREGTypeBREAK);
- if (error.Fail()) {
- m_hbr_regs[hw_idx].control = tempControl;
- m_hbr_regs[hw_idx].address = tempAddr;
- m_hbr_regs[hw_idx].refcount = tempRefCount;
+ if (error.Fail()) {
+ m_hbr_regs[hw_idx].control = tempControl;
+ m_hbr_regs[hw_idx].address = tempAddr;
- return false;
- }
+ return false;
+ }
- return true;
+ return true;
+}
+
+Error NativeRegisterContextLinux_arm64::GetHardwareBreakHitIndex(
+ uint32_t &bp_index, lldb::addr_t trap_addr) {
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS));
+
+ if (log)
+ log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
+
+ lldb::addr_t break_addr;
+
+ for (bp_index = 0; bp_index < m_max_hbp_supported; ++bp_index) {
+ break_addr = m_hbr_regs[bp_index].address;
+
+ if ((m_hbr_regs[bp_index].control & 0x1) && (trap_addr == break_addr)) {
+ m_hbr_regs[bp_index].hit_addr = trap_addr;
+ return Error();
+ }
}
- return false;
+ bp_index = LLDB_INVALID_INDEX32;
+ return Error();
}
-uint32_t NativeRegisterContextLinux_arm64::NumSupportedHardwareWatchpoints() {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+Error NativeRegisterContextLinux_arm64::ClearAllHardwareBreakpoints() {
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS));
if (log)
log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
@@ -497,22 +505,57 @@ uint32_t NativeRegisterContextLinux_arm64::NumSupportedHardwareWatchpoints() {
error = ReadHardwareDebugInfo();
if (error.Fail())
+ return error;
+
+ lldb::addr_t tempAddr = 0;
+ uint32_t tempControl = 0;
+
+ for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
+ if (m_hbr_regs[i].control & 0x01) {
+ // Create a backup we can revert to in case of failure.
+ tempAddr = m_hbr_regs[i].address;
+ tempControl = m_hbr_regs[i].control;
+
+ // Clear watchpoints in local cache
+ m_hbr_regs[i].control &= ~1;
+ m_hbr_regs[i].address = 0;
+
+ // Ptrace call to update hardware debug registers
+ error = WriteHardwareDebugRegs(eDREGTypeBREAK);
+
+ if (error.Fail()) {
+ m_hbr_regs[i].control = tempControl;
+ m_hbr_regs[i].address = tempAddr;
+
+ return error;
+ }
+ }
+ }
+
+ return Error();
+}
+
+uint32_t NativeRegisterContextLinux_arm64::NumSupportedHardwareWatchpoints() {
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
+
+ // Read hardware breakpoint and watchpoint information.
+ Error error = ReadHardwareDebugInfo();
+
+ if (error.Fail())
return 0;
+ LLDB_LOG(log, "{0}", m_max_hwp_supported);
return m_max_hwp_supported;
}
uint32_t NativeRegisterContextLinux_arm64::SetHardwareWatchpoint(
lldb::addr_t addr, size_t size, uint32_t watch_flags) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
-
- if (log)
- log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
-
- Error error;
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
+ LLDB_LOG(log, "addr: {0:x}, size: {1:x} watch_flags: {2:x}", addr, size,
+ watch_flags);
// Read hardware breakpoint and watchpoint information.
- error = ReadHardwareDebugInfo();
+ Error error = ReadHardwareDebugInfo();
if (error.Fail())
return LLDB_INVALID_INDEX32;
@@ -595,15 +638,11 @@ uint32_t NativeRegisterContextLinux_arm64::SetHardwareWatchpoint(
bool NativeRegisterContextLinux_arm64::ClearHardwareWatchpoint(
uint32_t wp_index) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
-
- if (log)
- log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
-
- Error error;
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
+ LLDB_LOG(log, "wp_index: {0}", wp_index);
// Read hardware breakpoint and watchpoint information.
- error = ReadHardwareDebugInfo();
+ Error error = ReadHardwareDebugInfo();
if (error.Fail())
return false;
@@ -633,15 +672,8 @@ bool NativeRegisterContextLinux_arm64::ClearHardwareWatchpoint(
}
Error NativeRegisterContextLinux_arm64::ClearAllHardwareWatchpoints() {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
-
- if (log)
- log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
-
- Error error;
-
// Read hardware breakpoint and watchpoint information.
- error = ReadHardwareDebugInfo();
+ Error error = ReadHardwareDebugInfo();
if (error.Fail())
return error;
@@ -676,10 +708,9 @@ Error NativeRegisterContextLinux_arm64::ClearAllHardwareWatchpoints() {
uint32_t
NativeRegisterContextLinux_arm64::GetWatchpointSize(uint32_t wp_index) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
+ LLDB_LOG(log, "wp_index: {0}", wp_index);
- if (log)
- log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
switch ((m_hwp_regs[wp_index].control >> 5) & 0xff) {
case 0x01:
return 1;
@@ -694,10 +725,8 @@ NativeRegisterContextLinux_arm64::GetWatchpointSize(uint32_t wp_index) {
}
}
bool NativeRegisterContextLinux_arm64::WatchpointIsEnabled(uint32_t wp_index) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
-
- if (log)
- log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
+ LLDB_LOG(log, "wp_index: {0}", wp_index);
if ((m_hwp_regs[wp_index].control & 0x1) == 0x1)
return true;
@@ -707,10 +736,8 @@ bool NativeRegisterContextLinux_arm64::WatchpointIsEnabled(uint32_t wp_index) {
Error NativeRegisterContextLinux_arm64::GetWatchpointHitIndex(
uint32_t &wp_index, lldb::addr_t trap_addr) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
-
- if (log)
- log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
+ LLDB_LOG(log, "wp_index: {0}, trap_addr: {1:x}", wp_index, trap_addr);
uint32_t watch_size;
lldb::addr_t watch_addr;
@@ -732,10 +759,8 @@ Error NativeRegisterContextLinux_arm64::GetWatchpointHitIndex(
lldb::addr_t
NativeRegisterContextLinux_arm64::GetWatchpointAddress(uint32_t wp_index) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
-
- if (log)
- log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
+ LLDB_LOG(log, "wp_index: {0}", wp_index);
if (wp_index >= m_max_hwp_supported)
return LLDB_INVALID_ADDRESS;
@@ -748,10 +773,8 @@ NativeRegisterContextLinux_arm64::GetWatchpointAddress(uint32_t wp_index) {
lldb::addr_t
NativeRegisterContextLinux_arm64::GetWatchpointHitAddress(uint32_t wp_index) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
-
- if (log)
- log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
+ LLDB_LOG(log, "wp_index: {0}", wp_index);
if (wp_index >= m_max_hwp_supported)
return LLDB_INVALID_ADDRESS;
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
index c46c375acfe7..4ffbd97ee33a 100644
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
@@ -46,10 +46,17 @@ public:
// Hardware breakpoints/watchpoint mangement functions
//------------------------------------------------------------------
+ uint32_t NumSupportedHardwareBreakpoints() override;
+
uint32_t SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override;
bool ClearHardwareBreakpoint(uint32_t hw_idx) override;
+ Error ClearAllHardwareBreakpoints() override;
+
+ Error GetHardwareBreakHitIndex(uint32_t &bp_index,
+ lldb::addr_t trap_addr) override;
+
uint32_t NumSupportedHardwareWatchpoints() override;
uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size,
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp
index c050a2ec0cc6..7c5c42477170 100644
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp
@@ -17,16 +17,17 @@
// Other libraries and framework includes
#include "Plugins/Process/Linux/NativeProcessLinux.h"
#include "Plugins/Process/Linux/Procfs.h"
+#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
#include "Plugins/Process/Utility/RegisterContextLinux_mips.h"
#include "Plugins/Process/Utility/RegisterContextLinux_mips64.h"
-#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/EmulateInstruction.h"
-#include "lldb/Core/Error.h"
-#include "lldb/Core/Log.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
+#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/Error.h"
#include "lldb/Utility/LLDBAssert.h"
+#include "lldb/Utility/Log.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-private-enumerations.h"
#define NT_MIPS_MSA 0x600
@@ -71,157 +72,14 @@ struct pt_watch_regs {
#define IRW (I | R | W)
+#ifndef PTRACE_GETREGSET
+#define PTRACE_GETREGSET 0x4204
+#endif
struct pt_watch_regs default_watch_regs;
using namespace lldb_private;
using namespace lldb_private::process_linux;
-// ----------------------------------------------------------------------------
-// Private namespace.
-// ----------------------------------------------------------------------------
-
-namespace {
-// mips general purpose registers.
-const uint32_t g_gp_regnums_mips[] = {
- gpr_zero_mips, gpr_r1_mips, gpr_r2_mips, gpr_r3_mips,
- gpr_r4_mips, gpr_r5_mips, gpr_r6_mips, gpr_r7_mips,
- gpr_r8_mips, gpr_r9_mips, gpr_r10_mips, gpr_r11_mips,
- gpr_r12_mips, gpr_r13_mips, gpr_r14_mips, gpr_r15_mips,
- gpr_r16_mips, gpr_r17_mips, gpr_r18_mips, gpr_r19_mips,
- gpr_r20_mips, gpr_r21_mips, gpr_r22_mips, gpr_r23_mips,
- gpr_r24_mips, gpr_r25_mips, gpr_r26_mips, gpr_r27_mips,
- gpr_gp_mips, gpr_sp_mips, gpr_r30_mips, gpr_ra_mips,
- gpr_sr_mips, gpr_mullo_mips, gpr_mulhi_mips, gpr_badvaddr_mips,
- gpr_cause_mips, gpr_pc_mips, gpr_config5_mips,
- LLDB_INVALID_REGNUM // register sets need to end with this flag
-};
-
-static_assert((sizeof(g_gp_regnums_mips) / sizeof(g_gp_regnums_mips[0])) - 1 ==
- k_num_gpr_registers_mips,
- "g_gp_regnums_mips has wrong number of register infos");
-
-// mips floating point registers.
-const uint32_t g_fp_regnums_mips[] = {
- fpr_f0_mips, fpr_f1_mips, fpr_f2_mips, fpr_f3_mips,
- fpr_f4_mips, fpr_f5_mips, fpr_f6_mips, fpr_f7_mips,
- fpr_f8_mips, fpr_f9_mips, fpr_f10_mips, fpr_f11_mips,
- fpr_f12_mips, fpr_f13_mips, fpr_f14_mips, fpr_f15_mips,
- fpr_f16_mips, fpr_f17_mips, fpr_f18_mips, fpr_f19_mips,
- fpr_f20_mips, fpr_f21_mips, fpr_f22_mips, fpr_f23_mips,
- fpr_f24_mips, fpr_f25_mips, fpr_f26_mips, fpr_f27_mips,
- fpr_f28_mips, fpr_f29_mips, fpr_f30_mips, fpr_f31_mips,
- fpr_fcsr_mips, fpr_fir_mips, fpr_config5_mips,
- LLDB_INVALID_REGNUM // register sets need to end with this flag
-};
-
-static_assert((sizeof(g_fp_regnums_mips) / sizeof(g_fp_regnums_mips[0])) - 1 ==
- k_num_fpr_registers_mips,
- "g_fp_regnums_mips has wrong number of register infos");
-
-// mips MSA registers.
-const uint32_t g_msa_regnums_mips[] = {
- msa_w0_mips, msa_w1_mips, msa_w2_mips, msa_w3_mips,
- msa_w4_mips, msa_w5_mips, msa_w6_mips, msa_w7_mips,
- msa_w8_mips, msa_w9_mips, msa_w10_mips, msa_w11_mips,
- msa_w12_mips, msa_w13_mips, msa_w14_mips, msa_w15_mips,
- msa_w16_mips, msa_w17_mips, msa_w18_mips, msa_w19_mips,
- msa_w20_mips, msa_w21_mips, msa_w22_mips, msa_w23_mips,
- msa_w24_mips, msa_w25_mips, msa_w26_mips, msa_w27_mips,
- msa_w28_mips, msa_w29_mips, msa_w30_mips, msa_w31_mips,
- msa_fcsr_mips, msa_fir_mips, msa_mcsr_mips, msa_mir_mips,
- msa_config5_mips,
- LLDB_INVALID_REGNUM // register sets need to end with this flag
-};
-
-static_assert((sizeof(g_msa_regnums_mips) / sizeof(g_msa_regnums_mips[0])) -
- 1 ==
- k_num_msa_registers_mips,
- "g_msa_regnums_mips has wrong number of register infos");
-
-// mips64 general purpose registers.
-const uint32_t g_gp_regnums_mips64[] = {
- gpr_zero_mips64, gpr_r1_mips64, gpr_r2_mips64,
- gpr_r3_mips64, gpr_r4_mips64, gpr_r5_mips64,
- gpr_r6_mips64, gpr_r7_mips64, gpr_r8_mips64,
- gpr_r9_mips64, gpr_r10_mips64, gpr_r11_mips64,
- gpr_r12_mips64, gpr_r13_mips64, gpr_r14_mips64,
- gpr_r15_mips64, gpr_r16_mips64, gpr_r17_mips64,
- gpr_r18_mips64, gpr_r19_mips64, gpr_r20_mips64,
- gpr_r21_mips64, gpr_r22_mips64, gpr_r23_mips64,
- gpr_r24_mips64, gpr_r25_mips64, gpr_r26_mips64,
- gpr_r27_mips64, gpr_gp_mips64, gpr_sp_mips64,
- gpr_r30_mips64, gpr_ra_mips64, gpr_sr_mips64,
- gpr_mullo_mips64, gpr_mulhi_mips64, gpr_badvaddr_mips64,
- gpr_cause_mips64, gpr_pc_mips64, gpr_config5_mips64,
- LLDB_INVALID_REGNUM // register sets need to end with this flag
-};
-
-static_assert((sizeof(g_gp_regnums_mips64) / sizeof(g_gp_regnums_mips64[0])) -
- 1 ==
- k_num_gpr_registers_mips64,
- "g_gp_regnums_mips64 has wrong number of register infos");
-
-// mips64 floating point registers.
-const uint32_t g_fp_regnums_mips64[] = {
- fpr_f0_mips64, fpr_f1_mips64, fpr_f2_mips64, fpr_f3_mips64,
- fpr_f4_mips64, fpr_f5_mips64, fpr_f6_mips64, fpr_f7_mips64,
- fpr_f8_mips64, fpr_f9_mips64, fpr_f10_mips64, fpr_f11_mips64,
- fpr_f12_mips64, fpr_f13_mips64, fpr_f14_mips64, fpr_f15_mips64,
- fpr_f16_mips64, fpr_f17_mips64, fpr_f18_mips64, fpr_f19_mips64,
- fpr_f20_mips64, fpr_f21_mips64, fpr_f22_mips64, fpr_f23_mips64,
- fpr_f24_mips64, fpr_f25_mips64, fpr_f26_mips64, fpr_f27_mips64,
- fpr_f28_mips64, fpr_f29_mips64, fpr_f30_mips64, fpr_f31_mips64,
- fpr_fcsr_mips64, fpr_fir_mips64, fpr_config5_mips64,
- LLDB_INVALID_REGNUM // register sets need to end with this flag
-};
-
-static_assert((sizeof(g_fp_regnums_mips64) / sizeof(g_fp_regnums_mips64[0])) -
- 1 ==
- k_num_fpr_registers_mips64,
- "g_fp_regnums_mips64 has wrong number of register infos");
-
-// mips64 MSA registers.
-const uint32_t g_msa_regnums_mips64[] = {
- msa_w0_mips64, msa_w1_mips64, msa_w2_mips64, msa_w3_mips64,
- msa_w4_mips64, msa_w5_mips64, msa_w6_mips64, msa_w7_mips64,
- msa_w8_mips64, msa_w9_mips64, msa_w10_mips64, msa_w11_mips64,
- msa_w12_mips64, msa_w13_mips64, msa_w14_mips64, msa_w15_mips64,
- msa_w16_mips64, msa_w17_mips64, msa_w18_mips64, msa_w19_mips64,
- msa_w20_mips64, msa_w21_mips64, msa_w22_mips64, msa_w23_mips64,
- msa_w24_mips64, msa_w25_mips64, msa_w26_mips64, msa_w27_mips64,
- msa_w28_mips64, msa_w29_mips64, msa_w30_mips64, msa_w31_mips64,
- msa_fcsr_mips64, msa_fir_mips64, msa_mcsr_mips64, msa_mir_mips64,
- msa_config5_mips64,
- LLDB_INVALID_REGNUM // register sets need to end with this flag
-};
-
-static_assert((sizeof(g_msa_regnums_mips64) / sizeof(g_msa_regnums_mips64[0])) -
- 1 ==
- k_num_msa_registers_mips64,
- "g_msa_regnums_mips64 has wrong number of register infos");
-
-// Number of register sets provided by this context.
-enum { k_num_register_sets = 3 };
-
-// Register sets for mips.
-static const RegisterSet g_reg_sets_mips[k_num_register_sets] = {
- {"General Purpose Registers", "gpr", k_num_gpr_registers_mips,
- g_gp_regnums_mips},
- {"Floating Point Registers", "fpu", k_num_fpr_registers_mips,
- g_fp_regnums_mips},
- {"MSA Registers", "msa", k_num_msa_registers_mips, g_msa_regnums_mips}};
-
-// Register sets for mips64.
-static const RegisterSet g_reg_sets_mips64[k_num_register_sets] = {
- {"General Purpose Registers", "gpr", k_num_gpr_registers_mips64,
- g_gp_regnums_mips64},
- {"Floating Point Registers", "fpu", k_num_fpr_registers_mips64,
- g_fp_regnums_mips64},
- {"MSA Registers", "msa", k_num_msa_registers_mips64, g_msa_regnums_mips64},
-};
-
-} // end of anonymous namespace
-
NativeRegisterContextLinux *
NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
const ArchSpec &target_arch, NativeThreadProtocol &native_thread,
@@ -240,15 +98,12 @@ NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
static RegisterInfoInterface *
CreateRegisterInfoInterface(const ArchSpec &target_arch) {
- if (HostInfo::GetArchitecture().GetAddressByteSize() == 4) {
+ if ((target_arch.GetMachine() == llvm::Triple::mips) ||
+ (target_arch.GetMachine() == llvm::Triple::mipsel)) {
// 32-bit hosts run with a RegisterContextLinux_mips context.
return new RegisterContextLinux_mips(
target_arch, NativeRegisterContextLinux_mips64::IsMSAAvailable());
} else {
- assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
- "Register setting path assumes this is a 64-bit host");
- // mips64 hosts know how to work with 64-bit and 32-bit EXEs using the
- // mips64 register context.
return new RegisterContextLinux_mips64(
target_arch, NativeRegisterContextLinux_mips64::IsMSAAvailable());
}
@@ -303,7 +158,22 @@ NativeRegisterContextLinux_mips64::NativeRegisterContextLinux_mips64(
}
uint32_t NativeRegisterContextLinux_mips64::GetRegisterSetCount() const {
- return k_num_register_sets;
+ switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el: {
+ const auto context = static_cast<const RegisterContextLinux_mips64 &>
+ (GetRegisterInfoInterface());
+ return context.GetRegisterSetCount();
+ }
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel: {
+ const auto context = static_cast<const RegisterContextLinux_mips &>
+ (GetRegisterInfoInterface());
+ return context.GetRegisterSetCount();
+ }
+ default:
+ llvm_unreachable("Unhandled target architecture.");
+ }
}
lldb::addr_t NativeRegisterContextLinux_mips64::GetPCfromBreakpointLocation(
@@ -311,12 +181,8 @@ lldb::addr_t NativeRegisterContextLinux_mips64::GetPCfromBreakpointLocation(
Error error;
RegisterValue pc_value;
lldb::addr_t pc = fail_value;
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
-
- if (log)
- log->Printf("NativeRegisterContextLinux_mips64::%s Reading PC from "
- "breakpoint location",
- __FUNCTION__);
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS));
+ LLDB_LOG(log, "Reading PC from breakpoint location");
// PC register is at index 34 of the register array
const RegisterInfo *const pc_info_p = GetRegisterInfoAtIndex(gpr_pc_mips64);
@@ -333,11 +199,7 @@ lldb::addr_t NativeRegisterContextLinux_mips64::GetPCfromBreakpointLocation(
ReadRegister(cause_info_p, cause_value);
uint64_t cause = cause_value.GetAsUInt64();
-
- if (log)
- log->Printf("NativeRegisterContextLinux_mips64::%s PC 0x%" PRIx64
- " Cause 0x%" PRIx64,
- __FUNCTION__, pc, cause);
+ LLDB_LOG(log, "PC {0:x} cause {1:x}", pc, cause);
/*
* The breakpoint might be in a delay slot. In this case PC points
@@ -352,10 +214,7 @@ lldb::addr_t NativeRegisterContextLinux_mips64::GetPCfromBreakpointLocation(
pc = pc + branch_delay;
pc_value.SetUInt64(pc);
WriteRegister(pc_info_p, pc_value);
-
- if (log)
- log->Printf("NativeRegisterContextLinux_mips64::%s New PC 0x%" PRIx64,
- __FUNCTION__, pc);
+ LLDB_LOG(log, "New PC {0:x}", pc);
}
}
@@ -364,22 +223,25 @@ lldb::addr_t NativeRegisterContextLinux_mips64::GetPCfromBreakpointLocation(
const RegisterSet *
NativeRegisterContextLinux_mips64::GetRegisterSet(uint32_t set_index) const {
- if (set_index >= k_num_register_sets)
+ if (set_index >= GetRegisterSetCount())
return nullptr;
switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- return &g_reg_sets_mips64[set_index];
+ case llvm::Triple::mips64el: {
+ const auto context = static_cast<const RegisterContextLinux_mips64 &>
+ (GetRegisterInfoInterface());
+ return context.GetRegisterSet(set_index);
+ }
case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- return &g_reg_sets_mips[set_index];
+ case llvm::Triple::mipsel: {
+ const auto context = static_cast<const RegisterContextLinux_mips &>
+ (GetRegisterInfoInterface());
+ return context.GetRegisterSet(set_index);
+ }
default:
- assert(false && "Unhandled target architecture.");
- return nullptr;
+ llvm_unreachable("Unhandled target architecture.");
}
-
- return nullptr;
}
lldb_private::Error
@@ -727,70 +589,64 @@ bool NativeRegisterContextLinux_mips64::IsFPR(uint32_t reg_index) const {
}
static uint32_t GetWatchHi(struct pt_watch_regs *regs, uint32_t index) {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
if (regs->style == pt_watch_style_mips32)
return regs->mips32.watchhi[index];
else if (regs->style == pt_watch_style_mips64)
return regs->mips64.watchhi[index];
- if (log)
- log->Printf("Invalid watch register style");
+ LLDB_LOG(log, "Invalid watch register style");
return 0;
}
static void SetWatchHi(struct pt_watch_regs *regs, uint32_t index,
uint16_t value) {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
if (regs->style == pt_watch_style_mips32)
regs->mips32.watchhi[index] = value;
else if (regs->style == pt_watch_style_mips64)
regs->mips64.watchhi[index] = value;
- if (log)
- log->Printf("Invalid watch register style");
+ LLDB_LOG(log, "Invalid watch register style");
return;
}
static lldb::addr_t GetWatchLo(struct pt_watch_regs *regs, uint32_t index) {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
if (regs->style == pt_watch_style_mips32)
return regs->mips32.watchlo[index];
else if (regs->style == pt_watch_style_mips64)
return regs->mips64.watchlo[index];
- if (log)
- log->Printf("Invalid watch register style");
+ LLDB_LOG(log, "Invalid watch register style");
return LLDB_INVALID_ADDRESS;
}
static void SetWatchLo(struct pt_watch_regs *regs, uint32_t index,
uint64_t value) {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
if (regs->style == pt_watch_style_mips32)
regs->mips32.watchlo[index] = (uint32_t)value;
else if (regs->style == pt_watch_style_mips64)
regs->mips64.watchlo[index] = value;
- if (log)
- log->Printf("Invalid watch register style");
- return;
+ else
+ LLDB_LOG(log, "Invalid watch register style");
}
static uint32_t GetIRWMask(struct pt_watch_regs *regs, uint32_t index) {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
if (regs->style == pt_watch_style_mips32)
return regs->mips32.watch_masks[index] & IRW;
else if (regs->style == pt_watch_style_mips64)
return regs->mips64.watch_masks[index] & IRW;
- if (log)
- log->Printf("Invalid watch register style");
+ LLDB_LOG(log, "Invalid watch register style");
return 0;
}
static uint32_t GetRegMask(struct pt_watch_regs *regs, uint32_t index) {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
if (regs->style == pt_watch_style_mips32)
return regs->mips32.watch_masks[index] & ~IRW;
else if (regs->style == pt_watch_style_mips64)
return regs->mips64.watch_masks[index] & ~IRW;
- if (log)
- log->Printf("Invalid watch register style");
+ LLDB_LOG(log, "Invalid watch register style");
return 0;
}
@@ -1114,7 +970,7 @@ NativeRegisterContextLinux_mips64::GetWatchpointHitAddress(uint32_t wp_index) {
}
uint32_t NativeRegisterContextLinux_mips64::NumSupportedHardwareWatchpoints() {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
struct pt_watch_regs regs;
static int num_valid = 0;
if (!num_valid) {
@@ -1128,12 +984,8 @@ uint32_t NativeRegisterContextLinux_mips64::NumSupportedHardwareWatchpoints() {
case pt_watch_style_mips64:
num_valid = regs.mips64.num_valid;
return num_valid;
- default:
- if (log)
- log->Printf("NativeRegisterContextLinux_mips64::%s Error: Unrecognized "
- "watch register style",
- __FUNCTION__);
}
+ LLDB_LOG(log, "Invalid watch register style");
return 0;
}
return num_valid;
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp
index 7ec4dc551fac..3e782d39f72e 100644
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp
@@ -11,11 +11,11 @@
#include "NativeRegisterContextLinux_s390x.h"
-#include "lldb/Core/DataBufferHeap.h"
-#include "lldb/Core/Error.h"
-#include "lldb/Core/Log.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Host/HostInfo.h"
+#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/Error.h"
+#include "lldb/Utility/Log.h"
#include "Plugins/Process/Utility/RegisterContextLinux_s390x.h"
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
index 2bd819b456ab..dd35705a8ae8 100755
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
@@ -11,11 +11,11 @@
#include "NativeRegisterContextLinux_x86_64.h"
-#include "lldb/Core/DataBufferHeap.h"
-#include "lldb/Core/Error.h"
-#include "lldb/Core/Log.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Host/HostInfo.h"
+#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/Error.h"
+#include "lldb/Utility/Log.h"
#include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
diff --git a/source/Plugins/Process/Linux/NativeThreadLinux.cpp b/source/Plugins/Process/Linux/NativeThreadLinux.cpp
index d18d3c16d2c9..04b6fe6d71e9 100644
--- a/source/Plugins/Process/Linux/NativeThreadLinux.cpp
+++ b/source/Plugins/Process/Linux/NativeThreadLinux.cpp
@@ -16,11 +16,12 @@
#include "NativeRegisterContextLinux.h"
#include "SingleStepCheck.h"
-#include "lldb/Core/Log.h"
#include "lldb/Core/State.h"
#include "lldb/Host/HostNativeThread.h"
#include "lldb/Host/linux/Ptrace.h"
+#include "lldb/Host/linux/Support.h"
#include "lldb/Utility/LLDBAssert.h"
+#include "lldb/Utility/Log.h"
#include "lldb/lldb-enumerations.h"
#include "llvm/ADT/SmallString.h"
@@ -90,15 +91,12 @@ NativeThreadLinux::NativeThreadLinux(NativeProcessLinux *process,
m_stop_info(), m_reg_context_sp(), m_stop_description() {}
std::string NativeThreadLinux::GetName() {
- NativeProcessProtocolSP process_sp = m_process_wp.lock();
- if (!process_sp)
- return "<unknown: no process>";
-
- // const NativeProcessLinux *const process =
- // reinterpret_cast<NativeProcessLinux*> (process_sp->get ());
- llvm::SmallString<32> thread_name;
- HostNativeThread::GetName(GetID(), thread_name);
- return thread_name.c_str();
+ NativeProcessLinux &process = GetProcess();
+
+ auto BufferOrError = getProcFile(process.GetID(), GetID(), "comm");
+ if (!BufferOrError)
+ return "";
+ return BufferOrError.get()->getBuffer().rtrim('\n');
}
lldb::StateType NativeThreadLinux::GetState() { return m_state; }
@@ -190,6 +188,38 @@ Error NativeThreadLinux::RemoveWatchpoint(lldb::addr_t addr) {
return Error("Clearing hardware watchpoint failed.");
}
+Error NativeThreadLinux::SetHardwareBreakpoint(lldb::addr_t addr, size_t size) {
+ if (m_state == eStateLaunching)
+ return Error();
+
+ Error error = RemoveHardwareBreakpoint(addr);
+ if (error.Fail())
+ return error;
+
+ NativeRegisterContextSP reg_ctx = GetRegisterContext();
+ uint32_t bp_index = reg_ctx->SetHardwareBreakpoint(addr, size);
+
+ if (bp_index == LLDB_INVALID_INDEX32)
+ return Error("Setting hardware breakpoint failed.");
+
+ m_hw_break_index_map.insert({addr, bp_index});
+ return Error();
+}
+
+Error NativeThreadLinux::RemoveHardwareBreakpoint(lldb::addr_t addr) {
+ auto bp = m_hw_break_index_map.find(addr);
+ if (bp == m_hw_break_index_map.end())
+ return Error();
+
+ uint32_t bp_index = bp->second;
+ if (GetRegisterContext()->ClearHardwareBreakpoint(bp_index)) {
+ m_hw_break_index_map.erase(bp);
+ return Error();
+ }
+
+ return Error("Clearing hardware breakpoint failed.");
+}
+
Error NativeThreadLinux::Resume(uint32_t signo) {
const StateType new_state = StateType::eStateRunning;
MaybeLogStateChange(new_state);
@@ -211,6 +241,18 @@ Error NativeThreadLinux::Resume(uint32_t signo) {
}
}
+ // Set all active hardware breakpoint on all threads.
+ if (m_hw_break_index_map.empty()) {
+ NativeProcessLinux &process = GetProcess();
+
+ const auto &hw_breakpoint_map = process.GetHardwareBreakpointMap();
+ GetRegisterContext()->ClearAllHardwareBreakpoints();
+ for (const auto &pair : hw_breakpoint_map) {
+ const auto &bp = pair.second;
+ SetHardwareBreakpoint(bp.m_addr, bp.m_size);
+ }
+ }
+
intptr_t data = 0;
if (signo != LLDB_INVALID_SIGNAL_NUMBER)
@@ -220,63 +262,18 @@ Error NativeThreadLinux::Resume(uint32_t signo) {
reinterpret_cast<void *>(data));
}
-void NativeThreadLinux::MaybePrepareSingleStepWorkaround() {
- if (!SingleStepWorkaroundNeeded())
- return;
-
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
-
- if (sched_getaffinity(static_cast<::pid_t>(m_tid), sizeof m_original_cpu_set,
- &m_original_cpu_set) != 0) {
- // This should really not fail. But, just in case...
- if (log) {
- Error error(errno, eErrorTypePOSIX);
- log->Printf(
- "NativeThreadLinux::%s Unable to get cpu affinity for thread %" PRIx64
- ": %s",
- __FUNCTION__, m_tid, error.AsCString());
- }
- return;
- }
-
- cpu_set_t set;
- CPU_ZERO(&set);
- CPU_SET(0, &set);
- if (sched_setaffinity(static_cast<::pid_t>(m_tid), sizeof set, &set) != 0 &&
- log) {
- // 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...
- Error error(errno, eErrorTypePOSIX);
- log->Printf(
- "NativeThreadLinux::%s Unable to set cpu affinity for thread %" PRIx64
- ": %s",
- __FUNCTION__, m_tid, error.AsCString());
- }
-}
-
-void NativeThreadLinux::MaybeCleanupSingleStepWorkaround() {
- if (!SingleStepWorkaroundNeeded())
- return;
-
- if (sched_setaffinity(static_cast<::pid_t>(m_tid), sizeof m_original_cpu_set,
- &m_original_cpu_set) != 0) {
- Error error(errno, eErrorTypePOSIX);
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
- log->Printf(
- "NativeThreadLinux::%s Unable to reset cpu affinity for thread %" PRIx64
- ": %s",
- __FUNCTION__, m_tid, error.AsCString());
- }
-}
-
Error NativeThreadLinux::SingleStep(uint32_t signo) {
const StateType new_state = StateType::eStateStepping;
MaybeLogStateChange(new_state);
m_state = new_state;
m_stop_info.reason = StopReason::eStopReasonNone;
- MaybePrepareSingleStepWorkaround();
+ if(!m_step_workaround) {
+ // If we already hava a workaround inplace, don't reset it. Otherwise, the
+ // destructor of the existing instance will run after the new instance has
+ // fetched the cpu mask, and the thread will end up with the wrong mask.
+ m_step_workaround = SingleStepWorkaround::Get(m_tid);
+ }
intptr_t data = 0;
if (signo != LLDB_INVALID_SIGNAL_NUMBER)
@@ -338,7 +335,7 @@ bool NativeThreadLinux::IsStopped(int *signo) {
void NativeThreadLinux::SetStopped() {
if (m_state == StateType::eStateStepping)
- MaybeCleanupSingleStepWorkaround();
+ m_step_workaround.reset();
const StateType new_state = StateType::eStateStopped;
MaybeLogStateChange(new_state);
diff --git a/source/Plugins/Process/Linux/NativeThreadLinux.h b/source/Plugins/Process/Linux/NativeThreadLinux.h
index f170bb1e8508..42697497c0af 100644
--- a/source/Plugins/Process/Linux/NativeThreadLinux.h
+++ b/source/Plugins/Process/Linux/NativeThreadLinux.h
@@ -10,11 +10,10 @@
#ifndef liblldb_NativeThreadLinux_H_
#define liblldb_NativeThreadLinux_H_
+#include "SingleStepCheck.h"
#include "lldb/Host/common/NativeThreadProtocol.h"
#include "lldb/lldb-private-forward.h"
-#include <sched.h>
-
#include <map>
#include <memory>
#include <string>
@@ -47,6 +46,10 @@ public:
Error RemoveWatchpoint(lldb::addr_t addr) override;
+ Error SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override;
+
+ Error RemoveHardwareBreakpoint(lldb::addr_t addr) override;
+
private:
// ---------------------------------------------------------------------
// Interface for friend classes
@@ -94,10 +97,6 @@ private:
void SetStopped();
- inline void MaybePrepareSingleStepWorkaround();
-
- inline void MaybeCleanupSingleStepWorkaround();
-
// ---------------------------------------------------------------------
// Member Variables
// ---------------------------------------------------------------------
@@ -107,7 +106,8 @@ private:
std::string m_stop_description;
using WatchpointIndexMap = std::map<lldb::addr_t, uint32_t>;
WatchpointIndexMap m_watchpoint_index_map;
- cpu_set_t m_original_cpu_set; // For single-step workaround.
+ WatchpointIndexMap m_hw_break_index_map;
+ std::unique_ptr<SingleStepWorkaround> m_step_workaround;
};
typedef std::shared_ptr<NativeThreadLinux> NativeThreadLinuxSP;
diff --git a/source/Plugins/Process/Linux/ProcFileReader.cpp b/source/Plugins/Process/Linux/ProcFileReader.cpp
deleted file mode 100644
index a1bb7a6e09d5..000000000000
--- a/source/Plugins/Process/Linux/ProcFileReader.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-//===-- ProcFileReader.cpp --------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Plugins/Process/Linux/ProcFileReader.h"
-
-// C Headers
-#include <fcntl.h>
-#include <inttypes.h>
-#include <limits.h>
-#include <stdio.h>
-#include <sys/stat.h>
-
-// C++ Headers
-#include <fstream>
-
-// LLDB Headers
-#include "lldb/Core/DataBufferHeap.h"
-#include "lldb/Core/Error.h"
-
-using namespace lldb_private;
-using namespace lldb_private::process_linux;
-
-lldb::DataBufferSP ProcFileReader::ReadIntoDataBuffer(lldb::pid_t pid,
- const char *name) {
- int fd;
- char path[PATH_MAX];
-
- // Make sure we've got a nil terminated buffer for all the folks calling
- // GetBytes() directly off our returned DataBufferSP if we hit an error.
- lldb::DataBufferSP buf_sp(new DataBufferHeap(1, 0));
-
- // Ideally, we would simply create a FileSpec and call ReadFileContents.
- // However, files in procfs have zero size (since they are, in general,
- // dynamically generated by the kernel) which is incompatible with the
- // current ReadFileContents implementation. Therefore we simply stream the
- // data into a DataBuffer ourselves.
- if (snprintf(path, PATH_MAX, "/proc/%" PRIu64 "/%s", pid, name) > 0) {
- if ((fd = open(path, O_RDONLY, 0)) >= 0) {
- size_t bytes_read = 0;
- std::unique_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(1024, 0));
-
- for (;;) {
- size_t avail = buf_ap->GetByteSize() - bytes_read;
- ssize_t status = read(fd, buf_ap->GetBytes() + bytes_read, avail);
-
- if (status < 0)
- break;
-
- if (status == 0) {
- buf_ap->SetByteSize(bytes_read);
- buf_sp.reset(buf_ap.release());
- break;
- }
-
- bytes_read += status;
-
- if (avail - status == 0)
- buf_ap->SetByteSize(2 * buf_ap->GetByteSize());
- }
-
- close(fd);
- }
- }
-
- return buf_sp;
-}
-
-Error ProcFileReader::ProcessLineByLine(
- lldb::pid_t pid, const char *name,
- std::function<bool(const std::string &line)> line_parser) {
- Error error;
-
- // Try to open the /proc/{pid}/maps entry.
- char filename[PATH_MAX];
- snprintf(filename, sizeof(filename), "/proc/%" PRIu64 "/%s", pid, name);
- filename[sizeof(filename) - 1] = '\0';
-
- std::ifstream proc_file(filename);
- if (proc_file.fail()) {
- error.SetErrorStringWithFormat("failed to open file '%s'", filename);
- return error;
- }
-
- // Read the file line by line, processing until either end of file or when the
- // line_parser returns false.
- std::string line;
- bool should_continue = true;
-
- while (should_continue && std::getline(proc_file, line)) {
- // Pass the line over to the line_parser for processing. If the line_parser
- // returns false, we
- // stop processing.
- should_continue = line_parser(line);
- }
-
- return error;
-}
diff --git a/source/Plugins/Process/Linux/ProcFileReader.h b/source/Plugins/Process/Linux/ProcFileReader.h
deleted file mode 100644
index dcdb3553d8c3..000000000000
--- a/source/Plugins/Process/Linux/ProcFileReader.h
+++ /dev/null
@@ -1,37 +0,0 @@
-//===-- ProcFileReader.h ----------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_ProcFileReader_h_
-#define liblldb_ProcFileReader_h_
-
-#include <functional>
-
-#include "lldb/lldb-forward.h"
-#include "lldb/lldb-types.h"
-
-namespace lldb_private {
-namespace process_linux {
-
-class ProcFileReader {
-public:
- static lldb::DataBufferSP ReadIntoDataBuffer(lldb::pid_t pid,
- const char *name);
-
- /// Parse the /proc/{@a pid}/{@a name} file line by line, passing each line to
- /// line_parser, until
- /// either end of file or until line_parser returns false.
- static Error
- ProcessLineByLine(lldb::pid_t pid, const char *name,
- std::function<bool(const std::string &line)> line_parser);
-};
-
-} // namespace process_linux
-} // namespace lldb_private
-
-#endif // #ifndef liblldb_ProcFileReader_h_
diff --git a/source/Plugins/Process/Linux/SingleStepCheck.cpp b/source/Plugins/Process/Linux/SingleStepCheck.cpp
index b23c1bd245d5..4e979bd45532 100644
--- a/source/Plugins/Process/Linux/SingleStepCheck.cpp
+++ b/source/Plugins/Process/Linux/SingleStepCheck.cpp
@@ -18,10 +18,12 @@
#include "llvm/Support/Compiler.h"
-#include "lldb/Core/Error.h"
-#include "lldb/Core/Log.h"
+#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
#include "lldb/Host/linux/Ptrace.h"
+#include "lldb/Utility/Error.h"
+using namespace lldb;
+using namespace lldb_private;
using namespace lldb_private::process_linux;
#if defined(__arm64__) || defined(__aarch64__)
@@ -32,16 +34,14 @@ void LLVM_ATTRIBUTE_NORETURN Child() {
_exit(1);
// We just do an endless loop SIGSTOPPING ourselves until killed. The tracer
- // will fiddle with our cpu
- // affinities and monitor the behaviour.
+ // 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.
+ // 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)
;
}
@@ -57,25 +57,16 @@ struct ChildDeleter {
}
};
-} // end anonymous namespace
-
-bool impl::SingleStepWorkaroundNeeded() {
+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(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
- Error error;
+ // 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) {
- if (log) {
- error.SetErrorToErrno();
- log->Printf("%s failed to fork(): %s", __FUNCTION__, error.AsCString());
- }
+ LLDB_LOG(log, "failed to fork(): {0}", Error(errno, eErrorTypePOSIX));
return false;
}
if (child_pid == 0)
@@ -85,22 +76,16 @@ bool impl::SingleStepWorkaroundNeeded() {
cpu_set_t available_cpus;
if (sched_getaffinity(child_pid, sizeof available_cpus, &available_cpus) ==
-1) {
- if (log) {
- error.SetErrorToErrno();
- log->Printf("%s failed to get available cpus: %s", __FUNCTION__,
- error.AsCString());
- }
+ LLDB_LOG(log, "failed to get available cpus: {0}",
+ Error(errno, eErrorTypePOSIX));
return false;
}
int status;
::pid_t wpid = waitpid(child_pid, &status, __WALL);
if (wpid != child_pid || !WIFSTOPPED(status)) {
- if (log) {
- error.SetErrorToErrno();
- log->Printf("%s waitpid() failed (status = %x): %s", __FUNCTION__, status,
- error.AsCString());
- }
+ LLDB_LOG(log, "waitpid() failed (status = {0:x}): {1}", status,
+ Error(errno, eErrorTypePOSIX));
return false;
}
@@ -113,46 +98,37 @@ bool impl::SingleStepWorkaroundNeeded() {
CPU_ZERO(&cpus);
CPU_SET(cpu, &cpus);
if (sched_setaffinity(child_pid, sizeof cpus, &cpus) == -1) {
- if (log) {
- error.SetErrorToErrno();
- log->Printf("%s failed to switch to cpu %u: %s", __FUNCTION__, cpu,
- error.AsCString());
- }
+ LLDB_LOG(log, "failed to switch to cpu {0}: {1}", cpu,
+ Error(errno, eErrorTypePOSIX));
continue;
}
int status;
- error = NativeProcessLinux::PtraceWrapper(PTRACE_SINGLESTEP, child_pid);
+ Error error =
+ NativeProcessLinux::PtraceWrapper(PTRACE_SINGLESTEP, child_pid);
if (error.Fail()) {
- if (log)
- log->Printf("%s single step failed: %s", __FUNCTION__,
- error.AsCString());
+ LLDB_LOG(log, "single step failed: {0}", error);
break;
}
wpid = waitpid(child_pid, &status, __WALL);
if (wpid != child_pid || !WIFSTOPPED(status)) {
- if (log) {
- error.SetErrorToErrno();
- log->Printf("%s waitpid() failed (status = %x): %s", __FUNCTION__,
- status, error.AsCString());
- }
+ LLDB_LOG(log, "waitpid() failed (status = {0:x}): {1}", status,
+ Error(errno, eErrorTypePOSIX));
break;
}
if (WSTOPSIG(status) != SIGTRAP) {
- if (log)
- log->Printf("%s single stepping on cpu %d failed with status %x",
- __FUNCTION__, cpu, status);
+ 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) {
- if (log)
- log->Printf("%s SINGLE STEPPING ON FIRST CPU IS NOT WORKING. DEBUGGING "
- "LIKELY TO BE UNRELIABLE.",
- __FUNCTION__);
+ 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;
@@ -161,6 +137,46 @@ bool impl::SingleStepWorkaroundNeeded() {
return cpu != CPU_SETSIZE;
}
-#else // !arm64
-bool impl::SingleStepWorkaroundNeeded() { return false; }
+} // 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,
+ Error(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,
+ Error(errno, eErrorTypePOSIX));
+ }
+
+ LLDB_LOG(log, "workaround for thread {0} prepared", tid);
+ return llvm::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,
+ Error(errno, eErrorTypePOSIX));
+ }
+}
#endif
diff --git a/source/Plugins/Process/Linux/SingleStepCheck.h b/source/Plugins/Process/Linux/SingleStepCheck.h
index 6e3310da840b..afeda7310349 100644
--- a/source/Plugins/Process/Linux/SingleStepCheck.h
+++ b/source/Plugins/Process/Linux/SingleStepCheck.h
@@ -10,30 +10,47 @@
#ifndef liblldb_SingleStepCheck_H_
#define liblldb_SingleStepCheck_H_
+#include <memory>
+#include <sched.h>
+#include <sys/types.h>
+
namespace lldb_private {
namespace process_linux {
-namespace impl {
-extern bool SingleStepWorkaroundNeeded();
-}
-
// arm64 linux had a bug which prevented single-stepping and watchpoints from
-// working on non-boot
-// cpus, due to them being incorrectly initialized after coming out of suspend.
-// This issue is
-// particularly affecting android M, which uses suspend ("doze mode") quite
-// aggressively. This
-// code detects that situation and makes single-stepping work by doing all the
-// step operations on
+// working on non-boot cpus, due to them being incorrectly initialized after
+// coming out of suspend. This issue is particularly affecting android M, which
+// uses suspend ("doze mode") quite aggressively. This code detects that
+// situation and makes single-stepping work by doing all the step operations on
// the boot cpu.
//
// The underlying issue has been fixed in android N and linux 4.4. This code can
-// be removed once
-// these systems become obsolete.
-inline bool SingleStepWorkaroundNeeded() {
- static bool value = impl::SingleStepWorkaroundNeeded();
- return value;
-}
+// be removed once these systems become obsolete.
+
+#if defined(__arm64__) || defined(__aarch64__)
+class SingleStepWorkaround {
+ ::pid_t m_tid;
+ cpu_set_t m_original_set;
+
+ SingleStepWorkaround(const SingleStepWorkaround &) = delete;
+ void operator=(const SingleStepWorkaround &) = delete;
+
+public:
+ SingleStepWorkaround(::pid_t tid, cpu_set_t original_set)
+ : m_tid(tid), m_original_set(original_set) {}
+ ~SingleStepWorkaround();
+
+ static std::unique_ptr<SingleStepWorkaround> Get(::pid_t tid);
+};
+#else
+class SingleStepWorkaround {
+public:
+ static std::unique_ptr<SingleStepWorkaround> Get(::pid_t tid) {
+ return nullptr;
+ }
+};
+#endif
+
} // end namespace process_linux
} // end namespace lldb_private