aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/Process/Linux
diff options
context:
space:
mode:
authorKate Stone <katherine.stone@apple.com>2016-09-06 20:57:50 +0000
committerKate Stone <katherine.stone@apple.com>2016-09-06 20:57:50 +0000
commitb9c1b51e45b845debb76d8658edabca70ca56079 (patch)
treedfcb5a13ef2b014202340f47036da383eaee74aa /lldb/source/Plugins/Process/Linux
parentd5aa73376966339caad04013510626ec2e42c760 (diff)
downloadllvm-b9c1b51e45b845debb76d8658edabca70ca56079.zip
llvm-b9c1b51e45b845debb76d8658edabca70ca56079.tar.gz
llvm-b9c1b51e45b845debb76d8658edabca70ca56079.tar.bz2
*** This commit represents a complete reformatting of the LLDB source code
*** to conform to clang-format’s LLVM style. This kind of mass change has *** two obvious implications: Firstly, merging this particular commit into a downstream fork may be a huge effort. Alternatively, it may be worth merging all changes up to this commit, performing the same reformatting operation locally, and then discarding the merge for this particular commit. The commands used to accomplish this reformatting were as follows (with current working directory as the root of the repository): find . \( -iname "*.c" -or -iname "*.cpp" -or -iname "*.h" -or -iname "*.mm" \) -exec clang-format -i {} + find . -iname "*.py" -exec autopep8 --in-place --aggressive --aggressive {} + ; The version of clang-format used was 3.9.0, and autopep8 was 1.2.4. Secondly, “blame” style tools will generally point to this commit instead of a meaningful prior commit. There are alternatives available that will attempt to look through this change and find the appropriate prior commit. YMMV. llvm-svn: 280751
Diffstat (limited to 'lldb/source/Plugins/Process/Linux')
-rw-r--r--lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp4402
-rw-r--r--lldb/source/Plugins/Process/Linux/NativeProcessLinux.h291
-rw-r--r--lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp315
-rw-r--r--lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.h105
-rw-r--r--lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp1645
-rw-r--r--lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h219
-rw-r--r--lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp1630
-rw-r--r--lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h220
-rw-r--r--lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp2148
-rw-r--r--lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h162
-rw-r--r--lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp1050
-rw-r--r--lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.h131
-rwxr-xr-xlldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp1958
-rw-r--r--lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h181
-rw-r--r--lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp759
-rw-r--r--lldb/source/Plugins/Process/Linux/NativeThreadLinux.h145
-rw-r--r--lldb/source/Plugins/Process/Linux/ProcFileReader.cpp139
-rw-r--r--lldb/source/Plugins/Process/Linux/ProcFileReader.h24
-rw-r--r--lldb/source/Plugins/Process/Linux/Procfs.h14
-rw-r--r--lldb/source/Plugins/Process/Linux/SingleStepCheck.cpp249
-rw-r--r--lldb/source/Plugins/Process/Linux/SingleStepCheck.h35
21 files changed, 7371 insertions, 8451 deletions
diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
index 4af5b6d..2510d27 100644
--- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
@@ -11,8 +11,8 @@
// C Includes
#include <errno.h>
-#include <string.h>
#include <stdint.h>
+#include <string.h>
#include <unistd.h>
// C++ Includes
@@ -42,12 +42,13 @@
#include "lldb/Utility/PseudoTerminal.h"
#include "lldb/Utility/StringExtractor.h"
-#include "Plugins/Process/POSIX/ProcessPOSIXLog.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
+// System includes - They have to be included after framework includes because
+// they define some
// macros which collide with variable names in other modules
#include <linux/unistd.h>
#include <sys/socket.h>
@@ -63,7 +64,7 @@
// Support hardware breakpoints in case it has not been defined
#ifndef TRAP_HWBKPT
- #define TRAP_HWBKPT 4
+#define TRAP_HWBKPT 4
#endif
using namespace lldb;
@@ -73,1911 +74,1907 @@ using namespace llvm;
// Private bits we only need internally.
-static bool ProcessVmReadvSupported()
-{
- static bool is_supported;
- static std::once_flag flag;
-
- std::call_once(flag, [] {
- Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
-
- uint32_t source = 0x47424742;
- uint32_t dest = 0;
-
- struct iovec local, remote;
- remote.iov_base = &source;
- local.iov_base = &dest;
- remote.iov_len = local.iov_len = sizeof source;
-
- // We shall try if cross-process-memory reads work by attempting to read a 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));
- }
- });
+static bool ProcessVmReadvSupported() {
+ static bool is_supported;
+ static std::once_flag flag;
- return is_supported;
-}
-
-namespace
-{
-void
-MaybeLogLaunchInfo(const ProcessLaunchInfo &info)
-{
+ std::call_once(flag, [] {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (!log)
- return;
-
- if (const FileAction *action = info.GetFileActionForFD(STDIN_FILENO))
- log->Printf("%s: setting STDIN to '%s'", __FUNCTION__, action->GetFileSpec().GetCString());
- else
- log->Printf("%s leaving STDIN as is", __FUNCTION__);
- if (const FileAction *action = info.GetFileActionForFD(STDOUT_FILENO))
- log->Printf("%s setting STDOUT to '%s'", __FUNCTION__, action->GetFileSpec().GetCString());
- else
- log->Printf("%s leaving STDOUT as is", __FUNCTION__);
+ uint32_t source = 0x47424742;
+ uint32_t dest = 0;
- if (const FileAction *action = info.GetFileActionForFD(STDERR_FILENO))
- log->Printf("%s setting STDERR to '%s'", __FUNCTION__, action->GetFileSpec().GetCString());
- else
- log->Printf("%s leaving STDERR as is", __FUNCTION__);
-
- int i = 0;
- for (const char **args = info.GetArguments().GetConstArgumentVector(); *args; ++args, ++i)
- log->Printf("%s arg %d: \"%s\"", __FUNCTION__, i, *args ? *args : "nullptr");
-}
+ struct iovec local, remote;
+ remote.iov_base = &source;
+ local.iov_base = &dest;
+ remote.iov_len = local.iov_len = sizeof source;
-void
-DisplayBytes(StreamString &s, void *bytes, uint32_t count)
-{
- uint8_t *ptr = (uint8_t *)bytes;
- const uint32_t loop_count = std::min<uint32_t>(DEBUG_PTRACE_MAXBYTES, count);
- for (uint32_t i = 0; i < loop_count; i++)
- {
- s.Printf("[%x]", *ptr);
- ptr++;
+ // We shall try if cross-process-memory reads work by attempting to read a
+ // 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));
}
-}
+ });
- void
- PtraceDisplayBytes(int &req, void *data, size_t data_size)
- {
- 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:
- {
- }
- }
- }
- }
+ return is_supported;
+}
- static constexpr unsigned k_ptrace_word_size = sizeof(void*);
- static_assert(sizeof(long) >= k_ptrace_word_size, "Size of long must be larger than ptrace word size");
+namespace {
+void MaybeLogLaunchInfo(const ProcessLaunchInfo &info) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (!log)
+ return;
+
+ if (const FileAction *action = info.GetFileActionForFD(STDIN_FILENO))
+ log->Printf("%s: setting STDIN to '%s'", __FUNCTION__,
+ action->GetFileSpec().GetCString());
+ else
+ log->Printf("%s leaving STDIN as is", __FUNCTION__);
+
+ if (const FileAction *action = info.GetFileActionForFD(STDOUT_FILENO))
+ log->Printf("%s setting STDOUT to '%s'", __FUNCTION__,
+ action->GetFileSpec().GetCString());
+ else
+ log->Printf("%s leaving STDOUT as is", __FUNCTION__);
+
+ if (const FileAction *action = info.GetFileActionForFD(STDERR_FILENO))
+ log->Printf("%s setting STDERR to '%s'", __FUNCTION__,
+ action->GetFileSpec().GetCString());
+ else
+ log->Printf("%s leaving STDERR as is", __FUNCTION__);
+
+ int i = 0;
+ for (const char **args = info.GetArguments().GetConstArgumentVector(); *args;
+ ++args, ++i)
+ log->Printf("%s arg %d: \"%s\"", __FUNCTION__, i,
+ *args ? *args : "nullptr");
+}
+
+void DisplayBytes(StreamString &s, void *bytes, uint32_t count) {
+ uint8_t *ptr = (uint8_t *)bytes;
+ const uint32_t loop_count = std::min<uint32_t>(DEBUG_PTRACE_MAXBYTES, count);
+ for (uint32_t i = 0; i < loop_count; i++) {
+ s.Printf("[%x]", *ptr);
+ ptr++;
+ }
+}
+
+void PtraceDisplayBytes(int &req, void *data, size_t data_size) {
+ 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: {}
+ }
+ }
+}
+
+static constexpr unsigned k_ptrace_word_size = sizeof(void *);
+static_assert(sizeof(long) >= k_ptrace_word_size,
+ "Size of long must be larger than ptrace word size");
} // end of anonymous namespace
// Simple helper function to ensure flags are enabled on the given file
// descriptor.
-static Error
-EnsureFDFlags(int fd, int flags)
-{
- Error error;
+static Error EnsureFDFlags(int fd, int flags) {
+ Error error;
- int status = fcntl(fd, F_GETFL);
- if (status == -1)
- {
- error.SetErrorToErrno();
- return error;
- }
-
- if (fcntl(fd, F_SETFL, status | flags) == -1)
- {
- error.SetErrorToErrno();
- return error;
- }
+ int status = fcntl(fd, F_GETFL);
+ if (status == -1) {
+ error.SetErrorToErrno();
+ return error;
+ }
+ if (fcntl(fd, F_SETFL, status | flags) == -1) {
+ error.SetErrorToErrno();
return error;
+ }
+
+ return error;
}
// -----------------------------------------------------------------------------
// Public Static Methods
// -----------------------------------------------------------------------------
-Error
-NativeProcessProtocol::Launch (
+Error NativeProcessProtocol::Launch(
ProcessLaunchInfo &launch_info,
- NativeProcessProtocol::NativeDelegate &native_delegate,
- MainLoop &mainloop,
- NativeProcessProtocolSP &native_process_sp)
-{
- Log *log (GetLogIfAllCategoriesSet (LIBLLDB_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))
- {
- error.SetErrorStringWithFormat ("No such file or directory: %s",
- working_dir.GetCString());
- return error;
- }
+ NativeProcessProtocol::NativeDelegate &native_delegate, MainLoop &mainloop,
+ NativeProcessProtocolSP &native_process_sp) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_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)) {
+ error.SetErrorStringWithFormat("No such file or directory: %s",
+ working_dir.GetCString());
+ return error;
+ }
- // Create the NativeProcessLinux in launch mode.
- native_process_sp.reset (new NativeProcessLinux ());
+ // Create the NativeProcessLinux in launch mode.
+ native_process_sp.reset(new NativeProcessLinux());
- if (!native_process_sp->RegisterNativeDelegate (native_delegate))
- {
- native_process_sp.reset ();
- error.SetErrorStringWithFormat ("failed to register the native delegate");
- return error;
- }
+ if (!native_process_sp->RegisterNativeDelegate(native_delegate)) {
+ native_process_sp.reset();
+ error.SetErrorStringWithFormat("failed to register the native delegate");
+ return error;
+ }
- error = std::static_pointer_cast<NativeProcessLinux>(native_process_sp)->LaunchInferior(mainloop, launch_info);
+ error = std::static_pointer_cast<NativeProcessLinux>(native_process_sp)
+ ->LaunchInferior(mainloop, launch_info);
- if (error.Fail ())
- {
- native_process_sp.reset ();
- if (log)
- log->Printf ("NativeProcessLinux::%s failed to launch process: %s", __FUNCTION__, error.AsCString ());
- return error;
- }
+ if (error.Fail()) {
+ native_process_sp.reset();
+ if (log)
+ log->Printf("NativeProcessLinux::%s failed to launch process: %s",
+ __FUNCTION__, error.AsCString());
+ return error;
+ }
- launch_info.SetProcessID (native_process_sp->GetID ());
+ launch_info.SetProcessID(native_process_sp->GetID());
- return error;
+ return error;
}
-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);
-
- // Retrieve the architecture for the running process.
- ArchSpec process_arch;
- Error error = ResolveProcessArchitecture(pid, process_arch);
- if (!error.Success ())
- return error;
+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);
- std::shared_ptr<NativeProcessLinux> native_process_linux_sp (new NativeProcessLinux ());
+ // Retrieve the architecture for the running process.
+ ArchSpec process_arch;
+ Error error = ResolveProcessArchitecture(pid, process_arch);
+ if (!error.Success())
+ return error;
- if (!native_process_linux_sp->RegisterNativeDelegate (native_delegate))
- {
- error.SetErrorStringWithFormat ("failed to register the native delegate");
- return error;
- }
+ std::shared_ptr<NativeProcessLinux> native_process_linux_sp(
+ new NativeProcessLinux());
- native_process_linux_sp->AttachToInferior (mainloop, pid, error);
- if (!error.Success ())
- return error;
+ if (!native_process_linux_sp->RegisterNativeDelegate(native_delegate)) {
+ error.SetErrorStringWithFormat("failed to register the native delegate");
+ return error;
+ }
- native_process_sp = native_process_linux_sp;
+ native_process_linux_sp->AttachToInferior(mainloop, pid, error);
+ if (!error.Success())
return error;
+
+ native_process_sp = native_process_linux_sp;
+ return error;
}
// -----------------------------------------------------------------------------
// Public Instance Methods
// -----------------------------------------------------------------------------
-NativeProcessLinux::NativeProcessLinux () :
- NativeProcessProtocol (LLDB_INVALID_PROCESS_ID),
- m_arch (),
- m_supports_mem_region (eLazyBoolCalculate),
- m_mem_region_cache (),
- m_pending_notification_tid(LLDB_INVALID_THREAD_ID)
-{
-}
-
-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);
-
- m_sigchld_handle = mainloop.RegisterSignal(SIGCHLD,
- [this] (MainLoopBase &) { SigchldHandler(); }, error);
- if (! m_sigchld_handle)
- return;
-
- error = ResolveProcessArchitecture(pid, m_arch);
- if (!error.Success())
- return;
-
- // Set the architecture to the exe architecture.
- if (log)
- log->Printf ("NativeProcessLinux::%s (pid = %" PRIi64 ") detected architecture %s", __FUNCTION__, pid, m_arch.GetArchitectureName ());
-
- m_pid = pid;
- SetState(eStateAttaching);
+NativeProcessLinux::NativeProcessLinux()
+ : NativeProcessProtocol(LLDB_INVALID_PROCESS_ID), m_arch(),
+ m_supports_mem_region(eLazyBoolCalculate), m_mem_region_cache(),
+ m_pending_notification_tid(LLDB_INVALID_THREAD_ID) {}
+
+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);
+
+ m_sigchld_handle = mainloop.RegisterSignal(
+ SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, error);
+ if (!m_sigchld_handle)
+ return;
+
+ error = ResolveProcessArchitecture(pid, m_arch);
+ if (!error.Success())
+ return;
+
+ // Set the architecture to the exe architecture.
+ if (log)
+ log->Printf("NativeProcessLinux::%s (pid = %" PRIi64
+ ") detected architecture %s",
+ __FUNCTION__, pid, m_arch.GetArchitectureName());
+
+ m_pid = pid;
+ SetState(eStateAttaching);
+
+ Attach(pid, error);
+}
+
+Error NativeProcessLinux::LaunchInferior(MainLoop &mainloop,
+ ProcessLaunchInfo &launch_info) {
+ Error error;
+ m_sigchld_handle = mainloop.RegisterSignal(
+ SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, error);
+ if (!m_sigchld_handle)
+ return error;
- Attach(pid, error);
-}
+ SetState(eStateLaunching);
-Error
-NativeProcessLinux::LaunchInferior(MainLoop &mainloop, ProcessLaunchInfo &launch_info)
-{
- Error error;
- m_sigchld_handle = mainloop.RegisterSignal(SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, error);
- if (!m_sigchld_handle)
- return error;
+ MaybeLogLaunchInfo(launch_info);
- SetState(eStateLaunching);
+ ::pid_t pid =
+ ProcessLauncherLinux().LaunchProcess(launch_info, error).GetProcessId();
+ if (error.Fail())
+ return error;
- MaybeLogLaunchInfo(launch_info);
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- ::pid_t pid = ProcessLauncherLinux().LaunchProcess(launch_info, error).GetProcessId();
- if (error.Fail())
- return error;
+ // 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());
- Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
+ // Mark the inferior as invalid.
+ // FIXME this could really use a new state - eStateLaunchFailure. For now,
+ // using eStateInvalid.
+ SetState(StateType::eStateInvalid);
- // 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 ());
+ return error;
+ }
+ assert(WIFSTOPPED(status) && (wpid == static_cast<::pid_t>(pid)) &&
+ "Could not sync with inferior process.");
- // Mark the inferior as invalid.
- // FIXME this could really use a new state - eStateLaunchFailure. For now, using eStateInvalid.
- SetState (StateType::eStateInvalid);
-
- return error;
- }
- 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__);
+ error = SetDefaultPtraceOpts(pid);
+ if (error.Fail()) {
if (log)
- log->Printf ("NativeProcessLinux::%s inferior started, now in stopped state", __FUNCTION__);
+ log->Printf("NativeProcessLinux::%s inferior failed to set default "
+ "ptrace options: %s",
+ __FUNCTION__, error.AsCString());
- error = SetDefaultPtraceOpts(pid);
- if (error.Fail())
- {
- if (log)
- log->Printf ("NativeProcessLinux::%s inferior failed to set default ptrace options: %s",
- __FUNCTION__, error.AsCString ());
+ // Mark the inferior as invalid.
+ // FIXME this could really use a new state - eStateLaunchFailure. For now,
+ // using eStateInvalid.
+ SetState(StateType::eStateInvalid);
- // Mark the inferior as invalid.
- // FIXME this could really use a new state - eStateLaunchFailure. For now, using eStateInvalid.
- SetState (StateType::eStateInvalid);
+ return error;
+ }
+
+ // Release the master terminal descriptor and pass it off to the
+ // NativeProcessLinux instance. Similarly stash the inferior pid.
+ m_terminal_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor();
+ m_pid = pid;
+ launch_info.SetProcessID(pid);
+
+ 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());
- return error;
+ // Mark the inferior as invalid.
+ // FIXME this could really use a new state - eStateLaunchFailure. For
+ // now, using eStateInvalid.
+ SetState(StateType::eStateInvalid);
+
+ return error;
}
+ }
- // Release the master terminal descriptor and pass it off to the
- // NativeProcessLinux instance. Similarly stash the inferior pid.
- m_terminal_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor();
- m_pid = pid;
- launch_info.SetProcessID(pid);
+ if (log)
+ log->Printf("NativeProcessLinux::%s() adding pid = %" PRIu64, __FUNCTION__,
+ uint64_t(pid));
- 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());
+ ResolveProcessArchitecture(m_pid, m_arch);
+ NativeThreadLinuxSP thread_sp = AddThread(pid);
+ assert(thread_sp && "AddThread() returned a nullptr thread");
+ thread_sp->SetStoppedBySignal(SIGSTOP);
+ ThreadWasCreated(*thread_sp);
- // Mark the inferior as invalid.
- // FIXME this could really use a new state - eStateLaunchFailure. For now, using eStateInvalid.
- SetState(StateType::eStateInvalid);
+ // Let our process instance know the thread has stopped.
+ SetCurrentThreadID(thread_sp->GetID());
+ SetState(StateType::eStateStopped);
- return error;
+ 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());
+ }
+ return error;
+}
+
+::pid_t NativeProcessLinux::Attach(lldb::pid_t pid, Error &error) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ // Use a map to keep track of the threads which we have attached/need to
+ // attach.
+ Host::TidMap tids_to_attach;
+ if (pid <= 1) {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Attaching to process 1 is not allowed.");
+ return -1;
+ }
+
+ while (Host::FindProcessThreads(pid, tids_to_attach)) {
+ for (Host::TidMap::iterator it = tids_to_attach.begin();
+ it != tids_to_attach.end();) {
+ if (it->second == false) {
+ lldb::tid_t tid = it->first;
+
+ // Attach to the requested process.
+ // An attach will cause the thread to stop with a SIGSTOP.
+ error = PtraceWrapper(PTRACE_ATTACH, tid);
+ if (error.Fail()) {
+ // No such thread. The thread may have exited.
+ // More error handling may be needed.
+ if (error.GetError() == ESRCH) {
+ it = tids_to_attach.erase(it);
+ continue;
+ } else
+ return -1;
}
- }
- if (log)
- log->Printf("NativeProcessLinux::%s() adding pid = %" PRIu64, __FUNCTION__, uint64_t(pid));
+ int status;
+ // Need to use __WALL otherwise we receive an error with errno=ECHLD
+ // At this point we should have a thread stopped if waitpid succeeds.
+ if ((status = waitpid(tid, NULL, __WALL)) < 0) {
+ // No such thread. The thread may have exited.
+ // More error handling may be needed.
+ if (errno == ESRCH) {
+ it = tids_to_attach.erase(it);
+ continue;
+ } else {
+ error.SetErrorToErrno();
+ return -1;
+ }
+ }
- ResolveProcessArchitecture(m_pid, m_arch);
- NativeThreadLinuxSP thread_sp = AddThread(pid);
- assert (thread_sp && "AddThread() returned a nullptr thread");
- thread_sp->SetStoppedBySignal(SIGSTOP);
- ThreadWasCreated(*thread_sp);
+ error = SetDefaultPtraceOpts(tid);
+ if (error.Fail())
+ return -1;
- // Let our process instance know the thread has stopped.
- SetCurrentThreadID (thread_sp->GetID ());
- SetState (StateType::eStateStopped);
+ if (log)
+ log->Printf("NativeProcessLinux::%s() adding tid = %" PRIu64,
+ __FUNCTION__, tid);
- 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());
- }
- return error;
-}
+ it->second = true;
-::pid_t
-NativeProcessLinux::Attach(lldb::pid_t pid, Error &error)
-{
- Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
+ // Create the thread, mark it as stopped.
+ NativeThreadLinuxSP thread_sp(AddThread(static_cast<lldb::tid_t>(tid)));
+ assert(thread_sp && "AddThread() returned a nullptr");
- // Use a map to keep track of the threads which we have attached/need to attach.
- Host::TidMap tids_to_attach;
- if (pid <= 1)
- {
- error.SetErrorToGenericError();
- error.SetErrorString("Attaching to process 1 is not allowed.");
- return -1;
- }
+ // This will notify this is a new thread and tell the system it is
+ // stopped.
+ thread_sp->SetStoppedBySignal(SIGSTOP);
+ ThreadWasCreated(*thread_sp);
+ SetCurrentThreadID(thread_sp->GetID());
+ }
- while (Host::FindProcessThreads(pid, tids_to_attach))
- {
- for (Host::TidMap::iterator it = tids_to_attach.begin();
- it != tids_to_attach.end();)
- {
- if (it->second == false)
- {
- lldb::tid_t tid = it->first;
-
- // Attach to the requested process.
- // An attach will cause the thread to stop with a SIGSTOP.
- error = PtraceWrapper(PTRACE_ATTACH, tid);
- if (error.Fail())
- {
- // No such thread. The thread may have exited.
- // More error handling may be needed.
- if (error.GetError() == ESRCH)
- {
- it = tids_to_attach.erase(it);
- continue;
- }
- else
- return -1;
- }
-
- int status;
- // Need to use __WALL otherwise we receive an error with errno=ECHLD
- // At this point we should have a thread stopped if waitpid succeeds.
- if ((status = waitpid(tid, NULL, __WALL)) < 0)
- {
- // No such thread. The thread may have exited.
- // More error handling may be needed.
- if (errno == ESRCH)
- {
- it = tids_to_attach.erase(it);
- continue;
- }
- else
- {
- error.SetErrorToErrno();
- return -1;
- }
- }
-
- error = SetDefaultPtraceOpts(tid);
- if (error.Fail())
- return -1;
-
- if (log)
- log->Printf ("NativeProcessLinux::%s() adding tid = %" PRIu64, __FUNCTION__, tid);
-
- it->second = true;
-
- // Create the thread, mark it as stopped.
- NativeThreadLinuxSP thread_sp (AddThread(static_cast<lldb::tid_t>(tid)));
- assert (thread_sp && "AddThread() returned a nullptr");
-
- // This will notify this is a new thread and tell the system it is stopped.
- thread_sp->SetStoppedBySignal(SIGSTOP);
- ThreadWasCreated(*thread_sp);
- SetCurrentThreadID (thread_sp->GetID ());
- }
-
- // move the loop forward
- ++it;
- }
+ // move the loop forward
+ ++it;
}
+ }
- if (tids_to_attach.size() > 0)
- {
- m_pid = pid;
- // Let our process instance know the thread has stopped.
- SetState (StateType::eStateStopped);
- }
- else
- {
- error.SetErrorToGenericError();
- error.SetErrorString("No such process.");
- return -1;
- }
+ if (tids_to_attach.size() > 0) {
+ m_pid = pid;
+ // Let our process instance know the thread has stopped.
+ SetState(StateType::eStateStopped);
+ } else {
+ error.SetErrorToGenericError();
+ error.SetErrorString("No such process.");
+ return -1;
+ }
- return pid;
+ return pid;
}
-Error
-NativeProcessLinux::SetDefaultPtraceOpts(lldb::pid_t pid)
-{
- long ptrace_opts = 0;
+Error NativeProcessLinux::SetDefaultPtraceOpts(lldb::pid_t pid) {
+ long ptrace_opts = 0;
- // Have the child raise an event on exit. This is used to keep the child in
- // limbo until it is destroyed.
- ptrace_opts |= PTRACE_O_TRACEEXIT;
+ // Have the child raise an event on exit. This is used to keep the child in
+ // limbo until it is destroyed.
+ ptrace_opts |= PTRACE_O_TRACEEXIT;
- // Have the tracer trace threads which spawn in the inferior process.
- // TODO: if we want to support tracing the inferiors' child, add the
- // appropriate ptrace flags here (PTRACE_O_TRACEFORK, PTRACE_O_TRACEVFORK)
- ptrace_opts |= PTRACE_O_TRACECLONE;
+ // Have the tracer trace threads which spawn in the inferior process.
+ // TODO: if we want to support tracing the inferiors' child, add the
+ // appropriate ptrace flags here (PTRACE_O_TRACEFORK, PTRACE_O_TRACEVFORK)
+ ptrace_opts |= PTRACE_O_TRACECLONE;
- // Have the tracer notify us before execve returns
- // (needed to disable legacy SIGTRAP generation)
- ptrace_opts |= PTRACE_O_TRACEEXEC;
+ // Have the tracer notify us before execve returns
+ // (needed to disable legacy SIGTRAP generation)
+ ptrace_opts |= PTRACE_O_TRACEEXEC;
- return PtraceWrapper(PTRACE_SETOPTIONS, pid, nullptr, (void*)ptrace_opts);
+ return PtraceWrapper(PTRACE_SETOPTIONS, pid, nullptr, (void *)ptrace_opts);
}
-static ExitType convert_pid_status_to_exit_type (int status)
-{
- if (WIFEXITED (status))
- return ExitType::eExitTypeExit;
- else if (WIFSIGNALED (status))
- return ExitType::eExitTypeSignal;
- else if (WIFSTOPPED (status))
- return ExitType::eExitTypeStop;
- else
- {
- // We don't know what this is.
- return ExitType::eExitTypeInvalid;
- }
+static ExitType convert_pid_status_to_exit_type(int status) {
+ if (WIFEXITED(status))
+ return ExitType::eExitTypeExit;
+ else if (WIFSIGNALED(status))
+ return ExitType::eExitTypeSignal;
+ else if (WIFSTOPPED(status))
+ return ExitType::eExitTypeStop;
+ else {
+ // We don't know what this is.
+ return ExitType::eExitTypeInvalid;
+ }
}
-static int convert_pid_status_to_return_code (int status)
-{
- if (WIFEXITED (status))
- return WEXITSTATUS (status);
- else if (WIFSIGNALED (status))
- return WTERMSIG (status);
- else if (WIFSTOPPED (status))
- return WSTOPSIG (status);
- else
- {
- // We don't know what this is.
- return ExitType::eExitTypeInvalid;
- }
+static int convert_pid_status_to_return_code(int status) {
+ if (WIFEXITED(status))
+ return WEXITSTATUS(status);
+ else if (WIFSIGNALED(status))
+ return WTERMSIG(status);
+ else if (WIFSTOPPED(status))
+ return WSTOPSIG(status);
+ else {
+ // We don't know what this is.
+ return ExitType::eExitTypeInvalid;
+ }
}
// Handles all waitpid events from the inferior process.
-void
-NativeProcessLinux::MonitorCallback(lldb::pid_t pid,
- bool exited,
- int signal,
- int status)
-{
- Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS));
+void NativeProcessLinux::MonitorCallback(lldb::pid_t pid, bool exited,
+ int signal, int status) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
- // Certain activities differ based on whether the pid is the tid of the main thread.
- const bool is_main_thread = (pid == GetID ());
+ // Certain activities differ based on whether the pid is the tid of the main
+ // thread.
+ const bool is_main_thread = (pid == GetID());
- // Handle when the thread exits.
- if (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");
+
+ // This is a thread that exited. Ensure we're not tracking it anymore.
+ const bool thread_found = StopTrackingThread(pid);
+
+ if (is_main_thread) {
+ // We only set the exit status and notify the delegate if we haven't
+ // already set the process
+ // state to an exited state. We normally should have received a SIGTRAP |
+ // (PTRACE_EVENT_EXIT << 8)
+ // for the main thread.
+ const bool already_notified = (GetState() == StateType::eStateExited) ||
+ (GetState() == StateType::eStateCrashed);
+ if (!already_notified) {
if (log)
- log->Printf ("NativeProcessLinux::%s() got exit signal(%d) , tid = %" PRIu64 " (%s main thread)", __FUNCTION__, 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);
-
- if (is_main_thread)
- {
- // We only set the exit status and notify the delegate if we haven't already set the process
- // state to an exited state. We normally should have received a SIGTRAP | (PTRACE_EVENT_EXIT << 8)
- // for the main thread.
- 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 ()));
- // 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
- {
- // 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");
- }
- return;
- }
-
- siginfo_t info;
- const auto info_err = GetSignalInfo(pid, &info);
- auto thread_sp = GetThreadByID(pid);
-
- 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
+ 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()));
+ // 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 received notification about an unknown tid %" PRIu64 ".", __FUNCTION__, pid);
-
- if (info_err.Fail())
- {
- if (log)
- log->Printf("NativeProcessLinux::%s (tid %" PRIu64 ") GetSignalInfo failed (%s). Ingoring this notification.", __FUNCTION__, pid, info_err.AsCString());
- 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);
-
- auto thread_sp = AddThread(pid);
- // Resume the newly created thread.
- ResumeThread(*thread_sp, eStateRunning, LLDB_INVALID_SIGNAL_NUMBER);
- ThreadWasCreated(*thread_sp);
- return;
- }
-
- // Get details on the signal raised.
- if (info_err.Success())
- {
- // We have retrieved the signal info. Dispatch appropriately.
- if (info.si_signo == SIGTRAP)
- MonitorSIGTRAP(info, *thread_sp);
- else
- MonitorSignal(info, *thread_sp, exited);
- }
+ log->Printf("NativeProcessLinux::%s() tid = %" PRIu64
+ " main thread now exited (%s)",
+ __FUNCTION__, 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");
+ }
+ return;
+ }
+
+ siginfo_t info;
+ const auto info_err = GetSignalInfo(pid, &info);
+ auto thread_sp = GetThreadByID(pid);
+
+ 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);
+
+ if (info_err.Fail()) {
+ if (log)
+ log->Printf("NativeProcessLinux::%s (tid %" PRIu64
+ ") GetSignalInfo failed (%s). Ingoring this notification.",
+ __FUNCTION__, pid, info_err.AsCString());
+ 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);
+
+ auto thread_sp = AddThread(pid);
+ // Resume the newly created thread.
+ ResumeThread(*thread_sp, eStateRunning, LLDB_INVALID_SIGNAL_NUMBER);
+ ThreadWasCreated(*thread_sp);
+ return;
+ }
+
+ // Get details on the signal raised.
+ if (info_err.Success()) {
+ // We have retrieved the signal info. Dispatch appropriately.
+ if (info.si_signo == SIGTRAP)
+ MonitorSIGTRAP(info, *thread_sp);
else
- {
- 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
- // 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);
- 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.
-
- // 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");
-
- if (is_main_thread)
- {
- // Notify the delegate - our process is not available but appears to have been killed outside
- // our control. Is eStateExited the right exit state in this case?
- SetExitStatus (convert_pid_status_to_exit_type (status), convert_pid_status_to_return_code (status), nullptr, true);
- SetState (StateType::eStateExited, true);
- }
- 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);
- }
- }
- }
-}
-
-void
-NativeProcessLinux::WaitForNewThread(::pid_t tid)
-{
- Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
-
- NativeThreadLinuxSP new_thread_sp = GetThreadByID(tid);
-
- if (new_thread_sp)
- {
- // We are already tracking the thread - we got the event on the new thread (see
- // MonitorSignal) before this one. We are done.
- return;
- }
-
- // The thread is not tracked yet, let's wait for it to appear.
- 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);
- 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.
- 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);
- // 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);
- // Also a very improbable event.
- return;
- }
-
- siginfo_t info;
- Error error = GetSignalInfo(tid, &info);
- if (error.Fail())
- {
+ MonitorSignal(info, *thread_sp, exited);
+ } else {
+ 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
+ // 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);
+ 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.
+
+ // 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");
+
+ if (is_main_thread) {
+ // Notify the delegate - our process is not available but appears to
+ // have been killed outside
+ // our control. Is eStateExited the right exit state in this case?
+ SetExitStatus(convert_pid_status_to_exit_type(status),
+ convert_pid_status_to_return_code(status), nullptr, true);
+ SetState(StateType::eStateExited, true);
+ } 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() GetSignalInfo for tid %" PRIu32 " failed. Assuming the thread has disappeared in the meantime.", __FUNCTION__, tid);
- return;
+ 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);
+ }
}
-
- 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);
-
- new_thread_sp = AddThread(tid);
- ResumeThread(*new_thread_sp, eStateRunning, LLDB_INVALID_SIGNAL_NUMBER);
- ThreadWasCreated(*new_thread_sp);
+ }
}
-void
-NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, NativeThreadLinux &thread)
-{
- Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
- const bool is_main_thread = (thread.GetID() == GetID ());
+void NativeProcessLinux::WaitForNewThread(::pid_t tid) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- assert(info.si_signo == SIGTRAP && "Unexpected child signal!");
+ NativeThreadLinuxSP new_thread_sp = GetThreadByID(tid);
- switch (info.si_code)
- {
- // TODO: these two cases are required if we want to support tracing of the inferiors' children. We'd need this to debug a monitor.
- // case (SIGTRAP | (PTRACE_EVENT_FORK << 8)):
- // case (SIGTRAP | (PTRACE_EVENT_VFORK << 8)):
+ if (new_thread_sp) {
+ // We are already tracking the thread - we got the event on the new thread
+ // (see
+ // MonitorSignal) before this one. We are done.
+ return;
+ }
- case (SIGTRAP | (PTRACE_EVENT_CLONE << 8)):
- {
- // This is the notification on the parent thread which informs us of new thread
- // creation.
- // We don't want to do anything with the parent thread so we just resume it. In case we
- // want to implement "break on thread creation" functionality, we would need to stop
- // here.
-
- 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());
- } else
- WaitForNewThread(event_message);
+ // The thread is not tracked yet, let's wait for it to appear.
+ 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);
+ 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.
+ 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);
+ // 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);
+ // 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);
+
+ new_thread_sp = AddThread(tid);
+ ResumeThread(*new_thread_sp, eStateRunning, LLDB_INVALID_SIGNAL_NUMBER);
+ ThreadWasCreated(*new_thread_sp);
+}
+
+void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info,
+ NativeThreadLinux &thread) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ const bool is_main_thread = (thread.GetID() == GetID());
+
+ assert(info.si_signo == SIGTRAP && "Unexpected child signal!");
+
+ switch (info.si_code) {
+ // TODO: these two cases are required if we want to support tracing of the
+ // inferiors' children. We'd need this to debug a monitor.
+ // case (SIGTRAP | (PTRACE_EVENT_FORK << 8)):
+ // case (SIGTRAP | (PTRACE_EVENT_VFORK << 8)):
+
+ case (SIGTRAP | (PTRACE_EVENT_CLONE << 8)): {
+ // This is the notification on the parent thread which informs us of new
+ // thread
+ // creation.
+ // We don't want to do anything with the parent thread so we just resume it.
+ // In case we
+ // want to implement "break on thread creation" functionality, we would need
+ // to stop
+ // here.
+
+ 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());
+ } else
+ WaitForNewThread(event_message);
+
+ ResumeThread(thread, thread.GetState(), LLDB_INVALID_SIGNAL_NUMBER);
+ break;
+ }
+
+ 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);
- ResumeThread(thread, thread.GetState(), LLDB_INVALID_SIGNAL_NUMBER);
- break;
- }
+ // Exec clears any pending notifications.
+ m_pending_notification_tid = LLDB_INVALID_THREAD_ID;
- case (SIGTRAP | (PTRACE_EVENT_EXEC << 8)):
- {
- NativeThreadLinuxSP main_thread_sp;
+ // 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__);
+
+ 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() received exec event, code = %d", __FUNCTION__, 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.
+ log->Printf(
+ "NativeProcessLinux::%s found main thread with tid %" PRIu64
+ ", keeping",
+ __FUNCTION__, main_thread_sp->GetID());
+ } else {
if (log)
- log->Printf ("NativeProcessLinux::%s exec received, stop tracking all but main thread", __FUNCTION__);
-
- 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 ());
- }
- else
- {
- if (log)
- log->Printf ("NativeProcessLinux::%s discarding non-main-thread tid %" PRIu64 " due to exec", __FUNCTION__, thread_sp->GetID ());
- }
- }
-
- m_threads.clear ();
-
- if (main_thread_sp)
- {
- m_threads.push_back (main_thread_sp);
- SetCurrentThreadID (main_thread_sp->GetID ());
- 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 ());
- }
-
- // Tell coordinator about about the "new" (since exec) stopped main thread.
- ThreadWasCreated(*main_thread_sp);
-
- // Let our delegate know we have just exec'd.
- NotifyDidExec ();
-
- // If we have a main thread, indicate we are stopped.
- assert (main_thread_sp && "exec called during ptraced process but no main thread metadata tracked");
-
- // Let the process know we're stopped.
- StopRunningThreads(main_thread_sp->GetID());
-
- break;
- }
-
- case (SIGTRAP | (PTRACE_EVENT_EXIT << 8)):
- {
- // The inferior process or one of its threads is about to exit.
- // We don't want to do anything with the thread so we just resume it. In case we
- // want to implement "break on thread exit" functionality, we would need to stop
- // here.
-
- unsigned long data = 0;
- 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");
- }
-
- if (is_main_thread)
- {
- SetExitStatus (convert_pid_status_to_exit_type (data), convert_pid_status_to_return_code (data), nullptr, true);
- }
-
- StateType state = thread.GetState();
- if (! StateIsRunningState(state))
- {
- // Due to a kernel bug, we may sometimes get this stop after the inferior gets a
- // SIGKILL. This confuses our state tracking logic in ResumeThread(), since normally,
- // we should not be receiving any ptrace events while the inferior is stopped. This
- // makes sure that the inferior is resumed and exits normally.
- state = eStateRunning;
- }
- ResumeThread(thread, state, LLDB_INVALID_SIGNAL_NUMBER);
-
- break;
+ log->Printf(
+ "NativeProcessLinux::%s discarding non-main-thread tid %" PRIu64
+ " due to exec",
+ __FUNCTION__, thread_sp->GetID());
+ }
}
- case 0:
- case TRAP_TRACE: // We receive this on single stepping.
- case TRAP_HWBKPT: // We receive this on watchpoint hit
- {
- // If a watchpoint was hit, report it
- 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 (wp_index != LLDB_INVALID_INDEX32)
- {
- MonitorWatchpoint(thread, wp_index);
- break;
- }
-
- // Otherwise, report step over
- MonitorTrace(thread);
- break;
- }
+ m_threads.clear();
- case SI_KERNEL:
+ if (main_thread_sp) {
+ m_threads.push_back(main_thread_sp);
+ SetCurrentThreadID(main_thread_sp->GetID());
+ 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());
+ }
+
+ // Tell coordinator about about the "new" (since exec) stopped main thread.
+ ThreadWasCreated(*main_thread_sp);
+
+ // Let our delegate know we have just exec'd.
+ NotifyDidExec();
+
+ // If we have a main thread, indicate we are stopped.
+ assert(main_thread_sp && "exec called during ptraced process but no main "
+ "thread metadata tracked");
+
+ // Let the process know we're stopped.
+ StopRunningThreads(main_thread_sp->GetID());
+
+ break;
+ }
+
+ case (SIGTRAP | (PTRACE_EVENT_EXIT << 8)): {
+ // The inferior process or one of its threads is about to exit.
+ // We don't want to do anything with the thread so we just resume it. In
+ // case we
+ // want to implement "break on thread exit" functionality, we would need to
+ // stop
+ // here.
+
+ unsigned long data = 0;
+ 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");
+ }
+
+ if (is_main_thread) {
+ SetExitStatus(convert_pid_status_to_exit_type(data),
+ convert_pid_status_to_return_code(data), nullptr, true);
+ }
+
+ StateType state = thread.GetState();
+ if (!StateIsRunningState(state)) {
+ // Due to a kernel bug, we may sometimes get this stop after the inferior
+ // gets a
+ // SIGKILL. This confuses our state tracking logic in ResumeThread(),
+ // since normally,
+ // we should not be receiving any ptrace events while the inferior is
+ // stopped. This
+ // makes sure that the inferior is resumed and exits normally.
+ state = eStateRunning;
+ }
+ ResumeThread(thread, state, LLDB_INVALID_SIGNAL_NUMBER);
+
+ break;
+ }
+
+ case 0:
+ case TRAP_TRACE: // We receive this on single stepping.
+ case TRAP_HWBKPT: // We receive this on watchpoint hit
+ {
+ // If a watchpoint was hit, report it
+ 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 (wp_index != LLDB_INVALID_INDEX32) {
+ MonitorWatchpoint(thread, wp_index);
+ break;
+ }
+
+ // Otherwise, report step over
+ MonitorTrace(thread);
+ break;
+ }
+
+ case SI_KERNEL:
#if defined __mips__
- // For mips there is no special signal for watchpoint
- // So we check for watchpoint in kernel trap
- {
- // If a watchpoint was hit, report it
- 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 (wp_index != LLDB_INVALID_INDEX32)
- {
- MonitorWatchpoint(thread, wp_index);
- break;
- }
+ // For mips there is no special signal for watchpoint
+ // So we check for watchpoint in kernel trap
+ {
+ // If a watchpoint was hit, report it
+ 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 (wp_index != LLDB_INVALID_INDEX32) {
+ MonitorWatchpoint(thread, wp_index);
+ break;
+ }
}
- // NO BREAK
+// NO BREAK
#endif
- case TRAP_BRKPT:
- MonitorBreakpoint(thread);
- break;
-
- 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());
+ case TRAP_BRKPT:
+ MonitorBreakpoint(thread);
+ break;
- // Ignore these signals until we know more about them.
- ResumeThread(thread, thread.GetState(), LLDB_INVALID_SIGNAL_NUMBER);
- break;
+ 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());
- 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);
- break;
-
- }
-}
+ // Ignore these signals until we know more about them.
+ ResumeThread(thread, thread.GetState(), LLDB_INVALID_SIGNAL_NUMBER);
+ break;
-void
-NativeProcessLinux::MonitorTrace(NativeThreadLinux &thread)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ default:
+ assert(false && "Unexpected SIGTRAP code!");
if (log)
- log->Printf("NativeProcessLinux::%s() received trace event, pid = %" PRIu64 " (single stepping)",
+ log->Printf("NativeProcessLinux::%s() pid %" PRIu64 "tid %" PRIu64
+ " received unhandled SIGTRAP code: 0x%d",
+ __FUNCTION__, GetID(), thread.GetID(), info.si_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());
- // This thread is currently stopped.
- thread.SetStoppedByTrace();
+ // This thread is currently stopped.
+ thread.SetStoppedByTrace();
- StopRunningThreads(thread.GetID());
+ StopRunningThreads(thread.GetID());
}
-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());
+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());
- // 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());
+ // 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());
- if (m_threads_stepping_with_breakpoint.find(thread.GetID()) != m_threads_stepping_with_breakpoint.end())
- thread.SetStoppedByTrace();
+ if (m_threads_stepping_with_breakpoint.find(thread.GetID()) !=
+ m_threads_stepping_with_breakpoint.end())
+ thread.SetStoppedByTrace();
- StopRunningThreads(thread.GetID());
+ StopRunningThreads(thread.GetID());
}
-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);
+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);
- // Mark the thread as stopped at watchpoint.
- // The address is at (lldb::addr_t)info->si_addr if we need it.
- thread.SetStoppedByWatchpoint(wp_index);
+ // Mark the thread as stopped at watchpoint.
+ // The address is at (lldb::addr_t)info->si_addr if we need it.
+ thread.SetStoppedByWatchpoint(wp_index);
- // We need to tell all other running threads before we notify the delegate about this stop.
- StopRunningThreads(thread.GetID());
+ // We need to tell all other running threads before we notify the delegate
+ // about this stop.
+ StopRunningThreads(thread.GetID());
}
-void
-NativeProcessLinux::MonitorSignal(const siginfo_t &info, NativeThreadLinux &thread, bool exited)
-{
- const int signo = info.si_signo;
- const bool is_from_llgs = info.si_pid == getpid ();
-
- Log *log (GetLogIfAllCategoriesSet (LIBLLDB_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
- // kill(2) or raise(3). Similarly for tgkill(2) on Linux.
- //
- // IOW, user generated signals never generate what we consider to be a
- // "crash".
- //
- // 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());
- }
+void NativeProcessLinux::MonitorSignal(const siginfo_t &info,
+ NativeThreadLinux &thread, bool exited) {
+ const int signo = info.si_signo;
+ const bool is_from_llgs = info.si_pid == getpid();
- // 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());
-
- // 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.
- 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.
- if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID)
- {
- if (m_pending_notification_tid == thread.GetID())
- thread.SetStoppedBySignal(SIGSTOP, &info);
- else
- thread.SetStoppedWithNoReason();
-
- SetCurrentThreadID (thread.GetID ());
- SignalIfAllThreadsStopped();
- }
- else
- {
- // 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());
- }
- }
- }
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_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
+ // kill(2) or raise(3). Similarly for tgkill(2) on Linux.
+ //
+ // IOW, user generated signals never generate what we consider to be a
+ // "crash".
+ //
+ // 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());
+ }
+
+ // 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());
+
+ // 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.
+ 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.
+ if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID) {
+ if (m_pending_notification_tid == thread.GetID())
+ thread.SetStoppedBySignal(SIGSTOP, &info);
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);
- }
- SignalIfAllThreadsStopped();
+ thread.SetStoppedWithNoReason();
+
+ SetCurrentThreadID(thread.GetID());
+ SignalIfAllThreadsStopped();
+ } else {
+ // 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());
}
+ }
+ } 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>";
- // Done handling.
- return;
+ 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);
+ }
+ SignalIfAllThreadsStopped();
}
- if (log)
- log->Printf ("NativeProcessLinux::%s() received signal %s", __FUNCTION__, Host::GetSignalAsCString(signo));
+ // Done handling.
+ return;
+ }
- // This thread is stopped.
- thread.SetStoppedBySignal(signo, &info);
+ if (log)
+ log->Printf("NativeProcessLinux::%s() received signal %s", __FUNCTION__,
+ Host::GetSignalAsCString(signo));
- // Send a stop to the debugger after we get all other threads to stop.
- StopRunningThreads(thread.GetID());
+ // This thread is stopped.
+ thread.SetStoppedBySignal(signo, &info);
+
+ // Send a stop to the debugger after we get all other threads to stop.
+ StopRunningThreads(thread.GetID());
}
namespace {
-struct EmulatorBaton
-{
- NativeProcessLinux* m_process;
- NativeRegisterContext* m_reg_context;
+struct EmulatorBaton {
+ NativeProcessLinux *m_process;
+ NativeRegisterContext *m_reg_context;
- // eRegisterKindDWARF -> RegsiterValue
- std::unordered_map<uint32_t, RegisterValue> m_register_values;
+ // eRegisterKindDWARF -> RegsiterValue
+ std::unordered_map<uint32_t, RegisterValue> m_register_values;
- EmulatorBaton(NativeProcessLinux* process, NativeRegisterContext* reg_context) :
- m_process(process), m_reg_context(reg_context) {}
+ EmulatorBaton(NativeProcessLinux *process, NativeRegisterContext *reg_context)
+ : m_process(process), m_reg_context(reg_context) {}
};
} // anonymous namespace
-static size_t
-ReadMemoryCallback (EmulateInstruction *instruction,
- void *baton,
- const EmulateInstruction::Context &context,
- lldb::addr_t addr,
- void *dst,
- size_t length)
-{
- EmulatorBaton* emulator_baton = static_cast<EmulatorBaton*>(baton);
+static size_t ReadMemoryCallback(EmulateInstruction *instruction, void *baton,
+ const EmulateInstruction::Context &context,
+ lldb::addr_t addr, void *dst, size_t length) {
+ EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);
- size_t bytes_read;
- emulator_baton->m_process->ReadMemory(addr, dst, length, bytes_read);
- return bytes_read;
+ size_t bytes_read;
+ emulator_baton->m_process->ReadMemory(addr, dst, length, bytes_read);
+ return bytes_read;
}
-static bool
-ReadRegisterCallback (EmulateInstruction *instruction,
- void *baton,
- const RegisterInfo *reg_info,
- RegisterValue &reg_value)
-{
- EmulatorBaton* emulator_baton = static_cast<EmulatorBaton*>(baton);
-
- auto it = emulator_baton->m_register_values.find(reg_info->kinds[eRegisterKindDWARF]);
- if (it != emulator_baton->m_register_values.end())
- {
- reg_value = it->second;
- return true;
- }
+static bool ReadRegisterCallback(EmulateInstruction *instruction, void *baton,
+ const RegisterInfo *reg_info,
+ RegisterValue &reg_value) {
+ EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);
- // The emulator only fill in the dwarf regsiter numbers (and in some case
- // the generic register numbers). Get the full register info from the
- // register context based on the dwarf register numbers.
- const RegisterInfo* full_reg_info = emulator_baton->m_reg_context->GetRegisterInfo(
- eRegisterKindDWARF, reg_info->kinds[eRegisterKindDWARF]);
-
- Error error = emulator_baton->m_reg_context->ReadRegister(full_reg_info, reg_value);
- if (error.Success())
- return true;
+ auto it = emulator_baton->m_register_values.find(
+ reg_info->kinds[eRegisterKindDWARF]);
+ if (it != emulator_baton->m_register_values.end()) {
+ reg_value = it->second;
+ return true;
+ }
+
+ // The emulator only fill in the dwarf regsiter numbers (and in some case
+ // the generic register numbers). Get the full register info from the
+ // register context based on the dwarf register numbers.
+ const RegisterInfo *full_reg_info =
+ emulator_baton->m_reg_context->GetRegisterInfo(
+ eRegisterKindDWARF, reg_info->kinds[eRegisterKindDWARF]);
+
+ Error error =
+ emulator_baton->m_reg_context->ReadRegister(full_reg_info, reg_value);
+ if (error.Success())
+ return true;
- return false;
+ return false;
}
-static bool
-WriteRegisterCallback (EmulateInstruction *instruction,
- void *baton,
- const EmulateInstruction::Context &context,
- const RegisterInfo *reg_info,
- const RegisterValue &reg_value)
-{
- EmulatorBaton* emulator_baton = static_cast<EmulatorBaton*>(baton);
- emulator_baton->m_register_values[reg_info->kinds[eRegisterKindDWARF]] = reg_value;
- return true;
+static bool WriteRegisterCallback(EmulateInstruction *instruction, void *baton,
+ const EmulateInstruction::Context &context,
+ const RegisterInfo *reg_info,
+ const RegisterValue &reg_value) {
+ EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);
+ emulator_baton->m_register_values[reg_info->kinds[eRegisterKindDWARF]] =
+ reg_value;
+ return true;
}
-static size_t
-WriteMemoryCallback (EmulateInstruction *instruction,
- void *baton,
- const EmulateInstruction::Context &context,
- lldb::addr_t addr,
- const void *dst,
- size_t length)
-{
- return length;
+static size_t WriteMemoryCallback(EmulateInstruction *instruction, void *baton,
+ const EmulateInstruction::Context &context,
+ lldb::addr_t addr, const void *dst,
+ size_t length) {
+ return length;
}
-static lldb::addr_t
-ReadFlags (NativeRegisterContext* regsiter_context)
-{
- const RegisterInfo* flags_info = regsiter_context->GetRegisterInfo(
- eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
- return regsiter_context->ReadRegisterAsUnsigned(flags_info, LLDB_INVALID_ADDRESS);
+static lldb::addr_t ReadFlags(NativeRegisterContext *regsiter_context) {
+ const RegisterInfo *flags_info = regsiter_context->GetRegisterInfo(
+ eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
+ return regsiter_context->ReadRegisterAsUnsigned(flags_info,
+ LLDB_INVALID_ADDRESS);
}
-Error
-NativeProcessLinux::SetupSoftwareSingleStepping(NativeThreadLinux &thread)
-{
- Error error;
- NativeRegisterContextSP register_context_sp = thread.GetRegisterContext();
-
- std::unique_ptr<EmulateInstruction> emulator_ap(
- EmulateInstruction::FindPlugin(m_arch, eInstructionTypePCModifying, nullptr));
+Error NativeProcessLinux::SetupSoftwareSingleStepping(
+ NativeThreadLinux &thread) {
+ Error error;
+ NativeRegisterContextSP register_context_sp = thread.GetRegisterContext();
- if (emulator_ap == nullptr)
- return Error("Instruction emulator not found!");
+ std::unique_ptr<EmulateInstruction> emulator_ap(
+ EmulateInstruction::FindPlugin(m_arch, eInstructionTypePCModifying,
+ nullptr));
- EmulatorBaton baton(this, register_context_sp.get());
- emulator_ap->SetBaton(&baton);
- emulator_ap->SetReadMemCallback(&ReadMemoryCallback);
- emulator_ap->SetReadRegCallback(&ReadRegisterCallback);
- emulator_ap->SetWriteMemCallback(&WriteMemoryCallback);
- emulator_ap->SetWriteRegCallback(&WriteRegisterCallback);
+ if (emulator_ap == nullptr)
+ return Error("Instruction emulator not found!");
- if (!emulator_ap->ReadInstruction())
- return Error("Read instruction failed!");
+ EmulatorBaton baton(this, register_context_sp.get());
+ emulator_ap->SetBaton(&baton);
+ emulator_ap->SetReadMemCallback(&ReadMemoryCallback);
+ emulator_ap->SetReadRegCallback(&ReadRegisterCallback);
+ emulator_ap->SetWriteMemCallback(&WriteMemoryCallback);
+ emulator_ap->SetWriteRegCallback(&WriteRegisterCallback);
- bool emulation_result = emulator_ap->EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC);
+ if (!emulator_ap->ReadInstruction())
+ return Error("Read instruction failed!");
- const RegisterInfo* reg_info_pc = register_context_sp->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
- const RegisterInfo* reg_info_flags = register_context_sp->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
+ bool emulation_result =
+ emulator_ap->EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC);
- auto pc_it = baton.m_register_values.find(reg_info_pc->kinds[eRegisterKindDWARF]);
- auto flags_it = baton.m_register_values.find(reg_info_flags->kinds[eRegisterKindDWARF]);
+ const RegisterInfo *reg_info_pc = register_context_sp->GetRegisterInfo(
+ eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+ const RegisterInfo *reg_info_flags = register_context_sp->GetRegisterInfo(
+ eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
- lldb::addr_t next_pc;
- lldb::addr_t next_flags;
- if (emulation_result)
- {
- assert(pc_it != baton.m_register_values.end() && "Emulation was successfull but PC wasn't updated");
- next_pc = pc_it->second.GetAsUInt64();
+ auto pc_it =
+ baton.m_register_values.find(reg_info_pc->kinds[eRegisterKindDWARF]);
+ auto flags_it =
+ baton.m_register_values.find(reg_info_flags->kinds[eRegisterKindDWARF]);
- if (flags_it != baton.m_register_values.end())
- next_flags = flags_it->second.GetAsUInt64();
- else
- next_flags = ReadFlags (register_context_sp.get());
- }
- else if (pc_it == baton.m_register_values.end())
- {
- // Emulate instruction failed and it haven't changed PC. Advance PC
- // with the size of the current opcode because the emulation of all
- // PC modifying instruction should be successful. The failure most
- // likely caused by a not supported instruction which don't modify PC.
- next_pc = register_context_sp->GetPC() + emulator_ap->GetOpcode().GetByteSize();
- next_flags = ReadFlags (register_context_sp.get());
- }
- else
- {
- // The instruction emulation failed after it modified the PC. It is an
- // unknown error where we can't continue because the next instruction is
- // modifying the PC but we don't know how.
- return Error ("Instruction emulation failed unexpectedly.");
- }
+ lldb::addr_t next_pc;
+ lldb::addr_t next_flags;
+ if (emulation_result) {
+ assert(pc_it != baton.m_register_values.end() &&
+ "Emulation was successfull but PC wasn't updated");
+ next_pc = pc_it->second.GetAsUInt64();
- if (m_arch.GetMachine() == llvm::Triple::arm)
- {
- if (next_flags & 0x20)
- {
- // Thumb mode
- error = SetSoftwareBreakpoint(next_pc, 2);
- }
- else
- {
- // Arm mode
- error = SetSoftwareBreakpoint(next_pc, 4);
- }
- }
- else if (m_arch.GetMachine() == llvm::Triple::mips64
- || m_arch.GetMachine() == llvm::Triple::mips64el
- || m_arch.GetMachine() == llvm::Triple::mips
- || m_arch.GetMachine() == llvm::Triple::mipsel)
- error = SetSoftwareBreakpoint(next_pc, 4);
+ if (flags_it != baton.m_register_values.end())
+ next_flags = flags_it->second.GetAsUInt64();
else
- {
- // No size hint is given for the next breakpoint
- error = SetSoftwareBreakpoint(next_pc, 0);
- }
-
- if (error.Fail())
- return error;
+ next_flags = ReadFlags(register_context_sp.get());
+ } else if (pc_it == baton.m_register_values.end()) {
+ // Emulate instruction failed and it haven't changed PC. Advance PC
+ // with the size of the current opcode because the emulation of all
+ // PC modifying instruction should be successful. The failure most
+ // likely caused by a not supported instruction which don't modify PC.
+ next_pc =
+ register_context_sp->GetPC() + emulator_ap->GetOpcode().GetByteSize();
+ next_flags = ReadFlags(register_context_sp.get());
+ } else {
+ // The instruction emulation failed after it modified the PC. It is an
+ // unknown error where we can't continue because the next instruction is
+ // modifying the PC but we don't know how.
+ return Error("Instruction emulation failed unexpectedly.");
+ }
+
+ if (m_arch.GetMachine() == llvm::Triple::arm) {
+ if (next_flags & 0x20) {
+ // Thumb mode
+ error = SetSoftwareBreakpoint(next_pc, 2);
+ } else {
+ // Arm mode
+ error = SetSoftwareBreakpoint(next_pc, 4);
+ }
+ } else if (m_arch.GetMachine() == llvm::Triple::mips64 ||
+ m_arch.GetMachine() == llvm::Triple::mips64el ||
+ m_arch.GetMachine() == llvm::Triple::mips ||
+ m_arch.GetMachine() == llvm::Triple::mipsel)
+ error = SetSoftwareBreakpoint(next_pc, 4);
+ else {
+ // No size hint is given for the next breakpoint
+ error = SetSoftwareBreakpoint(next_pc, 0);
+ }
+
+ if (error.Fail())
+ return error;
- m_threads_stepping_with_breakpoint.insert({thread.GetID(), next_pc});
+ m_threads_stepping_with_breakpoint.insert({thread.GetID(), next_pc});
- return Error();
+ return Error();
}
-bool
-NativeProcessLinux::SupportHardwareSingleStepping() const
-{
- if (m_arch.GetMachine() == llvm::Triple::arm
- || m_arch.GetMachine() == llvm::Triple::mips64 || m_arch.GetMachine() == llvm::Triple::mips64el
- || m_arch.GetMachine() == llvm::Triple::mips || m_arch.GetMachine() == llvm::Triple::mipsel)
- return false;
- return true;
+bool NativeProcessLinux::SupportHardwareSingleStepping() const {
+ if (m_arch.GetMachine() == llvm::Triple::arm ||
+ m_arch.GetMachine() == llvm::Triple::mips64 ||
+ m_arch.GetMachine() == llvm::Triple::mips64el ||
+ m_arch.GetMachine() == llvm::Triple::mips ||
+ m_arch.GetMachine() == llvm::Triple::mipsel)
+ return false;
+ return true;
}
-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 ());
+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());
- bool software_single_step = !SupportHardwareSingleStepping();
+ bool software_single_step = !SupportHardwareSingleStepping();
- if (software_single_step)
- {
- for (auto thread_sp : m_threads)
- {
- assert (thread_sp && "thread list should not contain NULL threads");
-
- const ResumeAction *const action = resume_actions.GetActionForThread (thread_sp->GetID (), true);
- if (action == nullptr)
- continue;
-
- if (action->state == eStateStepping)
- {
- Error error = SetupSoftwareSingleStepping(static_cast<NativeThreadLinux &>(*thread_sp));
- if (error.Fail())
- return error;
- }
- }
+ if (software_single_step) {
+ for (auto thread_sp : m_threads) {
+ assert(thread_sp && "thread list should not contain NULL threads");
+
+ const ResumeAction *const action =
+ resume_actions.GetActionForThread(thread_sp->GetID(), true);
+ if (action == nullptr)
+ continue;
+
+ if (action->state == eStateStepping) {
+ Error error = SetupSoftwareSingleStepping(
+ static_cast<NativeThreadLinux &>(*thread_sp));
+ if (error.Fail())
+ return error;
+ }
}
+ }
- for (auto thread_sp : m_threads)
- {
- assert (thread_sp && "thread list should not contain NULL threads");
+ for (auto thread_sp : m_threads) {
+ assert(thread_sp && "thread list should not contain NULL threads");
- const ResumeAction *const action = resume_actions.GetActionForThread (thread_sp->GetID (), true);
+ const ResumeAction *const action =
+ 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 ());
- continue;
- }
+ if (action == nullptr) {
+ if (log)
+ log->Printf(
+ "NativeProcessLinux::%s no action specified for pid %" PRIu64
+ " tid %" PRIu64,
+ __FUNCTION__, 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 ());
- }
+ if (log) {
+ log->Printf("NativeProcessLinux::%s processing resume action state %s "
+ "for pid %" PRIu64 " tid %" PRIu64,
+ __FUNCTION__, StateAsCString(action->state), GetID(),
+ thread_sp->GetID());
+ }
- switch (action->state)
- {
- case eStateRunning:
- case eStateStepping:
- {
- // Run the thread, possibly feeding it the signal.
- const int signo = action->signal;
- ResumeThread(static_cast<NativeThreadLinux &>(*thread_sp), action->state, signo);
- break;
- }
+ switch (action->state) {
+ case eStateRunning:
+ case eStateStepping: {
+ // Run the thread, possibly feeding it the signal.
+ const int signo = action->signal;
+ ResumeThread(static_cast<NativeThreadLinux &>(*thread_sp), action->state,
+ signo);
+ break;
+ }
- case eStateSuspended:
- case eStateStopped:
- lldbassert(0 && "Unexpected state");
+ case eStateSuspended:
+ case eStateStopped:
+ lldbassert(0 && "Unexpected state");
- default:
- return Error ("NativeProcessLinux::%s (): unexpected state %s specified for pid %" PRIu64 ", tid %" PRIu64,
- __FUNCTION__, StateAsCString (action->state), GetID (), thread_sp->GetID ());
- }
+ default:
+ return Error("NativeProcessLinux::%s (): unexpected state %s specified "
+ "for pid %" PRIu64 ", tid %" PRIu64,
+ __FUNCTION__, StateAsCString(action->state), GetID(),
+ thread_sp->GetID());
}
+ }
- return Error();
+ return Error();
}
-Error
-NativeProcessLinux::Halt ()
-{
- Error error;
+Error NativeProcessLinux::Halt() {
+ Error error;
- if (kill (GetID (), SIGSTOP) != 0)
- error.SetErrorToErrno ();
+ if (kill(GetID(), SIGSTOP) != 0)
+ error.SetErrorToErrno();
- return error;
+ return error;
}
-Error
-NativeProcessLinux::Detach ()
-{
- Error error;
+Error NativeProcessLinux::Detach() {
+ Error error;
- // Stop monitoring the inferior.
- m_sigchld_handle.reset();
+ // Stop monitoring the inferior.
+ m_sigchld_handle.reset();
- // Tell ptrace to detach from the process.
- if (GetID () == LLDB_INVALID_PROCESS_ID)
- return error;
+ // Tell ptrace to detach from the process.
+ if (GetID() == LLDB_INVALID_PROCESS_ID)
+ return error;
- for (auto thread_sp : m_threads)
- {
- Error e = Detach(thread_sp->GetID());
- if (e.Fail())
- error = e; // Save the error, but still attempt to detach from other threads.
- }
+ for (auto thread_sp : m_threads) {
+ Error e = Detach(thread_sp->GetID());
+ if (e.Fail())
+ error =
+ e; // Save the error, but still attempt to detach from other threads.
+ }
- return error;
+ return error;
}
-Error
-NativeProcessLinux::Signal (int signo)
-{
- Error error;
+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(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf(
+ "NativeProcessLinux::%s: sending signal %d (%s) to pid %" PRIu64,
+ __FUNCTION__, signo, Host::GetSignalAsCString(signo), GetID());
- if (kill(GetID(), signo))
- error.SetErrorToErrno();
+ if (kill(GetID(), signo))
+ error.SetErrorToErrno();
- return error;
+ return error;
}
-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));
+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));
- NativeThreadProtocolSP running_thread_sp;
- NativeThreadProtocolSP stopped_thread_sp;
-
- if (log)
- log->Printf ("NativeProcessLinux::%s selecting running thread for interrupt target", __FUNCTION__);
-
- for (auto thread_sp : m_threads)
- {
- // The thread shouldn't be null but lets just cover that here.
- if (!thread_sp)
- continue;
+ NativeThreadProtocolSP running_thread_sp;
+ NativeThreadProtocolSP stopped_thread_sp;
- // If we have a running or stepping thread, we'll call that the
- // target of the interrupt.
- const auto thread_state = thread_sp->GetState ();
- if (thread_state == eStateRunning ||
- thread_state == eStateStepping)
- {
- running_thread_sp = thread_sp;
- break;
- }
- else if (!stopped_thread_sp && StateIsStoppedState (thread_state, true))
- {
- // Remember the first non-dead stopped thread. We'll use that as a backup if there are no running threads.
- stopped_thread_sp = thread_sp;
- }
- }
+ if (log)
+ log->Printf(
+ "NativeProcessLinux::%s selecting running thread for interrupt target",
+ __FUNCTION__);
- 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 ());
+ for (auto thread_sp : m_threads) {
+ // The thread shouldn't be null but lets just cover that here.
+ if (!thread_sp)
+ continue;
- return error;
+ // If we have a running or stepping thread, we'll call that the
+ // target of the interrupt.
+ const auto thread_state = thread_sp->GetState();
+ if (thread_state == eStateRunning || thread_state == eStateStepping) {
+ running_thread_sp = thread_sp;
+ break;
+ } else if (!stopped_thread_sp && StateIsStoppedState(thread_state, true)) {
+ // Remember the first non-dead stopped thread. We'll use that as a backup
+ // if there are no running threads.
+ stopped_thread_sp = thread_sp;
}
+ }
- NativeThreadProtocolSP deferred_signal_thread_sp = running_thread_sp ? running_thread_sp : stopped_thread_sp;
-
+ 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 pid %" PRIu64 " %s tid %" PRIu64 " chosen for interrupt target",
- __FUNCTION__,
- GetID (),
- running_thread_sp ? "running" : "stopped",
- deferred_signal_thread_sp->GetID ());
-
- StopRunningThreads(deferred_signal_thread_sp->GetID());
-
- return Error();
-}
-
-Error
-NativeProcessLinux::Kill ()
-{
- Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
- if (log)
- log->Printf ("NativeProcessLinux::%s called for PID %" PRIu64, __FUNCTION__, GetID ());
-
- Error error;
-
- switch (m_state)
- {
- case StateType::eStateInvalid:
- case StateType::eStateExited:
- case StateType::eStateCrashed:
- 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));
- return error;
-
- case StateType::eStateConnected:
- case StateType::eStateAttaching:
- case StateType::eStateLaunching:
- case StateType::eStateStopped:
- case StateType::eStateRunning:
- case StateType::eStateStepping:
- case StateType::eStateSuspended:
- // We can try to kill a process in these states.
- break;
- }
-
- if (kill (GetID (), SIGKILL) != 0)
- {
- error.SetErrorToErrno ();
- return error;
- }
+ log->Printf("NativeProcessLinux::%s skipping due to error: %s",
+ __FUNCTION__, error.AsCString());
return error;
-}
-
-static Error
-ParseMemoryRegionInfoFromProcMapsLine (const std::string &maps_line, MemoryRegionInfo &memory_region_info)
-{
- memory_region_info.Clear();
-
- StringExtractor line_extractor (maps_line.c_str ());
-
- // Format: {address_start_hex}-{address_end_hex} perms offset dev inode pathname
- // perms: rwxp (letter is present if set, '-' if not, final character is p=private, s=shared).
-
- // Parse out the starting address
- lldb::addr_t start_address = line_extractor.GetHexMaxU64 (false, 0);
-
- // Parse out hyphen separating start and end address from range.
- if (!line_extractor.GetBytesLeft () || (line_extractor.GetChar () != '-'))
- return Error ("malformed /proc/{pid}/maps entry, missing dash between address range");
+ }
- // Parse out the ending address
- lldb::addr_t end_address = line_extractor.GetHexMaxU64 (false, start_address);
+ NativeThreadProtocolSP deferred_signal_thread_sp =
+ running_thread_sp ? running_thread_sp : stopped_thread_sp;
- // Parse out the space after the address.
- if (!line_extractor.GetBytesLeft () || (line_extractor.GetChar () != ' '))
- return Error ("malformed /proc/{pid}/maps entry, missing space after range");
+ 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());
- // Save the range.
- memory_region_info.GetRange ().SetRangeBase (start_address);
- memory_region_info.GetRange ().SetRangeEnd (end_address);
+ StopRunningThreads(deferred_signal_thread_sp->GetID());
- // Any memory region in /proc/{pid}/maps is by definition mapped into the process.
- memory_region_info.SetMapped(MemoryRegionInfo::OptionalBool::eYes);
+ return Error();
+}
- // Parse out each permission entry.
- if (line_extractor.GetBytesLeft () < 4)
- return Error ("malformed /proc/{pid}/maps entry, missing some portion of permissions");
+Error NativeProcessLinux::Kill() {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf("NativeProcessLinux::%s called for PID %" PRIu64, __FUNCTION__,
+ GetID());
- // Handle read permission.
- const char read_perm_char = line_extractor.GetChar ();
- if (read_perm_char == 'r')
- memory_region_info.SetReadable (MemoryRegionInfo::OptionalBool::eYes);
- else if (read_perm_char == '-')
- memory_region_info.SetReadable (MemoryRegionInfo::OptionalBool::eNo);
- else
- return Error ("unexpected /proc/{pid}/maps read permission char");
-
- // Handle write permission.
- const char write_perm_char = line_extractor.GetChar ();
- if (write_perm_char == 'w')
- memory_region_info.SetWritable (MemoryRegionInfo::OptionalBool::eYes);
- else if (write_perm_char == '-')
- memory_region_info.SetWritable (MemoryRegionInfo::OptionalBool::eNo);
- else
- return Error ("unexpected /proc/{pid}/maps write permission char");
-
- // Handle execute permission.
- const char exec_perm_char = line_extractor.GetChar ();
- if (exec_perm_char == 'x')
- memory_region_info.SetExecutable (MemoryRegionInfo::OptionalBool::eYes);
- else if (exec_perm_char == '-')
- memory_region_info.SetExecutable (MemoryRegionInfo::OptionalBool::eNo);
- else
- return Error ("unexpected /proc/{pid}/maps exec permission char");
+ Error error;
- line_extractor.GetChar(); // Read the private bit
- line_extractor.SkipSpaces(); // Skip the separator
- line_extractor.GetHexMaxU64(false, 0); // Read the offset
- line_extractor.GetHexMaxU64(false, 0); // Read the major device number
- line_extractor.GetChar(); // Read the device id separator
- line_extractor.GetHexMaxU64(false, 0); // Read the major device number
- line_extractor.SkipSpaces(); // Skip the separator
- line_extractor.GetU64(0, 10); // Read the inode number
+ switch (m_state) {
+ case StateType::eStateInvalid:
+ case StateType::eStateExited:
+ case StateType::eStateCrashed:
+ 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));
+ return error;
- line_extractor.SkipSpaces();
- const char* name = line_extractor.Peek();
- if (name)
- memory_region_info.SetName(name);
+ case StateType::eStateConnected:
+ case StateType::eStateAttaching:
+ case StateType::eStateLaunching:
+ case StateType::eStateStopped:
+ case StateType::eStateRunning:
+ case StateType::eStateStepping:
+ case StateType::eStateSuspended:
+ // We can try to kill a process in these states.
+ break;
+ }
+
+ if (kill(GetID(), SIGKILL) != 0) {
+ error.SetErrorToErrno();
+ return error;
+ }
- return Error ();
+ return error;
}
-Error
-NativeProcessLinux::GetMemoryRegionInfo (lldb::addr_t load_addr, MemoryRegionInfo &range_info)
-{
- // FIXME review that the final memory region returned extends to the end of the virtual address space,
- // with no perms if it is not mapped.
-
- // Use an approach that reads memory regions from /proc/{pid}/maps.
- // Assume proc maps entries are in ascending order.
- // FIXME assert if we find differently.
-
- Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
- Error error;
-
- if (m_supports_mem_region == LazyBool::eLazyBoolNo)
- {
- // We're done.
- error.SetErrorString ("unsupported");
- return error;
- }
-
- // 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 ())
- {
- 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.push_back (info);
- return true;
- }
- else
- {
- if (log)
- log->Printf ("NativeProcessLinux::%s failed to parse proc maps line '%s': %s", __FUNCTION__, line.c_str (), error.AsCString ());
- return false;
- }
- });
-
- // If we had an error, we'll mark unsupported.
- if (error.Fail ())
- {
- m_supports_mem_region = LazyBool::eLazyBoolNo;
- return error;
- }
- else 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.
+static Error
+ParseMemoryRegionInfoFromProcMapsLine(const std::string &maps_line,
+ MemoryRegionInfo &memory_region_info) {
+ memory_region_info.Clear();
+
+ StringExtractor line_extractor(maps_line.c_str());
+
+ // Format: {address_start_hex}-{address_end_hex} perms offset dev inode
+ // pathname
+ // perms: rwxp (letter is present if set, '-' if not, final character is
+ // p=private, s=shared).
+
+ // Parse out the starting address
+ lldb::addr_t start_address = line_extractor.GetHexMaxU64(false, 0);
+
+ // Parse out hyphen separating start and end address from range.
+ if (!line_extractor.GetBytesLeft() || (line_extractor.GetChar() != '-'))
+ return Error(
+ "malformed /proc/{pid}/maps entry, missing dash between address range");
+
+ // Parse out the ending address
+ lldb::addr_t end_address = line_extractor.GetHexMaxU64(false, start_address);
+
+ // Parse out the space after the address.
+ if (!line_extractor.GetBytesLeft() || (line_extractor.GetChar() != ' '))
+ return Error("malformed /proc/{pid}/maps entry, missing space after range");
+
+ // Save the range.
+ memory_region_info.GetRange().SetRangeBase(start_address);
+ memory_region_info.GetRange().SetRangeEnd(end_address);
+
+ // Any memory region in /proc/{pid}/maps is by definition mapped into the
+ // process.
+ memory_region_info.SetMapped(MemoryRegionInfo::OptionalBool::eYes);
+
+ // Parse out each permission entry.
+ if (line_extractor.GetBytesLeft() < 4)
+ return Error("malformed /proc/{pid}/maps entry, missing some portion of "
+ "permissions");
+
+ // Handle read permission.
+ const char read_perm_char = line_extractor.GetChar();
+ if (read_perm_char == 'r')
+ memory_region_info.SetReadable(MemoryRegionInfo::OptionalBool::eYes);
+ else if (read_perm_char == '-')
+ memory_region_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
+ else
+ return Error("unexpected /proc/{pid}/maps read permission char");
+
+ // Handle write permission.
+ const char write_perm_char = line_extractor.GetChar();
+ if (write_perm_char == 'w')
+ memory_region_info.SetWritable(MemoryRegionInfo::OptionalBool::eYes);
+ else if (write_perm_char == '-')
+ memory_region_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo);
+ else
+ return Error("unexpected /proc/{pid}/maps write permission char");
+
+ // Handle execute permission.
+ const char exec_perm_char = line_extractor.GetChar();
+ if (exec_perm_char == 'x')
+ memory_region_info.SetExecutable(MemoryRegionInfo::OptionalBool::eYes);
+ else if (exec_perm_char == '-')
+ memory_region_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo);
+ else
+ return Error("unexpected /proc/{pid}/maps exec permission char");
+
+ line_extractor.GetChar(); // Read the private bit
+ line_extractor.SkipSpaces(); // Skip the separator
+ line_extractor.GetHexMaxU64(false, 0); // Read the offset
+ line_extractor.GetHexMaxU64(false, 0); // Read the major device number
+ line_extractor.GetChar(); // Read the device id separator
+ line_extractor.GetHexMaxU64(false, 0); // Read the major device number
+ line_extractor.SkipSpaces(); // Skip the separator
+ line_extractor.GetU64(0, 10); // Read the inode number
+
+ line_extractor.SkipSpaces();
+ const char *name = line_extractor.Peek();
+ if (name)
+ memory_region_info.SetName(name);
+
+ return Error();
+}
+
+Error NativeProcessLinux::GetMemoryRegionInfo(lldb::addr_t load_addr,
+ MemoryRegionInfo &range_info) {
+ // FIXME review that the final memory region returned extends to the end of
+ // the virtual address space,
+ // with no perms if it is not mapped.
+
+ // Use an approach that reads memory regions from /proc/{pid}/maps.
+ // Assume proc maps entries are in ascending order.
+ // FIXME assert if we find differently.
+
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ Error error;
+
+ if (m_supports_mem_region == LazyBool::eLazyBoolNo) {
+ // We're done.
+ error.SetErrorString("unsupported");
+ return error;
+ }
+
+ // 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()) {
+ 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.push_back(info);
+ return true;
+ } else {
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;
- }
-
- 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 ());
-
- // We support memory retrieval, remember that.
- m_supports_mem_region = LazyBool::eLazyBoolYes;
- }
- else
- {
- if (log)
- log->Printf ("NativeProcessLinux::%s reusing %" PRIu64 " cached memory region entries", __FUNCTION__, static_cast<uint64_t> (m_mem_region_cache.size ()));
- }
-
- lldb::addr_t prev_base_address = 0;
-
- // FIXME start by finding the last region that is <= target address using binary search. Data is sorted.
- // There can be a ton of regions on pthreads apps with lots of threads.
- for (auto it = m_mem_region_cache.begin(); it != m_mem_region_cache.end (); ++it)
- {
- MemoryRegionInfo &proc_entry_info = *it;
-
- // Sanity check assumption that /proc/{pid}/maps entries are ascending.
- assert ((proc_entry_info.GetRange ().GetRangeBase () >= prev_base_address) && "descending /proc/pid/maps entries detected, unexpected");
- prev_base_address = proc_entry_info.GetRange ().GetRangeBase ();
-
- // If the target address comes before this entry, indicate distance to next region.
- if (load_addr < proc_entry_info.GetRange ().GetRangeBase ())
- {
- range_info.GetRange ().SetRangeBase (load_addr);
- range_info.GetRange ().SetByteSize (proc_entry_info.GetRange ().GetRangeBase () - load_addr);
- range_info.SetReadable (MemoryRegionInfo::OptionalBool::eNo);
- range_info.SetWritable (MemoryRegionInfo::OptionalBool::eNo);
- range_info.SetExecutable (MemoryRegionInfo::OptionalBool::eNo);
- range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo);
-
- return error;
- }
- else if (proc_entry_info.GetRange ().Contains (load_addr))
- {
- // The target address is within the memory region we're processing here.
- range_info = proc_entry_info;
- return error;
- }
+ log->Printf("NativeProcessLinux::%s failed to parse proc maps "
+ "line '%s': %s",
+ __FUNCTION__, line.c_str(), error.AsCString());
+ return false;
+ }
+ });
- // The target memory address comes somewhere after the region we just parsed.
+ // If we had an error, we'll mark unsupported.
+ if (error.Fail()) {
+ m_supports_mem_region = LazyBool::eLazyBoolNo;
+ return error;
+ } else 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;
}
- // If we made it here, we didn't find an entry that contained the given address. Return the
- // load_addr as start and the amount of bytes betwwen load address and the end of the memory as
- // size.
- range_info.GetRange ().SetRangeBase (load_addr);
- range_info.GetRange ().SetRangeEnd(LLDB_INVALID_ADDRESS);
- range_info.SetReadable (MemoryRegionInfo::OptionalBool::eNo);
- range_info.SetWritable (MemoryRegionInfo::OptionalBool::eNo);
- range_info.SetExecutable (MemoryRegionInfo::OptionalBool::eNo);
- range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo);
- return error;
-}
-
-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 ()));
- m_mem_region_cache.clear ();
-}
-
-Error
-NativeProcessLinux::AllocateMemory(size_t size, uint32_t permissions, lldb::addr_t &addr)
-{
- // FIXME implementing this requires the equivalent of
- // InferiorCallPOSIX::InferiorCallMmap, which depends on
- // functional ThreadPlans working with Native*Protocol.
+ log->Printf("NativeProcessLinux::%s read %" PRIu64
+ " memory region entries from /proc/%" PRIu64 "/maps",
+ __FUNCTION__,
+ static_cast<uint64_t>(m_mem_region_cache.size()), GetID());
+
+ // We support memory retrieval, remember that.
+ m_supports_mem_region = LazyBool::eLazyBoolYes;
+ } else {
+ if (log)
+ log->Printf("NativeProcessLinux::%s reusing %" PRIu64
+ " cached memory region entries",
+ __FUNCTION__,
+ static_cast<uint64_t>(m_mem_region_cache.size()));
+ }
+
+ lldb::addr_t prev_base_address = 0;
+
+ // FIXME start by finding the last region that is <= target address using
+ // binary search. Data is sorted.
+ // There can be a ton of regions on pthreads apps with lots of threads.
+ for (auto it = m_mem_region_cache.begin(); it != m_mem_region_cache.end();
+ ++it) {
+ MemoryRegionInfo &proc_entry_info = *it;
+
+ // Sanity check assumption that /proc/{pid}/maps entries are ascending.
+ assert((proc_entry_info.GetRange().GetRangeBase() >= prev_base_address) &&
+ "descending /proc/pid/maps entries detected, unexpected");
+ prev_base_address = proc_entry_info.GetRange().GetRangeBase();
+
+ // If the target address comes before this entry, indicate distance to next
+ // region.
+ if (load_addr < proc_entry_info.GetRange().GetRangeBase()) {
+ range_info.GetRange().SetRangeBase(load_addr);
+ range_info.GetRange().SetByteSize(
+ proc_entry_info.GetRange().GetRangeBase() - load_addr);
+ range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
+ range_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo);
+ range_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo);
+ range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo);
+
+ return error;
+ } else if (proc_entry_info.GetRange().Contains(load_addr)) {
+ // The target address is within the memory region we're processing here.
+ range_info = proc_entry_info;
+ return error;
+ }
+
+ // The target memory address comes somewhere after the region we just
+ // parsed.
+ }
+
+ // If we made it here, we didn't find an entry that contained the given
+ // address. Return the
+ // load_addr as start and the amount of bytes betwwen load address and the end
+ // of the memory as
+ // size.
+ range_info.GetRange().SetRangeBase(load_addr);
+ range_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);
+ range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
+ range_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo);
+ range_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo);
+ range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo);
+ return error;
+}
+
+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()));
+ m_mem_region_cache.clear();
+}
+
+Error NativeProcessLinux::AllocateMemory(size_t size, uint32_t permissions,
+ lldb::addr_t &addr) {
+// FIXME implementing this requires the equivalent of
+// InferiorCallPOSIX::InferiorCallMmap, which depends on
+// functional ThreadPlans working with Native*Protocol.
#if 1
- return Error ("not implemented yet");
+ return Error("not implemented yet");
#else
+ addr = LLDB_INVALID_ADDRESS;
+
+ unsigned prot = 0;
+ if (permissions & lldb::ePermissionsReadable)
+ prot |= eMmapProtRead;
+ if (permissions & lldb::ePermissionsWritable)
+ prot |= eMmapProtWrite;
+ if (permissions & lldb::ePermissionsExecutable)
+ prot |= eMmapProtExec;
+
+ // TODO implement this directly in NativeProcessLinux
+ // (and lift to NativeProcessPOSIX if/when that class is
+ // refactored out).
+ if (InferiorCallMmap(this, addr, 0, size, prot,
+ eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) {
+ m_addr_to_mmap_size[addr] = size;
+ return Error();
+ } else {
addr = LLDB_INVALID_ADDRESS;
-
- unsigned prot = 0;
- if (permissions & lldb::ePermissionsReadable)
- prot |= eMmapProtRead;
- if (permissions & lldb::ePermissionsWritable)
- prot |= eMmapProtWrite;
- if (permissions & lldb::ePermissionsExecutable)
- prot |= eMmapProtExec;
-
- // TODO implement this directly in NativeProcessLinux
- // (and lift to NativeProcessPOSIX if/when that class is
- // refactored out).
- if (InferiorCallMmap(this, addr, 0, size, prot,
- eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) {
- m_addr_to_mmap_size[addr] = size;
- return Error ();
- } else {
- addr = LLDB_INVALID_ADDRESS;
- return Error("unable to allocate %" PRIu64 " bytes of memory with permissions %s", size, GetPermissionsAsCString (permissions));
- }
+ return Error("unable to allocate %" PRIu64
+ " bytes of memory with permissions %s",
+ size, GetPermissionsAsCString(permissions));
+ }
#endif
}
-Error
-NativeProcessLinux::DeallocateMemory (lldb::addr_t addr)
-{
- // FIXME see comments in AllocateMemory - required lower-level
- // bits not in place yet (ThreadPlans)
- return Error ("not implemented");
+Error NativeProcessLinux::DeallocateMemory(lldb::addr_t addr) {
+ // FIXME see comments in AllocateMemory - required lower-level
+ // bits not in place yet (ThreadPlans)
+ return Error("not implemented");
}
-lldb::addr_t
-NativeProcessLinux::GetSharedLibraryInfoAddress ()
-{
- // punt on this for now
- return LLDB_INVALID_ADDRESS;
+lldb::addr_t NativeProcessLinux::GetSharedLibraryInfoAddress() {
+ // punt on this for now
+ return LLDB_INVALID_ADDRESS;
}
-size_t
-NativeProcessLinux::UpdateThreads ()
-{
- // The NativeProcessLinux monitoring threads are always up to date
- // with respect to thread state and they keep the thread list
- // populated properly. All this method needs to do is return the
- // thread count.
- return m_threads.size ();
+size_t NativeProcessLinux::UpdateThreads() {
+ // The NativeProcessLinux monitoring threads are always up to date
+ // with respect to thread state and they keep the thread list
+ // populated properly. All this method needs to do is return the
+ // thread count.
+ return m_threads.size();
}
-bool
-NativeProcessLinux::GetArchitecture (ArchSpec &arch) const
-{
- arch = m_arch;
- return true;
+bool NativeProcessLinux::GetArchitecture(ArchSpec &arch) const {
+ arch = m_arch;
+ return true;
}
-Error
-NativeProcessLinux::GetSoftwareBreakpointPCOffset(uint32_t &actual_opcode_size)
-{
- // FIXME put this behind a breakpoint protocol class that can be
- // set per architecture. Need ARM, MIPS support here.
- static const uint8_t g_i386_opcode [] = { 0xCC };
- static const uint8_t g_s390x_opcode[] = { 0x00, 0x01 };
+Error NativeProcessLinux::GetSoftwareBreakpointPCOffset(
+ uint32_t &actual_opcode_size) {
+ // FIXME put this behind a breakpoint protocol class that can be
+ // set per architecture. Need ARM, MIPS support here.
+ static const uint8_t g_i386_opcode[] = {0xCC};
+ static const uint8_t g_s390x_opcode[] = {0x00, 0x01};
- switch (m_arch.GetMachine ())
- {
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- actual_opcode_size = static_cast<uint32_t> (sizeof(g_i386_opcode));
- return Error ();
-
- case llvm::Triple::systemz:
- actual_opcode_size = static_cast<uint32_t> (sizeof(g_s390x_opcode));
- return Error ();
-
- case llvm::Triple::arm:
- case llvm::Triple::aarch64:
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- // On these architectures the PC don't get updated for breakpoint hits
- actual_opcode_size = 0;
- return Error ();
-
- default:
- assert(false && "CPU type not supported!");
- return Error ("CPU type not supported");
- }
-}
+ switch (m_arch.GetMachine()) {
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ actual_opcode_size = static_cast<uint32_t>(sizeof(g_i386_opcode));
+ return Error();
-Error
-NativeProcessLinux::SetBreakpoint (lldb::addr_t addr, uint32_t size, bool hardware)
-{
- if (hardware)
- return Error ("NativeProcessLinux does not support hardware breakpoints");
- else
- return SetSoftwareBreakpoint (addr, size);
-}
+ case llvm::Triple::systemz:
+ actual_opcode_size = static_cast<uint32_t>(sizeof(g_s390x_opcode));
+ return Error();
-Error
-NativeProcessLinux::GetSoftwareBreakpointTrapOpcode (size_t trap_opcode_size_hint,
- size_t &actual_opcode_size,
- const uint8_t *&trap_opcode_bytes)
-{
- // FIXME put this behind a breakpoint protocol class that can be set per
- // architecture. Need MIPS support here.
- static const uint8_t g_aarch64_opcode[] = { 0x00, 0x00, 0x20, 0xd4 };
- // The ARM reference recommends the use of 0xe7fddefe and 0xdefe but the
- // linux kernel does otherwise.
- static const uint8_t g_arm_breakpoint_opcode[] = { 0xf0, 0x01, 0xf0, 0xe7 };
- static const uint8_t g_i386_opcode [] = { 0xCC };
- static const uint8_t g_mips64_opcode[] = { 0x00, 0x00, 0x00, 0x0d };
- static const uint8_t g_mips64el_opcode[] = { 0x0d, 0x00, 0x00, 0x00 };
- static const uint8_t g_s390x_opcode[] = { 0x00, 0x01 };
- static const uint8_t g_thumb_breakpoint_opcode[] = { 0x01, 0xde };
-
- switch (m_arch.GetMachine ())
- {
- case llvm::Triple::aarch64:
- trap_opcode_bytes = g_aarch64_opcode;
- actual_opcode_size = sizeof(g_aarch64_opcode);
- return Error ();
-
- case llvm::Triple::arm:
- switch (trap_opcode_size_hint)
- {
- case 2:
- trap_opcode_bytes = g_thumb_breakpoint_opcode;
- actual_opcode_size = sizeof(g_thumb_breakpoint_opcode);
- return Error ();
- case 4:
- trap_opcode_bytes = g_arm_breakpoint_opcode;
- actual_opcode_size = sizeof(g_arm_breakpoint_opcode);
- return Error ();
- default:
- assert(false && "Unrecognised trap opcode size hint!");
- return Error ("Unrecognised trap opcode size hint!");
- }
+ case llvm::Triple::arm:
+ case llvm::Triple::aarch64:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ // On these architectures the PC don't get updated for breakpoint hits
+ actual_opcode_size = 0;
+ return Error();
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- trap_opcode_bytes = g_i386_opcode;
- actual_opcode_size = sizeof(g_i386_opcode);
- return Error ();
-
- case llvm::Triple::mips:
- case llvm::Triple::mips64:
- trap_opcode_bytes = g_mips64_opcode;
- actual_opcode_size = sizeof(g_mips64_opcode);
- return Error ();
-
- case llvm::Triple::mipsel:
- case llvm::Triple::mips64el:
- trap_opcode_bytes = g_mips64el_opcode;
- actual_opcode_size = sizeof(g_mips64el_opcode);
- return Error ();
-
- case llvm::Triple::systemz:
- trap_opcode_bytes = g_s390x_opcode;
- actual_opcode_size = sizeof(g_s390x_opcode);
- return Error ();
+ default:
+ assert(false && "CPU type not supported!");
+ return Error("CPU type not supported");
+ }
+}
+
+Error NativeProcessLinux::SetBreakpoint(lldb::addr_t addr, uint32_t size,
+ bool hardware) {
+ if (hardware)
+ return Error("NativeProcessLinux does not support hardware breakpoints");
+ else
+ return SetSoftwareBreakpoint(addr, size);
+}
+
+Error NativeProcessLinux::GetSoftwareBreakpointTrapOpcode(
+ size_t trap_opcode_size_hint, size_t &actual_opcode_size,
+ const uint8_t *&trap_opcode_bytes) {
+ // FIXME put this behind a breakpoint protocol class that can be set per
+ // architecture. Need MIPS support here.
+ static const uint8_t g_aarch64_opcode[] = {0x00, 0x00, 0x20, 0xd4};
+ // The ARM reference recommends the use of 0xe7fddefe and 0xdefe but the
+ // linux kernel does otherwise.
+ static const uint8_t g_arm_breakpoint_opcode[] = {0xf0, 0x01, 0xf0, 0xe7};
+ static const uint8_t g_i386_opcode[] = {0xCC};
+ static const uint8_t g_mips64_opcode[] = {0x00, 0x00, 0x00, 0x0d};
+ static const uint8_t g_mips64el_opcode[] = {0x0d, 0x00, 0x00, 0x00};
+ static const uint8_t g_s390x_opcode[] = {0x00, 0x01};
+ static const uint8_t g_thumb_breakpoint_opcode[] = {0x01, 0xde};
+
+ switch (m_arch.GetMachine()) {
+ case llvm::Triple::aarch64:
+ trap_opcode_bytes = g_aarch64_opcode;
+ actual_opcode_size = sizeof(g_aarch64_opcode);
+ return Error();
+ case llvm::Triple::arm:
+ switch (trap_opcode_size_hint) {
+ case 2:
+ trap_opcode_bytes = g_thumb_breakpoint_opcode;
+ actual_opcode_size = sizeof(g_thumb_breakpoint_opcode);
+ return Error();
+ case 4:
+ trap_opcode_bytes = g_arm_breakpoint_opcode;
+ actual_opcode_size = sizeof(g_arm_breakpoint_opcode);
+ return Error();
default:
- assert(false && "CPU type not supported!");
- return Error ("CPU type not supported");
+ assert(false && "Unrecognised trap opcode size hint!");
+ return Error("Unrecognised trap opcode size hint!");
}
+
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ trap_opcode_bytes = g_i386_opcode;
+ actual_opcode_size = sizeof(g_i386_opcode);
+ return Error();
+
+ case llvm::Triple::mips:
+ case llvm::Triple::mips64:
+ trap_opcode_bytes = g_mips64_opcode;
+ actual_opcode_size = sizeof(g_mips64_opcode);
+ return Error();
+
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64el:
+ trap_opcode_bytes = g_mips64el_opcode;
+ actual_opcode_size = sizeof(g_mips64el_opcode);
+ return Error();
+
+ case llvm::Triple::systemz:
+ trap_opcode_bytes = g_s390x_opcode;
+ actual_opcode_size = sizeof(g_s390x_opcode);
+ return Error();
+
+ default:
+ assert(false && "CPU type not supported!");
+ return Error("CPU type not supported");
+ }
}
#if 0
@@ -2012,7 +2009,6 @@ NativeProcessLinux::GetCrashReasonForSIGSEGV(const siginfo_t *info)
}
#endif
-
#if 0
ProcessMessage::CrashReason
NativeProcessLinux::GetCrashReasonForSIGILL(const siginfo_t *info)
@@ -2130,640 +2126,628 @@ NativeProcessLinux::GetCrashReasonForSIGBUS(const siginfo_t *info)
}
#endif
-Error
-NativeProcessLinux::ReadMemory (lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read)
-{
- if (ProcessVmReadvSupported()) {
- // The process_vm_readv path is about 50 times faster than ptrace api. We want to use
- // this syscall if it is supported.
-
- const ::pid_t pid = GetID();
+Error NativeProcessLinux::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
+ size_t &bytes_read) {
+ if (ProcessVmReadvSupported()) {
+ // The process_vm_readv path is about 50 times faster than ptrace api. We
+ // want to use
+ // this syscall if it is supported.
- struct iovec local_iov, remote_iov;
- local_iov.iov_base = buf;
- local_iov.iov_len = size;
- remote_iov.iov_base = reinterpret_cast<void *>(addr);
- remote_iov.iov_len = size;
+ const ::pid_t pid = GetID();
- bytes_read = process_vm_readv(pid, &local_iov, 1, &remote_iov, 1, 0);
- const bool success = bytes_read == size;
+ struct iovec local_iov, remote_iov;
+ local_iov.iov_base = buf;
+ local_iov.iov_len = size;
+ remote_iov.iov_base = reinterpret_cast<void *>(addr);
+ remote_iov.iov_len = 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));
+ bytes_read = process_vm_readv(pid, &local_iov, 1, &remote_iov, 1, 0);
+ const bool success = bytes_read == size;
- if (success)
- return Error();
- // else
- // the call failed for some reason, let's retry the read using ptrace api.
+ 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));
+
+ if (success)
+ return Error();
+ // 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);
+
+ 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();
+ return error;
}
- 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);
+ remainder = size - bytes_read;
+ remainder = remainder > k_ptrace_word_size ? k_ptrace_word_size : remainder;
- 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();
- return error;
- }
+ // Copy the data into our buffer
+ memcpy(dst, &data, remainder);
- remainder = size - bytes_read;
- remainder = remainder > k_ptrace_word_size ? k_ptrace_word_size : remainder;
-
- // 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));
- }
- addr += k_ptrace_word_size;
- dst += 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))) {
+ 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));
}
+ addr += k_ptrace_word_size;
+ dst += k_ptrace_word_size;
+ }
- if (log)
- ProcessPOSIXLog::DecNestLevel();
- return Error();
+ if (log)
+ ProcessPOSIXLog::DecNestLevel();
+ return Error();
}
-Error
-NativeProcessLinux::ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read)
-{
- Error error = ReadMemory(addr, buf, size, bytes_read);
- if (error.Fail()) return error;
- return m_breakpoint_list.RemoveTrapsFromBuffer(addr, buf, size);
-}
+Error NativeProcessLinux::ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf,
+ size_t size,
+ size_t &bytes_read) {
+ Error error = ReadMemory(addr, buf, size, bytes_read);
+ if (error.Fail())
+ return error;
+ return m_breakpoint_list.RemoveTrapsFromBuffer(addr, buf, size);
+}
+
+Error NativeProcessLinux::WriteMemory(lldb::addr_t addr, const void *buf,
+ size_t size, size_t &bytes_written) {
+ const unsigned char *src = static_cast<const unsigned char *>(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);
+
+ for (bytes_written = 0; bytes_written < size; bytes_written += remainder) {
+ remainder = size - bytes_written;
+ remainder = remainder > k_ptrace_word_size ? k_ptrace_word_size : remainder;
+
+ if (remainder == k_ptrace_word_size) {
+ 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);
+
+ error = NativeProcessLinux::PtraceWrapper(PTRACE_POKEDATA, GetID(),
+ (void *)addr, (void *)data);
+ if (error.Fail()) {
+ if (log)
+ ProcessPOSIXLog::DecNestLevel();
+ 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();
+ return error;
+ }
-Error
-NativeProcessLinux::WriteMemory(lldb::addr_t addr, const void *buf, size_t size, size_t &bytes_written)
-{
- const unsigned char *src = static_cast<const unsigned char*>(buf);
- size_t remainder;
- Error error;
+ memcpy(buff, src, remainder);
- 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);
-
- for (bytes_written = 0; bytes_written < size; bytes_written += remainder)
- {
- remainder = size - bytes_written;
- remainder = remainder > k_ptrace_word_size ? k_ptrace_word_size : remainder;
-
- if (remainder == k_ptrace_word_size)
- {
- 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);
-
- error = NativeProcessLinux::PtraceWrapper(PTRACE_POKEDATA, GetID(), (void*)addr, (void*)data);
- if (error.Fail())
- {
- if (log)
- ProcessPOSIXLog::DecNestLevel();
- 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();
- 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();
- 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);
- }
+ size_t bytes_written_rec;
+ error = WriteMemory(addr, buff, k_ptrace_word_size, bytes_written_rec);
+ if (error.Fail()) {
+ if (log)
+ ProcessPOSIXLog::DecNestLevel();
+ return error;
+ }
- addr += k_ptrace_word_size;
- 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,
+ *(unsigned long *)buff);
}
- if (log)
- ProcessPOSIXLog::DecNestLevel();
- return error;
+
+ addr += k_ptrace_word_size;
+ src += k_ptrace_word_size;
+ }
+ if (log)
+ ProcessPOSIXLog::DecNestLevel();
+ return error;
}
-Error
-NativeProcessLinux::GetSignalInfo(lldb::tid_t tid, void *siginfo)
-{
- return PtraceWrapper(PTRACE_GETSIGINFO, tid, nullptr, siginfo);
+Error NativeProcessLinux::GetSignalInfo(lldb::tid_t tid, void *siginfo) {
+ return PtraceWrapper(PTRACE_GETSIGINFO, tid, nullptr, siginfo);
}
-Error
-NativeProcessLinux::GetEventMessage(lldb::tid_t tid, unsigned long *message)
-{
- return PtraceWrapper(PTRACE_GETEVENTMSG, tid, nullptr, message);
+Error NativeProcessLinux::GetEventMessage(lldb::tid_t tid,
+ unsigned long *message) {
+ return PtraceWrapper(PTRACE_GETEVENTMSG, tid, nullptr, message);
}
-Error
-NativeProcessLinux::Detach(lldb::tid_t tid)
-{
- if (tid == LLDB_INVALID_THREAD_ID)
- return Error();
+Error NativeProcessLinux::Detach(lldb::tid_t tid) {
+ if (tid == LLDB_INVALID_THREAD_ID)
+ return Error();
- return PtraceWrapper(PTRACE_DETACH, tid);
+ return PtraceWrapper(PTRACE_DETACH, tid);
}
-bool
-NativeProcessLinux::HasThreadNoLock (lldb::tid_t thread_id)
-{
- for (auto thread_sp : m_threads)
- {
- assert (thread_sp && "thread list should not contain NULL threads");
- if (thread_sp->GetID () == thread_id)
- {
- // We have this thread.
- return true;
- }
+bool NativeProcessLinux::HasThreadNoLock(lldb::tid_t thread_id) {
+ for (auto thread_sp : m_threads) {
+ assert(thread_sp && "thread list should not contain NULL threads");
+ if (thread_sp->GetID() == thread_id) {
+ // We have this thread.
+ return true;
}
+ }
- // We don't have this thread.
- return false;
+ // We don't have this thread.
+ return false;
}
-bool
-NativeProcessLinux::StopTrackingThread (lldb::tid_t thread_id)
-{
- Log *const log = GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD);
+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);
+ if (log)
+ log->Printf("NativeProcessLinux::%s (tid: %" PRIu64 ")", __FUNCTION__,
+ thread_id);
- bool found = false;
+ bool found = false;
- for (auto it = m_threads.begin (); it != m_threads.end (); ++it)
- {
- if (*it && ((*it)->GetID () == thread_id))
- {
- m_threads.erase (it);
- found = true;
- break;
- }
+ for (auto it = m_threads.begin(); it != m_threads.end(); ++it) {
+ if (*it && ((*it)->GetID() == thread_id)) {
+ m_threads.erase(it);
+ found = true;
+ break;
}
+ }
- SignalIfAllThreadsStopped();
+ SignalIfAllThreadsStopped();
- return found;
+ return found;
}
-NativeThreadLinuxSP
-NativeProcessLinux::AddThread (lldb::tid_t thread_id)
-{
- Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
+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);
- }
+ if (log) {
+ log->Printf("NativeProcessLinux::%s pid %" PRIu64
+ " adding thread with tid %" PRIu64,
+ __FUNCTION__, GetID(), thread_id);
+ }
- assert (!HasThreadNoLock (thread_id) && "attempted to add a thread by id that already exists");
+ assert(!HasThreadNoLock(thread_id) &&
+ "attempted to add a thread by id that already exists");
- // If this is the first thread, save it as the current thread
- if (m_threads.empty ())
- SetCurrentThreadID (thread_id);
+ // If this is the first thread, save it as the current thread
+ if (m_threads.empty())
+ SetCurrentThreadID(thread_id);
- auto thread_sp = std::make_shared<NativeThreadLinux>(this, thread_id);
- m_threads.push_back (thread_sp);
- return thread_sp;
+ auto thread_sp = std::make_shared<NativeThreadLinux>(this, thread_id);
+ m_threads.push_back(thread_sp);
+ return thread_sp;
}
-Error
-NativeProcessLinux::FixupBreakpointPCAsNeeded(NativeThreadLinux &thread)
-{
- Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
+Error NativeProcessLinux::FixupBreakpointPCAsNeeded(NativeThreadLinux &thread) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
- Error error;
+ Error error;
- // Find out the size of a breakpoint (might depend on where we are in the code).
- 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 ());
- 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 ());
- return error;
- }
- else
- {
- if (log)
- log->Printf ("NativeProcessLinux::%s breakpoint size: %" PRIu32, __FUNCTION__, breakpoint_size);
- }
-
- // First try probing for a breakpoint at a software breakpoint location: PC - breakpoint size.
- const lldb::addr_t initial_pc_addr = context_sp->GetPCfromBreakpointLocation ();
- lldb::addr_t breakpoint_addr = initial_pc_addr;
- if (breakpoint_size > 0)
- {
- // Do not allow breakpoint probe to wrap around.
- if (breakpoint_addr >= breakpoint_size)
- breakpoint_addr -= breakpoint_size;
- }
-
- // Check if we stopped because of a breakpoint.
- NativeBreakpointSP breakpoint_sp;
- 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);
- 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);
- return Error ();
- }
-
- //
- // We have a software breakpoint and need to adjust the PC.
- //
-
- // 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);
- return Error ();
- }
-
- // Change the program counter.
+ // Find out the size of a breakpoint (might depend on where we are in the
+ // code).
+ NativeRegisterContextSP context_sp = thread.GetRegisterContext();
+ if (!context_sp) {
+ error.SetErrorString("cannot get a NativeRegisterContext for the thread");
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);
-
- 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 ());
- return error;
- }
-
+ log->Printf("NativeProcessLinux::%s failed: %s", __FUNCTION__,
+ error.AsCString());
return error;
-}
+ }
-Error
-NativeProcessLinux::GetLoadedModuleFileSpec(const char* module_path, FileSpec& file_spec)
-{
- FileSpec module_file_spec(module_path, true);
-
- bool found = false;
- file_spec.Clear();
- ProcFileReader::ProcessLineByLine(GetID(), "maps",
- [&] (const std::string &line)
- {
- SmallVector<StringRef, 16> columns;
- StringRef(line).split(columns, " ", -1, false);
- if (columns.size() < 6)
- return true; // continue searching
-
- FileSpec this_file_spec(columns[5].str().c_str(), false);
- if (this_file_spec.GetFilename() != module_file_spec.GetFilename())
- return true; // continue searching
-
- file_spec = this_file_spec;
- found = true;
- return false; // we are done
- });
-
- if (! found)
- return Error("Module file (%s) not found in /proc/%" PRIu64 "/maps file!",
- module_file_spec.GetFilename().AsCString(), GetID());
+ uint32_t breakpoint_size = 0;
+ error = GetSoftwareBreakpointPCOffset(breakpoint_size);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("NativeProcessLinux::%s GetBreakpointSize() failed: %s",
+ __FUNCTION__, error.AsCString());
+ return error;
+ } else {
+ if (log)
+ log->Printf("NativeProcessLinux::%s breakpoint size: %" PRIu32,
+ __FUNCTION__, breakpoint_size);
+ }
+
+ // First try probing for a breakpoint at a software breakpoint location: PC -
+ // breakpoint size.
+ const lldb::addr_t initial_pc_addr =
+ context_sp->GetPCfromBreakpointLocation();
+ lldb::addr_t breakpoint_addr = initial_pc_addr;
+ if (breakpoint_size > 0) {
+ // Do not allow breakpoint probe to wrap around.
+ if (breakpoint_addr >= breakpoint_size)
+ breakpoint_addr -= breakpoint_size;
+ }
+
+ // Check if we stopped because of a breakpoint.
+ NativeBreakpointSP breakpoint_sp;
+ 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);
+ 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);
return Error();
-}
+ }
-Error
-NativeProcessLinux::GetFileLoadAddress(const llvm::StringRef& file_name, lldb::addr_t& load_addr)
-{
- load_addr = LLDB_INVALID_ADDRESS;
- Error error = ProcFileReader::ProcessLineByLine (GetID (), "maps",
- [&] (const std::string &line) -> bool
- {
- StringRef maps_row(line);
-
- SmallVector<StringRef, 16> maps_columns;
- maps_row.split(maps_columns, StringRef(" "), -1, false);
-
- if (maps_columns.size() < 6)
- {
- // Return true to continue reading the proc file
- return true;
- }
-
- if (maps_columns[5] == file_name)
- {
- StringExtractor addr_extractor(maps_columns[0].str().c_str());
- load_addr = addr_extractor.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
-
- // Return false to stop reading the proc file further
- return false;
- }
-
- // Return true to continue reading the proc file
- return true;
- });
- return error;
-}
+ //
+ // We have a software breakpoint and need to adjust the PC.
+ //
-NativeThreadLinuxSP
-NativeProcessLinux::GetThreadByID(lldb::tid_t tid)
-{
- return std::static_pointer_cast<NativeThreadLinux>(NativeProcessProtocol::GetThreadByID(tid));
-}
+ // 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);
+ return Error();
+ }
-Error
-NativeProcessLinux::ResumeThread(NativeThreadLinux &thread, lldb::StateType state, int signo)
-{
- Log *const log = GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD);
+ // 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);
+ error = context_sp->SetPC(breakpoint_addr);
+ if (error.Fail()) {
if (log)
- log->Printf("NativeProcessLinux::%s (tid: %" PRIu64 ")",
- __FUNCTION__, thread.GetID());
-
- // Before we do the resume below, first check if we have a pending
- // stop notification that is currently waiting for
- // all threads to stop. This is potentially a buggy situation since
- // 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);
- }
+ log->Printf("NativeProcessLinux::%s pid %" PRIu64 " tid %" PRIu64
+ ": failed to set PC: %s",
+ __FUNCTION__, GetID(), thread.GetID(), error.AsCString());
+ return error;
+ }
- // Request a resume. We expect this to be synchronous and the system
- // to reflect it is running after this completes.
- switch (state)
- {
- case eStateRunning:
- {
- const auto resume_result = thread.Resume(signo);
- if (resume_result.Success())
- SetState(eStateRunning, true);
- return resume_result;
- }
- case eStateStepping:
- {
- const auto step_result = thread.SingleStep(signo);
- if (step_result.Success())
- SetState(eStateRunning, true);
- return step_result;
- }
- default:
- if (log)
- log->Printf("NativeProcessLinux::%s Unhandled state %s.",
- __FUNCTION__, StateAsCString(state));
- llvm_unreachable("Unhandled state for resume");
- }
+ return error;
}
-//===----------------------------------------------------------------------===//
+Error NativeProcessLinux::GetLoadedModuleFileSpec(const char *module_path,
+ FileSpec &file_spec) {
+ FileSpec module_file_spec(module_path, true);
-void
-NativeProcessLinux::StopRunningThreads(const lldb::tid_t triggering_tid)
-{
- Log *const log = GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD);
+ bool found = false;
+ file_spec.Clear();
+ ProcFileReader::ProcessLineByLine(
+ GetID(), "maps", [&](const std::string &line) {
+ SmallVector<StringRef, 16> columns;
+ StringRef(line).split(columns, " ", -1, false);
+ if (columns.size() < 6)
+ return true; // continue searching
- if (log)
- {
- log->Printf("NativeProcessLinux::%s about to process event: (triggering_tid: %" PRIu64 ")",
- __FUNCTION__, triggering_tid);
- }
-
- m_pending_notification_tid = triggering_tid;
+ FileSpec this_file_spec(columns[5].str().c_str(), false);
+ if (this_file_spec.GetFilename() != module_file_spec.GetFilename())
+ return true; // continue searching
- // Request a stop for all the thread stops that need to be stopped
- // and are not already known to be stopped.
- for (const auto &thread_sp: m_threads)
- {
- if (StateIsRunningState(thread_sp->GetState()))
- static_pointer_cast<NativeThreadLinux>(thread_sp)->RequestStop();
- }
+ file_spec = this_file_spec;
+ found = true;
+ return false; // we are done
+ });
- SignalIfAllThreadsStopped();
+ if (!found)
+ return Error("Module file (%s) not found in /proc/%" PRIu64 "/maps file!",
+ module_file_spec.GetFilename().AsCString(), GetID());
- if (log)
- {
- log->Printf("NativeProcessLinux::%s event processing done", __FUNCTION__);
- }
+ return Error();
}
-void
-NativeProcessLinux::SignalIfAllThreadsStopped()
-{
- if (m_pending_notification_tid == LLDB_INVALID_THREAD_ID)
- return; // No pending notification. Nothing to do.
+Error NativeProcessLinux::GetFileLoadAddress(const llvm::StringRef &file_name,
+ lldb::addr_t &load_addr) {
+ load_addr = LLDB_INVALID_ADDRESS;
+ Error error = ProcFileReader::ProcessLineByLine(
+ GetID(), "maps", [&](const std::string &line) -> bool {
+ StringRef maps_row(line);
- for (const auto &thread_sp: m_threads)
- {
- if (StateIsRunningState(thread_sp->GetState()))
- return; // Some threads are still running. Don't signal yet.
- }
-
- // We have a pending notification and all threads have stopped.
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_BREAKPOINTS));
+ SmallVector<StringRef, 16> maps_columns;
+ maps_row.split(maps_columns, StringRef(" "), -1, false);
- // Clear any temporary breakpoints we used to implement software single stepping.
- 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());
- }
- m_threads_stepping_with_breakpoint.clear();
+ if (maps_columns.size() < 6) {
+ // Return true to continue reading the proc file
+ return true;
+ }
- // Notify the delegate about the stop
- SetCurrentThreadID(m_pending_notification_tid);
- SetState(StateType::eStateStopped, true);
- m_pending_notification_tid = LLDB_INVALID_THREAD_ID;
-}
+ if (maps_columns[5] == file_name) {
+ StringExtractor addr_extractor(maps_columns[0].str().c_str());
+ load_addr = addr_extractor.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
-void
-NativeProcessLinux::ThreadWasCreated(NativeThreadLinux &thread)
-{
- Log *const log = GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD);
+ // Return false to stop reading the proc file further
+ return false;
+ }
+ // Return true to continue reading the proc file
+ return true;
+ });
+ return error;
+}
+
+NativeThreadLinuxSP NativeProcessLinux::GetThreadByID(lldb::tid_t tid) {
+ return std::static_pointer_cast<NativeThreadLinux>(
+ NativeProcessProtocol::GetThreadByID(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());
+
+ // Before we do the resume below, first check if we have a pending
+ // stop notification that is currently waiting for
+ // all threads to stop. This is potentially a buggy situation since
+ // 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);
+ }
+
+ // Request a resume. We expect this to be synchronous and the system
+ // to reflect it is running after this completes.
+ switch (state) {
+ case eStateRunning: {
+ const auto resume_result = thread.Resume(signo);
+ if (resume_result.Success())
+ SetState(eStateRunning, true);
+ return resume_result;
+ }
+ case eStateStepping: {
+ const auto step_result = thread.SingleStep(signo);
+ if (step_result.Success())
+ SetState(eStateRunning, true);
+ return step_result;
+ }
+ default:
if (log)
- log->Printf("NativeProcessLinux::%s (tid: %" PRIu64 ")", __FUNCTION__, thread.GetID());
-
- if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID && StateIsRunningState(thread.GetState()))
- {
- // We will need to wait for this new thread to stop as well before firing the
- // notification.
- thread.RequestStop();
- }
+ log->Printf("NativeProcessLinux::%s Unhandled state %s.", __FUNCTION__,
+ StateAsCString(state));
+ llvm_unreachable("Unhandled state for resume");
+ }
}
-void
-NativeProcessLinux::SigchldHandler()
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- // Process all pending waitpid notifications.
- while (true)
- {
- int status = -1;
- ::pid_t wait_pid = waitpid(-1, &status, __WALL | __WNOTHREAD | WNOHANG);
+//===----------------------------------------------------------------------===//
- if (wait_pid == 0)
- break; // We are done.
+void NativeProcessLinux::StopRunningThreads(const lldb::tid_t triggering_tid) {
+ Log *const log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD);
- if (wait_pid == -1)
- {
- if (errno == EINTR)
- continue;
+ if (log) {
+ log->Printf("NativeProcessLinux::%s about to process event: "
+ "(triggering_tid: %" PRIu64 ")",
+ __FUNCTION__, triggering_tid);
+ }
- Error error(errno, eErrorTypePOSIX);
- if (log)
- log->Printf("NativeProcessLinux::%s waitpid (-1, &status, __WALL | __WNOTHREAD | WNOHANG) failed: %s",
- __FUNCTION__, error.AsCString());
- break;
- }
+ m_pending_notification_tid = triggering_tid;
- bool exited = false;
- int signal = 0;
- int exit_status = 0;
- const char *status_cstr = nullptr;
- if (WIFSTOPPED(status))
- {
- signal = WSTOPSIG(status);
- status_cstr = "STOPPED";
- }
- else if (WIFEXITED(status))
- {
- exit_status = WEXITSTATUS(status);
- status_cstr = "EXITED";
- exited = true;
- }
- else if (WIFSIGNALED(status))
- {
- signal = WTERMSIG(status);
- status_cstr = "SIGNALED";
- if (wait_pid == static_cast< ::pid_t>(GetID())) {
- exited = true;
- exit_status = -1;
- }
- }
- else
- status_cstr = "(\?\?\?)";
+ // Request a stop for all the thread stops that need to be stopped
+ // and are not already known to be stopped.
+ for (const auto &thread_sp : m_threads) {
+ if (StateIsRunningState(thread_sp->GetState()))
+ static_pointer_cast<NativeThreadLinux>(thread_sp)->RequestStop();
+ }
- 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);
+ SignalIfAllThreadsStopped();
- MonitorCallback (wait_pid, exited, signal, exit_status);
- }
+ if (log) {
+ log->Printf("NativeProcessLinux::%s event processing done", __FUNCTION__);
+ }
}
-// Wrapper for ptrace to catch errors and log calls.
-// Note that ptrace sets errno on error because -1 can be a valid result (i.e. for PTRACE_PEEK*)
-Error
-NativeProcessLinux::PtraceWrapper(int req, lldb::pid_t pid, void *addr, void *data, size_t data_size, long *result)
-{
- Error error;
- long int ret;
+void NativeProcessLinux::SignalIfAllThreadsStopped() {
+ if (m_pending_notification_tid == LLDB_INVALID_THREAD_ID)
+ return; // No pending notification. Nothing to do.
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PTRACE));
+ for (const auto &thread_sp : m_threads) {
+ if (StateIsRunningState(thread_sp->GetState()))
+ return; // Some threads are still running. Don't signal yet.
+ }
- PtraceDisplayBytes(req, data, data_size);
+ // We have a pending notification and all threads have stopped.
+ Log *log(
+ GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_BREAKPOINTS));
- errno = 0;
- if (req == PTRACE_GETREGSET || req == PTRACE_SETREGSET)
- ret = ptrace(static_cast<__ptrace_request>(req), static_cast< ::pid_t>(pid), *(unsigned int *)addr, data);
- else
- ret = ptrace(static_cast<__ptrace_request>(req), static_cast< ::pid_t>(pid), addr, data);
+ // Clear any temporary breakpoints we used to implement software single
+ // stepping.
+ 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());
+ }
+ m_threads_stepping_with_breakpoint.clear();
+
+ // Notify the delegate about the stop
+ SetCurrentThreadID(m_pending_notification_tid);
+ SetState(StateType::eStateStopped, true);
+ m_pending_notification_tid = LLDB_INVALID_THREAD_ID;
+}
+
+void NativeProcessLinux::ThreadWasCreated(NativeThreadLinux &thread) {
+ Log *const log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD);
+
+ if (log)
+ log->Printf("NativeProcessLinux::%s (tid: %" PRIu64 ")", __FUNCTION__,
+ thread.GetID());
+
+ if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID &&
+ StateIsRunningState(thread.GetState())) {
+ // We will need to wait for this new thread to stop as well before firing
+ // the
+ // notification.
+ thread.RequestStop();
+ }
+}
+
+void NativeProcessLinux::SigchldHandler() {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ // Process all pending waitpid notifications.
+ while (true) {
+ int status = -1;
+ ::pid_t wait_pid = waitpid(-1, &status, __WALL | __WNOTHREAD | WNOHANG);
- if (ret == -1)
- error.SetErrorToErrno();
+ if (wait_pid == 0)
+ break; // We are done.
- if (result)
- *result = ret;
+ if (wait_pid == -1) {
+ if (errno == EINTR)
+ continue;
+
+ Error error(errno, eErrorTypePOSIX);
+ if (log)
+ log->Printf("NativeProcessLinux::%s waitpid (-1, &status, __WALL | "
+ "__WNOTHREAD | WNOHANG) failed: %s",
+ __FUNCTION__, error.AsCString());
+ break;
+ }
+
+ bool exited = false;
+ int signal = 0;
+ int exit_status = 0;
+ const char *status_cstr = nullptr;
+ if (WIFSTOPPED(status)) {
+ signal = WSTOPSIG(status);
+ status_cstr = "STOPPED";
+ } else if (WIFEXITED(status)) {
+ exit_status = WEXITSTATUS(status);
+ status_cstr = "EXITED";
+ exited = true;
+ } else if (WIFSIGNALED(status)) {
+ signal = WTERMSIG(status);
+ status_cstr = "SIGNALED";
+ if (wait_pid == static_cast<::pid_t>(GetID())) {
+ exited = true;
+ exit_status = -1;
+ }
+ } else
+ status_cstr = "(\?\?\?)";
if (log)
- log->Printf("ptrace(%d, %" PRIu64 ", %p, %p, %zu)=%lX", req, pid, addr, data, data_size, ret);
+ 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);
- PtraceDisplayBytes(req, data, data_size);
+ MonitorCallback(wait_pid, exited, signal, exit_status);
+ }
+}
- 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);
+// Wrapper for ptrace to catch errors and log calls.
+// Note that ptrace sets errno on error because -1 can be a valid result (i.e.
+// for PTRACE_PEEK*)
+Error NativeProcessLinux::PtraceWrapper(int req, lldb::pid_t pid, void *addr,
+ void *data, size_t data_size,
+ long *result) {
+ Error error;
+ long int ret;
+
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
+
+ PtraceDisplayBytes(req, data, data_size);
+
+ errno = 0;
+ if (req == PTRACE_GETREGSET || req == PTRACE_SETREGSET)
+ ret = ptrace(static_cast<__ptrace_request>(req), static_cast<::pid_t>(pid),
+ *(unsigned int *)addr, data);
+ else
+ ret = ptrace(static_cast<__ptrace_request>(req), static_cast<::pid_t>(pid),
+ addr, data);
+
+ if (ret == -1)
+ error.SetErrorToErrno();
+
+ if (result)
+ *result = ret;
+
+ if (log)
+ log->Printf("ptrace(%d, %" PRIu64 ", %p, %p, %zu)=%lX", 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);
+ }
- return error;
+ return error;
}
diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h
index 7b1fcd8..fcb13c8 100644
--- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h
+++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h
@@ -15,186 +15,151 @@
// Other libraries and framework includes
#include "lldb/Core/ArchSpec.h"
-#include "lldb/lldb-types.h"
#include "lldb/Host/Debug.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/HostThread.h"
#include "lldb/Target/MemoryRegionInfo.h"
+#include "lldb/lldb-types.h"
-#include "lldb/Host/common/NativeProcessProtocol.h"
#include "NativeThreadLinux.h"
+#include "lldb/Host/common/NativeProcessProtocol.h"
namespace lldb_private {
- class Error;
- class Scalar;
+class Error;
+class Scalar;
namespace process_linux {
- /// @class NativeProcessLinux
- /// @brief Manages communication with the inferior (debugee) process.
- ///
- /// Upon construction, this class prepares and launches an inferior process for
- /// debugging.
- ///
- /// Changes in the inferior process state are broadcasted.
- class NativeProcessLinux: public NativeProcessProtocol
- {
- friend Error
- NativeProcessProtocol::Launch (ProcessLaunchInfo &launch_info,
- NativeDelegate &native_delegate,
- MainLoop &mainloop,
- NativeProcessProtocolSP &process_sp);
+/// @class NativeProcessLinux
+/// @brief Manages communication with the inferior (debugee) process.
+///
+/// Upon construction, this class prepares and launches an inferior process for
+/// debugging.
+///
+/// Changes in the inferior process state are broadcasted.
+class NativeProcessLinux : public NativeProcessProtocol {
+ friend Error NativeProcessProtocol::Launch(
+ ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate,
+ MainLoop &mainloop, NativeProcessProtocolSP &process_sp);
- friend Error
- NativeProcessProtocol::Attach (lldb::pid_t pid,
- NativeProcessProtocol::NativeDelegate &native_delegate,
- MainLoop &mainloop,
- NativeProcessProtocolSP &process_sp);
+ friend Error NativeProcessProtocol::Attach(
+ lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate,
+ MainLoop &mainloop, NativeProcessProtocolSP &process_sp);
- public:
- // ---------------------------------------------------------------------
- // NativeProcessProtocol Interface
- // ---------------------------------------------------------------------
- Error
- Resume (const ResumeActionList &resume_actions) override;
+public:
+ // ---------------------------------------------------------------------
+ // NativeProcessProtocol Interface
+ // ---------------------------------------------------------------------
+ Error Resume(const ResumeActionList &resume_actions) override;
- Error
- Halt () override;
+ Error Halt() override;
- Error
- Detach () override;
+ Error Detach() override;
- Error
- Signal (int signo) override;
+ Error Signal(int signo) override;
- Error
- Interrupt () override;
+ Error Interrupt() override;
- Error
- Kill () override;
+ Error Kill() override;
- Error
- GetMemoryRegionInfo (lldb::addr_t load_addr, MemoryRegionInfo &range_info) override;
+ Error GetMemoryRegionInfo(lldb::addr_t load_addr,
+ MemoryRegionInfo &range_info) override;
- Error
- ReadMemory(lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read) override;
+ Error ReadMemory(lldb::addr_t addr, void *buf, size_t size,
+ size_t &bytes_read) override;
- Error
- ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read) override;
+ Error ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf, size_t size,
+ size_t &bytes_read) override;
- Error
- WriteMemory(lldb::addr_t addr, const void *buf, size_t size, size_t &bytes_written) override;
+ Error WriteMemory(lldb::addr_t addr, const void *buf, size_t size,
+ size_t &bytes_written) override;
- Error
- AllocateMemory(size_t size, uint32_t permissions, lldb::addr_t &addr) override;
+ Error AllocateMemory(size_t size, uint32_t permissions,
+ lldb::addr_t &addr) override;
- Error
- DeallocateMemory (lldb::addr_t addr) override;
+ Error DeallocateMemory(lldb::addr_t addr) override;
- lldb::addr_t
- GetSharedLibraryInfoAddress () override;
+ lldb::addr_t GetSharedLibraryInfoAddress() override;
- size_t
- UpdateThreads () override;
+ size_t UpdateThreads() override;
- bool
- GetArchitecture (ArchSpec &arch) const override;
+ bool GetArchitecture(ArchSpec &arch) const override;
- Error
- SetBreakpoint (lldb::addr_t addr, uint32_t size, bool hardware) override;
+ Error SetBreakpoint(lldb::addr_t addr, uint32_t size, bool hardware) override;
- void
- DoStopIDBumped (uint32_t newBumpId) override;
+ void DoStopIDBumped(uint32_t newBumpId) override;
- Error
- GetLoadedModuleFileSpec(const char* module_path, FileSpec& file_spec) override;
+ Error GetLoadedModuleFileSpec(const char *module_path,
+ FileSpec &file_spec) override;
- Error
- GetFileLoadAddress(const llvm::StringRef& file_name, lldb::addr_t& load_addr) override;
+ Error GetFileLoadAddress(const llvm::StringRef &file_name,
+ lldb::addr_t &load_addr) override;
- NativeThreadLinuxSP
- GetThreadByID(lldb::tid_t id);
+ NativeThreadLinuxSP GetThreadByID(lldb::tid_t id);
- // ---------------------------------------------------------------------
- // Interface used by NativeRegisterContext-derived classes.
- // ---------------------------------------------------------------------
- static Error
- PtraceWrapper(int req,
- lldb::pid_t pid,
- void *addr = nullptr,
- void *data = nullptr,
- size_t data_size = 0,
- long *result = nullptr);
+ // ---------------------------------------------------------------------
+ // Interface used by NativeRegisterContext-derived classes.
+ // ---------------------------------------------------------------------
+ static Error PtraceWrapper(int req, lldb::pid_t pid, void *addr = nullptr,
+ void *data = nullptr, size_t data_size = 0,
+ long *result = nullptr);
- bool
- SupportHardwareSingleStepping() const;
+ bool SupportHardwareSingleStepping() const;
- protected:
- // ---------------------------------------------------------------------
- // NativeProcessProtocol protected interface
- // ---------------------------------------------------------------------
- Error
- GetSoftwareBreakpointTrapOpcode (size_t trap_opcode_size_hint, size_t &actual_opcode_size, const uint8_t *&trap_opcode_bytes) override;
+protected:
+ // ---------------------------------------------------------------------
+ // NativeProcessProtocol protected interface
+ // ---------------------------------------------------------------------
+ Error
+ GetSoftwareBreakpointTrapOpcode(size_t trap_opcode_size_hint,
+ size_t &actual_opcode_size,
+ const uint8_t *&trap_opcode_bytes) override;
- private:
+private:
+ MainLoop::SignalHandleUP m_sigchld_handle;
+ ArchSpec m_arch;
- MainLoop::SignalHandleUP m_sigchld_handle;
- ArchSpec m_arch;
+ LazyBool m_supports_mem_region;
+ std::vector<MemoryRegionInfo> m_mem_region_cache;
- LazyBool m_supports_mem_region;
- std::vector<MemoryRegionInfo> m_mem_region_cache;
+ lldb::tid_t m_pending_notification_tid;
- lldb::tid_t m_pending_notification_tid;
+ // List of thread ids stepping with a breakpoint with the address of
+ // the relevan breakpoint
+ std::map<lldb::tid_t, lldb::addr_t> m_threads_stepping_with_breakpoint;
- // List of thread ids stepping with a breakpoint with the address of
- // the relevan breakpoint
- std::map<lldb::tid_t, lldb::addr_t> m_threads_stepping_with_breakpoint;
+ // ---------------------------------------------------------------------
+ // Private Instance Methods
+ // ---------------------------------------------------------------------
+ NativeProcessLinux();
+ Error LaunchInferior(MainLoop &mainloop, ProcessLaunchInfo &launch_info);
- // ---------------------------------------------------------------------
- // Private Instance Methods
- // ---------------------------------------------------------------------
- NativeProcessLinux ();
+ /// Attaches to an existing process. Forms the
+ /// implementation of Process::DoAttach
+ void AttachToInferior(MainLoop &mainloop, lldb::pid_t pid, Error &error);
- Error
- LaunchInferior(MainLoop &mainloop, ProcessLaunchInfo &launch_info);
+ ::pid_t Attach(lldb::pid_t pid, Error &error);
- /// Attaches to an existing process. Forms the
- /// implementation of Process::DoAttach
- void
- AttachToInferior (MainLoop &mainloop, lldb::pid_t pid, Error &error);
+ static Error SetDefaultPtraceOpts(const lldb::pid_t);
- ::pid_t
- Attach(lldb::pid_t pid, Error &error);
+ static void *MonitorThread(void *baton);
- static Error
- SetDefaultPtraceOpts(const lldb::pid_t);
+ void MonitorCallback(lldb::pid_t pid, bool exited, int signal, int status);
- static void *
- MonitorThread(void *baton);
+ void WaitForNewThread(::pid_t tid);
- void
- MonitorCallback(lldb::pid_t pid, bool exited, int signal, int status);
+ void MonitorSIGTRAP(const siginfo_t &info, NativeThreadLinux &thread);
- void
- WaitForNewThread(::pid_t tid);
+ void MonitorTrace(NativeThreadLinux &thread);
- void
- MonitorSIGTRAP(const siginfo_t &info, NativeThreadLinux &thread);
+ void MonitorBreakpoint(NativeThreadLinux &thread);
- void
- MonitorTrace(NativeThreadLinux &thread);
+ void MonitorWatchpoint(NativeThreadLinux &thread, uint32_t wp_index);
- void
- MonitorBreakpoint(NativeThreadLinux &thread);
+ void MonitorSignal(const siginfo_t &info, NativeThreadLinux &thread,
+ bool exited);
- void
- MonitorWatchpoint(NativeThreadLinux &thread, uint32_t wp_index);
-
- void
- MonitorSignal(const siginfo_t &info, NativeThreadLinux &thread, bool exited);
-
- Error
- SetupSoftwareSingleStepping(NativeThreadLinux &thread);
+ Error SetupSoftwareSingleStepping(NativeThreadLinux &thread);
#if 0
static ::ProcessMessage::CrashReason
@@ -210,59 +175,49 @@ namespace process_linux {
GetCrashReasonForSIGBUS(const siginfo_t *info);
#endif
- bool
- HasThreadNoLock (lldb::tid_t thread_id);
-
- bool
- StopTrackingThread (lldb::tid_t thread_id);
+ bool HasThreadNoLock(lldb::tid_t thread_id);
- NativeThreadLinuxSP
- AddThread (lldb::tid_t thread_id);
+ bool StopTrackingThread(lldb::tid_t thread_id);
- Error
- GetSoftwareBreakpointPCOffset(uint32_t &actual_opcode_size);
+ NativeThreadLinuxSP AddThread(lldb::tid_t thread_id);
- Error
- FixupBreakpointPCAsNeeded(NativeThreadLinux &thread);
+ Error GetSoftwareBreakpointPCOffset(uint32_t &actual_opcode_size);
- /// Writes a siginfo_t structure corresponding to the given thread ID to the
- /// memory region pointed to by @p siginfo.
- Error
- GetSignalInfo(lldb::tid_t tid, void *siginfo);
+ Error FixupBreakpointPCAsNeeded(NativeThreadLinux &thread);
- /// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG)
- /// corresponding to the given thread ID to the memory pointed to by @p
- /// message.
- Error
- GetEventMessage(lldb::tid_t tid, unsigned long *message);
+ /// Writes a siginfo_t structure corresponding to the given thread ID to the
+ /// memory region pointed to by @p siginfo.
+ Error GetSignalInfo(lldb::tid_t tid, void *siginfo);
- void
- NotifyThreadDeath (lldb::tid_t tid);
+ /// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG)
+ /// corresponding to the given thread ID to the memory pointed to by @p
+ /// message.
+ Error GetEventMessage(lldb::tid_t tid, unsigned long *message);
- Error
- Detach(lldb::tid_t tid);
+ void NotifyThreadDeath(lldb::tid_t tid);
+ Error Detach(lldb::tid_t tid);
- // This method is requests a stop on all threads which are still running. It sets up a
- // deferred delegate notification, which will fire once threads report as stopped. The
- // triggerring_tid will be set as the current thread (main stop reason).
- void
- StopRunningThreads(lldb::tid_t triggering_tid);
+ // This method is requests a stop on all threads which are still running. It
+ // sets up a
+ // deferred delegate notification, which will fire once threads report as
+ // stopped. The
+ // triggerring_tid will be set as the current thread (main stop reason).
+ void StopRunningThreads(lldb::tid_t triggering_tid);
- // Notify the delegate if all threads have stopped.
- void SignalIfAllThreadsStopped();
+ // Notify the delegate if all threads have stopped.
+ void SignalIfAllThreadsStopped();
- // Resume the given thread, optionally passing it the given signal. The type of resume
- // operation (continue, single-step) depends on the state parameter.
- Error
- ResumeThread(NativeThreadLinux &thread, lldb::StateType state, int signo);
+ // Resume the given thread, optionally passing it the given signal. The type
+ // of resume
+ // operation (continue, single-step) depends on the state parameter.
+ Error ResumeThread(NativeThreadLinux &thread, lldb::StateType state,
+ int signo);
- void
- ThreadWasCreated(NativeThreadLinux &thread);
+ void ThreadWasCreated(NativeThreadLinux &thread);
- void
- SigchldHandler();
- };
+ void SigchldHandler();
+};
} // namespace process_linux
} // namespace lldb_private
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp
index df0a008..a59a288 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp
@@ -19,212 +19,195 @@
using namespace lldb_private;
using namespace lldb_private::process_linux;
-NativeRegisterContextLinux::NativeRegisterContextLinux(NativeThreadProtocol &native_thread,
- uint32_t concrete_frame_idx,
- RegisterInfoInterface *reg_info_interface_p) :
- NativeRegisterContextRegisterInfo(native_thread, concrete_frame_idx, reg_info_interface_p)
-{}
-
-lldb::ByteOrder
-NativeRegisterContextLinux::GetByteOrder() const
-{
- // Get the target process whose privileged thread was used for the register read.
- lldb::ByteOrder byte_order = lldb::eByteOrderInvalid;
-
- NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
- if (!process_sp)
- return byte_order;
-
- if (!process_sp->GetByteOrder (byte_order))
- {
- // FIXME log here
- }
-
+NativeRegisterContextLinux::NativeRegisterContextLinux(
+ NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx,
+ RegisterInfoInterface *reg_info_interface_p)
+ : NativeRegisterContextRegisterInfo(native_thread, concrete_frame_idx,
+ reg_info_interface_p) {}
+
+lldb::ByteOrder NativeRegisterContextLinux::GetByteOrder() const {
+ // Get the target process whose privileged thread was used for the register
+ // read.
+ lldb::ByteOrder byte_order = lldb::eByteOrderInvalid;
+
+ NativeProcessProtocolSP process_sp(m_thread.GetProcess());
+ if (!process_sp)
return byte_order;
-}
-Error
-NativeRegisterContextLinux::ReadRegisterRaw(uint32_t reg_index, RegisterValue &reg_value)
-{
- const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(reg_index);
- if (!reg_info)
- return Error("register %" PRIu32 " not found", reg_index);
+ if (!process_sp->GetByteOrder(byte_order)) {
+ // FIXME log here
+ }
- return DoReadRegisterValue(reg_info->byte_offset, reg_info->name, reg_info->byte_size, reg_value);
+ return byte_order;
}
-Error
-NativeRegisterContextLinux::WriteRegisterRaw(uint32_t reg_index, const RegisterValue &reg_value)
-{
- uint32_t reg_to_write = reg_index;
- RegisterValue value_to_write = reg_value;
-
- // Check if this is a subregister of a full register.
- const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_index);
- if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM))
- {
- Error error;
-
- RegisterValue full_value;
- uint32_t full_reg = reg_info->invalidate_regs[0];
- const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
-
- // Read the full register.
- error = ReadRegister(full_reg_info, full_value);
- if (error.Fail ())
- return error;
-
- lldb::ByteOrder byte_order = GetByteOrder();
- uint8_t dst[RegisterValue::kMaxRegisterByteSize];
-
- // Get the bytes for the full register.
- const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info,
- dst,
- sizeof(dst),
- byte_order,
- error);
- if (error.Success() && dest_size)
- {
- uint8_t src[RegisterValue::kMaxRegisterByteSize];
-
- // Get the bytes for the source data.
- const uint32_t src_size = reg_value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error);
- if (error.Success() && src_size && (src_size < dest_size))
- {
- // Copy the src bytes to the destination.
- memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size);
- // Set this full register as the value to write.
- value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
- value_to_write.SetType(full_reg_info);
- reg_to_write = full_reg;
- }
- }
- }
+Error NativeRegisterContextLinux::ReadRegisterRaw(uint32_t reg_index,
+ RegisterValue &reg_value) {
+ const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(reg_index);
+ if (!reg_info)
+ return Error("register %" PRIu32 " not found", reg_index);
- const RegisterInfo *const register_to_write_info_p = GetRegisterInfoAtIndex (reg_to_write);
- assert (register_to_write_info_p && "register to write does not have valid RegisterInfo");
- if (!register_to_write_info_p)
- return Error("NativeRegisterContextLinux::%s failed to get RegisterInfo for write register index %" PRIu32, __FUNCTION__, reg_to_write);
+ return DoReadRegisterValue(reg_info->byte_offset, reg_info->name,
+ reg_info->byte_size, reg_value);
+}
- return DoWriteRegisterValue(reg_info->byte_offset, reg_info->name, reg_value);
+Error NativeRegisterContextLinux::WriteRegisterRaw(
+ uint32_t reg_index, const RegisterValue &reg_value) {
+ uint32_t reg_to_write = reg_index;
+ RegisterValue value_to_write = reg_value;
+
+ // Check if this is a subregister of a full register.
+ const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_index);
+ if (reg_info->invalidate_regs &&
+ (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) {
+ Error error;
+
+ RegisterValue full_value;
+ uint32_t full_reg = reg_info->invalidate_regs[0];
+ const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
+
+ // Read the full register.
+ error = ReadRegister(full_reg_info, full_value);
+ if (error.Fail())
+ return error;
+
+ lldb::ByteOrder byte_order = GetByteOrder();
+ uint8_t dst[RegisterValue::kMaxRegisterByteSize];
+
+ // Get the bytes for the full register.
+ const uint32_t dest_size = full_value.GetAsMemoryData(
+ full_reg_info, dst, sizeof(dst), byte_order, error);
+ if (error.Success() && dest_size) {
+ uint8_t src[RegisterValue::kMaxRegisterByteSize];
+
+ // Get the bytes for the source data.
+ const uint32_t src_size = reg_value.GetAsMemoryData(
+ reg_info, src, sizeof(src), byte_order, error);
+ if (error.Success() && src_size && (src_size < dest_size)) {
+ // Copy the src bytes to the destination.
+ memcpy(dst + (reg_info->byte_offset & 0x1), src, src_size);
+ // Set this full register as the value to write.
+ value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
+ value_to_write.SetType(full_reg_info);
+ reg_to_write = full_reg;
+ }
+ }
+ }
+
+ const RegisterInfo *const register_to_write_info_p =
+ GetRegisterInfoAtIndex(reg_to_write);
+ assert(register_to_write_info_p &&
+ "register to write does not have valid RegisterInfo");
+ if (!register_to_write_info_p)
+ return Error("NativeRegisterContextLinux::%s failed to get RegisterInfo "
+ "for write register index %" PRIu32,
+ __FUNCTION__, reg_to_write);
+
+ return DoWriteRegisterValue(reg_info->byte_offset, reg_info->name, reg_value);
}
-Error
-NativeRegisterContextLinux::ReadGPR()
-{
- void* buf = GetGPRBuffer();
- if (!buf)
- return Error("GPR buffer is NULL");
- size_t buf_size = GetGPRSize();
+Error NativeRegisterContextLinux::ReadGPR() {
+ void *buf = GetGPRBuffer();
+ if (!buf)
+ return Error("GPR buffer is NULL");
+ size_t buf_size = GetGPRSize();
- return DoReadGPR(buf, buf_size);
+ return DoReadGPR(buf, buf_size);
}
-Error
-NativeRegisterContextLinux::WriteGPR()
-{
- void* buf = GetGPRBuffer();
- if (!buf)
- return Error("GPR buffer is NULL");
- size_t buf_size = GetGPRSize();
+Error NativeRegisterContextLinux::WriteGPR() {
+ void *buf = GetGPRBuffer();
+ if (!buf)
+ return Error("GPR buffer is NULL");
+ size_t buf_size = GetGPRSize();
- return DoWriteGPR(buf, buf_size);
+ return DoWriteGPR(buf, buf_size);
}
-Error
-NativeRegisterContextLinux::ReadFPR()
-{
- void* buf = GetFPRBuffer();
- if (!buf)
- return Error("FPR buffer is NULL");
- size_t buf_size = GetFPRSize();
+Error NativeRegisterContextLinux::ReadFPR() {
+ void *buf = GetFPRBuffer();
+ if (!buf)
+ return Error("FPR buffer is NULL");
+ size_t buf_size = GetFPRSize();
- return DoReadFPR(buf, buf_size);
+ return DoReadFPR(buf, buf_size);
}
-Error
-NativeRegisterContextLinux::WriteFPR()
-{
- void* buf = GetFPRBuffer();
- if (!buf)
- return Error("FPR buffer is NULL");
- size_t buf_size = GetFPRSize();
+Error NativeRegisterContextLinux::WriteFPR() {
+ void *buf = GetFPRBuffer();
+ if (!buf)
+ return Error("FPR buffer is NULL");
+ size_t buf_size = GetFPRSize();
- return DoWriteFPR(buf, buf_size);
+ return DoWriteFPR(buf, buf_size);
}
-Error
-NativeRegisterContextLinux::ReadRegisterSet(void *buf, size_t buf_size, unsigned int regset)
-{
- return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_thread.GetID(),
- static_cast<void *>(&regset), buf, buf_size);
+Error NativeRegisterContextLinux::ReadRegisterSet(void *buf, size_t buf_size,
+ unsigned int regset) {
+ return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_thread.GetID(),
+ static_cast<void *>(&regset), buf,
+ buf_size);
}
-Error
-NativeRegisterContextLinux::WriteRegisterSet(void *buf, size_t buf_size, unsigned int regset)
-{
- return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(),
- static_cast<void *>(&regset), buf, buf_size);
+Error NativeRegisterContextLinux::WriteRegisterSet(void *buf, size_t buf_size,
+ unsigned int regset) {
+ return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(),
+ static_cast<void *>(&regset), buf,
+ buf_size);
}
-Error
-NativeRegisterContextLinux::DoReadRegisterValue(uint32_t offset,
- const char* reg_name,
- uint32_t size,
- RegisterValue &value)
-{
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS));
+Error NativeRegisterContextLinux::DoReadRegisterValue(uint32_t offset,
+ const char *reg_name,
+ uint32_t size,
+ RegisterValue &value) {
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_REGISTERS));
- long data;
- Error error = NativeProcessLinux::PtraceWrapper(
- PTRACE_PEEKUSER, m_thread.GetID(), reinterpret_cast<void *>(offset), nullptr, 0, &data);
+ long data;
+ Error error = NativeProcessLinux::PtraceWrapper(
+ PTRACE_PEEKUSER, m_thread.GetID(), reinterpret_cast<void *>(offset),
+ nullptr, 0, &data);
- if (error.Success())
- // First cast to an unsigned of the same size to avoid sign extension.
- value.SetUInt64(static_cast<unsigned long>(data));
+ if (error.Success())
+ // First cast to an unsigned of the same size to avoid sign extension.
+ value.SetUInt64(static_cast<unsigned long>(data));
- if (log)
- log->Printf ("NativeRegisterContextLinux::%s() reg %s: 0x%lx", __FUNCTION__, reg_name, data);
+ if (log)
+ log->Printf("NativeRegisterContextLinux::%s() reg %s: 0x%lx", __FUNCTION__,
+ reg_name, data);
- return error;
+ return error;
}
-Error
-NativeRegisterContextLinux::DoWriteRegisterValue(uint32_t offset,
- const char* reg_name,
- const RegisterValue &value)
-{
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS));
+Error NativeRegisterContextLinux::DoWriteRegisterValue(
+ uint32_t offset, const char *reg_name, const RegisterValue &value) {
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_REGISTERS));
- void* buf = reinterpret_cast<void *>(value.GetAsUInt64());
+ void *buf = reinterpret_cast<void *>(value.GetAsUInt64());
- if (log)
- log->Printf ("NativeRegisterContextLinux::%s() reg %s: %p", __FUNCTION__, reg_name, buf);
+ if (log)
+ log->Printf("NativeRegisterContextLinux::%s() reg %s: %p", __FUNCTION__,
+ reg_name, buf);
- return NativeProcessLinux::PtraceWrapper(
- PTRACE_POKEUSER, m_thread.GetID(), reinterpret_cast<void *>(offset), buf);
+ return NativeProcessLinux::PtraceWrapper(
+ PTRACE_POKEUSER, m_thread.GetID(), reinterpret_cast<void *>(offset), buf);
}
-Error
-NativeRegisterContextLinux::DoReadGPR(void *buf, size_t buf_size)
-{
- return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGS, m_thread.GetID(), nullptr, buf, buf_size);
+Error NativeRegisterContextLinux::DoReadGPR(void *buf, size_t buf_size) {
+ return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGS, m_thread.GetID(),
+ nullptr, buf, buf_size);
}
-Error
-NativeRegisterContextLinux::DoWriteGPR(void *buf, size_t buf_size)
-{
- return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGS, m_thread.GetID(), nullptr, buf, buf_size);
+Error NativeRegisterContextLinux::DoWriteGPR(void *buf, size_t buf_size) {
+ return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGS, m_thread.GetID(),
+ nullptr, buf, buf_size);
}
-Error
-NativeRegisterContextLinux::DoReadFPR(void *buf, size_t buf_size)
-{
- return NativeProcessLinux::PtraceWrapper(PTRACE_GETFPREGS, m_thread.GetID(), nullptr, buf, buf_size);
+Error NativeRegisterContextLinux::DoReadFPR(void *buf, size_t buf_size) {
+ return NativeProcessLinux::PtraceWrapper(PTRACE_GETFPREGS, m_thread.GetID(),
+ nullptr, buf, buf_size);
}
-Error
-NativeRegisterContextLinux::DoWriteFPR(void *buf, size_t buf_size)
-{
- return NativeProcessLinux::PtraceWrapper(PTRACE_SETFPREGS, m_thread.GetID(), nullptr, buf, buf_size);
+Error NativeRegisterContextLinux::DoWriteFPR(void *buf, size_t buf_size) {
+ return NativeProcessLinux::PtraceWrapper(PTRACE_SETFPREGS, m_thread.GetID(),
+ nullptr, buf, buf_size);
}
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.h b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.h
index 0b0b747..a16c65b 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.h
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.h
@@ -18,87 +18,72 @@
namespace lldb_private {
namespace process_linux {
-class NativeRegisterContextLinux : public NativeRegisterContextRegisterInfo
-{
+class NativeRegisterContextLinux : public NativeRegisterContextRegisterInfo {
public:
- NativeRegisterContextLinux(NativeThreadProtocol &native_thread,
- uint32_t concrete_frame_idx,
- RegisterInfoInterface *reg_info_interface_p);
-
- // This function is implemented in the NativeRegisterContextLinux_* subclasses to create a new
- // instance of the host specific NativeRegisterContextLinux. The implementations can't collide
- // as only one NativeRegisterContextLinux_* variant should be compiled into the final
- // executable.
- static NativeRegisterContextLinux*
- CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch,
- NativeThreadProtocol &native_thread,
- uint32_t concrete_frame_idx);
+ NativeRegisterContextLinux(NativeThreadProtocol &native_thread,
+ uint32_t concrete_frame_idx,
+ RegisterInfoInterface *reg_info_interface_p);
+
+ // This function is implemented in the NativeRegisterContextLinux_* subclasses
+ // to create a new
+ // instance of the host specific NativeRegisterContextLinux. The
+ // implementations can't collide
+ // as only one NativeRegisterContextLinux_* variant should be compiled into
+ // the final
+ // executable.
+ static NativeRegisterContextLinux *
+ CreateHostNativeRegisterContextLinux(const ArchSpec &target_arch,
+ NativeThreadProtocol &native_thread,
+ uint32_t concrete_frame_idx);
protected:
- lldb::ByteOrder
- GetByteOrder() const;
+ lldb::ByteOrder GetByteOrder() const;
- virtual Error
- ReadRegisterRaw(uint32_t reg_index, RegisterValue& reg_value);
+ virtual Error ReadRegisterRaw(uint32_t reg_index, RegisterValue &reg_value);
- virtual Error
- WriteRegisterRaw(uint32_t reg_index, const RegisterValue& reg_value);
+ virtual Error WriteRegisterRaw(uint32_t reg_index,
+ const RegisterValue &reg_value);
- virtual Error
- ReadRegisterSet(void *buf, size_t buf_size, unsigned int regset);
+ virtual Error ReadRegisterSet(void *buf, size_t buf_size,
+ unsigned int regset);
- virtual Error
- WriteRegisterSet(void *buf, size_t buf_size, unsigned int regset);
+ virtual Error WriteRegisterSet(void *buf, size_t buf_size,
+ unsigned int regset);
- virtual Error
- ReadGPR();
+ virtual Error ReadGPR();
- virtual Error
- WriteGPR();
+ virtual Error WriteGPR();
- virtual Error
- ReadFPR();
+ virtual Error ReadFPR();
- virtual Error
- WriteFPR();
+ virtual Error WriteFPR();
- virtual void*
- GetGPRBuffer() { return nullptr; }
+ virtual void *GetGPRBuffer() { return nullptr; }
- virtual size_t
- GetGPRSize() { return GetRegisterInfoInterface().GetGPRSize(); }
+ virtual size_t GetGPRSize() {
+ return GetRegisterInfoInterface().GetGPRSize();
+ }
- virtual void*
- GetFPRBuffer() { return nullptr; }
+ virtual void *GetFPRBuffer() { return nullptr; }
- virtual size_t
- GetFPRSize() { return 0; }
+ virtual size_t GetFPRSize() { return 0; }
+ // The Do*** functions are executed on the privileged thread and can perform
+ // ptrace
+ // operations directly.
+ virtual Error DoReadRegisterValue(uint32_t offset, const char *reg_name,
+ uint32_t size, RegisterValue &value);
- // The Do*** functions are executed on the privileged thread and can perform ptrace
- // operations directly.
- virtual Error
- DoReadRegisterValue(uint32_t offset,
- const char* reg_name,
- uint32_t size,
- RegisterValue &value);
+ virtual Error DoWriteRegisterValue(uint32_t offset, const char *reg_name,
+ const RegisterValue &value);
- virtual Error
- DoWriteRegisterValue(uint32_t offset,
- const char* reg_name,
- const RegisterValue &value);
+ virtual Error DoReadGPR(void *buf, size_t buf_size);
- virtual Error
- DoReadGPR(void *buf, size_t buf_size);
+ virtual Error DoWriteGPR(void *buf, size_t buf_size);
- virtual Error
- DoWriteGPR(void *buf, size_t buf_size);
+ virtual Error DoReadFPR(void *buf, size_t buf_size);
- virtual Error
- DoReadFPR(void *buf, size_t buf_size);
-
- virtual Error
- DoWriteFPR(void *buf, size_t buf_size);
+ virtual Error DoWriteFPR(void *buf, size_t buf_size);
};
} // namespace process_linux
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
index 5dfbaff..758d5e7 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
@@ -22,21 +22,21 @@
#include <elf.h>
#include <sys/socket.h>
-#define REG_CONTEXT_SIZE (GetGPRSize() + sizeof (m_fpr))
+#define REG_CONTEXT_SIZE (GetGPRSize() + sizeof(m_fpr))
#ifndef PTRACE_GETVFPREGS
- #define PTRACE_GETVFPREGS 27
- #define PTRACE_SETVFPREGS 28
+#define PTRACE_GETVFPREGS 27
+#define PTRACE_SETVFPREGS 28
#endif
#ifndef PTRACE_GETHBPREGS
- #define PTRACE_GETHBPREGS 29
- #define PTRACE_SETHBPREGS 30
+#define PTRACE_GETHBPREGS 29
+#define PTRACE_SETHBPREGS 30
#endif
#if !defined(PTRACE_TYPE_ARG3)
- #define PTRACE_TYPE_ARG3 void *
+#define PTRACE_TYPE_ARG3 void *
#endif
#if !defined(PTRACE_TYPE_ARG4)
- #define PTRACE_TYPE_ARG4 void *
+#define PTRACE_TYPE_ARG4 void *
#endif
using namespace lldb;
@@ -44,1084 +44,933 @@ using namespace lldb_private;
using namespace lldb_private::process_linux;
// arm general purpose registers.
-static const uint32_t g_gpr_regnums_arm[] =
-{
- gpr_r0_arm,
- gpr_r1_arm,
- gpr_r2_arm,
- gpr_r3_arm,
- gpr_r4_arm,
- gpr_r5_arm,
- gpr_r6_arm,
- gpr_r7_arm,
- gpr_r8_arm,
- gpr_r9_arm,
- gpr_r10_arm,
- gpr_r11_arm,
- gpr_r12_arm,
- gpr_sp_arm,
- gpr_lr_arm,
- gpr_pc_arm,
- gpr_cpsr_arm,
+static const uint32_t g_gpr_regnums_arm[] = {
+ gpr_r0_arm, gpr_r1_arm, gpr_r2_arm, gpr_r3_arm, gpr_r4_arm,
+ gpr_r5_arm, gpr_r6_arm, gpr_r7_arm, gpr_r8_arm, gpr_r9_arm,
+ gpr_r10_arm, gpr_r11_arm, gpr_r12_arm, gpr_sp_arm, gpr_lr_arm,
+ gpr_pc_arm, gpr_cpsr_arm,
LLDB_INVALID_REGNUM // register sets need to end with this flag
};
-static_assert(((sizeof g_gpr_regnums_arm / sizeof g_gpr_regnums_arm[0]) - 1) == k_num_gpr_registers_arm, \
+static_assert(((sizeof g_gpr_regnums_arm / sizeof g_gpr_regnums_arm[0]) - 1) ==
+ k_num_gpr_registers_arm,
"g_gpr_regnums_arm has wrong number of register infos");
// arm floating point registers.
-static const uint32_t g_fpu_regnums_arm[] =
-{
- fpu_s0_arm,
- fpu_s1_arm,
- fpu_s2_arm,
- fpu_s3_arm,
- fpu_s4_arm,
- fpu_s5_arm,
- fpu_s6_arm,
- fpu_s7_arm,
- fpu_s8_arm,
- fpu_s9_arm,
- fpu_s10_arm,
- fpu_s11_arm,
- fpu_s12_arm,
- fpu_s13_arm,
- fpu_s14_arm,
- fpu_s15_arm,
- fpu_s16_arm,
- fpu_s17_arm,
- fpu_s18_arm,
- fpu_s19_arm,
- fpu_s20_arm,
- fpu_s21_arm,
- fpu_s22_arm,
- fpu_s23_arm,
- fpu_s24_arm,
- fpu_s25_arm,
- fpu_s26_arm,
- fpu_s27_arm,
- fpu_s28_arm,
- fpu_s29_arm,
- fpu_s30_arm,
- fpu_s31_arm,
- fpu_fpscr_arm,
- fpu_d0_arm,
- fpu_d1_arm,
- fpu_d2_arm,
- fpu_d3_arm,
- fpu_d4_arm,
- fpu_d5_arm,
- fpu_d6_arm,
- fpu_d7_arm,
- fpu_d8_arm,
- fpu_d9_arm,
- fpu_d10_arm,
- fpu_d11_arm,
- fpu_d12_arm,
- fpu_d13_arm,
- fpu_d14_arm,
- fpu_d15_arm,
- fpu_d16_arm,
- fpu_d17_arm,
- fpu_d18_arm,
- fpu_d19_arm,
- fpu_d20_arm,
- fpu_d21_arm,
- fpu_d22_arm,
- fpu_d23_arm,
- fpu_d24_arm,
- fpu_d25_arm,
- fpu_d26_arm,
- fpu_d27_arm,
- fpu_d28_arm,
- fpu_d29_arm,
- fpu_d30_arm,
- fpu_d31_arm,
- fpu_q0_arm,
- fpu_q1_arm,
- fpu_q2_arm,
- fpu_q3_arm,
- fpu_q4_arm,
- fpu_q5_arm,
- fpu_q6_arm,
- fpu_q7_arm,
- fpu_q8_arm,
- fpu_q9_arm,
- fpu_q10_arm,
- fpu_q11_arm,
- fpu_q12_arm,
- fpu_q13_arm,
- fpu_q14_arm,
+static const uint32_t g_fpu_regnums_arm[] = {
+ fpu_s0_arm, fpu_s1_arm, fpu_s2_arm, fpu_s3_arm, fpu_s4_arm,
+ fpu_s5_arm, fpu_s6_arm, fpu_s7_arm, fpu_s8_arm, fpu_s9_arm,
+ fpu_s10_arm, fpu_s11_arm, fpu_s12_arm, fpu_s13_arm, fpu_s14_arm,
+ fpu_s15_arm, fpu_s16_arm, fpu_s17_arm, fpu_s18_arm, fpu_s19_arm,
+ fpu_s20_arm, fpu_s21_arm, fpu_s22_arm, fpu_s23_arm, fpu_s24_arm,
+ fpu_s25_arm, fpu_s26_arm, fpu_s27_arm, fpu_s28_arm, fpu_s29_arm,
+ fpu_s30_arm, fpu_s31_arm, fpu_fpscr_arm, fpu_d0_arm, fpu_d1_arm,
+ fpu_d2_arm, fpu_d3_arm, fpu_d4_arm, fpu_d5_arm, fpu_d6_arm,
+ fpu_d7_arm, fpu_d8_arm, fpu_d9_arm, fpu_d10_arm, fpu_d11_arm,
+ fpu_d12_arm, fpu_d13_arm, fpu_d14_arm, fpu_d15_arm, fpu_d16_arm,
+ fpu_d17_arm, fpu_d18_arm, fpu_d19_arm, fpu_d20_arm, fpu_d21_arm,
+ fpu_d22_arm, fpu_d23_arm, fpu_d24_arm, fpu_d25_arm, fpu_d26_arm,
+ fpu_d27_arm, fpu_d28_arm, fpu_d29_arm, fpu_d30_arm, fpu_d31_arm,
+ fpu_q0_arm, fpu_q1_arm, fpu_q2_arm, fpu_q3_arm, fpu_q4_arm,
+ fpu_q5_arm, fpu_q6_arm, fpu_q7_arm, fpu_q8_arm, fpu_q9_arm,
+ fpu_q10_arm, fpu_q11_arm, fpu_q12_arm, fpu_q13_arm, fpu_q14_arm,
fpu_q15_arm,
LLDB_INVALID_REGNUM // register sets need to end with this flag
};
-static_assert(((sizeof g_fpu_regnums_arm / sizeof g_fpu_regnums_arm[0]) - 1) == k_num_fpr_registers_arm, \
+static_assert(((sizeof g_fpu_regnums_arm / sizeof g_fpu_regnums_arm[0]) - 1) ==
+ k_num_fpr_registers_arm,
"g_fpu_regnums_arm has wrong number of register infos");
namespace {
- // Number of register sets provided by this context.
- enum
- {
- k_num_register_sets = 2
- };
+// Number of register sets provided by this context.
+enum { k_num_register_sets = 2 };
}
// Register sets for arm.
-static const RegisterSet
-g_reg_sets_arm[k_num_register_sets] =
-{
- { "General Purpose Registers", "gpr", k_num_gpr_registers_arm, g_gpr_regnums_arm },
- { "Floating Point Registers", "fpu", k_num_fpr_registers_arm, g_fpu_regnums_arm }
-};
+static const RegisterSet g_reg_sets_arm[k_num_register_sets] = {
+ {"General Purpose Registers", "gpr", k_num_gpr_registers_arm,
+ g_gpr_regnums_arm},
+ {"Floating Point Registers", "fpu", k_num_fpr_registers_arm,
+ g_fpu_regnums_arm}};
#if defined(__arm__)
-NativeRegisterContextLinux*
-NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch,
- NativeThreadProtocol &native_thread,
- uint32_t concrete_frame_idx)
-{
- return new NativeRegisterContextLinux_arm(target_arch, native_thread, concrete_frame_idx);
+NativeRegisterContextLinux *
+NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
+ const ArchSpec &target_arch, NativeThreadProtocol &native_thread,
+ uint32_t concrete_frame_idx) {
+ return new NativeRegisterContextLinux_arm(target_arch, native_thread,
+ concrete_frame_idx);
}
#endif // defined(__arm__)
-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))
-{
- switch (target_arch.GetMachine())
- {
- case llvm::Triple::arm:
- m_reg_info.num_registers = k_num_registers_arm;
- m_reg_info.num_gpr_registers = k_num_gpr_registers_arm;
- m_reg_info.num_fpr_registers = k_num_fpr_registers_arm;
- m_reg_info.last_gpr = k_last_gpr_arm;
- m_reg_info.first_fpr = k_first_fpr_arm;
- m_reg_info.last_fpr = k_last_fpr_arm;
- m_reg_info.first_fpr_v = fpu_s0_arm;
- m_reg_info.last_fpr_v = fpu_s31_arm;
- m_reg_info.gpr_flags = gpr_cpsr_arm;
- break;
- default:
- assert(false && "Unhandled target architecture.");
- break;
- }
-
- ::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));
-
- // 16 is just a maximum value, query hardware for actual watchpoint count
- m_max_hwp_supported = 16;
- m_max_hbp_supported = 16;
- m_refresh_hwdebug_info = true;
+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)) {
+ switch (target_arch.GetMachine()) {
+ case llvm::Triple::arm:
+ m_reg_info.num_registers = k_num_registers_arm;
+ m_reg_info.num_gpr_registers = k_num_gpr_registers_arm;
+ m_reg_info.num_fpr_registers = k_num_fpr_registers_arm;
+ m_reg_info.last_gpr = k_last_gpr_arm;
+ m_reg_info.first_fpr = k_first_fpr_arm;
+ m_reg_info.last_fpr = k_last_fpr_arm;
+ m_reg_info.first_fpr_v = fpu_s0_arm;
+ m_reg_info.last_fpr_v = fpu_s31_arm;
+ m_reg_info.gpr_flags = gpr_cpsr_arm;
+ break;
+ default:
+ assert(false && "Unhandled target architecture.");
+ break;
+ }
+
+ ::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));
+
+ // 16 is just a maximum value, query hardware for actual watchpoint count
+ m_max_hwp_supported = 16;
+ m_max_hbp_supported = 16;
+ m_refresh_hwdebug_info = true;
+}
+
+uint32_t NativeRegisterContextLinux_arm::GetRegisterSetCount() const {
+ return k_num_register_sets;
+}
+
+uint32_t NativeRegisterContextLinux_arm::GetUserRegisterCount() const {
+ uint32_t count = 0;
+ for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index)
+ count += g_reg_sets_arm[set_index].num_registers;
+ return count;
}
-uint32_t
-NativeRegisterContextLinux_arm::GetRegisterSetCount () const
-{
- return k_num_register_sets;
-}
+const RegisterSet *
+NativeRegisterContextLinux_arm::GetRegisterSet(uint32_t set_index) const {
+ if (set_index < k_num_register_sets)
+ return &g_reg_sets_arm[set_index];
-uint32_t
-NativeRegisterContextLinux_arm::GetUserRegisterCount() const
-{
- uint32_t count = 0;
- for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index)
- count += g_reg_sets_arm[set_index].num_registers;
- return count;
+ return nullptr;
}
-const RegisterSet *
-NativeRegisterContextLinux_arm::GetRegisterSet (uint32_t set_index) const
-{
- if (set_index < k_num_register_sets)
- return &g_reg_sets_arm[set_index];
+Error NativeRegisterContextLinux_arm::ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue &reg_value) {
+ Error error;
- return nullptr;
-}
+ if (!reg_info) {
+ error.SetErrorString("reg_info NULL");
+ return error;
+ }
-Error
-NativeRegisterContextLinux_arm::ReadRegister (const RegisterInfo *reg_info, RegisterValue &reg_value)
-{
- Error error;
+ const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
- if (!reg_info)
- {
- error.SetErrorString ("reg_info NULL");
- return error;
+ if (IsFPR(reg)) {
+ error = ReadFPR();
+ if (error.Fail())
+ return error;
+ } else {
+ uint32_t full_reg = reg;
+ bool is_subreg = reg_info->invalidate_regs &&
+ (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
+
+ if (is_subreg) {
+ // Read the full aligned 64-bit register.
+ full_reg = reg_info->invalidate_regs[0];
}
- const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+ error = ReadRegisterRaw(full_reg, reg_value);
- if (IsFPR(reg))
- {
- error = ReadFPR();
- if (error.Fail())
- return error;
- }
- else
- {
- uint32_t full_reg = reg;
- bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
-
- if (is_subreg)
- {
- // Read the full aligned 64-bit register.
- full_reg = reg_info->invalidate_regs[0];
- }
-
- error = ReadRegisterRaw(full_reg, reg_value);
-
- if (error.Success ())
- {
- // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right.
- if (is_subreg && (reg_info->byte_offset & 0x1))
- reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8);
-
- // If our return byte size was greater than the return value reg size, then
- // use the type specified by reg_info rather than the uint64_t default
- if (reg_value.GetByteSize() > reg_info->byte_size)
- reg_value.SetType(reg_info);
- }
- return error;
- }
+ if (error.Success()) {
+ // If our read was not aligned (for ah,bh,ch,dh), shift our returned value
+ // one byte to the right.
+ if (is_subreg && (reg_info->byte_offset & 0x1))
+ reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8);
- // Get pointer to m_fpr variable and set the data from it.
- uint32_t fpr_offset = CalculateFprOffset(reg_info);
- assert (fpr_offset < sizeof m_fpr);
- uint8_t *src = (uint8_t *)&m_fpr + fpr_offset;
- switch (reg_info->byte_size)
- {
- case 2:
- reg_value.SetUInt16(*(uint16_t *)src);
- break;
- case 4:
- reg_value.SetUInt32(*(uint32_t *)src);
- break;
- case 8:
- reg_value.SetUInt64(*(uint64_t *)src);
- break;
- case 16:
- reg_value.SetBytes(src, 16, GetByteOrder());
- break;
- default:
- assert(false && "Unhandled data size.");
- error.SetErrorStringWithFormat ("unhandled byte size: %" PRIu32, reg_info->byte_size);
- break;
+ // If our return byte size was greater than the return value reg size,
+ // then
+ // use the type specified by reg_info rather than the uint64_t default
+ if (reg_value.GetByteSize() > reg_info->byte_size)
+ reg_value.SetType(reg_info);
}
-
return error;
-}
-
-Error
-NativeRegisterContextLinux_arm::WriteRegister (const RegisterInfo *reg_info, const RegisterValue &reg_value)
-{
- if (!reg_info)
- return Error ("reg_info NULL");
-
- const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB];
- if (reg_index == LLDB_INVALID_REGNUM)
- return Error ("no lldb regnum for %s", reg_info && reg_info->name ? reg_info->name : "<unknown register>");
-
- if (IsGPR(reg_index))
- return WriteRegisterRaw(reg_index, reg_value);
-
- if (IsFPR(reg_index))
- {
- // Get pointer to m_fpr variable and set the data to it.
- uint32_t fpr_offset = CalculateFprOffset(reg_info);
- assert (fpr_offset < sizeof m_fpr);
- uint8_t *dst = (uint8_t *)&m_fpr + fpr_offset;
- switch (reg_info->byte_size)
- {
- case 2:
- *(uint16_t *)dst = reg_value.GetAsUInt16();
- break;
- case 4:
- *(uint32_t *)dst = reg_value.GetAsUInt32();
- break;
- case 8:
- *(uint64_t *)dst = reg_value.GetAsUInt64();
- break;
- default:
- assert(false && "Unhandled data size.");
- return Error ("unhandled register data size %" PRIu32, reg_info->byte_size);
- }
-
- Error error = WriteFPR();
- if (error.Fail())
- return error;
-
- return Error ();
+ }
+
+ // Get pointer to m_fpr variable and set the data from it.
+ uint32_t fpr_offset = CalculateFprOffset(reg_info);
+ assert(fpr_offset < sizeof m_fpr);
+ uint8_t *src = (uint8_t *)&m_fpr + fpr_offset;
+ switch (reg_info->byte_size) {
+ case 2:
+ reg_value.SetUInt16(*(uint16_t *)src);
+ break;
+ case 4:
+ reg_value.SetUInt32(*(uint32_t *)src);
+ break;
+ case 8:
+ reg_value.SetUInt64(*(uint64_t *)src);
+ break;
+ case 16:
+ reg_value.SetBytes(src, 16, GetByteOrder());
+ break;
+ default:
+ assert(false && "Unhandled data size.");
+ error.SetErrorStringWithFormat("unhandled byte size: %" PRIu32,
+ reg_info->byte_size);
+ break;
+ }
+
+ return error;
+}
+
+Error NativeRegisterContextLinux_arm::WriteRegister(
+ const RegisterInfo *reg_info, const RegisterValue &reg_value) {
+ if (!reg_info)
+ return Error("reg_info NULL");
+
+ const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB];
+ if (reg_index == LLDB_INVALID_REGNUM)
+ return Error("no lldb regnum for %s", reg_info && reg_info->name
+ ? reg_info->name
+ : "<unknown register>");
+
+ if (IsGPR(reg_index))
+ return WriteRegisterRaw(reg_index, reg_value);
+
+ if (IsFPR(reg_index)) {
+ // Get pointer to m_fpr variable and set the data to it.
+ uint32_t fpr_offset = CalculateFprOffset(reg_info);
+ assert(fpr_offset < sizeof m_fpr);
+ uint8_t *dst = (uint8_t *)&m_fpr + fpr_offset;
+ switch (reg_info->byte_size) {
+ case 2:
+ *(uint16_t *)dst = reg_value.GetAsUInt16();
+ break;
+ case 4:
+ *(uint32_t *)dst = reg_value.GetAsUInt32();
+ break;
+ case 8:
+ *(uint64_t *)dst = reg_value.GetAsUInt64();
+ break;
+ default:
+ assert(false && "Unhandled data size.");
+ return Error("unhandled register data size %" PRIu32,
+ reg_info->byte_size);
}
- return Error ("failed - register wasn't recognized to be a GPR or an FPR, write strategy unknown");
-}
-
-Error
-NativeRegisterContextLinux_arm::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
-{
- Error error;
+ Error error = WriteFPR();
+ if (error.Fail())
+ return error;
- data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
- if (!data_sp)
- return Error ("failed to allocate DataBufferHeap instance of size %" PRIu64, (uint64_t)REG_CONTEXT_SIZE);
+ return Error();
+ }
- error = ReadGPR();
- if (error.Fail())
- return error;
+ return Error("failed - register wasn't recognized to be a GPR or an FPR, "
+ "write strategy unknown");
+}
- error = ReadFPR();
- if (error.Fail())
- return error;
+Error NativeRegisterContextLinux_arm::ReadAllRegisterValues(
+ lldb::DataBufferSP &data_sp) {
+ Error error;
- uint8_t *dst = data_sp->GetBytes ();
- if (dst == nullptr)
- {
- error.SetErrorStringWithFormat ("DataBufferHeap instance of size %" PRIu64 " returned a null pointer", (uint64_t)REG_CONTEXT_SIZE);
- return error;
- }
+ data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
+ if (!data_sp)
+ return Error("failed to allocate DataBufferHeap instance of size %" PRIu64,
+ (uint64_t)REG_CONTEXT_SIZE);
- ::memcpy (dst, &m_gpr_arm, GetGPRSize());
- dst += GetGPRSize();
- ::memcpy (dst, &m_fpr, sizeof(m_fpr));
+ error = ReadGPR();
+ if (error.Fail())
+ return error;
+ error = ReadFPR();
+ if (error.Fail())
return error;
-}
-Error
-NativeRegisterContextLinux_arm::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
-{
- Error error;
+ uint8_t *dst = data_sp->GetBytes();
+ if (dst == nullptr) {
+ error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64
+ " returned a null pointer",
+ (uint64_t)REG_CONTEXT_SIZE);
+ return error;
+ }
- if (!data_sp)
- {
- error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s invalid data_sp provided", __FUNCTION__);
- return error;
- }
+ ::memcpy(dst, &m_gpr_arm, GetGPRSize());
+ dst += GetGPRSize();
+ ::memcpy(dst, &m_fpr, sizeof(m_fpr));
- if (data_sp->GetByteSize () != REG_CONTEXT_SIZE)
- {
- error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched data size, expected %" PRIu64 ", actual %" PRIu64, __FUNCTION__, (uint64_t)REG_CONTEXT_SIZE, data_sp->GetByteSize ());
- return error;
- }
+ return error;
+}
+Error NativeRegisterContextLinux_arm::WriteAllRegisterValues(
+ const lldb::DataBufferSP &data_sp) {
+ Error error;
- uint8_t *src = data_sp->GetBytes ();
- if (src == nullptr)
- {
- error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s DataBuffer::GetBytes() returned a null pointer", __FUNCTION__);
- return error;
- }
- ::memcpy (&m_gpr_arm, src, GetRegisterInfoInterface ().GetGPRSize ());
+ if (!data_sp) {
+ error.SetErrorStringWithFormat(
+ "NativeRegisterContextLinux_x86_64::%s invalid data_sp provided",
+ __FUNCTION__);
+ return error;
+ }
- error = WriteGPR();
- if (error.Fail())
- return error;
+ if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) {
+ error.SetErrorStringWithFormat(
+ "NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched "
+ "data size, expected %" PRIu64 ", actual %" PRIu64,
+ __FUNCTION__, (uint64_t)REG_CONTEXT_SIZE, data_sp->GetByteSize());
+ return error;
+ }
+
+ uint8_t *src = data_sp->GetBytes();
+ if (src == nullptr) {
+ error.SetErrorStringWithFormat("NativeRegisterContextLinux_x86_64::%s "
+ "DataBuffer::GetBytes() returned a null "
+ "pointer",
+ __FUNCTION__);
+ return error;
+ }
+ ::memcpy(&m_gpr_arm, src, GetRegisterInfoInterface().GetGPRSize());
- src += GetRegisterInfoInterface ().GetGPRSize ();
- ::memcpy (&m_fpr, src, sizeof(m_fpr));
+ error = WriteGPR();
+ if (error.Fail())
+ return error;
- error = WriteFPR();
- if (error.Fail())
- return error;
+ src += GetRegisterInfoInterface().GetGPRSize();
+ ::memcpy(&m_fpr, src, sizeof(m_fpr));
+ error = WriteFPR();
+ if (error.Fail())
return error;
+
+ return error;
}
-bool
-NativeRegisterContextLinux_arm::IsGPR(unsigned reg) const
-{
- return reg <= m_reg_info.last_gpr; // GPR's come first.
+bool NativeRegisterContextLinux_arm::IsGPR(unsigned reg) const {
+ return reg <= m_reg_info.last_gpr; // GPR's come first.
}
-bool
-NativeRegisterContextLinux_arm::IsFPR(unsigned reg) const
-{
- return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr);
+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));
+NativeRegisterContextLinux_arm::SetHardwareBreakpoint(lldb::addr_t addr,
+ size_t size) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
- if (log)
- log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
+ if (log)
+ log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
- Error error;
+ Error error;
- // Read hardware breakpoint and watchpoint information.
- error = ReadHardwareDebugInfo ();
+ // Read hardware breakpoint and watchpoint information.
+ error = ReadHardwareDebugInfo();
- if (error.Fail())
- return LLDB_INVALID_INDEX32;
-
- uint32_t control_value = 0, bp_index = 0;
-
- // 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;
-
- // Setup control value
- // Make the byte_mask into a valid Byte Address Select mask
- control_value = 0xfu << 5;
-
- // Enable this breakpoint and make it stop in privileged or user mode;
- control_value |= 7;
-
- // Make sure bits 1:0 are clear in our address
- // This should be different once we support thumb here.
- addr &= ~((lldb::addr_t)3);
-
- // Iterate over stored hardware breakpoints
- // Find a free bp_index or update reference count if duplicate.
- 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
- }
+ if (error.Fail())
+ return LLDB_INVALID_INDEX32;
+
+ uint32_t control_value = 0, bp_index = 0;
+
+ // 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;
+
+ // Setup control value
+ // Make the byte_mask into a valid Byte Address Select mask
+ control_value = 0xfu << 5;
+
+ // Enable this breakpoint and make it stop in privileged or user mode;
+ control_value |= 7;
+
+ // Make sure bits 1:0 are clear in our address
+ // This should be different once we support thumb here.
+ addr &= ~((lldb::addr_t)3);
+
+ // Iterate over stored hardware breakpoints
+ // Find a free bp_index or update reference count if duplicate.
+ 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
}
+ }
- if (bp_index == LLDB_INVALID_INDEX32)
- return LLDB_INVALID_INDEX32;
+ 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;
+ // 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;
- // 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;
+ m_hbr_regs[bp_index].refcount = 0;
- return LLDB_INVALID_INDEX32;
- }
+ return LLDB_INVALID_INDEX32;
}
- else
- m_hbr_regs[bp_index].refcount++;
+ } else
+ m_hbr_regs[bp_index].refcount++;
- return bp_index;
+ return bp_index;
}
-bool
-NativeRegisterContextLinux_arm::ClearHardwareBreakpoint (uint32_t hw_idx)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
+bool NativeRegisterContextLinux_arm::ClearHardwareBreakpoint(uint32_t hw_idx) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
- if (log)
- log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
+ if (log)
+ log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
- Error error;
+ Error error;
- // Read hardware breakpoint and watchpoint information.
- error = ReadHardwareDebugInfo ();
+ // Read hardware breakpoint and watchpoint information.
+ error = ReadHardwareDebugInfo();
- if (error.Fail())
- return false;
+ if (error.Fail())
+ return false;
- if (hw_idx >= m_max_hbp_supported)
- return false;
+ 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;
-
- m_hbr_regs[hw_idx].control &= ~1;
- m_hbr_regs[hw_idx].address = 0;
- m_hbr_regs[hw_idx].refcount = 0;
-
- // PTRACE call to clear corresponding hardware breakpoint register.
- 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;
-
- return false;
- }
-
- return true;
+ // 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;
+
+ m_hbr_regs[hw_idx].control &= ~1;
+ m_hbr_regs[hw_idx].address = 0;
+ m_hbr_regs[hw_idx].refcount = 0;
+
+ // PTRACE call to clear corresponding hardware breakpoint register.
+ 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;
+
+ return false;
}
- return false;
+ return true;
+ }
+
+ return false;
}
-uint32_t
-NativeRegisterContextLinux_arm::NumSupportedHardwareWatchpoints ()
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
+uint32_t NativeRegisterContextLinux_arm::NumSupportedHardwareWatchpoints() {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
- if (log)
- log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
+ if (log)
+ log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
- Error error;
+ Error error;
- // Read hardware breakpoint and watchpoint information.
- error = ReadHardwareDebugInfo ();
+ // Read hardware breakpoint and watchpoint information.
+ error = ReadHardwareDebugInfo();
- if (error.Fail())
- return 0;
+ if (error.Fail())
+ return 0;
- return 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));
+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;
+ if (log)
+ log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
- // Read hardware breakpoint and watchpoint information.
- error = ReadHardwareDebugInfo ();
+ Error error;
- if (error.Fail())
- return LLDB_INVALID_INDEX32;
-
- uint32_t control_value = 0, wp_index = 0, addr_word_offset = 0, byte_mask = 0;
- lldb::addr_t real_addr = addr;
-
- // Check if we are setting watchpoint other than read/write/access
- // Also update watchpoint flag to match Arm write-read bit configuration.
- switch (watch_flags)
- {
- case 1:
- watch_flags = 2;
- break;
- case 2:
- watch_flags = 1;
- break;
- case 3:
- break;
- default:
- return LLDB_INVALID_INDEX32;
- }
+ // Read hardware breakpoint and watchpoint information.
+ error = ReadHardwareDebugInfo();
- // Can't watch zero bytes
- // Can't watch more than 4 bytes per WVR/WCR pair
+ if (error.Fail())
+ return LLDB_INVALID_INDEX32;
- if (size == 0 || size > 4)
- return LLDB_INVALID_INDEX32;
+ uint32_t control_value = 0, wp_index = 0, addr_word_offset = 0, byte_mask = 0;
+ lldb::addr_t real_addr = addr;
- // Check 4-byte alignment for hardware watchpoint target address.
- // Below is a hack to recalculate address and size in order to
- // make sure we can watch non 4-byte alligned addresses as well.
- if (addr & 0x03)
- {
- uint8_t watch_mask = (addr & 0x03) + size;
+ // Check if we are setting watchpoint other than read/write/access
+ // Also update watchpoint flag to match Arm write-read bit configuration.
+ switch (watch_flags) {
+ case 1:
+ watch_flags = 2;
+ break;
+ case 2:
+ watch_flags = 1;
+ break;
+ case 3:
+ break;
+ default:
+ return LLDB_INVALID_INDEX32;
+ }
- if (watch_mask > 0x04)
- return LLDB_INVALID_INDEX32;
- else if (watch_mask <= 0x02)
- size = 2;
- else if (watch_mask <= 0x04)
- size = 4;
+ // Can't watch zero bytes
+ // Can't watch more than 4 bytes per WVR/WCR pair
- addr = addr & (~0x03);
- }
+ if (size == 0 || size > 4)
+ return LLDB_INVALID_INDEX32;
- // We can only watch up to four bytes that follow a 4 byte aligned address
- // per watchpoint register pair, so make sure we can properly encode this.
- addr_word_offset = addr % 4;
- byte_mask = ((1u << size) - 1u) << addr_word_offset;
-
- // Check if we need multiple watchpoint register
- if (byte_mask > 0xfu)
- return LLDB_INVALID_INDEX32;
-
- // Setup control value
- // Make the byte_mask into a valid Byte Address Select mask
- control_value = byte_mask << 5;
-
- //Turn on appropriate watchpoint flags read or write
- control_value |= (watch_flags << 3);
-
- // Enable this watchpoint and make it stop in privileged or user mode;
- control_value |= 7;
-
- // Make sure bits 1:0 are clear in our address
- addr &= ~((lldb::addr_t)3);
-
- // Iterate over stored watchpoints
- // Find a free wp_index or update reference count if duplicate.
- wp_index = LLDB_INVALID_INDEX32;
- for (uint32_t i = 0; i < m_max_hwp_supported; i++)
- {
- if ((m_hwp_regs[i].control & 1) == 0)
- {
- wp_index = i; // Mark last free slot
- }
- else if (m_hwp_regs[i].address == addr && m_hwp_regs[i].control == control_value)
- {
- wp_index = i; // Mark duplicate index
- break; // Stop searching here
- }
- }
+ // Check 4-byte alignment for hardware watchpoint target address.
+ // Below is a hack to recalculate address and size in order to
+ // make sure we can watch non 4-byte alligned addresses as well.
+ if (addr & 0x03) {
+ uint8_t watch_mask = (addr & 0x03) + size;
- if (wp_index == LLDB_INVALID_INDEX32)
- return LLDB_INVALID_INDEX32;
-
- // Add new or update existing watchpoint
- if ((m_hwp_regs[wp_index].control & 1) == 0)
- {
- // Update watchpoint in local cache
- m_hwp_regs[wp_index].real_addr = real_addr;
- m_hwp_regs[wp_index].address = addr;
- m_hwp_regs[wp_index].control = control_value;
- m_hwp_regs[wp_index].refcount = 1;
-
- // PTRACE call to set corresponding watchpoint register.
- error = WriteHardwareDebugRegs(eDREGTypeWATCH, wp_index);
-
- if (error.Fail())
- {
- m_hwp_regs[wp_index].address = 0;
- m_hwp_regs[wp_index].control &= ~1;
- m_hwp_regs[wp_index].refcount = 0;
-
- return LLDB_INVALID_INDEX32;
- }
- }
- else
- m_hwp_regs[wp_index].refcount++;
+ if (watch_mask > 0x04)
+ return LLDB_INVALID_INDEX32;
+ else if (watch_mask <= 0x02)
+ size = 2;
+ else if (watch_mask <= 0x04)
+ size = 4;
- return wp_index;
-}
+ addr = addr & (~0x03);
+ }
-bool
-NativeRegisterContextLinux_arm::ClearHardwareWatchpoint (uint32_t wp_index)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
+ // We can only watch up to four bytes that follow a 4 byte aligned address
+ // per watchpoint register pair, so make sure we can properly encode this.
+ addr_word_offset = addr % 4;
+ byte_mask = ((1u << size) - 1u) << addr_word_offset;
- if (log)
- log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
+ // Check if we need multiple watchpoint register
+ if (byte_mask > 0xfu)
+ return LLDB_INVALID_INDEX32;
- Error error;
+ // Setup control value
+ // Make the byte_mask into a valid Byte Address Select mask
+ control_value = byte_mask << 5;
- // Read hardware breakpoint and watchpoint information.
- error = ReadHardwareDebugInfo ();
+ // Turn on appropriate watchpoint flags read or write
+ control_value |= (watch_flags << 3);
- if (error.Fail())
- return false;
+ // Enable this watchpoint and make it stop in privileged or user mode;
+ control_value |= 7;
- if (wp_index >= m_max_hwp_supported)
- return false;
+ // Make sure bits 1:0 are clear in our address
+ addr &= ~((lldb::addr_t)3);
- // Update reference count if multiple references.
- if (m_hwp_regs[wp_index].refcount > 1)
- {
- m_hwp_regs[wp_index].refcount--;
- return true;
+ // Iterate over stored watchpoints
+ // Find a free wp_index or update reference count if duplicate.
+ wp_index = LLDB_INVALID_INDEX32;
+ for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
+ if ((m_hwp_regs[i].control & 1) == 0) {
+ wp_index = i; // Mark last free slot
+ } else if (m_hwp_regs[i].address == addr &&
+ m_hwp_regs[i].control == control_value) {
+ wp_index = i; // Mark duplicate index
+ break; // Stop searching here
}
- else if (m_hwp_regs[wp_index].refcount == 1)
- {
- // Create a backup we can revert to in case of failure.
- lldb::addr_t tempAddr = m_hwp_regs[wp_index].address;
- uint32_t tempControl = m_hwp_regs[wp_index].control;
- uint32_t tempRefCount = m_hwp_regs[wp_index].refcount;
-
- // Update watchpoint in local cache
- m_hwp_regs[wp_index].control &= ~1;
- m_hwp_regs[wp_index].address = 0;
- m_hwp_regs[wp_index].refcount = 0;
-
- // Ptrace call to update hardware debug registers
- error = WriteHardwareDebugRegs(eDREGTypeWATCH, wp_index);
-
- if (error.Fail())
- {
- m_hwp_regs[wp_index].control = tempControl;
- m_hwp_regs[wp_index].address = tempAddr;
- m_hwp_regs[wp_index].refcount = tempRefCount;
-
- return false;
- }
-
- return true;
+ }
+
+ if (wp_index == LLDB_INVALID_INDEX32)
+ return LLDB_INVALID_INDEX32;
+
+ // Add new or update existing watchpoint
+ if ((m_hwp_regs[wp_index].control & 1) == 0) {
+ // Update watchpoint in local cache
+ m_hwp_regs[wp_index].real_addr = real_addr;
+ m_hwp_regs[wp_index].address = addr;
+ m_hwp_regs[wp_index].control = control_value;
+ m_hwp_regs[wp_index].refcount = 1;
+
+ // PTRACE call to set corresponding watchpoint register.
+ error = WriteHardwareDebugRegs(eDREGTypeWATCH, wp_index);
+
+ if (error.Fail()) {
+ m_hwp_regs[wp_index].address = 0;
+ m_hwp_regs[wp_index].control &= ~1;
+ m_hwp_regs[wp_index].refcount = 0;
+
+ return LLDB_INVALID_INDEX32;
}
+ } else
+ m_hwp_regs[wp_index].refcount++;
- return false;
+ return wp_index;
}
-Error
-NativeRegisterContextLinux_arm::ClearAllHardwareWatchpoints ()
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
+bool NativeRegisterContextLinux_arm::ClearHardwareWatchpoint(
+ uint32_t wp_index) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
- if (log)
- log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
+ if (log)
+ log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
- Error error;
+ Error error;
- // Read hardware breakpoint and watchpoint information.
- error = ReadHardwareDebugInfo ();
+ // Read hardware breakpoint and watchpoint information.
+ error = ReadHardwareDebugInfo();
- if (error.Fail())
- return error;
+ if (error.Fail())
+ return false;
- lldb::addr_t tempAddr = 0;
- uint32_t tempControl = 0, tempRefCount = 0;
-
- for (uint32_t i = 0; i < m_max_hwp_supported; i++)
- {
- if (m_hwp_regs[i].control & 0x01)
- {
- // Create a backup we can revert to in case of failure.
- tempAddr = m_hwp_regs[i].address;
- tempControl = m_hwp_regs[i].control;
- tempRefCount = m_hwp_regs[i].refcount;
-
- // Clear watchpoints in local cache
- m_hwp_regs[i].control &= ~1;
- m_hwp_regs[i].address = 0;
- m_hwp_regs[i].refcount = 0;
-
- // Ptrace call to update hardware debug registers
- error = WriteHardwareDebugRegs(eDREGTypeWATCH, i);
-
- if (error.Fail())
- {
- m_hwp_regs[i].control = tempControl;
- m_hwp_regs[i].address = tempAddr;
- m_hwp_regs[i].refcount = tempRefCount;
-
- return error;
- }
- }
+ if (wp_index >= m_max_hwp_supported)
+ return false;
+
+ // Update reference count if multiple references.
+ if (m_hwp_regs[wp_index].refcount > 1) {
+ m_hwp_regs[wp_index].refcount--;
+ return true;
+ } else if (m_hwp_regs[wp_index].refcount == 1) {
+ // Create a backup we can revert to in case of failure.
+ lldb::addr_t tempAddr = m_hwp_regs[wp_index].address;
+ uint32_t tempControl = m_hwp_regs[wp_index].control;
+ uint32_t tempRefCount = m_hwp_regs[wp_index].refcount;
+
+ // Update watchpoint in local cache
+ m_hwp_regs[wp_index].control &= ~1;
+ m_hwp_regs[wp_index].address = 0;
+ m_hwp_regs[wp_index].refcount = 0;
+
+ // Ptrace call to update hardware debug registers
+ error = WriteHardwareDebugRegs(eDREGTypeWATCH, wp_index);
+
+ if (error.Fail()) {
+ m_hwp_regs[wp_index].control = tempControl;
+ m_hwp_regs[wp_index].address = tempAddr;
+ m_hwp_regs[wp_index].refcount = tempRefCount;
+
+ return false;
}
- return Error();
-}
+ return true;
+ }
-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__);
-
- switch ((m_hwp_regs[wp_index].control >> 5) & 0x0f)
- {
- case 0x01:
- return 1;
- case 0x03:
- return 2;
- case 0x07:
- return 3;
- case 0x0f:
- return 4;
- default:
- return 0;
- }
-}
-bool
-NativeRegisterContextLinux_arm::WatchpointIsEnabled(uint32_t wp_index)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
-
- if (log)
- log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
-
- if ((m_hwp_regs[wp_index].control & 0x1) == 0x1)
- return true;
- else
- return false;
+ return false;
}
-Error
-NativeRegisterContextLinux_arm::GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
+Error NativeRegisterContextLinux_arm::ClearAllHardwareWatchpoints() {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
- if (log)
- log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
+ if (log)
+ log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
- uint32_t watch_size;
- lldb::addr_t watch_addr;
+ Error error;
- for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index)
- {
- watch_size = GetWatchpointSize (wp_index);
- watch_addr = m_hwp_regs[wp_index].address;
+ // Read hardware breakpoint and watchpoint information.
+ error = ReadHardwareDebugInfo();
- if (m_hwp_regs[wp_index].refcount >= 1 && WatchpointIsEnabled(wp_index)
- && trap_addr >= watch_addr && trap_addr < watch_addr + watch_size)
- {
- m_hwp_regs[wp_index].hit_addr = trap_addr;
- return Error();
- }
- }
+ if (error.Fail())
+ return error;
- wp_index = LLDB_INVALID_INDEX32;
- return Error();
-}
+ lldb::addr_t tempAddr = 0;
+ uint32_t tempControl = 0, tempRefCount = 0;
-lldb::addr_t
-NativeRegisterContextLinux_arm::GetWatchpointAddress (uint32_t wp_index)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
+ for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
+ if (m_hwp_regs[i].control & 0x01) {
+ // Create a backup we can revert to in case of failure.
+ tempAddr = m_hwp_regs[i].address;
+ tempControl = m_hwp_regs[i].control;
+ tempRefCount = m_hwp_regs[i].refcount;
+
+ // Clear watchpoints in local cache
+ m_hwp_regs[i].control &= ~1;
+ m_hwp_regs[i].address = 0;
+ m_hwp_regs[i].refcount = 0;
- if (log)
- log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
+ // Ptrace call to update hardware debug registers
+ error = WriteHardwareDebugRegs(eDREGTypeWATCH, i);
- if (wp_index >= m_max_hwp_supported)
- return LLDB_INVALID_ADDRESS;
+ if (error.Fail()) {
+ m_hwp_regs[i].control = tempControl;
+ m_hwp_regs[i].address = tempAddr;
+ m_hwp_regs[i].refcount = tempRefCount;
- if (WatchpointIsEnabled(wp_index))
- return m_hwp_regs[wp_index].real_addr;
- else
- return LLDB_INVALID_ADDRESS;
+ return error;
+ }
+ }
+ }
+
+ return Error();
}
-lldb::addr_t
-NativeRegisterContextLinux_arm::GetWatchpointHitAddress (uint32_t wp_index)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
+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__);
+ if (log)
+ log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
- if (wp_index >= m_max_hwp_supported)
- return LLDB_INVALID_ADDRESS;
+ switch ((m_hwp_regs[wp_index].control >> 5) & 0x0f) {
+ case 0x01:
+ return 1;
+ case 0x03:
+ return 2;
+ case 0x07:
+ return 3;
+ case 0x0f:
+ return 4;
+ default:
+ return 0;
+ }
+}
+bool NativeRegisterContextLinux_arm::WatchpointIsEnabled(uint32_t wp_index) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
- if (WatchpointIsEnabled(wp_index))
- return m_hwp_regs[wp_index].hit_addr;
- else
- return LLDB_INVALID_ADDRESS;
+ if (log)
+ log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
+
+ if ((m_hwp_regs[wp_index].control & 0x1) == 0x1)
+ return true;
+ else
+ return false;
}
-Error
-NativeRegisterContextLinux_arm::ReadHardwareDebugInfo()
-{
- Error error;
+Error NativeRegisterContextLinux_arm::GetWatchpointHitIndex(
+ uint32_t &wp_index, lldb::addr_t trap_addr) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
- if (!m_refresh_hwdebug_info)
- {
- return Error();
+ if (log)
+ log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
+
+ uint32_t watch_size;
+ lldb::addr_t watch_addr;
+
+ for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index) {
+ watch_size = GetWatchpointSize(wp_index);
+ watch_addr = m_hwp_regs[wp_index].address;
+
+ if (m_hwp_regs[wp_index].refcount >= 1 && WatchpointIsEnabled(wp_index) &&
+ trap_addr >= watch_addr && trap_addr < watch_addr + watch_size) {
+ m_hwp_regs[wp_index].hit_addr = trap_addr;
+ return Error();
}
+ }
- unsigned int cap_val;
+ wp_index = LLDB_INVALID_INDEX32;
+ return Error();
+}
- error = NativeProcessLinux::PtraceWrapper(PTRACE_GETHBPREGS, m_thread.GetID(), nullptr, &cap_val, sizeof(unsigned int));
+lldb::addr_t
+NativeRegisterContextLinux_arm::GetWatchpointAddress(uint32_t wp_index) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
- if (error.Fail())
- return error;
+ if (log)
+ log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
- m_max_hwp_supported = (cap_val >> 8) & 0xff;
- m_max_hbp_supported = cap_val & 0xff;
- m_refresh_hwdebug_info = false;
+ if (wp_index >= m_max_hwp_supported)
+ return LLDB_INVALID_ADDRESS;
- return error;
+ if (WatchpointIsEnabled(wp_index))
+ return m_hwp_regs[wp_index].real_addr;
+ else
+ return LLDB_INVALID_ADDRESS;
}
-Error
-NativeRegisterContextLinux_arm::WriteHardwareDebugRegs(int hwbType, int hwb_index)
-{
- Error error;
+lldb::addr_t
+NativeRegisterContextLinux_arm::GetWatchpointHitAddress(uint32_t wp_index) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
- lldb::addr_t *addr_buf;
- uint32_t *ctrl_buf;
+ if (log)
+ log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
- if (hwbType == eDREGTypeWATCH)
- {
- addr_buf = &m_hwp_regs[hwb_index].address;
- ctrl_buf = &m_hwp_regs[hwb_index].control;
+ if (wp_index >= m_max_hwp_supported)
+ return LLDB_INVALID_ADDRESS;
- error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS,
- m_thread.GetID(), (PTRACE_TYPE_ARG3)(intptr_t) -((hwb_index << 1) + 1),
- addr_buf, sizeof(unsigned int));
+ if (WatchpointIsEnabled(wp_index))
+ return m_hwp_regs[wp_index].hit_addr;
+ else
+ return LLDB_INVALID_ADDRESS;
+}
- if (error.Fail())
- return error;
+Error NativeRegisterContextLinux_arm::ReadHardwareDebugInfo() {
+ Error error;
- error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS,
- m_thread.GetID(), (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;
+ if (!m_refresh_hwdebug_info) {
+ return Error();
+ }
- error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS,
- m_thread.GetID(), (PTRACE_TYPE_ARG3)(intptr_t) ((hwb_index << 1) + 1),
- addr_buf, sizeof(unsigned int));
+ unsigned int cap_val;
- if (error.Fail())
- return error;
+ error = NativeProcessLinux::PtraceWrapper(PTRACE_GETHBPREGS, m_thread.GetID(),
+ nullptr, &cap_val,
+ sizeof(unsigned int));
- error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS,
- m_thread.GetID(), (PTRACE_TYPE_ARG3)(intptr_t) ((hwb_index << 1) + 2),
- ctrl_buf, sizeof(unsigned int));
+ if (error.Fail())
+ return error;
- }
+ m_max_hwp_supported = (cap_val >> 8) & 0xff;
+ m_max_hbp_supported = cap_val & 0xff;
+ m_refresh_hwdebug_info = false;
- return error;
+ return error;
}
-uint32_t
-NativeRegisterContextLinux_arm::CalculateFprOffset(const RegisterInfo* reg_info) const
-{
- return reg_info->byte_offset - GetRegisterInfoAtIndex(m_reg_info.first_fpr)->byte_offset;
-}
+Error NativeRegisterContextLinux_arm::WriteHardwareDebugRegs(int hwbType,
+ int hwb_index) {
+ Error error;
+
+ lldb::addr_t *addr_buf;
+ uint32_t *ctrl_buf;
+
+ if (hwbType == eDREGTypeWATCH) {
+ addr_buf = &m_hwp_regs[hwb_index].address;
+ ctrl_buf = &m_hwp_regs[hwb_index].control;
+
+ error = NativeProcessLinux::PtraceWrapper(
+ PTRACE_SETHBPREGS, m_thread.GetID(),
+ (PTRACE_TYPE_ARG3)(intptr_t) - ((hwb_index << 1) + 1), addr_buf,
+ sizeof(unsigned int));
-Error
-NativeRegisterContextLinux_arm::DoReadRegisterValue(uint32_t offset,
- const char* reg_name,
- uint32_t size,
- RegisterValue &value)
-{
- // PTRACE_PEEKUSER don't work in the aarch64 linux kernel used on android devices (always return
- // "Bad address"). To avoid using PTRACE_PEEKUSER we read out the full GPR register set instead.
- // This approach is about 4 times slower but the performance overhead is negligible in
- // comparision to processing time in lldb-server.
- assert(offset % 4 == 0 && "Try to write a register with unaligned offset");
- if (offset + sizeof(uint32_t) > sizeof(m_gpr_arm))
- return Error("Register isn't fit into the size of the GPR area");
-
- Error error = DoReadGPR(m_gpr_arm, sizeof(m_gpr_arm));
if (error.Fail())
- return error;
+ return error;
- value.SetUInt32(m_gpr_arm[offset / sizeof(uint32_t)]);
- return Error();
-}
+ error = NativeProcessLinux::PtraceWrapper(
+ PTRACE_SETHBPREGS, m_thread.GetID(),
+ (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;
+
+ error = NativeProcessLinux::PtraceWrapper(
+ PTRACE_SETHBPREGS, m_thread.GetID(),
+ (PTRACE_TYPE_ARG3)(intptr_t)((hwb_index << 1) + 1), addr_buf,
+ sizeof(unsigned int));
-Error
-NativeRegisterContextLinux_arm::DoWriteRegisterValue(uint32_t offset,
- const char* reg_name,
- const RegisterValue &value)
-{
- // PTRACE_POKEUSER don't work in the aarch64 linux kernel used on android devices (always return
- // "Bad address"). To avoid using PTRACE_POKEUSER we read out the full GPR register set, modify
- // the requested register and write it back. This approach is about 4 times slower but the
- // performance overhead is negligible in comparision to processing time in lldb-server.
- assert(offset % 4 == 0 && "Try to write a register with unaligned offset");
- if (offset + sizeof(uint32_t) > sizeof(m_gpr_arm))
- return Error("Register isn't fit into the size of the GPR area");
-
- Error error = DoReadGPR(m_gpr_arm, sizeof(m_gpr_arm));
if (error.Fail())
- return error;
+ return error;
+
+ error = NativeProcessLinux::PtraceWrapper(
+ PTRACE_SETHBPREGS, m_thread.GetID(),
+ (PTRACE_TYPE_ARG3)(intptr_t)((hwb_index << 1) + 2), ctrl_buf,
+ sizeof(unsigned int));
+ }
+
+ return error;
+}
+
+uint32_t NativeRegisterContextLinux_arm::CalculateFprOffset(
+ const RegisterInfo *reg_info) const {
+ return reg_info->byte_offset -
+ GetRegisterInfoAtIndex(m_reg_info.first_fpr)->byte_offset;
+}
+
+Error NativeRegisterContextLinux_arm::DoReadRegisterValue(
+ uint32_t offset, const char *reg_name, uint32_t size,
+ RegisterValue &value) {
+ // PTRACE_PEEKUSER don't work in the aarch64 linux kernel used on android
+ // devices (always return
+ // "Bad address"). To avoid using PTRACE_PEEKUSER we read out the full GPR
+ // register set instead.
+ // This approach is about 4 times slower but the performance overhead is
+ // negligible in
+ // comparision to processing time in lldb-server.
+ assert(offset % 4 == 0 && "Try to write a register with unaligned offset");
+ if (offset + sizeof(uint32_t) > sizeof(m_gpr_arm))
+ return Error("Register isn't fit into the size of the GPR area");
+
+ Error error = DoReadGPR(m_gpr_arm, sizeof(m_gpr_arm));
+ if (error.Fail())
+ return error;
+
+ value.SetUInt32(m_gpr_arm[offset / sizeof(uint32_t)]);
+ return Error();
+}
+
+Error NativeRegisterContextLinux_arm::DoWriteRegisterValue(
+ uint32_t offset, const char *reg_name, const RegisterValue &value) {
+ // PTRACE_POKEUSER don't work in the aarch64 linux kernel used on android
+ // devices (always return
+ // "Bad address"). To avoid using PTRACE_POKEUSER we read out the full GPR
+ // register set, modify
+ // the requested register and write it back. This approach is about 4 times
+ // slower but the
+ // performance overhead is negligible in comparision to processing time in
+ // lldb-server.
+ assert(offset % 4 == 0 && "Try to write a register with unaligned offset");
+ if (offset + sizeof(uint32_t) > sizeof(m_gpr_arm))
+ return Error("Register isn't fit into the size of the GPR area");
+
+ Error error = DoReadGPR(m_gpr_arm, sizeof(m_gpr_arm));
+ if (error.Fail())
+ return error;
- uint32_t reg_value = value.GetAsUInt32();
- // As precaution for an undefined behavior encountered while setting PC we
- // will clear thumb bit of new PC if we are already in thumb mode; that is
- // CPSR thumb mode bit is set.
- if (offset / sizeof(uint32_t) == gpr_pc_arm)
- {
- // Check if we are already in thumb mode and
- // thumb bit of current PC is read out to be zero and
- // thumb bit of next PC is read out to be one.
- if ((m_gpr_arm[gpr_cpsr_arm] & 0x20) &&
- !(m_gpr_arm[gpr_pc_arm] & 0x01) &&
- (value.GetAsUInt32() & 0x01))
- {
- reg_value &= (~1ull);
- }
+ uint32_t reg_value = value.GetAsUInt32();
+ // As precaution for an undefined behavior encountered while setting PC we
+ // will clear thumb bit of new PC if we are already in thumb mode; that is
+ // CPSR thumb mode bit is set.
+ if (offset / sizeof(uint32_t) == gpr_pc_arm) {
+ // Check if we are already in thumb mode and
+ // thumb bit of current PC is read out to be zero and
+ // thumb bit of next PC is read out to be one.
+ if ((m_gpr_arm[gpr_cpsr_arm] & 0x20) && !(m_gpr_arm[gpr_pc_arm] & 0x01) &&
+ (value.GetAsUInt32() & 0x01)) {
+ reg_value &= (~1ull);
}
+ }
- m_gpr_arm[offset / sizeof(uint32_t)] = reg_value;
- return DoWriteGPR(m_gpr_arm, sizeof(m_gpr_arm));
+ m_gpr_arm[offset / sizeof(uint32_t)] = reg_value;
+ return DoWriteGPR(m_gpr_arm, sizeof(m_gpr_arm));
}
-Error
-NativeRegisterContextLinux_arm::DoReadGPR(void *buf, size_t buf_size)
-{
+Error NativeRegisterContextLinux_arm::DoReadGPR(void *buf, size_t buf_size) {
#ifdef __arm__
- return NativeRegisterContextLinux::DoReadGPR(buf, buf_size);
-#else // __aarch64__
- struct iovec ioVec;
- ioVec.iov_base = buf;
- ioVec.iov_len = buf_size;
+ return NativeRegisterContextLinux::DoReadGPR(buf, buf_size);
+#else // __aarch64__
+ struct iovec ioVec;
+ ioVec.iov_base = buf;
+ ioVec.iov_len = buf_size;
- return ReadRegisterSet(&ioVec, buf_size, NT_PRSTATUS);
+ return ReadRegisterSet(&ioVec, buf_size, NT_PRSTATUS);
#endif // __arm__
}
-Error
-NativeRegisterContextLinux_arm::DoWriteGPR(void *buf, size_t buf_size)
-{
+Error NativeRegisterContextLinux_arm::DoWriteGPR(void *buf, size_t buf_size) {
#ifdef __arm__
- return NativeRegisterContextLinux::DoWriteGPR(buf, buf_size);
-#else // __aarch64__
- struct iovec ioVec;
- ioVec.iov_base = buf;
- ioVec.iov_len = buf_size;
+ return NativeRegisterContextLinux::DoWriteGPR(buf, buf_size);
+#else // __aarch64__
+ struct iovec ioVec;
+ ioVec.iov_base = buf;
+ ioVec.iov_len = buf_size;
- return WriteRegisterSet(&ioVec, buf_size, NT_PRSTATUS);
+ return WriteRegisterSet(&ioVec, buf_size, NT_PRSTATUS);
#endif // __arm__
}
-Error
-NativeRegisterContextLinux_arm::DoReadFPR(void *buf, size_t buf_size)
-{
+Error NativeRegisterContextLinux_arm::DoReadFPR(void *buf, size_t buf_size) {
#ifdef __arm__
- return NativeProcessLinux::PtraceWrapper(PTRACE_GETVFPREGS,
- m_thread.GetID(),
- nullptr,
- buf,
- buf_size);
-#else // __aarch64__
- struct iovec ioVec;
- ioVec.iov_base = buf;
- ioVec.iov_len = buf_size;
-
- return ReadRegisterSet(&ioVec, buf_size, NT_ARM_VFP);
+ return NativeProcessLinux::PtraceWrapper(PTRACE_GETVFPREGS, m_thread.GetID(),
+ nullptr, buf, buf_size);
+#else // __aarch64__
+ struct iovec ioVec;
+ ioVec.iov_base = buf;
+ ioVec.iov_len = buf_size;
+
+ return ReadRegisterSet(&ioVec, buf_size, NT_ARM_VFP);
#endif // __arm__
}
-Error
-NativeRegisterContextLinux_arm::DoWriteFPR(void *buf, size_t buf_size)
-{
+Error NativeRegisterContextLinux_arm::DoWriteFPR(void *buf, size_t buf_size) {
#ifdef __arm__
- return NativeProcessLinux::PtraceWrapper(PTRACE_SETVFPREGS,
- m_thread.GetID(),
- nullptr,
- buf,
- buf_size);
-#else // __aarch64__
- struct iovec ioVec;
- ioVec.iov_base = buf;
- ioVec.iov_len = buf_size;
-
- return WriteRegisterSet(&ioVec, buf_size, NT_ARM_VFP);
+ return NativeProcessLinux::PtraceWrapper(PTRACE_SETVFPREGS, m_thread.GetID(),
+ nullptr, buf, buf_size);
+#else // __aarch64__
+ struct iovec ioVec;
+ ioVec.iov_base = buf;
+ ioVec.iov_len = buf_size;
+
+ return WriteRegisterSet(&ioVec, buf_size, NT_ARM_VFP);
#endif // __arm__
}
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h
index 452f132..f979811 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h
@@ -18,181 +18,142 @@
namespace lldb_private {
namespace process_linux {
- class NativeProcessLinux;
+class NativeProcessLinux;
- class NativeRegisterContextLinux_arm : public NativeRegisterContextLinux
- {
- public:
- NativeRegisterContextLinux_arm (const ArchSpec& target_arch,
- NativeThreadProtocol &native_thread,
- uint32_t concrete_frame_idx);
+class NativeRegisterContextLinux_arm : public NativeRegisterContextLinux {
+public:
+ NativeRegisterContextLinux_arm(const ArchSpec &target_arch,
+ NativeThreadProtocol &native_thread,
+ uint32_t concrete_frame_idx);
- uint32_t
- GetRegisterSetCount () const override;
+ uint32_t GetRegisterSetCount() const override;
- const RegisterSet *
- GetRegisterSet (uint32_t set_index) const override;
+ const RegisterSet *GetRegisterSet(uint32_t set_index) const override;
- uint32_t
- GetUserRegisterCount() const override;
+ uint32_t GetUserRegisterCount() const override;
- Error
- ReadRegister (const RegisterInfo *reg_info, RegisterValue &reg_value) override;
+ Error ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue &reg_value) override;
- Error
- WriteRegister (const RegisterInfo *reg_info, const RegisterValue &reg_value) override;
+ Error WriteRegister(const RegisterInfo *reg_info,
+ const RegisterValue &reg_value) override;
- Error
- ReadAllRegisterValues (lldb::DataBufferSP &data_sp) override;
+ Error ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
- Error
- WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) override;
+ Error WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
- //------------------------------------------------------------------
- // Hardware breakpoints/watchpoint mangement functions
- //------------------------------------------------------------------
+ //------------------------------------------------------------------
+ // Hardware breakpoints/watchpoint mangement functions
+ //------------------------------------------------------------------
- uint32_t
- SetHardwareBreakpoint (lldb::addr_t addr, size_t size) override;
+ uint32_t SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override;
- bool
- ClearHardwareBreakpoint (uint32_t hw_idx) override;
+ bool ClearHardwareBreakpoint(uint32_t hw_idx) override;
- uint32_t
- NumSupportedHardwareWatchpoints () override;
+ uint32_t NumSupportedHardwareWatchpoints() override;
- uint32_t
- SetHardwareWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags) override;
+ uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size,
+ uint32_t watch_flags) override;
- bool
- ClearHardwareWatchpoint (uint32_t hw_index) override;
+ bool ClearHardwareWatchpoint(uint32_t hw_index) override;
- Error
- ClearAllHardwareWatchpoints () override;
+ Error ClearAllHardwareWatchpoints() override;
- Error
- GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) override;
+ Error GetWatchpointHitIndex(uint32_t &wp_index,
+ lldb::addr_t trap_addr) override;
- lldb::addr_t
- GetWatchpointHitAddress (uint32_t wp_index) override;
+ lldb::addr_t GetWatchpointHitAddress(uint32_t wp_index) override;
- lldb::addr_t
- GetWatchpointAddress (uint32_t wp_index) override;
+ lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override;
- uint32_t
- GetWatchpointSize(uint32_t wp_index);
+ uint32_t GetWatchpointSize(uint32_t wp_index);
- bool
- WatchpointIsEnabled(uint32_t wp_index);
+ bool WatchpointIsEnabled(uint32_t wp_index);
- // Debug register type select
- enum DREGType
- {
- eDREGTypeWATCH = 0,
- eDREGTypeBREAK
- };
+ // Debug register type select
+ enum DREGType { eDREGTypeWATCH = 0, eDREGTypeBREAK };
- protected:
- Error
- DoReadRegisterValue(uint32_t offset,
- const char* reg_name,
- uint32_t size,
- RegisterValue &value) override;
+protected:
+ Error DoReadRegisterValue(uint32_t offset, const char *reg_name,
+ uint32_t size, RegisterValue &value) override;
- Error
- DoWriteRegisterValue(uint32_t offset,
- const char* reg_name,
+ Error DoWriteRegisterValue(uint32_t offset, const char *reg_name,
const RegisterValue &value) override;
- Error
- DoReadGPR(void *buf, size_t buf_size) override;
+ Error DoReadGPR(void *buf, size_t buf_size) override;
- Error
- DoWriteGPR(void *buf, size_t buf_size) override;
+ Error DoWriteGPR(void *buf, size_t buf_size) override;
- Error
- DoReadFPR(void *buf, size_t buf_size) override;
+ Error DoReadFPR(void *buf, size_t buf_size) override;
- Error
- DoWriteFPR(void *buf, size_t buf_size) override;
+ Error DoWriteFPR(void *buf, size_t buf_size) override;
- void*
- GetGPRBuffer() override { return &m_gpr_arm; }
+ void *GetGPRBuffer() override { return &m_gpr_arm; }
- void*
- GetFPRBuffer() override { return &m_fpr; }
+ void *GetFPRBuffer() override { return &m_fpr; }
- size_t
- GetFPRSize() override { return sizeof(m_fpr); }
+ size_t GetFPRSize() override { return sizeof(m_fpr); }
- private:
- struct RegInfo
- {
- uint32_t num_registers;
- uint32_t num_gpr_registers;
- uint32_t num_fpr_registers;
+private:
+ struct RegInfo {
+ uint32_t num_registers;
+ uint32_t num_gpr_registers;
+ uint32_t num_fpr_registers;
- uint32_t last_gpr;
- uint32_t first_fpr;
- uint32_t last_fpr;
+ uint32_t last_gpr;
+ uint32_t first_fpr;
+ uint32_t last_fpr;
- uint32_t first_fpr_v;
- uint32_t last_fpr_v;
+ uint32_t first_fpr_v;
+ uint32_t last_fpr_v;
- uint32_t gpr_flags;
- };
+ uint32_t gpr_flags;
+ };
- struct QReg
- {
- uint8_t bytes[16];
- };
+ struct QReg {
+ uint8_t bytes[16];
+ };
- struct FPU
- {
- union {
- uint32_t s[32];
- uint64_t d[32];
- QReg q[16]; // the 128-bit NEON registers
- } floats;
- uint32_t fpscr;
- };
+ struct FPU {
+ union {
+ uint32_t s[32];
+ uint64_t d[32];
+ QReg q[16]; // the 128-bit NEON registers
+ } floats;
+ uint32_t fpscr;
+ };
- uint32_t m_gpr_arm[k_num_gpr_registers_arm];
- RegInfo m_reg_info;
- FPU m_fpr;
+ uint32_t m_gpr_arm[k_num_gpr_registers_arm];
+ RegInfo m_reg_info;
+ FPU m_fpr;
- // Debug register info for hardware breakpoints and watchpoints management.
- struct DREG
- {
- lldb::addr_t address; // Breakpoint/watchpoint address value.
- lldb::addr_t hit_addr; // Address at which last watchpoint trigger exception occurred.
- lldb::addr_t real_addr; // Address value that should cause target to stop.
- uint32_t control; // Breakpoint/watchpoint control value.
- uint32_t refcount; // Serves as enable/disable and refernce counter.
- };
+ // Debug register info for hardware breakpoints and watchpoints management.
+ struct DREG {
+ lldb::addr_t address; // Breakpoint/watchpoint address value.
+ lldb::addr_t hit_addr; // Address at which last watchpoint trigger exception
+ // occurred.
+ lldb::addr_t real_addr; // Address value that should cause target to stop.
+ uint32_t control; // Breakpoint/watchpoint control value.
+ uint32_t refcount; // Serves as enable/disable and refernce counter.
+ };
- struct DREG m_hbr_regs[16]; // Arm native linux hardware breakpoints
- struct DREG m_hwp_regs[16]; // Arm native linux hardware watchpoints
+ struct DREG m_hbr_regs[16]; // Arm native linux hardware breakpoints
+ struct DREG m_hwp_regs[16]; // Arm native linux hardware watchpoints
- uint32_t m_max_hwp_supported;
- uint32_t m_max_hbp_supported;
- bool m_refresh_hwdebug_info;
+ uint32_t m_max_hwp_supported;
+ uint32_t m_max_hbp_supported;
+ bool m_refresh_hwdebug_info;
- bool
- IsGPR(unsigned reg) const;
+ bool IsGPR(unsigned reg) const;
- bool
- IsFPR(unsigned reg) const;
+ bool IsFPR(unsigned reg) const;
- Error
- ReadHardwareDebugInfo();
+ Error ReadHardwareDebugInfo();
- Error
- WriteHardwareDebugRegs(int hwbType, int hwb_index);
+ Error WriteHardwareDebugRegs(int hwbType, int hwb_index);
- uint32_t
- CalculateFprOffset(const RegisterInfo* reg_info) const;
- };
+ uint32_t CalculateFprOffset(const RegisterInfo *reg_info) const;
+};
} // namespace process_linux
} // namespace lldb_private
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
index 9489f00..83cd179 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
-#if defined (__arm64__) || defined (__aarch64__)
+#if defined(__arm64__) || defined(__aarch64__)
#include "NativeRegisterContextLinux_arm.h"
#include "NativeRegisterContextLinux_arm64.h"
@@ -27,7 +27,8 @@
#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
#include "Plugins/Process/Utility/RegisterContextLinux_arm64.h"
-// System includes - They have to be included after framework includes because they define some
+// System includes - They have to be included after framework includes because
+// they define some
// macros which collide with variable names in other modules
#include <sys/socket.h>
// NT_PRSTATUS and NT_FPREGSET definition
@@ -42,1051 +43,930 @@ using namespace lldb_private;
using namespace lldb_private::process_linux;
// ARM64 general purpose registers.
-static const uint32_t g_gpr_regnums_arm64[] =
-{
- gpr_x0_arm64,
- gpr_x1_arm64,
- gpr_x2_arm64,
- gpr_x3_arm64,
- gpr_x4_arm64,
- gpr_x5_arm64,
- gpr_x6_arm64,
- gpr_x7_arm64,
- gpr_x8_arm64,
- gpr_x9_arm64,
- gpr_x10_arm64,
- gpr_x11_arm64,
- gpr_x12_arm64,
- gpr_x13_arm64,
- gpr_x14_arm64,
- gpr_x15_arm64,
- gpr_x16_arm64,
- gpr_x17_arm64,
- gpr_x18_arm64,
- gpr_x19_arm64,
- gpr_x20_arm64,
- gpr_x21_arm64,
- gpr_x22_arm64,
- gpr_x23_arm64,
- gpr_x24_arm64,
- gpr_x25_arm64,
- gpr_x26_arm64,
- gpr_x27_arm64,
- gpr_x28_arm64,
- gpr_fp_arm64,
- gpr_lr_arm64,
- gpr_sp_arm64,
- gpr_pc_arm64,
- gpr_cpsr_arm64,
+static const uint32_t g_gpr_regnums_arm64[] = {
+ gpr_x0_arm64, gpr_x1_arm64, gpr_x2_arm64, gpr_x3_arm64,
+ gpr_x4_arm64, gpr_x5_arm64, gpr_x6_arm64, gpr_x7_arm64,
+ gpr_x8_arm64, gpr_x9_arm64, gpr_x10_arm64, gpr_x11_arm64,
+ gpr_x12_arm64, gpr_x13_arm64, gpr_x14_arm64, gpr_x15_arm64,
+ gpr_x16_arm64, gpr_x17_arm64, gpr_x18_arm64, gpr_x19_arm64,
+ gpr_x20_arm64, gpr_x21_arm64, gpr_x22_arm64, gpr_x23_arm64,
+ gpr_x24_arm64, gpr_x25_arm64, gpr_x26_arm64, gpr_x27_arm64,
+ gpr_x28_arm64, gpr_fp_arm64, gpr_lr_arm64, gpr_sp_arm64,
+ gpr_pc_arm64, gpr_cpsr_arm64,
LLDB_INVALID_REGNUM // register sets need to end with this flag
};
-static_assert(((sizeof g_gpr_regnums_arm64 / sizeof g_gpr_regnums_arm64[0]) - 1) == k_num_gpr_registers_arm64, \
+static_assert(((sizeof g_gpr_regnums_arm64 / sizeof g_gpr_regnums_arm64[0]) -
+ 1) == k_num_gpr_registers_arm64,
"g_gpr_regnums_arm64 has wrong number of register infos");
// ARM64 floating point registers.
-static const uint32_t g_fpu_regnums_arm64[] =
-{
- fpu_v0_arm64,
- fpu_v1_arm64,
- fpu_v2_arm64,
- fpu_v3_arm64,
- fpu_v4_arm64,
- fpu_v5_arm64,
- fpu_v6_arm64,
- fpu_v7_arm64,
- fpu_v8_arm64,
- fpu_v9_arm64,
- fpu_v10_arm64,
- fpu_v11_arm64,
- fpu_v12_arm64,
- fpu_v13_arm64,
- fpu_v14_arm64,
- fpu_v15_arm64,
- fpu_v16_arm64,
- fpu_v17_arm64,
- fpu_v18_arm64,
- fpu_v19_arm64,
- fpu_v20_arm64,
- fpu_v21_arm64,
- fpu_v22_arm64,
- fpu_v23_arm64,
- fpu_v24_arm64,
- fpu_v25_arm64,
- fpu_v26_arm64,
- fpu_v27_arm64,
- fpu_v28_arm64,
- fpu_v29_arm64,
- fpu_v30_arm64,
- fpu_v31_arm64,
- fpu_fpsr_arm64,
- fpu_fpcr_arm64,
+static const uint32_t g_fpu_regnums_arm64[] = {
+ fpu_v0_arm64, fpu_v1_arm64, fpu_v2_arm64, fpu_v3_arm64,
+ fpu_v4_arm64, fpu_v5_arm64, fpu_v6_arm64, fpu_v7_arm64,
+ fpu_v8_arm64, fpu_v9_arm64, fpu_v10_arm64, fpu_v11_arm64,
+ fpu_v12_arm64, fpu_v13_arm64, fpu_v14_arm64, fpu_v15_arm64,
+ fpu_v16_arm64, fpu_v17_arm64, fpu_v18_arm64, fpu_v19_arm64,
+ fpu_v20_arm64, fpu_v21_arm64, fpu_v22_arm64, fpu_v23_arm64,
+ fpu_v24_arm64, fpu_v25_arm64, fpu_v26_arm64, fpu_v27_arm64,
+ fpu_v28_arm64, fpu_v29_arm64, fpu_v30_arm64, fpu_v31_arm64,
+ fpu_fpsr_arm64, fpu_fpcr_arm64,
LLDB_INVALID_REGNUM // register sets need to end with this flag
};
-static_assert(((sizeof g_fpu_regnums_arm64 / sizeof g_fpu_regnums_arm64[0]) - 1) == k_num_fpr_registers_arm64, \
+static_assert(((sizeof g_fpu_regnums_arm64 / sizeof g_fpu_regnums_arm64[0]) -
+ 1) == k_num_fpr_registers_arm64,
"g_fpu_regnums_arm64 has wrong number of register infos");
namespace {
- // Number of register sets provided by this context.
- enum
- {
- k_num_register_sets = 2
- };
+// Number of register sets provided by this context.
+enum { k_num_register_sets = 2 };
}
// Register sets for ARM64.
-static const RegisterSet
-g_reg_sets_arm64[k_num_register_sets] =
-{
- { "General Purpose Registers", "gpr", k_num_gpr_registers_arm64, g_gpr_regnums_arm64 },
- { "Floating Point Registers", "fpu", k_num_fpr_registers_arm64, g_fpu_regnums_arm64 }
-};
-
-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, concrete_frame_idx);
- case llvm::Triple::aarch64:
- 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;
- }
+static const RegisterSet g_reg_sets_arm64[k_num_register_sets] = {
+ {"General Purpose Registers", "gpr", k_num_gpr_registers_arm64,
+ g_gpr_regnums_arm64},
+ {"Floating Point Registers", "fpu", k_num_fpr_registers_arm64,
+ g_fpu_regnums_arm64}};
+
+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,
+ concrete_frame_idx);
+ case llvm::Triple::aarch64:
+ 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;
+ }
+}
+
+NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64(
+ const ArchSpec &target_arch, NativeThreadProtocol &native_thread,
+ uint32_t concrete_frame_idx)
+ : NativeRegisterContextLinux(native_thread, concrete_frame_idx,
+ new RegisterContextLinux_arm64(target_arch)) {
+ switch (target_arch.GetMachine()) {
+ case llvm::Triple::aarch64:
+ m_reg_info.num_registers = k_num_registers_arm64;
+ m_reg_info.num_gpr_registers = k_num_gpr_registers_arm64;
+ m_reg_info.num_fpr_registers = k_num_fpr_registers_arm64;
+ m_reg_info.last_gpr = k_last_gpr_arm64;
+ m_reg_info.first_fpr = k_first_fpr_arm64;
+ m_reg_info.last_fpr = k_last_fpr_arm64;
+ m_reg_info.first_fpr_v = fpu_v0_arm64;
+ m_reg_info.last_fpr_v = fpu_v31_arm64;
+ m_reg_info.gpr_flags = gpr_cpsr_arm64;
+ break;
+ default:
+ assert(false && "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));
+
+ // 16 is just a maximum value, query hardware for actual watchpoint count
+ m_max_hwp_supported = 16;
+ m_max_hbp_supported = 16;
+ m_refresh_hwdebug_info = true;
+}
+
+uint32_t NativeRegisterContextLinux_arm64::GetRegisterSetCount() const {
+ return k_num_register_sets;
}
-NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64 (const ArchSpec& target_arch,
- NativeThreadProtocol &native_thread,
- uint32_t concrete_frame_idx) :
- NativeRegisterContextLinux (native_thread, concrete_frame_idx, new RegisterContextLinux_arm64(target_arch))
-{
- switch (target_arch.GetMachine())
- {
- case llvm::Triple::aarch64:
- m_reg_info.num_registers = k_num_registers_arm64;
- m_reg_info.num_gpr_registers = k_num_gpr_registers_arm64;
- m_reg_info.num_fpr_registers = k_num_fpr_registers_arm64;
- m_reg_info.last_gpr = k_last_gpr_arm64;
- m_reg_info.first_fpr = k_first_fpr_arm64;
- m_reg_info.last_fpr = k_last_fpr_arm64;
- m_reg_info.first_fpr_v = fpu_v0_arm64;
- m_reg_info.last_fpr_v = fpu_v31_arm64;
- m_reg_info.gpr_flags = gpr_cpsr_arm64;
- break;
- default:
- assert(false && "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));
+const RegisterSet *
+NativeRegisterContextLinux_arm64::GetRegisterSet(uint32_t set_index) const {
+ if (set_index < k_num_register_sets)
+ return &g_reg_sets_arm64[set_index];
- // 16 is just a maximum value, query hardware for actual watchpoint count
- m_max_hwp_supported = 16;
- m_max_hbp_supported = 16;
- m_refresh_hwdebug_info = true;
+ return nullptr;
}
-uint32_t
-NativeRegisterContextLinux_arm64::GetRegisterSetCount () const
-{
- return k_num_register_sets;
+uint32_t NativeRegisterContextLinux_arm64::GetUserRegisterCount() const {
+ uint32_t count = 0;
+ for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index)
+ count += g_reg_sets_arm64[set_index].num_registers;
+ return count;
}
-const RegisterSet *
-NativeRegisterContextLinux_arm64::GetRegisterSet (uint32_t set_index) const
-{
- if (set_index < k_num_register_sets)
- return &g_reg_sets_arm64[set_index];
+Error NativeRegisterContextLinux_arm64::ReadRegister(
+ const RegisterInfo *reg_info, RegisterValue &reg_value) {
+ Error error;
- return nullptr;
-}
-
-uint32_t
-NativeRegisterContextLinux_arm64::GetUserRegisterCount() const
-{
- uint32_t count = 0;
- for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index)
- count += g_reg_sets_arm64[set_index].num_registers;
- return count;
-}
+ if (!reg_info) {
+ error.SetErrorString("reg_info NULL");
+ return error;
+ }
-Error
-NativeRegisterContextLinux_arm64::ReadRegister (const RegisterInfo *reg_info, RegisterValue &reg_value)
-{
- Error error;
+ const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
- if (!reg_info)
- {
- error.SetErrorString ("reg_info NULL");
- return error;
+ if (IsFPR(reg)) {
+ error = ReadFPR();
+ if (error.Fail())
+ return error;
+ } else {
+ uint32_t full_reg = reg;
+ bool is_subreg = reg_info->invalidate_regs &&
+ (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
+
+ if (is_subreg) {
+ // Read the full aligned 64-bit register.
+ full_reg = reg_info->invalidate_regs[0];
}
- const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+ error = ReadRegisterRaw(full_reg, reg_value);
- if (IsFPR(reg))
- {
- error = ReadFPR();
- if (error.Fail())
- return error;
- }
- else
- {
- uint32_t full_reg = reg;
- bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
-
- if (is_subreg)
- {
- // Read the full aligned 64-bit register.
- full_reg = reg_info->invalidate_regs[0];
- }
-
- error = ReadRegisterRaw(full_reg, reg_value);
-
- if (error.Success ())
- {
- // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right.
- if (is_subreg && (reg_info->byte_offset & 0x1))
- reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8);
-
- // If our return byte size was greater than the return value reg size, then
- // use the type specified by reg_info rather than the uint64_t default
- if (reg_value.GetByteSize() > reg_info->byte_size)
- reg_value.SetType(reg_info);
- }
- return error;
+ if (error.Success()) {
+ // If our read was not aligned (for ah,bh,ch,dh), shift our returned value
+ // one byte to the right.
+ if (is_subreg && (reg_info->byte_offset & 0x1))
+ reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8);
+
+ // If our return byte size was greater than the return value reg size,
+ // then
+ // use the type specified by reg_info rather than the uint64_t default
+ if (reg_value.GetByteSize() > reg_info->byte_size)
+ reg_value.SetType(reg_info);
}
+ return error;
+ }
- // Get pointer to m_fpr variable and set the data from it.
- uint32_t fpr_offset = CalculateFprOffset(reg_info);
- assert (fpr_offset < sizeof m_fpr);
- uint8_t *src = (uint8_t *)&m_fpr + fpr_offset;
- reg_value.SetFromMemoryData(reg_info, src, reg_info->byte_size, eByteOrderLittle, error);
+ // Get pointer to m_fpr variable and set the data from it.
+ uint32_t fpr_offset = CalculateFprOffset(reg_info);
+ assert(fpr_offset < sizeof m_fpr);
+ uint8_t *src = (uint8_t *)&m_fpr + fpr_offset;
+ reg_value.SetFromMemoryData(reg_info, src, reg_info->byte_size,
+ eByteOrderLittle, error);
- return error;
+ return error;
}
-Error
-NativeRegisterContextLinux_arm64::WriteRegister (const RegisterInfo *reg_info, const RegisterValue &reg_value)
-{
- if (!reg_info)
- return Error ("reg_info NULL");
-
- const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB];
- if (reg_index == LLDB_INVALID_REGNUM)
- return Error ("no lldb regnum for %s", reg_info && reg_info->name ? reg_info->name : "<unknown register>");
-
- if (IsGPR(reg_index))
- return WriteRegisterRaw(reg_index, reg_value);
-
- if (IsFPR(reg_index))
- {
- // Get pointer to m_fpr variable and set the data to it.
- uint32_t fpr_offset = CalculateFprOffset(reg_info);
- assert (fpr_offset < sizeof m_fpr);
- uint8_t *dst = (uint8_t *)&m_fpr + fpr_offset;
- switch (reg_info->byte_size)
- {
- case 2:
- *(uint16_t *)dst = reg_value.GetAsUInt16();
- break;
- case 4:
- *(uint32_t *)dst = reg_value.GetAsUInt32();
- break;
- case 8:
- *(uint64_t *)dst = reg_value.GetAsUInt64();
- break;
- default:
- assert(false && "Unhandled data size.");
- return Error ("unhandled register data size %" PRIu32, reg_info->byte_size);
- }
-
- Error error = WriteFPR();
- if (error.Fail())
- return error;
-
- return Error ();
- }
+Error NativeRegisterContextLinux_arm64::WriteRegister(
+ const RegisterInfo *reg_info, const RegisterValue &reg_value) {
+ if (!reg_info)
+ return Error("reg_info NULL");
- return Error ("failed - register wasn't recognized to be a GPR or an FPR, write strategy unknown");
-}
+ const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB];
+ if (reg_index == LLDB_INVALID_REGNUM)
+ return Error("no lldb regnum for %s", reg_info && reg_info->name
+ ? reg_info->name
+ : "<unknown register>");
-Error
-NativeRegisterContextLinux_arm64::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
-{
- Error error;
+ if (IsGPR(reg_index))
+ return WriteRegisterRaw(reg_index, reg_value);
- data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
- if (!data_sp)
- return Error ("failed to allocate DataBufferHeap instance of size %" PRIu64, REG_CONTEXT_SIZE);
+ if (IsFPR(reg_index)) {
+ // Get pointer to m_fpr variable and set the data to it.
+ uint32_t fpr_offset = CalculateFprOffset(reg_info);
+ assert(fpr_offset < sizeof m_fpr);
+ uint8_t *dst = (uint8_t *)&m_fpr + fpr_offset;
+ switch (reg_info->byte_size) {
+ case 2:
+ *(uint16_t *)dst = reg_value.GetAsUInt16();
+ break;
+ case 4:
+ *(uint32_t *)dst = reg_value.GetAsUInt32();
+ break;
+ case 8:
+ *(uint64_t *)dst = reg_value.GetAsUInt64();
+ break;
+ default:
+ assert(false && "Unhandled data size.");
+ return Error("unhandled register data size %" PRIu32,
+ reg_info->byte_size);
+ }
- error = ReadGPR();
+ Error error = WriteFPR();
if (error.Fail())
- return error;
+ return error;
- error = ReadFPR();
- if (error.Fail())
- return error;
+ return Error();
+ }
- uint8_t *dst = data_sp->GetBytes ();
- if (dst == nullptr)
- {
- error.SetErrorStringWithFormat ("DataBufferHeap instance of size %" PRIu64 " returned a null pointer", REG_CONTEXT_SIZE);
- return error;
- }
+ return Error("failed - register wasn't recognized to be a GPR or an FPR, "
+ "write strategy unknown");
+}
+
+Error NativeRegisterContextLinux_arm64::ReadAllRegisterValues(
+ lldb::DataBufferSP &data_sp) {
+ Error error;
- ::memcpy (dst, &m_gpr_arm64, GetGPRSize());
- dst += GetGPRSize();
- ::memcpy (dst, &m_fpr, sizeof(m_fpr));
+ data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
+ if (!data_sp)
+ return Error("failed to allocate DataBufferHeap instance of size %" PRIu64,
+ REG_CONTEXT_SIZE);
+ error = ReadGPR();
+ if (error.Fail())
return error;
-}
-Error
-NativeRegisterContextLinux_arm64::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
-{
- Error error;
+ error = ReadFPR();
+ if (error.Fail())
+ return error;
- if (!data_sp)
- {
- error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s invalid data_sp provided", __FUNCTION__);
- return error;
- }
+ uint8_t *dst = data_sp->GetBytes();
+ if (dst == nullptr) {
+ error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64
+ " returned a null pointer",
+ REG_CONTEXT_SIZE);
+ return error;
+ }
- if (data_sp->GetByteSize () != REG_CONTEXT_SIZE)
- {
- error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched data size, expected %" PRIu64 ", actual %" PRIu64, __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize ());
- return error;
- }
+ ::memcpy(dst, &m_gpr_arm64, GetGPRSize());
+ dst += GetGPRSize();
+ ::memcpy(dst, &m_fpr, sizeof(m_fpr));
+ return error;
+}
- uint8_t *src = data_sp->GetBytes ();
- if (src == nullptr)
- {
- error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s DataBuffer::GetBytes() returned a null pointer", __FUNCTION__);
- return error;
- }
- ::memcpy (&m_gpr_arm64, src, GetRegisterInfoInterface ().GetGPRSize ());
+Error NativeRegisterContextLinux_arm64::WriteAllRegisterValues(
+ const lldb::DataBufferSP &data_sp) {
+ Error error;
- error = WriteGPR();
- if (error.Fail())
- return error;
+ if (!data_sp) {
+ error.SetErrorStringWithFormat(
+ "NativeRegisterContextLinux_x86_64::%s invalid data_sp provided",
+ __FUNCTION__);
+ return error;
+ }
- src += GetRegisterInfoInterface ().GetGPRSize ();
- ::memcpy (&m_fpr, src, sizeof(m_fpr));
+ if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) {
+ error.SetErrorStringWithFormat(
+ "NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched "
+ "data size, expected %" PRIu64 ", actual %" PRIu64,
+ __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize());
+ return error;
+ }
+
+ uint8_t *src = data_sp->GetBytes();
+ if (src == nullptr) {
+ error.SetErrorStringWithFormat("NativeRegisterContextLinux_x86_64::%s "
+ "DataBuffer::GetBytes() returned a null "
+ "pointer",
+ __FUNCTION__);
+ return error;
+ }
+ ::memcpy(&m_gpr_arm64, src, GetRegisterInfoInterface().GetGPRSize());
- error = WriteFPR();
- if (error.Fail())
- return error;
+ error = WriteGPR();
+ if (error.Fail())
+ return error;
+
+ src += GetRegisterInfoInterface().GetGPRSize();
+ ::memcpy(&m_fpr, src, sizeof(m_fpr));
+ error = WriteFPR();
+ if (error.Fail())
return error;
+
+ return error;
}
-bool
-NativeRegisterContextLinux_arm64::IsGPR(unsigned reg) const
-{
- return reg <= m_reg_info.last_gpr; // GPR's come first.
+bool NativeRegisterContextLinux_arm64::IsGPR(unsigned reg) const {
+ return reg <= m_reg_info.last_gpr; // GPR's come first.
}
-bool
-NativeRegisterContextLinux_arm64::IsFPR(unsigned reg) const
-{
- return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr);
+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));
-
- if (log)
- log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
-
- Error error;
-
- // Read hardware breakpoint and watchpoint information.
- error = ReadHardwareDebugInfo ();
-
- if (error.Fail())
- return LLDB_INVALID_INDEX32;
-
- uint32_t control_value = 0, bp_index = 0;
-
- // Check if size has a valid hardware breakpoint length.
- if (size != 4)
- return LLDB_INVALID_INDEX32; // Invalid size for a AArch64 hardware breakpoint
-
- // Check 4-byte alignment for hardware breakpoint target address.
- if (addr & 0x03)
- return LLDB_INVALID_INDEX32; // Invalid address, should be 4-byte aligned.
-
- // Setup control value
- control_value = 0;
- 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.
- 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
- }
+NativeRegisterContextLinux_arm64::SetHardwareBreakpoint(lldb::addr_t addr,
+ size_t size) {
+ 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();
+
+ if (error.Fail())
+ return LLDB_INVALID_INDEX32;
+
+ uint32_t control_value = 0, bp_index = 0;
+
+ // Check if size has a valid hardware breakpoint length.
+ if (size != 4)
+ return LLDB_INVALID_INDEX32; // Invalid size for a AArch64 hardware
+ // breakpoint
+
+ // Check 4-byte alignment for hardware breakpoint target address.
+ if (addr & 0x03)
+ return LLDB_INVALID_INDEX32; // Invalid address, should be 4-byte aligned.
+
+ // Setup control value
+ control_value = 0;
+ 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.
+ 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
}
+ }
- if (bp_index == LLDB_INVALID_INDEX32)
- return LLDB_INVALID_INDEX32;
+ 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;
+ // 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;
- // 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;
+ m_hbr_regs[bp_index].refcount = 0;
- return LLDB_INVALID_INDEX32;
- }
+ return LLDB_INVALID_INDEX32;
}
- else
- m_hbr_regs[bp_index].refcount++;
+ } else
+ m_hbr_regs[bp_index].refcount++;
- return bp_index;
+ return bp_index;
}
-bool
-NativeRegisterContextLinux_arm64::ClearHardwareBreakpoint (uint32_t hw_idx)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
+bool NativeRegisterContextLinux_arm64::ClearHardwareBreakpoint(
+ uint32_t hw_idx) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
- if (log)
- log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
+ if (log)
+ log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
- Error error;
+ Error error;
- // Read hardware breakpoint and watchpoint information.
- error = ReadHardwareDebugInfo ();
+ // Read hardware breakpoint and watchpoint information.
+ error = ReadHardwareDebugInfo();
- if (error.Fail())
- return false;
+ if (error.Fail())
+ return false;
- if (hw_idx >= m_max_hbp_supported)
- return false;
+ 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;
-
- m_hbr_regs[hw_idx].control &= ~1;
- m_hbr_regs[hw_idx].address = 0;
- m_hbr_regs[hw_idx].refcount = 0;
-
- // PTRACE call to clear corresponding hardware breakpoint register.
- 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;
-
- return false;
- }
-
- return true;
+ // 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;
+
+ m_hbr_regs[hw_idx].control &= ~1;
+ m_hbr_regs[hw_idx].address = 0;
+ m_hbr_regs[hw_idx].refcount = 0;
+
+ // PTRACE call to clear corresponding hardware breakpoint register.
+ 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;
+
+ return false;
}
- return false;
+ return true;
+ }
+
+ return false;
}
-uint32_t
-NativeRegisterContextLinux_arm64::NumSupportedHardwareWatchpoints ()
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
+uint32_t NativeRegisterContextLinux_arm64::NumSupportedHardwareWatchpoints() {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
- if (log)
- log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
+ if (log)
+ log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
- Error error;
+ Error error;
- // Read hardware breakpoint and watchpoint information.
- error = ReadHardwareDebugInfo ();
+ // Read hardware breakpoint and watchpoint information.
+ error = ReadHardwareDebugInfo();
- if (error.Fail())
- return 0;
+ if (error.Fail())
+ return 0;
- return 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));
+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;
+ if (log)
+ log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
- // Read hardware breakpoint and watchpoint information.
- error = ReadHardwareDebugInfo ();
+ Error error;
- if (error.Fail())
- return LLDB_INVALID_INDEX32;
-
- uint32_t control_value = 0, wp_index = 0;
- lldb::addr_t real_addr = addr;
-
- // Check if we are setting watchpoint other than read/write/access
- // Also update watchpoint flag to match AArch64 write-read bit configuration.
- switch (watch_flags)
- {
- case 1:
- watch_flags = 2;
- break;
- case 2:
- watch_flags = 1;
- break;
- case 3:
- break;
- default:
- return LLDB_INVALID_INDEX32;
- }
+ // Read hardware breakpoint and watchpoint information.
+ error = ReadHardwareDebugInfo();
- // Check if size has a valid hardware watchpoint length.
- if (size != 1 && size != 2 && size != 4 && size != 8)
- return LLDB_INVALID_INDEX32;
-
- // Check 8-byte alignment for hardware watchpoint target address.
- // Below is a hack to recalculate address and size in order to
- // make sure we can watch non 8-byte alligned addresses as well.
- if (addr & 0x07)
- {
- uint8_t watch_mask = (addr & 0x07) + size;
-
- if (watch_mask > 0x08)
- return LLDB_INVALID_INDEX32;
- else if (watch_mask <= 0x02)
- size = 2;
- else if (watch_mask <= 0x04)
- size = 4;
- else
- size = 8;
-
- addr = addr & (~0x07);
- }
+ if (error.Fail())
+ return LLDB_INVALID_INDEX32;
+
+ uint32_t control_value = 0, wp_index = 0;
+ lldb::addr_t real_addr = addr;
+
+ // Check if we are setting watchpoint other than read/write/access
+ // Also update watchpoint flag to match AArch64 write-read bit configuration.
+ switch (watch_flags) {
+ case 1:
+ watch_flags = 2;
+ break;
+ case 2:
+ watch_flags = 1;
+ break;
+ case 3:
+ break;
+ default:
+ return LLDB_INVALID_INDEX32;
+ }
- // Setup control value
- control_value = watch_flags << 3;
- control_value |= ((1 << size) - 1) << 5;
- control_value |= (2 << 1) | 1;
-
- // Iterate over stored watchpoints
- // Find a free wp_index or update reference count if duplicate.
- wp_index = LLDB_INVALID_INDEX32;
- for (uint32_t i = 0; i < m_max_hwp_supported; i++)
- {
- if ((m_hwp_regs[i].control & 1) == 0)
- {
- wp_index = i; // Mark last free slot
- }
- else if (m_hwp_regs[i].address == addr && m_hwp_regs[i].control == control_value)
- {
- wp_index = i; // Mark duplicate index
- break; // Stop searching here
- }
+ // Check if size has a valid hardware watchpoint length.
+ if (size != 1 && size != 2 && size != 4 && size != 8)
+ return LLDB_INVALID_INDEX32;
+
+ // Check 8-byte alignment for hardware watchpoint target address.
+ // Below is a hack to recalculate address and size in order to
+ // make sure we can watch non 8-byte alligned addresses as well.
+ if (addr & 0x07) {
+ uint8_t watch_mask = (addr & 0x07) + size;
+
+ if (watch_mask > 0x08)
+ return LLDB_INVALID_INDEX32;
+ else if (watch_mask <= 0x02)
+ size = 2;
+ else if (watch_mask <= 0x04)
+ size = 4;
+ else
+ size = 8;
+
+ addr = addr & (~0x07);
+ }
+
+ // Setup control value
+ control_value = watch_flags << 3;
+ control_value |= ((1 << size) - 1) << 5;
+ control_value |= (2 << 1) | 1;
+
+ // Iterate over stored watchpoints
+ // Find a free wp_index or update reference count if duplicate.
+ wp_index = LLDB_INVALID_INDEX32;
+ for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
+ if ((m_hwp_regs[i].control & 1) == 0) {
+ wp_index = i; // Mark last free slot
+ } else if (m_hwp_regs[i].address == addr &&
+ m_hwp_regs[i].control == control_value) {
+ wp_index = i; // Mark duplicate index
+ break; // Stop searching here
}
+ }
+
+ if (wp_index == LLDB_INVALID_INDEX32)
+ return LLDB_INVALID_INDEX32;
+
+ // Add new or update existing watchpoint
+ if ((m_hwp_regs[wp_index].control & 1) == 0) {
+ // Update watchpoint in local cache
+ m_hwp_regs[wp_index].real_addr = real_addr;
+ m_hwp_regs[wp_index].address = addr;
+ m_hwp_regs[wp_index].control = control_value;
+ m_hwp_regs[wp_index].refcount = 1;
+
+ // PTRACE call to set corresponding watchpoint register.
+ error = WriteHardwareDebugRegs(eDREGTypeWATCH);
- if (wp_index == LLDB_INVALID_INDEX32)
- return LLDB_INVALID_INDEX32;
-
- // Add new or update existing watchpoint
- if ((m_hwp_regs[wp_index].control & 1) == 0)
- {
- // Update watchpoint in local cache
- m_hwp_regs[wp_index].real_addr = real_addr;
- m_hwp_regs[wp_index].address = addr;
- m_hwp_regs[wp_index].control = control_value;
- m_hwp_regs[wp_index].refcount = 1;
-
- // PTRACE call to set corresponding watchpoint register.
- error = WriteHardwareDebugRegs(eDREGTypeWATCH);
-
- if (error.Fail())
- {
- m_hwp_regs[wp_index].address = 0;
- m_hwp_regs[wp_index].control &= ~1;
- m_hwp_regs[wp_index].refcount = 0;
-
- return LLDB_INVALID_INDEX32;
- }
+ if (error.Fail()) {
+ m_hwp_regs[wp_index].address = 0;
+ m_hwp_regs[wp_index].control &= ~1;
+ m_hwp_regs[wp_index].refcount = 0;
+
+ return LLDB_INVALID_INDEX32;
}
- else
- m_hwp_regs[wp_index].refcount++;
+ } else
+ m_hwp_regs[wp_index].refcount++;
- return wp_index;
+ return wp_index;
}
-bool
-NativeRegisterContextLinux_arm64::ClearHardwareWatchpoint (uint32_t wp_index)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
+bool NativeRegisterContextLinux_arm64::ClearHardwareWatchpoint(
+ uint32_t wp_index) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
- if (log)
- log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
+ if (log)
+ log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
- Error error;
+ Error error;
- // Read hardware breakpoint and watchpoint information.
- error = ReadHardwareDebugInfo ();
+ // Read hardware breakpoint and watchpoint information.
+ error = ReadHardwareDebugInfo();
- if (error.Fail())
- return false;
+ if (error.Fail())
+ return false;
- if (wp_index >= m_max_hwp_supported)
- return false;
+ if (wp_index >= m_max_hwp_supported)
+ return false;
- // Update reference count if multiple references.
- if (m_hwp_regs[wp_index].refcount > 1)
- {
- m_hwp_regs[wp_index].refcount--;
- return true;
- }
- else if (m_hwp_regs[wp_index].refcount == 1)
- {
- // Create a backup we can revert to in case of failure.
- lldb::addr_t tempAddr = m_hwp_regs[wp_index].address;
- uint32_t tempControl = m_hwp_regs[wp_index].control;
- uint32_t tempRefCount = m_hwp_regs[wp_index].refcount;
-
- // Update watchpoint in local cache
- m_hwp_regs[wp_index].control &= ~1;
- m_hwp_regs[wp_index].address = 0;
- m_hwp_regs[wp_index].refcount = 0;
-
- // Ptrace call to update hardware debug registers
- error = WriteHardwareDebugRegs(eDREGTypeWATCH);
-
- if (error.Fail())
- {
- m_hwp_regs[wp_index].control = tempControl;
- m_hwp_regs[wp_index].address = tempAddr;
- m_hwp_regs[wp_index].refcount = tempRefCount;
-
- return false;
- }
-
- return true;
+ // Update reference count if multiple references.
+ if (m_hwp_regs[wp_index].refcount > 1) {
+ m_hwp_regs[wp_index].refcount--;
+ return true;
+ } else if (m_hwp_regs[wp_index].refcount == 1) {
+ // Create a backup we can revert to in case of failure.
+ lldb::addr_t tempAddr = m_hwp_regs[wp_index].address;
+ uint32_t tempControl = m_hwp_regs[wp_index].control;
+ uint32_t tempRefCount = m_hwp_regs[wp_index].refcount;
+
+ // Update watchpoint in local cache
+ m_hwp_regs[wp_index].control &= ~1;
+ m_hwp_regs[wp_index].address = 0;
+ m_hwp_regs[wp_index].refcount = 0;
+
+ // Ptrace call to update hardware debug registers
+ error = WriteHardwareDebugRegs(eDREGTypeWATCH);
+
+ if (error.Fail()) {
+ m_hwp_regs[wp_index].control = tempControl;
+ m_hwp_regs[wp_index].address = tempAddr;
+ m_hwp_regs[wp_index].refcount = tempRefCount;
+
+ return false;
}
- return false;
+ return true;
+ }
+
+ return false;
}
-Error
-NativeRegisterContextLinux_arm64::ClearAllHardwareWatchpoints ()
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
+Error NativeRegisterContextLinux_arm64::ClearAllHardwareWatchpoints() {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
- if (log)
- log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
+ if (log)
+ log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
- Error error;
+ Error error;
- // Read hardware breakpoint and watchpoint information.
- error = ReadHardwareDebugInfo ();
+ // Read hardware breakpoint and watchpoint information.
+ error = ReadHardwareDebugInfo();
- if (error.Fail())
- return error;
+ if (error.Fail())
+ return error;
+
+ lldb::addr_t tempAddr = 0;
+ uint32_t tempControl = 0, tempRefCount = 0;
+
+ for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
+ if (m_hwp_regs[i].control & 0x01) {
+ // Create a backup we can revert to in case of failure.
+ tempAddr = m_hwp_regs[i].address;
+ tempControl = m_hwp_regs[i].control;
+ tempRefCount = m_hwp_regs[i].refcount;
- lldb::addr_t tempAddr = 0;
- uint32_t tempControl = 0, tempRefCount = 0;
-
- for (uint32_t i = 0; i < m_max_hwp_supported; i++)
- {
- if (m_hwp_regs[i].control & 0x01)
- {
- // Create a backup we can revert to in case of failure.
- tempAddr = m_hwp_regs[i].address;
- tempControl = m_hwp_regs[i].control;
- tempRefCount = m_hwp_regs[i].refcount;
-
- // Clear watchpoints in local cache
- m_hwp_regs[i].control &= ~1;
- m_hwp_regs[i].address = 0;
- m_hwp_regs[i].refcount = 0;
-
- // Ptrace call to update hardware debug registers
- error = WriteHardwareDebugRegs(eDREGTypeWATCH);
-
- if (error.Fail())
- {
- m_hwp_regs[i].control = tempControl;
- m_hwp_regs[i].address = tempAddr;
- m_hwp_regs[i].refcount = tempRefCount;
-
- return error;
- }
- }
+ // Clear watchpoints in local cache
+ m_hwp_regs[i].control &= ~1;
+ m_hwp_regs[i].address = 0;
+ m_hwp_regs[i].refcount = 0;
+
+ // Ptrace call to update hardware debug registers
+ error = WriteHardwareDebugRegs(eDREGTypeWATCH);
+
+ if (error.Fail()) {
+ m_hwp_regs[i].control = tempControl;
+ m_hwp_regs[i].address = tempAddr;
+ m_hwp_regs[i].refcount = tempRefCount;
+
+ return error;
+ }
}
+ }
- return Error();
+ return Error();
}
uint32_t
-NativeRegisterContextLinux_arm64::GetWatchpointSize(uint32_t wp_index)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
-
- if (log)
- log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
- switch ((m_hwp_regs[wp_index].control >> 5) & 0xff)
- {
- case 0x01:
- return 1;
- case 0x03:
- return 2;
- case 0x0f:
- return 4;
- case 0xff:
- return 8;
- default:
- return 0;
- }
+NativeRegisterContextLinux_arm64::GetWatchpointSize(uint32_t wp_index) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+
+ if (log)
+ log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
+ switch ((m_hwp_regs[wp_index].control >> 5) & 0xff) {
+ case 0x01:
+ return 1;
+ case 0x03:
+ return 2;
+ case 0x0f:
+ return 4;
+ case 0xff:
+ return 8;
+ default:
+ return 0;
+ }
+}
+bool NativeRegisterContextLinux_arm64::WatchpointIsEnabled(uint32_t wp_index) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+
+ if (log)
+ log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
+
+ if ((m_hwp_regs[wp_index].control & 0x1) == 0x1)
+ return true;
+ else
+ return false;
}
-bool
-NativeRegisterContextLinux_arm64::WatchpointIsEnabled(uint32_t wp_index)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
- if (log)
- log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
+Error NativeRegisterContextLinux_arm64::GetWatchpointHitIndex(
+ uint32_t &wp_index, lldb::addr_t trap_addr) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
- if ((m_hwp_regs[wp_index].control & 0x1) == 0x1)
- return true;
- else
- return false;
-}
+ if (log)
+ log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
-Error
-NativeRegisterContextLinux_arm64::GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
+ uint32_t watch_size;
+ lldb::addr_t watch_addr;
- if (log)
- log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
-
- uint32_t watch_size;
- lldb::addr_t watch_addr;
-
- for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index)
- {
- watch_size = GetWatchpointSize (wp_index);
- watch_addr = m_hwp_regs[wp_index].address;
-
- if (m_hwp_regs[wp_index].refcount >= 1 && WatchpointIsEnabled(wp_index)
- && trap_addr >= watch_addr && trap_addr < watch_addr + watch_size)
- {
- m_hwp_regs[wp_index].hit_addr = trap_addr;
- return Error();
- }
+ for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index) {
+ watch_size = GetWatchpointSize(wp_index);
+ watch_addr = m_hwp_regs[wp_index].address;
+
+ if (m_hwp_regs[wp_index].refcount >= 1 && WatchpointIsEnabled(wp_index) &&
+ trap_addr >= watch_addr && trap_addr < watch_addr + watch_size) {
+ m_hwp_regs[wp_index].hit_addr = trap_addr;
+ return Error();
}
+ }
- wp_index = LLDB_INVALID_INDEX32;
- return Error();
+ wp_index = LLDB_INVALID_INDEX32;
+ return Error();
}
lldb::addr_t
-NativeRegisterContextLinux_arm64::GetWatchpointAddress (uint32_t wp_index)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
+NativeRegisterContextLinux_arm64::GetWatchpointAddress(uint32_t wp_index) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
- if (log)
- log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
+ if (log)
+ log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
- if (wp_index >= m_max_hwp_supported)
- return LLDB_INVALID_ADDRESS;
+ if (wp_index >= m_max_hwp_supported)
+ return LLDB_INVALID_ADDRESS;
- if (WatchpointIsEnabled(wp_index))
- return m_hwp_regs[wp_index].real_addr;
- else
- return LLDB_INVALID_ADDRESS;
+ if (WatchpointIsEnabled(wp_index))
+ return m_hwp_regs[wp_index].real_addr;
+ else
+ return LLDB_INVALID_ADDRESS;
}
lldb::addr_t
-NativeRegisterContextLinux_arm64::GetWatchpointHitAddress (uint32_t wp_index)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
+NativeRegisterContextLinux_arm64::GetWatchpointHitAddress(uint32_t wp_index) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
- if (log)
- log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
+ if (log)
+ log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
- if (wp_index >= m_max_hwp_supported)
- return LLDB_INVALID_ADDRESS;
+ if (wp_index >= m_max_hwp_supported)
+ return LLDB_INVALID_ADDRESS;
- if (WatchpointIsEnabled(wp_index))
- return m_hwp_regs[wp_index].hit_addr;
- else
- return LLDB_INVALID_ADDRESS;
+ if (WatchpointIsEnabled(wp_index))
+ return m_hwp_regs[wp_index].hit_addr;
+ else
+ return LLDB_INVALID_ADDRESS;
}
-Error
-NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo()
-{
- if (!m_refresh_hwdebug_info)
- {
- return Error();
- }
-
- ::pid_t tid = m_thread.GetID();
+Error NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo() {
+ if (!m_refresh_hwdebug_info) {
+ return Error();
+ }
- int regset = NT_ARM_HW_WATCH;
- struct iovec ioVec;
- struct user_hwdebug_state dreg_state;
- Error error;
+ ::pid_t tid = m_thread.GetID();
- ioVec.iov_base = &dreg_state;
- ioVec.iov_len = sizeof (dreg_state);
- error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, &regset, &ioVec, ioVec.iov_len);
+ int regset = NT_ARM_HW_WATCH;
+ struct iovec ioVec;
+ struct user_hwdebug_state dreg_state;
+ Error error;
- if (error.Fail())
- return error;
+ ioVec.iov_base = &dreg_state;
+ ioVec.iov_len = sizeof(dreg_state);
+ error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, &regset,
+ &ioVec, ioVec.iov_len);
- m_max_hwp_supported = dreg_state.dbg_info & 0xff;
+ if (error.Fail())
+ return error;
- regset = NT_ARM_HW_BREAK;
- error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, &regset, &ioVec, ioVec.iov_len);
+ m_max_hwp_supported = dreg_state.dbg_info & 0xff;
- if (error.Fail())
- return error;
-
- m_max_hbp_supported = dreg_state.dbg_info & 0xff;
- m_refresh_hwdebug_info = false;
+ regset = NT_ARM_HW_BREAK;
+ error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, &regset,
+ &ioVec, ioVec.iov_len);
+ if (error.Fail())
return error;
+
+ m_max_hbp_supported = dreg_state.dbg_info & 0xff;
+ m_refresh_hwdebug_info = false;
+
+ return error;
}
-Error
-NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(int hwbType)
-{
- struct iovec ioVec;
- struct user_hwdebug_state dreg_state;
- Error error;
-
- memset (&dreg_state, 0, sizeof (dreg_state));
- ioVec.iov_base = &dreg_state;
-
- if (hwbType == eDREGTypeWATCH)
- {
- hwbType = NT_ARM_HW_WATCH;
- ioVec.iov_len = sizeof (dreg_state.dbg_info) + sizeof (dreg_state.pad)
- + (sizeof (dreg_state.dbg_regs [0]) * m_max_hwp_supported);
-
- for (uint32_t i = 0; i < m_max_hwp_supported; i++)
- {
- dreg_state.dbg_regs[i].addr = m_hwp_regs[i].address;
- dreg_state.dbg_regs[i].ctrl = m_hwp_regs[i].control;
- }
+Error NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(int hwbType) {
+ struct iovec ioVec;
+ struct user_hwdebug_state dreg_state;
+ Error error;
+
+ memset(&dreg_state, 0, sizeof(dreg_state));
+ ioVec.iov_base = &dreg_state;
+
+ if (hwbType == eDREGTypeWATCH) {
+ hwbType = NT_ARM_HW_WATCH;
+ ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) +
+ (sizeof(dreg_state.dbg_regs[0]) * m_max_hwp_supported);
+
+ for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
+ dreg_state.dbg_regs[i].addr = m_hwp_regs[i].address;
+ dreg_state.dbg_regs[i].ctrl = m_hwp_regs[i].control;
}
- else
- {
- hwbType = NT_ARM_HW_BREAK;
- ioVec.iov_len = sizeof (dreg_state.dbg_info) + sizeof (dreg_state.pad)
- + (sizeof (dreg_state.dbg_regs [0]) * m_max_hbp_supported);
-
- for (uint32_t i = 0; i < m_max_hbp_supported; i++)
- {
- dreg_state.dbg_regs[i].addr = m_hbr_regs[i].address;
- dreg_state.dbg_regs[i].ctrl = m_hbr_regs[i].control;
- }
+ } else {
+ hwbType = NT_ARM_HW_BREAK;
+ ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) +
+ (sizeof(dreg_state.dbg_regs[0]) * m_max_hbp_supported);
+
+ for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
+ dreg_state.dbg_regs[i].addr = m_hbr_regs[i].address;
+ dreg_state.dbg_regs[i].ctrl = m_hbr_regs[i].control;
}
+ }
- return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), &hwbType, &ioVec, ioVec.iov_len);
+ return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(),
+ &hwbType, &ioVec, ioVec.iov_len);
}
-Error
-NativeRegisterContextLinux_arm64::DoReadRegisterValue(uint32_t offset,
- const char* reg_name,
- uint32_t size,
- RegisterValue &value)
-{
- Error error;
- if (offset > sizeof(struct user_pt_regs))
- {
- uintptr_t offset = offset - sizeof(struct user_pt_regs);
- if (offset > sizeof(struct user_fpsimd_state))
- {
- error.SetErrorString("invalid offset value");
- return error;
- }
- elf_fpregset_t regs;
- int regset = NT_FPREGSET;
- struct iovec ioVec;
-
- ioVec.iov_base = &regs;
- ioVec.iov_len = sizeof regs;
- error = NativeProcessLinux::PtraceWrapper(
- PTRACE_GETREGSET, m_thread.GetID(), &regset, &ioVec, sizeof regs);
- if (error.Success())
- {
- ArchSpec arch;
- if (m_thread.GetProcess()->GetArchitecture(arch))
- value.SetBytes((void *)(((unsigned char *)(&regs)) + offset), 16, arch.GetByteOrder());
- else
- error.SetErrorString("failed to get architecture");
- }
+Error NativeRegisterContextLinux_arm64::DoReadRegisterValue(
+ uint32_t offset, const char *reg_name, uint32_t size,
+ RegisterValue &value) {
+ Error error;
+ if (offset > sizeof(struct user_pt_regs)) {
+ uintptr_t offset = offset - sizeof(struct user_pt_regs);
+ if (offset > sizeof(struct user_fpsimd_state)) {
+ error.SetErrorString("invalid offset value");
+ return error;
}
- else
- {
- elf_gregset_t regs;
- int regset = NT_PRSTATUS;
- struct iovec ioVec;
-
- ioVec.iov_base = &regs;
- ioVec.iov_len = sizeof regs;
- error = NativeProcessLinux::PtraceWrapper(
- PTRACE_GETREGSET, m_thread.GetID(), &regset, &ioVec, sizeof regs);
- if (error.Success())
- {
- ArchSpec arch;
- if (m_thread.GetProcess()->GetArchitecture(arch))
- value.SetBytes((void *)(((unsigned char *)(regs)) + offset), 8, arch.GetByteOrder());
- else
- error.SetErrorString("failed to get architecture");
- }
+ elf_fpregset_t regs;
+ int regset = NT_FPREGSET;
+ struct iovec ioVec;
+
+ ioVec.iov_base = &regs;
+ ioVec.iov_len = sizeof regs;
+ error = NativeProcessLinux::PtraceWrapper(
+ PTRACE_GETREGSET, m_thread.GetID(), &regset, &ioVec, sizeof regs);
+ if (error.Success()) {
+ ArchSpec arch;
+ if (m_thread.GetProcess()->GetArchitecture(arch))
+ value.SetBytes((void *)(((unsigned char *)(&regs)) + offset), 16,
+ arch.GetByteOrder());
+ else
+ error.SetErrorString("failed to get architecture");
}
- return error;
-}
+ } else {
+ elf_gregset_t regs;
+ int regset = NT_PRSTATUS;
+ struct iovec ioVec;
-Error
-NativeRegisterContextLinux_arm64::DoWriteRegisterValue(uint32_t offset,
- const char* reg_name,
- const RegisterValue &value)
-{
- Error error;
- ::pid_t tid = m_thread.GetID();
- if (offset > sizeof(struct user_pt_regs))
- {
- uintptr_t offset = offset - sizeof(struct user_pt_regs);
- if (offset > sizeof(struct user_fpsimd_state))
- {
- error.SetErrorString("invalid offset value");
- return error;
- }
- elf_fpregset_t regs;
- int regset = NT_FPREGSET;
- struct iovec ioVec;
-
- ioVec.iov_base = &regs;
- ioVec.iov_len = sizeof regs;
- error = NativeProcessLinux::PtraceWrapper( PTRACE_GETREGSET, tid, &regset, &ioVec, sizeof regs);
-
- if (error.Success())
- {
- ::memcpy((void *)(((unsigned char *)(&regs)) + offset), value.GetBytes(), 16);
- error = NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, tid, &regset, &ioVec, sizeof regs);
- }
+ ioVec.iov_base = &regs;
+ ioVec.iov_len = sizeof regs;
+ error = NativeProcessLinux::PtraceWrapper(
+ PTRACE_GETREGSET, m_thread.GetID(), &regset, &ioVec, sizeof regs);
+ if (error.Success()) {
+ ArchSpec arch;
+ if (m_thread.GetProcess()->GetArchitecture(arch))
+ value.SetBytes((void *)(((unsigned char *)(regs)) + offset), 8,
+ arch.GetByteOrder());
+ else
+ error.SetErrorString("failed to get architecture");
}
- else
- {
- elf_gregset_t regs;
- int regset = NT_PRSTATUS;
- struct iovec ioVec;
-
- ioVec.iov_base = &regs;
- ioVec.iov_len = sizeof regs;
- error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, &regset, &ioVec, sizeof regs);
- if (error.Success())
- {
- ::memcpy((void *)(((unsigned char *)(&regs)) + offset), value.GetBytes(), 8);
- error = NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, tid, &regset, &ioVec, sizeof regs);
- }
+ }
+ return error;
+}
+
+Error NativeRegisterContextLinux_arm64::DoWriteRegisterValue(
+ uint32_t offset, const char *reg_name, const RegisterValue &value) {
+ Error error;
+ ::pid_t tid = m_thread.GetID();
+ if (offset > sizeof(struct user_pt_regs)) {
+ uintptr_t offset = offset - sizeof(struct user_pt_regs);
+ if (offset > sizeof(struct user_fpsimd_state)) {
+ error.SetErrorString("invalid offset value");
+ return error;
}
- return error;
-}
+ elf_fpregset_t regs;
+ int regset = NT_FPREGSET;
+ struct iovec ioVec;
+
+ ioVec.iov_base = &regs;
+ ioVec.iov_len = sizeof regs;
+ error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, &regset,
+ &ioVec, sizeof regs);
-Error
-NativeRegisterContextLinux_arm64::DoReadGPR(void *buf, size_t buf_size)
-{
+ if (error.Success()) {
+ ::memcpy((void *)(((unsigned char *)(&regs)) + offset), value.GetBytes(),
+ 16);
+ error = NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, tid, &regset,
+ &ioVec, sizeof regs);
+ }
+ } else {
+ elf_gregset_t regs;
int regset = NT_PRSTATUS;
struct iovec ioVec;
- Error error;
- ioVec.iov_base = buf;
- ioVec.iov_len = buf_size;
- return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_thread.GetID(), &regset, &ioVec, buf_size);
+ ioVec.iov_base = &regs;
+ ioVec.iov_len = sizeof regs;
+ error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, &regset,
+ &ioVec, sizeof regs);
+ if (error.Success()) {
+ ::memcpy((void *)(((unsigned char *)(&regs)) + offset), value.GetBytes(),
+ 8);
+ error = NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, tid, &regset,
+ &ioVec, sizeof regs);
+ }
+ }
+ return error;
+}
+
+Error NativeRegisterContextLinux_arm64::DoReadGPR(void *buf, size_t buf_size) {
+ int regset = NT_PRSTATUS;
+ struct iovec ioVec;
+ Error error;
+
+ ioVec.iov_base = buf;
+ ioVec.iov_len = buf_size;
+ return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_thread.GetID(),
+ &regset, &ioVec, buf_size);
}
-Error
-NativeRegisterContextLinux_arm64::DoWriteGPR(void *buf, size_t buf_size)
-{
- int regset = NT_PRSTATUS;
- struct iovec ioVec;
- Error error;
+Error NativeRegisterContextLinux_arm64::DoWriteGPR(void *buf, size_t buf_size) {
+ int regset = NT_PRSTATUS;
+ struct iovec ioVec;
+ Error error;
- ioVec.iov_base = buf;
- ioVec.iov_len = buf_size;
- return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), &regset, &ioVec, buf_size);
+ ioVec.iov_base = buf;
+ ioVec.iov_len = buf_size;
+ return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(),
+ &regset, &ioVec, buf_size);
}
-Error
-NativeRegisterContextLinux_arm64::DoReadFPR(void *buf, size_t buf_size)
-{
- int regset = NT_FPREGSET;
- struct iovec ioVec;
- Error error;
+Error NativeRegisterContextLinux_arm64::DoReadFPR(void *buf, size_t buf_size) {
+ int regset = NT_FPREGSET;
+ struct iovec ioVec;
+ Error error;
- ioVec.iov_base = buf;
- ioVec.iov_len = buf_size;
- return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_thread.GetID(), &regset, &ioVec, buf_size);
+ ioVec.iov_base = buf;
+ ioVec.iov_len = buf_size;
+ return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_thread.GetID(),
+ &regset, &ioVec, buf_size);
}
-Error
-NativeRegisterContextLinux_arm64::DoWriteFPR(void *buf, size_t buf_size)
-{
- int regset = NT_FPREGSET;
- struct iovec ioVec;
- Error error;
+Error NativeRegisterContextLinux_arm64::DoWriteFPR(void *buf, size_t buf_size) {
+ int regset = NT_FPREGSET;
+ struct iovec ioVec;
+ Error error;
- ioVec.iov_base = buf;
- ioVec.iov_len = buf_size;
- return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), &regset, &ioVec, buf_size);
+ ioVec.iov_base = buf;
+ ioVec.iov_len = buf_size;
+ return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(),
+ &regset, &ioVec, buf_size);
}
-uint32_t
-NativeRegisterContextLinux_arm64::CalculateFprOffset(const RegisterInfo* reg_info) const
-{
- return reg_info->byte_offset - GetRegisterInfoAtIndex(m_reg_info.first_fpr)->byte_offset;
+uint32_t NativeRegisterContextLinux_arm64::CalculateFprOffset(
+ const RegisterInfo *reg_info) const {
+ return reg_info->byte_offset -
+ GetRegisterInfoAtIndex(m_reg_info.first_fpr)->byte_offset;
}
#endif // defined (__arm64__) || defined (__aarch64__)
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
index 4d9a990..c46c375 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
-#if defined (__arm64__) || defined (__aarch64__)
+#if defined(__arm64__) || defined(__aarch64__)
#ifndef lldb_NativeRegisterContextLinux_arm64_h
#define lldb_NativeRegisterContextLinux_arm64_h
@@ -18,180 +18,142 @@
namespace lldb_private {
namespace process_linux {
- class NativeProcessLinux;
+class NativeProcessLinux;
- class NativeRegisterContextLinux_arm64 : public NativeRegisterContextLinux
- {
- public:
- NativeRegisterContextLinux_arm64 (const ArchSpec& target_arch,
- NativeThreadProtocol &native_thread,
- uint32_t concrete_frame_idx);
+class NativeRegisterContextLinux_arm64 : public NativeRegisterContextLinux {
+public:
+ NativeRegisterContextLinux_arm64(const ArchSpec &target_arch,
+ NativeThreadProtocol &native_thread,
+ uint32_t concrete_frame_idx);
- uint32_t
- GetRegisterSetCount () const override;
+ uint32_t GetRegisterSetCount() const override;
- uint32_t
- GetUserRegisterCount() const override;
+ uint32_t GetUserRegisterCount() const override;
- const RegisterSet *
- GetRegisterSet (uint32_t set_index) const override;
+ const RegisterSet *GetRegisterSet(uint32_t set_index) const override;
- Error
- ReadRegister (const RegisterInfo *reg_info, RegisterValue &reg_value) override;
+ Error ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue &reg_value) override;
- Error
- WriteRegister (const RegisterInfo *reg_info, const RegisterValue &reg_value) override;
+ Error WriteRegister(const RegisterInfo *reg_info,
+ const RegisterValue &reg_value) override;
- Error
- ReadAllRegisterValues (lldb::DataBufferSP &data_sp) override;
+ Error ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
- Error
- WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) override;
+ Error WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
- //------------------------------------------------------------------
- // Hardware breakpoints/watchpoint mangement functions
- //------------------------------------------------------------------
+ //------------------------------------------------------------------
+ // Hardware breakpoints/watchpoint mangement functions
+ //------------------------------------------------------------------
- uint32_t
- SetHardwareBreakpoint (lldb::addr_t addr, size_t size) override;
+ uint32_t SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override;
- bool
- ClearHardwareBreakpoint (uint32_t hw_idx) override;
+ bool ClearHardwareBreakpoint(uint32_t hw_idx) override;
- uint32_t
- NumSupportedHardwareWatchpoints () override;
+ uint32_t NumSupportedHardwareWatchpoints() override;
- uint32_t
- SetHardwareWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags) override;
+ uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size,
+ uint32_t watch_flags) override;
- bool
- ClearHardwareWatchpoint (uint32_t hw_index) override;
+ bool ClearHardwareWatchpoint(uint32_t hw_index) override;
- Error
- ClearAllHardwareWatchpoints () override;
+ Error ClearAllHardwareWatchpoints() override;
- Error
- GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) override;
+ Error GetWatchpointHitIndex(uint32_t &wp_index,
+ lldb::addr_t trap_addr) override;
- lldb::addr_t
- GetWatchpointHitAddress (uint32_t wp_index) override;
+ lldb::addr_t GetWatchpointHitAddress(uint32_t wp_index) override;
- lldb::addr_t
- GetWatchpointAddress (uint32_t wp_index) override;
+ lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override;
- uint32_t
- GetWatchpointSize(uint32_t wp_index);
+ uint32_t GetWatchpointSize(uint32_t wp_index);
- bool
- WatchpointIsEnabled(uint32_t wp_index);
+ bool WatchpointIsEnabled(uint32_t wp_index);
- // Debug register type select
- enum DREGType
- {
- eDREGTypeWATCH = 0,
- eDREGTypeBREAK
- };
+ // Debug register type select
+ enum DREGType { eDREGTypeWATCH = 0, eDREGTypeBREAK };
- protected:
- Error
- DoReadRegisterValue(uint32_t offset,
- const char* reg_name,
- uint32_t size,
- RegisterValue &value) override;
+protected:
+ Error DoReadRegisterValue(uint32_t offset, const char *reg_name,
+ uint32_t size, RegisterValue &value) override;
- Error
- DoWriteRegisterValue(uint32_t offset,
- const char* reg_name,
+ Error DoWriteRegisterValue(uint32_t offset, const char *reg_name,
const RegisterValue &value) override;
- Error
- DoReadGPR(void *buf, size_t buf_size) override;
+ Error DoReadGPR(void *buf, size_t buf_size) override;
- Error
- DoWriteGPR(void *buf, size_t buf_size) override;
+ Error DoWriteGPR(void *buf, size_t buf_size) override;
- Error
- DoReadFPR(void *buf, size_t buf_size) override;
+ Error DoReadFPR(void *buf, size_t buf_size) override;
- Error
- DoWriteFPR(void *buf, size_t buf_size) override;
+ Error DoWriteFPR(void *buf, size_t buf_size) override;
- void*
- GetGPRBuffer() override { return &m_gpr_arm64; }
+ void *GetGPRBuffer() override { return &m_gpr_arm64; }
- void*
- GetFPRBuffer() override { return &m_fpr; }
+ void *GetFPRBuffer() override { return &m_fpr; }
- size_t
- GetFPRSize() override { return sizeof(m_fpr); }
+ size_t GetFPRSize() override { return sizeof(m_fpr); }
- private:
- struct RegInfo
- {
- uint32_t num_registers;
- uint32_t num_gpr_registers;
- uint32_t num_fpr_registers;
+private:
+ struct RegInfo {
+ uint32_t num_registers;
+ uint32_t num_gpr_registers;
+ uint32_t num_fpr_registers;
- uint32_t last_gpr;
- uint32_t first_fpr;
- uint32_t last_fpr;
+ uint32_t last_gpr;
+ uint32_t first_fpr;
+ uint32_t last_fpr;
- uint32_t first_fpr_v;
- uint32_t last_fpr_v;
+ uint32_t first_fpr_v;
+ uint32_t last_fpr_v;
- uint32_t gpr_flags;
- };
+ uint32_t gpr_flags;
+ };
- // based on RegisterContextDarwin_arm64.h
- struct VReg
- {
- uint8_t bytes[16];
- };
+ // based on RegisterContextDarwin_arm64.h
+ struct VReg {
+ uint8_t bytes[16];
+ };
- // based on RegisterContextDarwin_arm64.h
- struct FPU
- {
- VReg v[32];
- uint32_t fpsr;
- uint32_t fpcr;
- };
+ // based on RegisterContextDarwin_arm64.h
+ struct FPU {
+ VReg v[32];
+ uint32_t fpsr;
+ uint32_t fpcr;
+ };
- uint64_t m_gpr_arm64[k_num_gpr_registers_arm64]; // 64-bit general purpose registers.
- RegInfo m_reg_info;
- FPU m_fpr; // floating-point registers including extended register sets.
+ uint64_t m_gpr_arm64[k_num_gpr_registers_arm64]; // 64-bit general purpose
+ // registers.
+ RegInfo m_reg_info;
+ FPU m_fpr; // floating-point registers including extended register sets.
- // Debug register info for hardware breakpoints and watchpoints management.
- struct DREG
- {
- lldb::addr_t address; // Breakpoint/watchpoint address value.
- lldb::addr_t hit_addr; // Address at which last watchpoint trigger exception occurred.
- lldb::addr_t real_addr; // Address value that should cause target to stop.
- uint32_t control; // Breakpoint/watchpoint control value.
- uint32_t refcount; // Serves as enable/disable and refernce counter.
- };
+ // Debug register info for hardware breakpoints and watchpoints management.
+ struct DREG {
+ lldb::addr_t address; // Breakpoint/watchpoint address value.
+ lldb::addr_t hit_addr; // Address at which last watchpoint trigger exception
+ // occurred.
+ lldb::addr_t real_addr; // Address value that should cause target to stop.
+ uint32_t control; // Breakpoint/watchpoint control value.
+ uint32_t refcount; // Serves as enable/disable and refernce counter.
+ };
- struct DREG m_hbr_regs[16]; // Arm native linux hardware breakpoints
- struct DREG m_hwp_regs[16]; // Arm native linux hardware watchpoints
+ struct DREG m_hbr_regs[16]; // Arm native linux hardware breakpoints
+ struct DREG m_hwp_regs[16]; // Arm native linux hardware watchpoints
- uint32_t m_max_hwp_supported;
- uint32_t m_max_hbp_supported;
- bool m_refresh_hwdebug_info;
+ uint32_t m_max_hwp_supported;
+ uint32_t m_max_hbp_supported;
+ bool m_refresh_hwdebug_info;
- bool
- IsGPR(unsigned reg) const;
+ bool IsGPR(unsigned reg) const;
- bool
- IsFPR(unsigned reg) const;
+ bool IsFPR(unsigned reg) const;
- Error
- ReadHardwareDebugInfo();
+ Error ReadHardwareDebugInfo();
- Error
- WriteHardwareDebugRegs(int hwbType);
+ Error WriteHardwareDebugRegs(int hwbType);
- uint32_t
- CalculateFprOffset(const RegisterInfo* reg_info) const;
- };
+ uint32_t CalculateFprOffset(const RegisterInfo *reg_info) const;
+};
} // namespace process_linux
} // namespace lldb_private
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp
index d5a6172..6c79537 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
-#if defined (__mips__)
+#if defined(__mips__)
#include "NativeRegisterContextLinux_mips64.h"
@@ -15,57 +15,49 @@
// C++ Includes
// Other libraries and framework includes
+#include "Plugins/Process/Linux/NativeProcessLinux.h"
+#include "Plugins/Process/Linux/Procfs.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/RegisterValue.h"
#include "lldb/Core/Log.h"
-#include "lldb/Core/DataBufferHeap.h"
-#include "lldb/Host/HostInfo.h"
+#include "lldb/Core/RegisterValue.h"
#include "lldb/Host/Host.h"
-#include "lldb/Core/EmulateInstruction.h"
+#include "lldb/Host/HostInfo.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-private-enumerations.h"
-#include "Plugins/Process/Linux/NativeProcessLinux.h"
-#include "Plugins/Process/Linux/Procfs.h"
-#include "Plugins/Process/Utility/RegisterContextLinux_mips64.h"
-#include "Plugins/Process/Utility/RegisterContextLinux_mips.h"
#define NT_MIPS_MSA 0x600
#define CONFIG5_FRE (1 << 8)
#define SR_FR (1 << 26)
#define NUM_REGISTERS 32
-#include <sys/ptrace.h>
#include <asm/ptrace.h>
+#include <sys/ptrace.h>
#ifndef PTRACE_GET_WATCH_REGS
-enum pt_watch_style
-{
- pt_watch_style_mips32,
- pt_watch_style_mips64
-};
-struct mips32_watch_regs
-{
- uint32_t watchlo[8];
- uint16_t watchhi[8];
- uint16_t watch_masks[8];
- uint32_t num_valid;
+enum pt_watch_style { pt_watch_style_mips32, pt_watch_style_mips64 };
+struct mips32_watch_regs {
+ uint32_t watchlo[8];
+ uint16_t watchhi[8];
+ uint16_t watch_masks[8];
+ uint32_t num_valid;
} __attribute__((aligned(8)));
-struct mips64_watch_regs
-{
- uint64_t watchlo[8];
- uint16_t watchhi[8];
- uint16_t watch_masks[8];
- uint32_t num_valid;
+struct mips64_watch_regs {
+ uint64_t watchlo[8];
+ uint16_t watchhi[8];
+ uint16_t watch_masks[8];
+ uint32_t num_valid;
} __attribute__((aligned(8)));
-struct pt_watch_regs
-{
- enum pt_watch_style style;
- union
- {
- struct mips32_watch_regs mips32;
- struct mips64_watch_regs mips64;
- };
+struct pt_watch_regs {
+ enum pt_watch_style style;
+ union {
+ struct mips32_watch_regs mips32;
+ struct mips64_watch_regs mips64;
+ };
};
#define PTRACE_GET_WATCH_REGS 0xd0
@@ -76,7 +68,7 @@ struct pt_watch_regs
#define R (1 << 1)
#define I (1 << 2)
-#define IRW (I | R | W)
+#define IRW (I | R | W)
struct pt_watch_regs default_watch_regs;
@@ -87,1227 +79,993 @@ 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 },
- };
+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,
- uint32_t concrete_frame_idx)
-{
- return new NativeRegisterContextLinux_mips64(target_arch, native_thread, concrete_frame_idx);
+NativeRegisterContextLinux *
+NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
+ const ArchSpec &target_arch, NativeThreadProtocol &native_thread,
+ uint32_t concrete_frame_idx) {
+ return new NativeRegisterContextLinux_mips64(target_arch, native_thread,
+ concrete_frame_idx);
}
-#define REG_CONTEXT_SIZE (GetRegisterInfoInterface ().GetGPRSize () + sizeof(FPR_linux_mips) + sizeof(MSA_linux_mips))
+#define REG_CONTEXT_SIZE \
+ (GetRegisterInfoInterface().GetGPRSize() + sizeof(FPR_linux_mips) + \
+ sizeof(MSA_linux_mips))
// ----------------------------------------------------------------------------
// NativeRegisterContextLinux_mips64 members.
// ----------------------------------------------------------------------------
-static RegisterInfoInterface*
-CreateRegisterInfoInterface(const ArchSpec& target_arch)
-{
- if (HostInfo::GetArchitecture().GetAddressByteSize() == 4)
- {
- // 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());
- }
+static RegisterInfoInterface *
+CreateRegisterInfoInterface(const ArchSpec &target_arch) {
+ if (HostInfo::GetArchitecture().GetAddressByteSize() == 4) {
+ // 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());
+ }
}
-NativeRegisterContextLinux_mips64::NativeRegisterContextLinux_mips64 (const ArchSpec& target_arch,
- NativeThreadProtocol &native_thread,
- uint32_t concrete_frame_idx) :
- NativeRegisterContextLinux (native_thread, concrete_frame_idx, CreateRegisterInfoInterface(target_arch))
-{
- switch (target_arch.GetMachine ())
- {
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- m_reg_info.num_registers = k_num_registers_mips;
- m_reg_info.num_gpr_registers = k_num_gpr_registers_mips;
- m_reg_info.num_fpr_registers = k_num_fpr_registers_mips;
- m_reg_info.last_gpr = k_last_gpr_mips;
- m_reg_info.first_fpr = k_first_fpr_mips;
- m_reg_info.last_fpr = k_last_fpr_mips;
- m_reg_info.first_msa = k_first_msa_mips;
- m_reg_info.last_msa = k_last_msa_mips;
- break;
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- m_reg_info.num_registers = k_num_registers_mips64;
- m_reg_info.num_gpr_registers = k_num_gpr_registers_mips64;
- m_reg_info.num_fpr_registers = k_num_fpr_registers_mips64;
- m_reg_info.last_gpr = k_last_gpr_mips64;
- m_reg_info.first_fpr = k_first_fpr_mips64;
- m_reg_info.last_fpr = k_last_fpr_mips64;
- m_reg_info.first_msa = k_first_msa_mips64;
- m_reg_info.last_msa = k_last_msa_mips64;
- break;
- default:
- assert(false && "Unhandled target architecture.");
- break;
- }
+NativeRegisterContextLinux_mips64::NativeRegisterContextLinux_mips64(
+ const ArchSpec &target_arch, NativeThreadProtocol &native_thread,
+ uint32_t concrete_frame_idx)
+ : NativeRegisterContextLinux(native_thread, concrete_frame_idx,
+ CreateRegisterInfoInterface(target_arch)) {
+ switch (target_arch.GetMachine()) {
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ m_reg_info.num_registers = k_num_registers_mips;
+ m_reg_info.num_gpr_registers = k_num_gpr_registers_mips;
+ m_reg_info.num_fpr_registers = k_num_fpr_registers_mips;
+ m_reg_info.last_gpr = k_last_gpr_mips;
+ m_reg_info.first_fpr = k_first_fpr_mips;
+ m_reg_info.last_fpr = k_last_fpr_mips;
+ m_reg_info.first_msa = k_first_msa_mips;
+ m_reg_info.last_msa = k_last_msa_mips;
+ break;
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ m_reg_info.num_registers = k_num_registers_mips64;
+ m_reg_info.num_gpr_registers = k_num_gpr_registers_mips64;
+ m_reg_info.num_fpr_registers = k_num_fpr_registers_mips64;
+ m_reg_info.last_gpr = k_last_gpr_mips64;
+ m_reg_info.first_fpr = k_first_fpr_mips64;
+ m_reg_info.last_fpr = k_last_fpr_mips64;
+ m_reg_info.first_msa = k_first_msa_mips64;
+ m_reg_info.last_msa = k_last_msa_mips64;
+ break;
+ default:
+ assert(false && "Unhandled target architecture.");
+ break;
+ }
+
+ // Initialize m_iovec to point to the buffer and buffer size
+ // using the conventions of Berkeley style UIO structures, as required
+ // by PTRACE extensions.
+ m_iovec.iov_base = &m_msa;
+ m_iovec.iov_len = sizeof(MSA_linux_mips);
+
+ // init h/w watchpoint addr map
+ for (int index = 0; index <= MAX_NUM_WP; index++)
+ hw_addr_map[index] = LLDB_INVALID_ADDRESS;
+
+ ::memset(&m_gpr, 0, sizeof(GPR_linux_mips));
+ ::memset(&m_fpr, 0, sizeof(FPR_linux_mips));
+ ::memset(&m_msa, 0, sizeof(MSA_linux_mips));
+}
- // Initialize m_iovec to point to the buffer and buffer size
- // using the conventions of Berkeley style UIO structures, as required
- // by PTRACE extensions.
- m_iovec.iov_base = &m_msa;
- m_iovec.iov_len = sizeof(MSA_linux_mips);
+uint32_t NativeRegisterContextLinux_mips64::GetRegisterSetCount() const {
+ return k_num_register_sets;
+}
- // init h/w watchpoint addr map
- for (int index = 0;index <= MAX_NUM_WP; index++)
- hw_addr_map[index] = LLDB_INVALID_ADDRESS;
+lldb::addr_t NativeRegisterContextLinux_mips64::GetPCfromBreakpointLocation(
+ lldb::addr_t fail_value) {
+ Error error;
+ RegisterValue pc_value;
+ lldb::addr_t pc = fail_value;
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
- ::memset(&m_gpr, 0, sizeof(GPR_linux_mips));
- ::memset(&m_fpr, 0, sizeof(FPR_linux_mips));
- ::memset(&m_msa, 0, sizeof(MSA_linux_mips));
-}
+ if (log)
+ log->Printf("NativeRegisterContextLinux_mips64::%s Reading PC from "
+ "breakpoint location",
+ __FUNCTION__);
-uint32_t
-NativeRegisterContextLinux_mips64::GetRegisterSetCount () const
-{
- return k_num_register_sets;
-}
+ // PC register is at index 34 of the register array
+ const RegisterInfo *const pc_info_p = GetRegisterInfoAtIndex(gpr_pc_mips64);
+
+ error = ReadRegister(pc_info_p, pc_value);
+ if (error.Success()) {
+ pc = pc_value.GetAsUInt64();
+
+ // CAUSE register is at index 37 of the register array
+ const RegisterInfo *const cause_info_p =
+ GetRegisterInfoAtIndex(gpr_cause_mips64);
+ RegisterValue cause_value;
+
+ ReadRegister(cause_info_p, cause_value);
+
+ uint64_t cause = cause_value.GetAsUInt64();
-lldb::addr_t
-NativeRegisterContextLinux_mips64::GetPCfromBreakpointLocation (lldb::addr_t fail_value)
-{
- 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__);
-
- // PC register is at index 34 of the register array
- const RegisterInfo *const pc_info_p = GetRegisterInfoAtIndex (gpr_pc_mips64);
-
- error = ReadRegister (pc_info_p, pc_value);
- if (error.Success ())
- {
- pc = pc_value.GetAsUInt64 ();
-
- // CAUSE register is at index 37 of the register array
- const RegisterInfo *const cause_info_p = GetRegisterInfoAtIndex (gpr_cause_mips64);
- RegisterValue cause_value;
-
- 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);
-
- /*
- * The breakpoint might be in a delay slot. In this case PC points
- * to the delayed branch instruction rather then the instruction
- * in the delay slot. If the CAUSE.BD flag is set then adjust the
- * PC based on the size of the branch instruction.
- */
- if ((cause & (1 << 31)) != 0)
- {
- lldb::addr_t branch_delay = 0;
- branch_delay = 4; // FIXME - Adjust according to size of branch instruction at PC
- 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);
- }
+ log->Printf("NativeRegisterContextLinux_mips64::%s PC 0x%" PRIx64
+ " Cause 0x%" PRIx64,
+ __FUNCTION__, pc, cause);
+
+ /*
+ * The breakpoint might be in a delay slot. In this case PC points
+ * to the delayed branch instruction rather then the instruction
+ * in the delay slot. If the CAUSE.BD flag is set then adjust the
+ * PC based on the size of the branch instruction.
+ */
+ if ((cause & (1 << 31)) != 0) {
+ lldb::addr_t branch_delay = 0;
+ branch_delay =
+ 4; // FIXME - Adjust according to size of branch instruction at PC
+ 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);
}
+ }
- return pc;
+ return pc;
}
const RegisterSet *
-NativeRegisterContextLinux_mips64::GetRegisterSet (uint32_t set_index) const
-{
- if (set_index >= k_num_register_sets)
- return nullptr;
-
- switch (GetRegisterInfoInterface ().GetTargetArchitecture ().GetMachine ())
- {
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- return &g_reg_sets_mips64[set_index];
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- return &g_reg_sets_mips[set_index];
- default:
- assert (false && "Unhandled target architecture.");
- return nullptr;
- }
+NativeRegisterContextLinux_mips64::GetRegisterSet(uint32_t set_index) const {
+ if (set_index >= k_num_register_sets)
+ return nullptr;
+ switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ return &g_reg_sets_mips64[set_index];
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ return &g_reg_sets_mips[set_index];
+ default:
+ assert(false && "Unhandled target architecture.");
return nullptr;
+ }
+
+ return nullptr;
}
lldb_private::Error
-NativeRegisterContextLinux_mips64::ReadRegister (const RegisterInfo *reg_info, RegisterValue &reg_value)
-{
- Error error;
-
- if (!reg_info)
- {
- error.SetErrorString ("reg_info NULL");
- return error;
- }
+NativeRegisterContextLinux_mips64::ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue &reg_value) {
+ Error error;
- const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
- if (reg == LLDB_INVALID_REGNUM)
- {
- // This is likely an internal register for lldb use only and should not be directly queried.
- error.SetErrorStringWithFormat ("register \"%s\" is an internal-only lldb register, cannot read directly", reg_info->name);
- return error;
- }
+ if (!reg_info) {
+ error.SetErrorString("reg_info NULL");
+ return error;
+ }
+
+ const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+ if (reg == LLDB_INVALID_REGNUM) {
+ // This is likely an internal register for lldb use only and should not be
+ // directly queried.
+ error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb "
+ "register, cannot read directly",
+ reg_info->name);
+ return error;
+ }
- if (IsMSA(reg) && !IsMSAAvailable())
- {
- error.SetErrorString ("MSA not available on this processor");
- return error;
- }
+ if (IsMSA(reg) && !IsMSAAvailable()) {
+ error.SetErrorString("MSA not available on this processor");
+ return error;
+ }
- if (IsMSA(reg) || IsFPR(reg))
- {
- uint8_t *src;
+ if (IsMSA(reg) || IsFPR(reg)) {
+ uint8_t *src;
- error = ReadCP1();
+ error = ReadCP1();
- if (!error.Success())
- {
- error.SetErrorString ("failed to read co-processor 1 register");
- return error;
- }
+ if (!error.Success()) {
+ error.SetErrorString("failed to read co-processor 1 register");
+ return error;
+ }
- if (IsFPR(reg))
- {
- assert (reg_info->byte_offset < sizeof(UserArea));
- src = (uint8_t *)&m_fpr + reg_info->byte_offset - (sizeof(m_gpr));
- }
- else
- {
- assert (reg_info->byte_offset < sizeof(UserArea));
- src = (uint8_t *)&m_msa + reg_info->byte_offset - (sizeof(m_gpr) + sizeof(m_fpr));
- }
- switch (reg_info->byte_size)
- {
- case 4:
- reg_value.SetUInt32(*(uint32_t *)src);
- break;
- case 8:
- reg_value.SetUInt64(*(uint64_t *)src);
- break;
- case 16:
- reg_value.SetBytes((const void *)src, 16, GetByteOrder());
- break;
- default:
- assert(false && "Unhandled data size.");
- error.SetErrorStringWithFormat ("unhandled byte size: %" PRIu32, reg_info->byte_size);
- break;
- }
+ if (IsFPR(reg)) {
+ assert(reg_info->byte_offset < sizeof(UserArea));
+ src = (uint8_t *)&m_fpr + reg_info->byte_offset - (sizeof(m_gpr));
+ } else {
+ assert(reg_info->byte_offset < sizeof(UserArea));
+ src = (uint8_t *)&m_msa + reg_info->byte_offset -
+ (sizeof(m_gpr) + sizeof(m_fpr));
}
- else
- {
- error = ReadRegisterRaw(reg, reg_value);
+ switch (reg_info->byte_size) {
+ case 4:
+ reg_value.SetUInt32(*(uint32_t *)src);
+ break;
+ case 8:
+ reg_value.SetUInt64(*(uint64_t *)src);
+ break;
+ case 16:
+ reg_value.SetBytes((const void *)src, 16, GetByteOrder());
+ break;
+ default:
+ assert(false && "Unhandled data size.");
+ error.SetErrorStringWithFormat("unhandled byte size: %" PRIu32,
+ reg_info->byte_size);
+ break;
}
+ } else {
+ error = ReadRegisterRaw(reg, reg_value);
+ }
- return error;
+ return error;
}
-lldb_private::Error
-NativeRegisterContextLinux_mips64::WriteRegister (const RegisterInfo *reg_info, const RegisterValue &reg_value)
-{
- Error error;
+lldb_private::Error NativeRegisterContextLinux_mips64::WriteRegister(
+ const RegisterInfo *reg_info, const RegisterValue &reg_value) {
+ Error error;
- assert (reg_info && "reg_info is null");
+ assert(reg_info && "reg_info is null");
- const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB];
+ const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB];
- if (reg_index == LLDB_INVALID_REGNUM)
- return Error ("no lldb regnum for %s", reg_info && reg_info->name ? reg_info->name : "<unknown register>");
+ if (reg_index == LLDB_INVALID_REGNUM)
+ return Error("no lldb regnum for %s", reg_info && reg_info->name
+ ? reg_info->name
+ : "<unknown register>");
- if (IsMSA(reg_index) && !IsMSAAvailable())
- {
- error.SetErrorString ("MSA not available on this processor");
- return error;
+ if (IsMSA(reg_index) && !IsMSAAvailable()) {
+ error.SetErrorString("MSA not available on this processor");
+ return error;
+ }
+
+ if (IsFPR(reg_index) || IsMSA(reg_index)) {
+ uint8_t *dst;
+ uint64_t *src;
+
+ // Initialise the FP and MSA buffers by reading all co-processor 1 registers
+ ReadCP1();
+
+ if (IsFPR(reg_index)) {
+ assert(reg_info->byte_offset < sizeof(UserArea));
+ dst = (uint8_t *)&m_fpr + reg_info->byte_offset - (sizeof(m_gpr));
+ } else {
+ assert(reg_info->byte_offset < sizeof(UserArea));
+ dst = (uint8_t *)&m_msa + reg_info->byte_offset -
+ (sizeof(m_gpr) + sizeof(m_fpr));
}
-
- if (IsFPR(reg_index) || IsMSA(reg_index))
- {
- uint8_t *dst;
- uint64_t *src;
-
- // Initialise the FP and MSA buffers by reading all co-processor 1 registers
- ReadCP1();
-
- if (IsFPR(reg_index))
- {
- assert (reg_info->byte_offset < sizeof(UserArea));
- dst = (uint8_t *)&m_fpr + reg_info->byte_offset - (sizeof(m_gpr));
- }
- else
- {
- assert (reg_info->byte_offset < sizeof(UserArea));
- dst = (uint8_t *)&m_msa + reg_info->byte_offset - (sizeof(m_gpr) + sizeof(m_fpr));
- }
- switch (reg_info->byte_size)
- {
- case 4:
- *(uint32_t *)dst = reg_value.GetAsUInt32();
- break;
- case 8:
- *(uint64_t *)dst = reg_value.GetAsUInt64();
- break;
- case 16:
- src = (uint64_t *)reg_value.GetBytes();
- *(uint64_t *)dst = *src;
- *(uint64_t *)(dst + 8) = *(src + 1);
- break;
- default:
- assert(false && "Unhandled data size.");
- error.SetErrorStringWithFormat ("unhandled byte size: %" PRIu32, reg_info->byte_size);
- break;
- }
- error = WriteCP1();
- if (!error.Success())
- {
- error.SetErrorString ("failed to write co-processor 1 register");
- return error;
- }
+ switch (reg_info->byte_size) {
+ case 4:
+ *(uint32_t *)dst = reg_value.GetAsUInt32();
+ break;
+ case 8:
+ *(uint64_t *)dst = reg_value.GetAsUInt64();
+ break;
+ case 16:
+ src = (uint64_t *)reg_value.GetBytes();
+ *(uint64_t *)dst = *src;
+ *(uint64_t *)(dst + 8) = *(src + 1);
+ break;
+ default:
+ assert(false && "Unhandled data size.");
+ error.SetErrorStringWithFormat("unhandled byte size: %" PRIu32,
+ reg_info->byte_size);
+ break;
}
- else
- {
- error = WriteRegisterRaw(reg_index, reg_value);
+ error = WriteCP1();
+ if (!error.Success()) {
+ error.SetErrorString("failed to write co-processor 1 register");
+ return error;
}
+ } else {
+ error = WriteRegisterRaw(reg_index, reg_value);
+ }
- return error;
+ return error;
}
-Error
-NativeRegisterContextLinux_mips64::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
-{
- Error error;
+Error NativeRegisterContextLinux_mips64::ReadAllRegisterValues(
+ lldb::DataBufferSP &data_sp) {
+ Error error;
- data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
- if (!data_sp)
- {
- error.SetErrorStringWithFormat ("failed to allocate DataBufferHeap instance of size %" PRIu64, REG_CONTEXT_SIZE);
- return error;
- }
+ data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
+ if (!data_sp) {
+ error.SetErrorStringWithFormat(
+ "failed to allocate DataBufferHeap instance of size %" PRIu64,
+ REG_CONTEXT_SIZE);
+ return error;
+ }
- error = ReadGPR();
- if (!error.Success())
- {
- error.SetErrorString ("ReadGPR() failed");
- return error;
- }
+ error = ReadGPR();
+ if (!error.Success()) {
+ error.SetErrorString("ReadGPR() failed");
+ return error;
+ }
- error = ReadCP1();
- if (!error.Success())
- {
- error.SetErrorString ("ReadCP1() failed");
- return error;
- }
+ error = ReadCP1();
+ if (!error.Success()) {
+ error.SetErrorString("ReadCP1() failed");
+ return error;
+ }
- uint8_t *dst = data_sp->GetBytes ();
- if (dst == nullptr)
- {
- error.SetErrorStringWithFormat ("DataBufferHeap instance of size %" PRIu64 " returned a null pointer", REG_CONTEXT_SIZE);
- return error;
- }
+ uint8_t *dst = data_sp->GetBytes();
+ if (dst == nullptr) {
+ error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64
+ " returned a null pointer",
+ REG_CONTEXT_SIZE);
+ return error;
+ }
- ::memcpy (dst, &m_gpr, GetRegisterInfoInterface ().GetGPRSize ());
- dst += GetRegisterInfoInterface ().GetGPRSize ();
+ ::memcpy(dst, &m_gpr, GetRegisterInfoInterface().GetGPRSize());
+ dst += GetRegisterInfoInterface().GetGPRSize();
- ::memcpy (dst, &m_fpr, GetFPRSize ());
- dst += GetFPRSize ();
+ ::memcpy(dst, &m_fpr, GetFPRSize());
+ dst += GetFPRSize();
- ::memcpy (dst, &m_msa, sizeof(MSA_linux_mips));
+ ::memcpy(dst, &m_msa, sizeof(MSA_linux_mips));
- return error;
+ return error;
}
-Error
-NativeRegisterContextLinux_mips64::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
-{
- Error error;
-
- if (!data_sp)
- {
- error.SetErrorStringWithFormat ("NativeRegisterContextLinux_mips64::%s invalid data_sp provided", __FUNCTION__);
- return error;
- }
-
- if (data_sp->GetByteSize () != REG_CONTEXT_SIZE)
- {
- error.SetErrorStringWithFormat ("NativeRegisterContextLinux_mips64::%s data_sp contained mismatched data size, expected %" PRIu64 ", actual %" PRIu64, __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize ());
- return error;
- }
+Error NativeRegisterContextLinux_mips64::WriteAllRegisterValues(
+ const lldb::DataBufferSP &data_sp) {
+ Error error;
+ if (!data_sp) {
+ error.SetErrorStringWithFormat(
+ "NativeRegisterContextLinux_mips64::%s invalid data_sp provided",
+ __FUNCTION__);
+ return error;
+ }
- uint8_t *src = data_sp->GetBytes ();
- if (src == nullptr)
- {
- error.SetErrorStringWithFormat ("NativeRegisterContextLinux_mips64::%s DataBuffer::GetBytes() returned a null pointer", __FUNCTION__);
- return error;
- }
-
- ::memcpy (&m_gpr, src, GetRegisterInfoInterface ().GetGPRSize ());
- src += GetRegisterInfoInterface ().GetGPRSize ();
+ if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) {
+ error.SetErrorStringWithFormat(
+ "NativeRegisterContextLinux_mips64::%s data_sp contained mismatched "
+ "data size, expected %" PRIu64 ", actual %" PRIu64,
+ __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize());
+ return error;
+ }
+
+ uint8_t *src = data_sp->GetBytes();
+ if (src == nullptr) {
+ error.SetErrorStringWithFormat("NativeRegisterContextLinux_mips64::%s "
+ "DataBuffer::GetBytes() returned a null "
+ "pointer",
+ __FUNCTION__);
+ return error;
+ }
- ::memcpy (&m_fpr, src, GetFPRSize ());
- src += GetFPRSize ();
+ ::memcpy(&m_gpr, src, GetRegisterInfoInterface().GetGPRSize());
+ src += GetRegisterInfoInterface().GetGPRSize();
- ::memcpy (&m_msa, src, sizeof(MSA_linux_mips));
+ ::memcpy(&m_fpr, src, GetFPRSize());
+ src += GetFPRSize();
- error = WriteGPR();
- if (!error.Success())
- {
- error.SetErrorStringWithFormat ("NativeRegisterContextLinux_mips64::%s WriteGPR() failed", __FUNCTION__);
- return error;
- }
+ ::memcpy(&m_msa, src, sizeof(MSA_linux_mips));
- error = WriteCP1();
- if (!error.Success())
- {
- error.SetErrorStringWithFormat ("NativeRegisterContextLinux_mips64::%s WriteCP1() failed", __FUNCTION__);
- return error;
- }
+ error = WriteGPR();
+ if (!error.Success()) {
+ error.SetErrorStringWithFormat(
+ "NativeRegisterContextLinux_mips64::%s WriteGPR() failed",
+ __FUNCTION__);
+ return error;
+ }
+ error = WriteCP1();
+ if (!error.Success()) {
+ error.SetErrorStringWithFormat(
+ "NativeRegisterContextLinux_mips64::%s WriteCP1() failed",
+ __FUNCTION__);
return error;
+ }
+
+ return error;
}
-Error
-NativeRegisterContextLinux_mips64::ReadCP1()
-{
- Error error;
+Error NativeRegisterContextLinux_mips64::ReadCP1() {
+ Error error;
- uint8_t *src, *dst;
+ uint8_t *src, *dst;
- lldb::ByteOrder byte_order = GetByteOrder();
+ lldb::ByteOrder byte_order = GetByteOrder();
- uint32_t IsBigEndian = (byte_order == lldb::eByteOrderBig);
+ uint32_t IsBigEndian = (byte_order == lldb::eByteOrderBig);
- if (IsMSAAvailable())
- {
- error = NativeRegisterContextLinux::ReadRegisterSet(&m_iovec, sizeof(MSA_linux_mips), NT_MIPS_MSA);
- src = (uint8_t *)&m_msa + (IsBigEndian * 8);
- dst = (uint8_t *)&m_fpr;
- for ( int i = 0; i < NUM_REGISTERS; i++)
- {
- // Copy fp values from msa buffer fetched via ptrace
- *(uint64_t *) dst = *(uint64_t *) src;
- src = src + 16;
- dst = dst + 8;
- }
- m_fpr.fir = m_msa.fir;
- m_fpr.fcsr = m_msa.fcsr;
- m_fpr.config5 = m_msa.config5;
+ if (IsMSAAvailable()) {
+ error = NativeRegisterContextLinux::ReadRegisterSet(
+ &m_iovec, sizeof(MSA_linux_mips), NT_MIPS_MSA);
+ src = (uint8_t *)&m_msa + (IsBigEndian * 8);
+ dst = (uint8_t *)&m_fpr;
+ for (int i = 0; i < NUM_REGISTERS; i++) {
+ // Copy fp values from msa buffer fetched via ptrace
+ *(uint64_t *)dst = *(uint64_t *)src;
+ src = src + 16;
+ dst = dst + 8;
}
- else
- {
- error = NativeRegisterContextLinux::ReadFPR();
+ m_fpr.fir = m_msa.fir;
+ m_fpr.fcsr = m_msa.fcsr;
+ m_fpr.config5 = m_msa.config5;
+ } else {
+ error = NativeRegisterContextLinux::ReadFPR();
+ }
+
+ // TODO: Add support for FRE
+ if (IsFR0()) {
+ src = (uint8_t *)&m_fpr + 4 + (IsBigEndian * 4);
+ dst = (uint8_t *)&m_fpr + 8 + (IsBigEndian * 4);
+ for (int i = 0; i < (NUM_REGISTERS / 2); i++) {
+ // copy odd single from top of neighbouring even double
+ *(uint32_t *)dst = *(uint32_t *)src;
+ src = src + 16;
+ dst = dst + 16;
}
+ }
- // TODO: Add support for FRE
- if (IsFR0())
- {
- src = (uint8_t *)&m_fpr + 4 + (IsBigEndian * 4);
- dst = (uint8_t *)&m_fpr + 8 + (IsBigEndian * 4);
- for (int i = 0; i < (NUM_REGISTERS / 2); i++)
- {
- // copy odd single from top of neighbouring even double
- *(uint32_t *) dst = *(uint32_t *) src;
- src = src + 16;
- dst = dst + 16;
- }
- }
-
- return error;
+ return error;
}
-Error
-NativeRegisterContextLinux_mips64::WriteCP1()
-{
- Error error;
-
- uint8_t *src, *dst;
+Error NativeRegisterContextLinux_mips64::WriteCP1() {
+ Error error;
- lldb::ByteOrder byte_order = GetByteOrder();
+ uint8_t *src, *dst;
- uint32_t IsBigEndian = (byte_order == lldb::eByteOrderBig);
+ lldb::ByteOrder byte_order = GetByteOrder();
- // TODO: Add support for FRE
- if (IsFR0())
- {
- src = (uint8_t *)&m_fpr + 8 + (IsBigEndian * 4);
- dst = (uint8_t *)&m_fpr + 4 + (IsBigEndian * 4);
- for (int i = 0; i < (NUM_REGISTERS / 2); i++)
- {
- // copy odd single to top of neighbouring even double
- *(uint32_t *) dst = *(uint32_t *) src;
- src = src + 16;
- dst = dst + 16;
- }
- }
+ uint32_t IsBigEndian = (byte_order == lldb::eByteOrderBig);
- if (IsMSAAvailable())
- {
- dst = (uint8_t *)&m_msa + (IsBigEndian * 8);
- src = (uint8_t *)&m_fpr;
- for (int i = 0; i < NUM_REGISTERS; i++)
- {
- // Copy fp values to msa buffer for ptrace
- *(uint64_t *) dst = *(uint64_t *) src;
- dst = dst + 16;
- src = src + 8;
- }
- m_msa.fir = m_fpr.fir;
- m_msa.fcsr = m_fpr.fcsr;
- m_msa.config5 = m_fpr.config5;
- error = NativeRegisterContextLinux::WriteRegisterSet(&m_iovec, sizeof(MSA_linux_mips), NT_MIPS_MSA);
+ // TODO: Add support for FRE
+ if (IsFR0()) {
+ src = (uint8_t *)&m_fpr + 8 + (IsBigEndian * 4);
+ dst = (uint8_t *)&m_fpr + 4 + (IsBigEndian * 4);
+ for (int i = 0; i < (NUM_REGISTERS / 2); i++) {
+ // copy odd single to top of neighbouring even double
+ *(uint32_t *)dst = *(uint32_t *)src;
+ src = src + 16;
+ dst = dst + 16;
}
- else
- {
- error = NativeRegisterContextLinux::WriteFPR();
+ }
+
+ if (IsMSAAvailable()) {
+ dst = (uint8_t *)&m_msa + (IsBigEndian * 8);
+ src = (uint8_t *)&m_fpr;
+ for (int i = 0; i < NUM_REGISTERS; i++) {
+ // Copy fp values to msa buffer for ptrace
+ *(uint64_t *)dst = *(uint64_t *)src;
+ dst = dst + 16;
+ src = src + 8;
}
-
- return error;
+ m_msa.fir = m_fpr.fir;
+ m_msa.fcsr = m_fpr.fcsr;
+ m_msa.config5 = m_fpr.config5;
+ error = NativeRegisterContextLinux::WriteRegisterSet(
+ &m_iovec, sizeof(MSA_linux_mips), NT_MIPS_MSA);
+ } else {
+ error = NativeRegisterContextLinux::WriteFPR();
+ }
+
+ return error;
}
-bool
-NativeRegisterContextLinux_mips64::IsFR0()
-{
- const RegisterInfo *const reg_info_p = GetRegisterInfoAtIndex (gpr_sr_mips64);
+bool NativeRegisterContextLinux_mips64::IsFR0() {
+ const RegisterInfo *const reg_info_p = GetRegisterInfoAtIndex(gpr_sr_mips64);
- RegisterValue reg_value;
- ReadRegister (reg_info_p, reg_value);
+ RegisterValue reg_value;
+ ReadRegister(reg_info_p, reg_value);
- uint64_t value = reg_value.GetAsUInt64();
+ uint64_t value = reg_value.GetAsUInt64();
- return (!(value & SR_FR));
+ return (!(value & SR_FR));
}
-bool
-NativeRegisterContextLinux_mips64::IsFRE()
-{
- const RegisterInfo *const reg_info_p = GetRegisterInfoAtIndex (gpr_config5_mips64);
+bool NativeRegisterContextLinux_mips64::IsFRE() {
+ const RegisterInfo *const reg_info_p =
+ GetRegisterInfoAtIndex(gpr_config5_mips64);
- RegisterValue reg_value;
- ReadRegister (reg_info_p, reg_value);
+ RegisterValue reg_value;
+ ReadRegister(reg_info_p, reg_value);
- uint64_t config5 = reg_value.GetAsUInt64();
+ uint64_t config5 = reg_value.GetAsUInt64();
- return (config5 & CONFIG5_FRE);
+ return (config5 & CONFIG5_FRE);
}
-bool
-NativeRegisterContextLinux_mips64::IsFPR(uint32_t reg_index) const
-{
- return (m_reg_info.first_fpr <= reg_index && reg_index <= m_reg_info.last_fpr);
+bool NativeRegisterContextLinux_mips64::IsFPR(uint32_t reg_index) const {
+ return (m_reg_info.first_fpr <= reg_index &&
+ reg_index <= m_reg_info.last_fpr);
}
-static uint32_t
-GetWatchHi (struct pt_watch_regs *regs, uint32_t index)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_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");
- return 0;
+static uint32_t GetWatchHi(struct pt_watch_regs *regs, uint32_t index) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_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");
+ return 0;
}
-static void
-SetWatchHi (struct pt_watch_regs *regs, uint32_t index, uint16_t value)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_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");
- return;
+static void SetWatchHi(struct pt_watch_regs *regs, uint32_t index,
+ uint16_t value) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_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");
+ return;
}
-static lldb::addr_t
-GetWatchLo (struct pt_watch_regs *regs, uint32_t index)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_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");
- return LLDB_INVALID_ADDRESS;
+static lldb::addr_t GetWatchLo(struct pt_watch_regs *regs, uint32_t index) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_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");
+ return LLDB_INVALID_ADDRESS;
}
-static void
-SetWatchLo (struct pt_watch_regs *regs, uint32_t index, uint64_t value)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_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;
+static void SetWatchLo(struct pt_watch_regs *regs, uint32_t index,
+ uint64_t value) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_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;
}
-static uint32_t
-GetIRWMask (struct pt_watch_regs *regs, uint32_t index)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_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");
- return 0;
+static uint32_t GetIRWMask(struct pt_watch_regs *regs, uint32_t index) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_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");
+ return 0;
}
-static uint32_t
-GetRegMask (struct pt_watch_regs *regs, uint32_t index)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_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");
- return 0;
+static uint32_t GetRegMask(struct pt_watch_regs *regs, uint32_t index) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_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");
+ return 0;
}
-static lldb::addr_t
-GetRangeMask (lldb::addr_t mask)
-{
- lldb::addr_t mask_bit = 1;
- while (mask_bit < mask)
- {
- mask = mask | mask_bit;
- mask_bit <<= 1;
- }
- return mask;
+static lldb::addr_t GetRangeMask(lldb::addr_t mask) {
+ lldb::addr_t mask_bit = 1;
+ while (mask_bit < mask) {
+ mask = mask | mask_bit;
+ mask_bit <<= 1;
+ }
+ return mask;
}
-static int
-GetVacantWatchIndex (struct pt_watch_regs *regs, lldb::addr_t addr, uint32_t size, uint32_t irw, uint32_t num_valid)
-{
- lldb::addr_t last_byte = addr + size - 1;
- lldb::addr_t mask = GetRangeMask (addr ^ last_byte) | IRW;
- lldb::addr_t base_addr = addr & ~mask;
-
- // Check if this address is already watched by previous watch points.
- lldb::addr_t lo;
- uint16_t hi;
- uint32_t vacant_watches = 0;
- for (uint32_t index = 0; index < num_valid; index++)
- {
- lo = GetWatchLo (regs, index);
- if (lo != 0 && irw == ((uint32_t) lo & irw))
- {
- hi = GetWatchHi (regs, index) | IRW;
- lo &= ~(lldb::addr_t) hi;
- if (addr >= lo && last_byte <= (lo + hi))
- return index;
+static int GetVacantWatchIndex(struct pt_watch_regs *regs, lldb::addr_t addr,
+ uint32_t size, uint32_t irw,
+ uint32_t num_valid) {
+ lldb::addr_t last_byte = addr + size - 1;
+ lldb::addr_t mask = GetRangeMask(addr ^ last_byte) | IRW;
+ lldb::addr_t base_addr = addr & ~mask;
+
+ // Check if this address is already watched by previous watch points.
+ lldb::addr_t lo;
+ uint16_t hi;
+ uint32_t vacant_watches = 0;
+ for (uint32_t index = 0; index < num_valid; index++) {
+ lo = GetWatchLo(regs, index);
+ if (lo != 0 && irw == ((uint32_t)lo & irw)) {
+ hi = GetWatchHi(regs, index) | IRW;
+ lo &= ~(lldb::addr_t)hi;
+ if (addr >= lo && last_byte <= (lo + hi))
+ return index;
+ } else
+ vacant_watches++;
+ }
+
+ // Now try to find a vacant index
+ if (vacant_watches > 0) {
+ vacant_watches = 0;
+ for (uint32_t index = 0; index < num_valid; index++) {
+ lo = GetWatchLo(regs, index);
+ if (lo == 0 && irw == (GetIRWMask(regs, index) & irw)) {
+ if (mask <= (GetRegMask(regs, index) | IRW)) {
+ // It fits, we can use it.
+ SetWatchLo(regs, index, base_addr | irw);
+ SetWatchHi(regs, index, mask & ~IRW);
+ return index;
+ } else {
+ // It doesn't fit, but has the proper IRW capabilities
+ vacant_watches++;
}
- else
- vacant_watches++;
+ }
}
- // Now try to find a vacant index
- if(vacant_watches > 0)
- {
- vacant_watches = 0;
- for (uint32_t index = 0; index < num_valid; index++)
- {
- lo = GetWatchLo (regs, index);
- if (lo == 0
- && irw == (GetIRWMask (regs, index) & irw))
- {
- if (mask <= (GetRegMask (regs, index) | IRW))
- {
- // It fits, we can use it.
- SetWatchLo (regs, index, base_addr | irw);
- SetWatchHi (regs, index, mask & ~IRW);
- return index;
- }
- else
- {
- // It doesn't fit, but has the proper IRW capabilities
- vacant_watches++;
- }
- }
- }
-
- if (vacant_watches > 1)
- {
- // Split this watchpoint accross several registers
- struct pt_watch_regs regs_copy;
- regs_copy = *regs;
- lldb::addr_t break_addr;
- uint32_t segment_size;
- for (uint32_t index = 0; index < num_valid; index++)
- {
- lo = GetWatchLo (&regs_copy, index);
- hi = GetRegMask (&regs_copy, index) | IRW;
- if (lo == 0 && irw == (hi & irw))
- {
- lo = addr & ~(lldb::addr_t) hi;
- break_addr = lo + hi + 1;
- if (break_addr >= addr + size)
- segment_size = size;
- else
- segment_size = break_addr - addr;
- mask = GetRangeMask (addr ^ (addr + segment_size - 1));
- SetWatchLo (&regs_copy, index, (addr & ~mask) | irw);
- SetWatchHi (&regs_copy, index, mask & ~IRW);
- if (break_addr >= addr + size)
- {
- *regs = regs_copy;
- return index;
- }
- size = addr + size - break_addr;
- addr = break_addr;
- }
- }
+ if (vacant_watches > 1) {
+ // Split this watchpoint accross several registers
+ struct pt_watch_regs regs_copy;
+ regs_copy = *regs;
+ lldb::addr_t break_addr;
+ uint32_t segment_size;
+ for (uint32_t index = 0; index < num_valid; index++) {
+ lo = GetWatchLo(&regs_copy, index);
+ hi = GetRegMask(&regs_copy, index) | IRW;
+ if (lo == 0 && irw == (hi & irw)) {
+ lo = addr & ~(lldb::addr_t)hi;
+ break_addr = lo + hi + 1;
+ if (break_addr >= addr + size)
+ segment_size = size;
+ else
+ segment_size = break_addr - addr;
+ mask = GetRangeMask(addr ^ (addr + segment_size - 1));
+ SetWatchLo(&regs_copy, index, (addr & ~mask) | irw);
+ SetWatchHi(&regs_copy, index, mask & ~IRW);
+ if (break_addr >= addr + size) {
+ *regs = regs_copy;
+ return index;
+ }
+ size = addr + size - break_addr;
+ addr = break_addr;
}
+ }
}
- return LLDB_INVALID_INDEX32;
+ }
+ return LLDB_INVALID_INDEX32;
}
-bool
-NativeRegisterContextLinux_mips64::IsMSA(uint32_t reg_index) const
-{
- return (m_reg_info.first_msa <= reg_index && reg_index <= m_reg_info.last_msa);
+bool NativeRegisterContextLinux_mips64::IsMSA(uint32_t reg_index) const {
+ return (m_reg_info.first_msa <= reg_index &&
+ reg_index <= m_reg_info.last_msa);
}
-bool
-NativeRegisterContextLinux_mips64::IsMSAAvailable()
-{
- MSA_linux_mips msa_buf;
- unsigned int regset = NT_MIPS_MSA;
+bool NativeRegisterContextLinux_mips64::IsMSAAvailable() {
+ MSA_linux_mips msa_buf;
+ unsigned int regset = NT_MIPS_MSA;
- Error error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, Host::GetCurrentProcessID(), static_cast<void *>(&regset), &msa_buf, sizeof(MSA_linux_mips));
+ Error error = NativeProcessLinux::PtraceWrapper(
+ PTRACE_GETREGSET, Host::GetCurrentProcessID(),
+ static_cast<void *>(&regset), &msa_buf, sizeof(MSA_linux_mips));
- if (error.Success() && msa_buf.mir)
- {
- return true;
- }
+ if (error.Success() && msa_buf.mir) {
+ return true;
+ }
- return false;
+ return false;
}
-Error
-NativeRegisterContextLinux_mips64::IsWatchpointHit (uint32_t wp_index, bool &is_hit)
-{
- if (wp_index >= NumSupportedHardwareWatchpoints())
- return Error("Watchpoint index out of range");
-
- // reading the current state of watch regs
- struct pt_watch_regs watch_readback;
- Error error = DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(&watch_readback));
-
- if (GetWatchHi (&watch_readback, wp_index) & (IRW))
- {
- // clear hit flag in watchhi
- SetWatchHi (&watch_readback, wp_index, (GetWatchHi (&watch_readback, wp_index) & ~(IRW)));
- DoWriteWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(&watch_readback));
-
- is_hit = true;
- return error;
- }
- is_hit = false;
+Error NativeRegisterContextLinux_mips64::IsWatchpointHit(uint32_t wp_index,
+ bool &is_hit) {
+ if (wp_index >= NumSupportedHardwareWatchpoints())
+ return Error("Watchpoint index out of range");
+
+ // reading the current state of watch regs
+ struct pt_watch_regs watch_readback;
+ Error error = DoReadWatchPointRegisterValue(
+ m_thread.GetID(), static_cast<void *>(&watch_readback));
+
+ if (GetWatchHi(&watch_readback, wp_index) & (IRW)) {
+ // clear hit flag in watchhi
+ SetWatchHi(&watch_readback, wp_index,
+ (GetWatchHi(&watch_readback, wp_index) & ~(IRW)));
+ DoWriteWatchPointRegisterValue(m_thread.GetID(),
+ static_cast<void *>(&watch_readback));
+
+ is_hit = true;
return error;
+ }
+ is_hit = false;
+ return error;
}
-Error
-NativeRegisterContextLinux_mips64::GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) {
- uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
- for (wp_index = 0; wp_index < num_hw_wps; ++wp_index)
- {
- bool is_hit;
- Error error = IsWatchpointHit(wp_index, is_hit);
- if (error.Fail()) {
- wp_index = LLDB_INVALID_INDEX32;
- } else if (is_hit) {
- return error;
- }
+Error NativeRegisterContextLinux_mips64::GetWatchpointHitIndex(
+ uint32_t &wp_index, lldb::addr_t trap_addr) {
+ uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
+ for (wp_index = 0; wp_index < num_hw_wps; ++wp_index) {
+ bool is_hit;
+ Error error = IsWatchpointHit(wp_index, is_hit);
+ if (error.Fail()) {
+ wp_index = LLDB_INVALID_INDEX32;
+ } else if (is_hit) {
+ return error;
}
- wp_index = LLDB_INVALID_INDEX32;
- return Error();
+ }
+ wp_index = LLDB_INVALID_INDEX32;
+ return Error();
}
-Error
-NativeRegisterContextLinux_mips64::IsWatchpointVacant (uint32_t wp_index, bool &is_vacant)
-{
- is_vacant = false;
- return Error("MIPS TODO: NativeRegisterContextLinux_mips64::IsWatchpointVacant not implemented");
+Error NativeRegisterContextLinux_mips64::IsWatchpointVacant(uint32_t wp_index,
+ bool &is_vacant) {
+ is_vacant = false;
+ return Error("MIPS TODO: "
+ "NativeRegisterContextLinux_mips64::IsWatchpointVacant not "
+ "implemented");
}
-bool
-NativeRegisterContextLinux_mips64::ClearHardwareWatchpoint(uint32_t wp_index)
-{
- if (wp_index >= NumSupportedHardwareWatchpoints())
- return false;
-
- struct pt_watch_regs regs;
- // First reading the current state of watch regs
- DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void*>(&regs));
-
- if (regs.style == pt_watch_style_mips32)
- {
- regs.mips32.watchlo[wp_index] = default_watch_regs.mips32.watchlo[wp_index];
- regs.mips32.watchhi[wp_index] = default_watch_regs.mips32.watchhi[wp_index];
- regs.mips32.watch_masks[wp_index] = default_watch_regs.mips32.watch_masks[wp_index];
- }
- else // pt_watch_style_mips64
- {
- regs.mips64.watchlo[wp_index] = default_watch_regs.mips64.watchlo[wp_index];
- regs.mips64.watchhi[wp_index] = default_watch_regs.mips64.watchhi[wp_index];
- regs.mips64.watch_masks[wp_index] = default_watch_regs.mips64.watch_masks[wp_index];
- }
-
- Error error = DoWriteWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(&regs));
- if(!error.Fail())
- {
- hw_addr_map[wp_index] = LLDB_INVALID_ADDRESS;
- return true;
- }
+bool NativeRegisterContextLinux_mips64::ClearHardwareWatchpoint(
+ uint32_t wp_index) {
+ if (wp_index >= NumSupportedHardwareWatchpoints())
return false;
+
+ struct pt_watch_regs regs;
+ // First reading the current state of watch regs
+ DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(&regs));
+
+ if (regs.style == pt_watch_style_mips32) {
+ regs.mips32.watchlo[wp_index] = default_watch_regs.mips32.watchlo[wp_index];
+ regs.mips32.watchhi[wp_index] = default_watch_regs.mips32.watchhi[wp_index];
+ regs.mips32.watch_masks[wp_index] =
+ default_watch_regs.mips32.watch_masks[wp_index];
+ } else // pt_watch_style_mips64
+ {
+ regs.mips64.watchlo[wp_index] = default_watch_regs.mips64.watchlo[wp_index];
+ regs.mips64.watchhi[wp_index] = default_watch_regs.mips64.watchhi[wp_index];
+ regs.mips64.watch_masks[wp_index] =
+ default_watch_regs.mips64.watch_masks[wp_index];
+ }
+
+ Error error = DoWriteWatchPointRegisterValue(m_thread.GetID(),
+ static_cast<void *>(&regs));
+ if (!error.Fail()) {
+ hw_addr_map[wp_index] = LLDB_INVALID_ADDRESS;
+ return true;
+ }
+ return false;
}
-Error
-NativeRegisterContextLinux_mips64::ClearAllHardwareWatchpoints()
-{
- return DoWriteWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(&default_watch_regs));
+Error NativeRegisterContextLinux_mips64::ClearAllHardwareWatchpoints() {
+ return DoWriteWatchPointRegisterValue(
+ m_thread.GetID(), static_cast<void *>(&default_watch_regs));
}
-Error
-NativeRegisterContextLinux_mips64::SetHardwareWatchpointWithIndex (
- lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index)
-{
- Error error;
- error.SetErrorString ("MIPS TODO: NativeRegisterContextLinux_mips64::SetHardwareWatchpointWithIndex not implemented");
- return error;
+Error NativeRegisterContextLinux_mips64::SetHardwareWatchpointWithIndex(
+ lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) {
+ Error error;
+ error.SetErrorString("MIPS TODO: "
+ "NativeRegisterContextLinux_mips64::"
+ "SetHardwareWatchpointWithIndex not implemented");
+ return error;
}
-uint32_t
-NativeRegisterContextLinux_mips64::SetHardwareWatchpoint (
- lldb::addr_t addr, size_t size, uint32_t watch_flags)
-{
- struct pt_watch_regs regs;
+uint32_t NativeRegisterContextLinux_mips64::SetHardwareWatchpoint(
+ lldb::addr_t addr, size_t size, uint32_t watch_flags) {
+ struct pt_watch_regs regs;
- // First reading the current state of watch regs
- DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(&regs));
+ // First reading the current state of watch regs
+ DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(&regs));
- // Try if a new watch point fits in this state
- int index = GetVacantWatchIndex (&regs, addr, size, watch_flags, NumSupportedHardwareWatchpoints());
+ // Try if a new watch point fits in this state
+ int index = GetVacantWatchIndex(&regs, addr, size, watch_flags,
+ NumSupportedHardwareWatchpoints());
- // New watchpoint doesn't fit
- if (index == LLDB_INVALID_INDEX32)
+ // New watchpoint doesn't fit
+ if (index == LLDB_INVALID_INDEX32)
return LLDB_INVALID_INDEX32;
+ // It fits, so we go ahead with updating the state of watch regs
+ DoWriteWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(&regs));
- // It fits, so we go ahead with updating the state of watch regs
- DoWriteWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(&regs));
-
- // Storing exact address
- hw_addr_map[index] = addr;
- return index;
+ // Storing exact address
+ hw_addr_map[index] = addr;
+ return index;
}
lldb::addr_t
-NativeRegisterContextLinux_mips64::GetWatchpointAddress (uint32_t wp_index)
-{
- if (wp_index >= NumSupportedHardwareWatchpoints())
- return LLDB_INVALID_ADDRESS;
+NativeRegisterContextLinux_mips64::GetWatchpointAddress(uint32_t wp_index) {
+ if (wp_index >= NumSupportedHardwareWatchpoints())
+ return LLDB_INVALID_ADDRESS;
- return hw_addr_map[wp_index];
+ return hw_addr_map[wp_index];
}
-struct EmulatorBaton
-{
- lldb::addr_t m_watch_hit_addr;
- NativeProcessLinux* m_process;
- NativeRegisterContext* m_reg_context;
-
- EmulatorBaton(NativeProcessLinux* process, NativeRegisterContext* reg_context) :
- m_watch_hit_addr(LLDB_INVALID_ADDRESS),
- m_process(process),
- m_reg_context(reg_context)
- {}
+struct EmulatorBaton {
+ lldb::addr_t m_watch_hit_addr;
+ NativeProcessLinux *m_process;
+ NativeRegisterContext *m_reg_context;
+
+ EmulatorBaton(NativeProcessLinux *process, NativeRegisterContext *reg_context)
+ : m_watch_hit_addr(LLDB_INVALID_ADDRESS), m_process(process),
+ m_reg_context(reg_context) {}
};
-static size_t
-ReadMemoryCallback (EmulateInstruction *instruction, void *baton,
- const EmulateInstruction::Context &context, lldb::addr_t addr,
- void *dst, size_t length)
-{
- size_t bytes_read;
- EmulatorBaton* emulator_baton = static_cast<EmulatorBaton*>(baton);
- emulator_baton->m_process->ReadMemory(addr, dst, length, bytes_read);
- return bytes_read;
+static size_t ReadMemoryCallback(EmulateInstruction *instruction, void *baton,
+ const EmulateInstruction::Context &context,
+ lldb::addr_t addr, void *dst, size_t length) {
+ size_t bytes_read;
+ EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);
+ emulator_baton->m_process->ReadMemory(addr, dst, length, bytes_read);
+ return bytes_read;
}
-static size_t
-WriteMemoryCallback (EmulateInstruction *instruction, void *baton,
- const EmulateInstruction::Context &context,
- lldb::addr_t addr, const void *dst, size_t length)
-{
- return length;
+static size_t WriteMemoryCallback(EmulateInstruction *instruction, void *baton,
+ const EmulateInstruction::Context &context,
+ lldb::addr_t addr, const void *dst,
+ size_t length) {
+ return length;
}
-static bool
-ReadRegisterCallback (EmulateInstruction *instruction, void *baton,
- const RegisterInfo *reg_info, RegisterValue &reg_value)
-{
- EmulatorBaton* emulator_baton = static_cast<EmulatorBaton*>(baton);
+static bool ReadRegisterCallback(EmulateInstruction *instruction, void *baton,
+ const RegisterInfo *reg_info,
+ RegisterValue &reg_value) {
+ EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);
- const RegisterInfo* full_reg_info = emulator_baton->m_reg_context->GetRegisterInfo(
- lldb::eRegisterKindDWARF, reg_info->kinds[lldb::eRegisterKindDWARF]);
+ const RegisterInfo *full_reg_info =
+ emulator_baton->m_reg_context->GetRegisterInfo(
+ lldb::eRegisterKindDWARF, reg_info->kinds[lldb::eRegisterKindDWARF]);
- Error error = emulator_baton->m_reg_context->ReadRegister(full_reg_info, reg_value);
- if (error.Success())
- return true;
+ Error error =
+ emulator_baton->m_reg_context->ReadRegister(full_reg_info, reg_value);
+ if (error.Success())
+ return true;
- return false;
+ return false;
}
-static bool
-WriteRegisterCallback (EmulateInstruction *instruction, void *baton,
- const EmulateInstruction::Context &context,
- const RegisterInfo *reg_info, const RegisterValue &reg_value)
-{
- if (reg_info->kinds[lldb::eRegisterKindDWARF] == dwarf_bad_mips64)
- {
- EmulatorBaton* emulator_baton = static_cast<EmulatorBaton*>(baton);
- emulator_baton->m_watch_hit_addr = reg_value.GetAsUInt64 ();
- }
+static bool WriteRegisterCallback(EmulateInstruction *instruction, void *baton,
+ const EmulateInstruction::Context &context,
+ const RegisterInfo *reg_info,
+ const RegisterValue &reg_value) {
+ if (reg_info->kinds[lldb::eRegisterKindDWARF] == dwarf_bad_mips64) {
+ EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);
+ emulator_baton->m_watch_hit_addr = reg_value.GetAsUInt64();
+ }
- return true;
+ return true;
}
/*
@@ -1319,123 +1077,121 @@ WriteRegisterCallback (EmulateInstruction *instruction, void *baton,
* it can decide to stop or continue the thread.
*/
lldb::addr_t
-NativeRegisterContextLinux_mips64::GetWatchpointHitAddress (uint32_t wp_index)
-{
- if (wp_index >= NumSupportedHardwareWatchpoints())
- return LLDB_INVALID_ADDRESS;
+NativeRegisterContextLinux_mips64::GetWatchpointHitAddress(uint32_t wp_index) {
+ if (wp_index >= NumSupportedHardwareWatchpoints())
+ return LLDB_INVALID_ADDRESS;
- lldb_private::ArchSpec arch;
- arch = GetRegisterInfoInterface().GetTargetArchitecture();
- std::unique_ptr<EmulateInstruction> emulator_ap(
- EmulateInstruction::FindPlugin(arch, lldb_private::eInstructionTypeAny, nullptr));
-
- if (emulator_ap == nullptr)
- return LLDB_INVALID_ADDRESS;
-
- EmulatorBaton baton(static_cast<NativeProcessLinux*>(m_thread.GetProcess().get()), this);
- emulator_ap->SetBaton (&baton);
- emulator_ap->SetReadMemCallback (&ReadMemoryCallback);
- emulator_ap->SetReadRegCallback (&ReadRegisterCallback);
- emulator_ap->SetWriteMemCallback (&WriteMemoryCallback);
- emulator_ap->SetWriteRegCallback (&WriteRegisterCallback);
-
- if (!emulator_ap->ReadInstruction())
- return LLDB_INVALID_ADDRESS;
-
- if (emulator_ap->EvaluateInstruction(lldb::eEmulateInstructionOptionNone))
- return baton.m_watch_hit_addr;
+ lldb_private::ArchSpec arch;
+ arch = GetRegisterInfoInterface().GetTargetArchitecture();
+ std::unique_ptr<EmulateInstruction> emulator_ap(
+ EmulateInstruction::FindPlugin(arch, lldb_private::eInstructionTypeAny,
+ nullptr));
+
+ if (emulator_ap == nullptr)
+ return LLDB_INVALID_ADDRESS;
+ EmulatorBaton baton(
+ static_cast<NativeProcessLinux *>(m_thread.GetProcess().get()), this);
+ emulator_ap->SetBaton(&baton);
+ emulator_ap->SetReadMemCallback(&ReadMemoryCallback);
+ emulator_ap->SetReadRegCallback(&ReadRegisterCallback);
+ emulator_ap->SetWriteMemCallback(&WriteMemoryCallback);
+ emulator_ap->SetWriteRegCallback(&WriteRegisterCallback);
+
+ if (!emulator_ap->ReadInstruction())
return LLDB_INVALID_ADDRESS;
+
+ if (emulator_ap->EvaluateInstruction(lldb::eEmulateInstructionOptionNone))
+ return baton.m_watch_hit_addr;
+
+ return LLDB_INVALID_ADDRESS;
}
-uint32_t
-NativeRegisterContextLinux_mips64::NumSupportedHardwareWatchpoints ()
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
- struct pt_watch_regs regs;
- static int num_valid = 0;
- if (!num_valid)
- {
- DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(&regs));
- default_watch_regs = regs; // Keeping default watch regs values for future use
- switch (regs.style)
- {
- case pt_watch_style_mips32:
- num_valid = regs.mips32.num_valid; // Using num_valid as cache
- return num_valid;
- 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__);
- }
- return 0;
+uint32_t NativeRegisterContextLinux_mips64::NumSupportedHardwareWatchpoints() {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+ struct pt_watch_regs regs;
+ static int num_valid = 0;
+ if (!num_valid) {
+ DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(&regs));
+ default_watch_regs =
+ regs; // Keeping default watch regs values for future use
+ switch (regs.style) {
+ case pt_watch_style_mips32:
+ num_valid = regs.mips32.num_valid; // Using num_valid as cache
+ return num_valid;
+ 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__);
}
- return num_valid;
+ return 0;
+ }
+ return num_valid;
}
-Error
-NativeRegisterContextLinux_mips64::DoReadRegisterValue(uint32_t offset,
- const char* reg_name,
- uint32_t size,
- RegisterValue &value)
-{
- GPR_linux_mips regs;
- ::memset(&regs, 0, sizeof(GPR_linux_mips));
-
- // Clear all bits in RegisterValue before writing actual value read from ptrace to avoid garbage value in 32-bit MSB
- value.SetBytes((void *)(((unsigned char *)&regs) + offset), 8, GetByteOrder());
- Error error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGS, m_thread.GetID(), NULL, &regs, sizeof regs);
- if (error.Success())
- {
- lldb_private::ArchSpec arch;
- if (m_thread.GetProcess()->GetArchitecture(arch))
- {
- void* target_address = ((uint8_t*)&regs) + offset + 4 * (arch.GetMachine() == llvm::Triple::mips);
- uint32_t target_size;
- if ((::strcmp(reg_name, "sr") == 0) || (::strcmp(reg_name, "cause") == 0) || (::strcmp(reg_name, "config5") == 0))
- target_size = 4;
- else
- target_size = arch.GetFlags() & lldb_private::ArchSpec::eMIPSABI_O32 ? 4 : 8;
- value.SetBytes(target_address, target_size, arch.GetByteOrder());
- }
- else
- error.SetErrorString("failed to get architecture");
- }
- return error;
+Error NativeRegisterContextLinux_mips64::DoReadRegisterValue(
+ uint32_t offset, const char *reg_name, uint32_t size,
+ RegisterValue &value) {
+ GPR_linux_mips regs;
+ ::memset(&regs, 0, sizeof(GPR_linux_mips));
+
+ // Clear all bits in RegisterValue before writing actual value read from
+ // ptrace to avoid garbage value in 32-bit MSB
+ value.SetBytes((void *)(((unsigned char *)&regs) + offset), 8,
+ GetByteOrder());
+ Error error = NativeProcessLinux::PtraceWrapper(
+ PTRACE_GETREGS, m_thread.GetID(), NULL, &regs, sizeof regs);
+ if (error.Success()) {
+ lldb_private::ArchSpec arch;
+ if (m_thread.GetProcess()->GetArchitecture(arch)) {
+ void *target_address = ((uint8_t *)&regs) + offset +
+ 4 * (arch.GetMachine() == llvm::Triple::mips);
+ uint32_t target_size;
+ if ((::strcmp(reg_name, "sr") == 0) ||
+ (::strcmp(reg_name, "cause") == 0) ||
+ (::strcmp(reg_name, "config5") == 0))
+ target_size = 4;
+ else
+ target_size =
+ arch.GetFlags() & lldb_private::ArchSpec::eMIPSABI_O32 ? 4 : 8;
+ value.SetBytes(target_address, target_size, arch.GetByteOrder());
+ } else
+ error.SetErrorString("failed to get architecture");
+ }
+ return error;
}
-Error
-NativeRegisterContextLinux_mips64::DoWriteRegisterValue(uint32_t offset,
- const char* reg_name,
- const RegisterValue &value)
-{
- GPR_linux_mips regs;
- Error error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGS, m_thread.GetID(), NULL, &regs, sizeof regs);
- if (error.Success())
- {
- lldb_private::ArchSpec arch;
- if (m_thread.GetProcess()->GetArchitecture(arch))
- {
- ::memcpy((void *)(((unsigned char *)(&regs)) + offset), value.GetBytes(), arch.GetFlags() & lldb_private::ArchSpec::eMIPSABI_O32 ? 4 : 8);
- error = NativeProcessLinux::PtraceWrapper(PTRACE_SETREGS, m_thread.GetID(), NULL, &regs, sizeof regs);
- }
- else
- error.SetErrorString("failed to get architecture");
- }
- return error;
+Error NativeRegisterContextLinux_mips64::DoWriteRegisterValue(
+ uint32_t offset, const char *reg_name, const RegisterValue &value) {
+ GPR_linux_mips regs;
+ Error error = NativeProcessLinux::PtraceWrapper(
+ PTRACE_GETREGS, m_thread.GetID(), NULL, &regs, sizeof regs);
+ if (error.Success()) {
+ lldb_private::ArchSpec arch;
+ if (m_thread.GetProcess()->GetArchitecture(arch)) {
+ ::memcpy((void *)(((unsigned char *)(&regs)) + offset), value.GetBytes(),
+ arch.GetFlags() & lldb_private::ArchSpec::eMIPSABI_O32 ? 4 : 8);
+ error = NativeProcessLinux::PtraceWrapper(
+ PTRACE_SETREGS, m_thread.GetID(), NULL, &regs, sizeof regs);
+ } else
+ error.SetErrorString("failed to get architecture");
+ }
+ return error;
}
-Error
-NativeRegisterContextLinux_mips64::DoReadWatchPointRegisterValue(lldb::tid_t tid, void* watch_readback)
-{
- return NativeProcessLinux::PtraceWrapper( PTRACE_GET_WATCH_REGS, m_thread.GetID(), watch_readback);
+Error NativeRegisterContextLinux_mips64::DoReadWatchPointRegisterValue(
+ lldb::tid_t tid, void *watch_readback) {
+ return NativeProcessLinux::PtraceWrapper(PTRACE_GET_WATCH_REGS,
+ m_thread.GetID(), watch_readback);
}
-Error
-NativeRegisterContextLinux_mips64::DoWriteWatchPointRegisterValue(lldb::tid_t tid, void* watch_reg_value)
-{
- return NativeProcessLinux::PtraceWrapper(PTRACE_SET_WATCH_REGS, m_thread.GetID(), watch_reg_value);
+Error NativeRegisterContextLinux_mips64::DoWriteWatchPointRegisterValue(
+ lldb::tid_t tid, void *watch_reg_value) {
+ return NativeProcessLinux::PtraceWrapper(PTRACE_SET_WATCH_REGS,
+ m_thread.GetID(), watch_reg_value);
}
#endif // defined (__mips__)
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h
index 9368645..ef17942 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
-#if defined (__mips__)
+#if defined(__mips__)
#ifndef lldb_NativeRegisterContextLinux_mips64_h
#define lldb_NativeRegisterContextLinux_mips64_h
@@ -21,143 +21,111 @@
namespace lldb_private {
namespace process_linux {
- class NativeProcessLinux;
+class NativeProcessLinux;
- class NativeRegisterContextLinux_mips64 : public NativeRegisterContextLinux
- {
- public:
- NativeRegisterContextLinux_mips64 (const ArchSpec& target_arch,
- NativeThreadProtocol &native_thread,
- uint32_t concrete_frame_idx);
+class NativeRegisterContextLinux_mips64 : public NativeRegisterContextLinux {
+public:
+ NativeRegisterContextLinux_mips64(const ArchSpec &target_arch,
+ NativeThreadProtocol &native_thread,
+ uint32_t concrete_frame_idx);
- uint32_t
- GetRegisterSetCount () const override;
+ uint32_t GetRegisterSetCount() const override;
- lldb::addr_t
- GetPCfromBreakpointLocation (lldb::addr_t fail_value = LLDB_INVALID_ADDRESS) override;
+ lldb::addr_t GetPCfromBreakpointLocation(
+ lldb::addr_t fail_value = LLDB_INVALID_ADDRESS) override;
- lldb::addr_t
- GetWatchpointHitAddress (uint32_t wp_index) override;
+ lldb::addr_t GetWatchpointHitAddress(uint32_t wp_index) override;
- const RegisterSet *
- GetRegisterSet (uint32_t set_index) const override;
+ const RegisterSet *GetRegisterSet(uint32_t set_index) const override;
- Error
- ReadRegister (const RegisterInfo *reg_info, RegisterValue &reg_value) override;
+ Error ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue &reg_value) override;
- Error
- WriteRegister (const RegisterInfo *reg_info, const RegisterValue &reg_value) override;
+ Error WriteRegister(const RegisterInfo *reg_info,
+ const RegisterValue &reg_value) override;
- Error
- ReadAllRegisterValues (lldb::DataBufferSP &data_sp) override;
+ Error ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
- Error
- WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) override;
+ Error WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
- Error
- ReadCP1();
+ Error ReadCP1();
- Error
- WriteCP1();
+ Error WriteCP1();
- Error
- IsWatchpointHit (uint32_t wp_index, bool &is_hit) override;
+ Error IsWatchpointHit(uint32_t wp_index, bool &is_hit) override;
- Error
- GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) override;
+ Error GetWatchpointHitIndex(uint32_t &wp_index,
+ lldb::addr_t trap_addr) override;
- Error
- IsWatchpointVacant (uint32_t wp_index, bool &is_vacant) override;
+ Error IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) override;
- bool
- ClearHardwareWatchpoint (uint32_t wp_index) override;
+ bool ClearHardwareWatchpoint(uint32_t wp_index) override;
- Error
- ClearAllHardwareWatchpoints () override;
+ Error ClearAllHardwareWatchpoints() override;
- Error
- SetHardwareWatchpointWithIndex (lldb::addr_t addr, size_t size,
- uint32_t watch_flags, uint32_t wp_index);
+ Error SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size,
+ uint32_t watch_flags, uint32_t wp_index);
- uint32_t
- SetHardwareWatchpoint (lldb::addr_t addr, size_t size,
- uint32_t watch_flags) override;
+ uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size,
+ uint32_t watch_flags) override;
- lldb::addr_t
- GetWatchpointAddress (uint32_t wp_index) override;
+ lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override;
- uint32_t
- NumSupportedHardwareWatchpoints () override;
+ uint32_t NumSupportedHardwareWatchpoints() override;
- static bool
- IsMSAAvailable();
+ static bool IsMSAAvailable();
- protected:
- Error
- DoReadRegisterValue(uint32_t offset,
- const char* reg_name,
- uint32_t size,
- RegisterValue &value) override;
+protected:
+ Error DoReadRegisterValue(uint32_t offset, const char *reg_name,
+ uint32_t size, RegisterValue &value) override;
- Error
- DoWriteRegisterValue(uint32_t offset,
- const char* reg_name,
+ Error DoWriteRegisterValue(uint32_t offset, const char *reg_name,
const RegisterValue &value) override;
- Error
- DoReadWatchPointRegisterValue(lldb::tid_t tid, void* watch_readback);
+ Error DoReadWatchPointRegisterValue(lldb::tid_t tid, void *watch_readback);
- Error
- DoWriteWatchPointRegisterValue(lldb::tid_t tid, void* watch_readback);
+ Error DoWriteWatchPointRegisterValue(lldb::tid_t tid, void *watch_readback);
- bool
- IsFR0();
+ bool IsFR0();
- bool
- IsFRE();
+ bool IsFRE();
- bool
- IsFPR(uint32_t reg_index) const;
+ bool IsFPR(uint32_t reg_index) const;
- bool
- IsMSA(uint32_t reg_index) const;
+ bool IsMSA(uint32_t reg_index) const;
- void*
- GetGPRBuffer() override { return &m_gpr; }
+ void *GetGPRBuffer() override { return &m_gpr; }
- void*
- GetFPRBuffer() override { return &m_fpr; }
+ void *GetFPRBuffer() override { return &m_fpr; }
- size_t
- GetFPRSize() override { return sizeof(FPR_linux_mips); }
+ size_t GetFPRSize() override { return sizeof(FPR_linux_mips); }
- private:
- // Info about register ranges.
- struct RegInfo
- {
- uint32_t num_registers;
- uint32_t num_gpr_registers;
- uint32_t num_fpr_registers;
+private:
+ // Info about register ranges.
+ struct RegInfo {
+ uint32_t num_registers;
+ uint32_t num_gpr_registers;
+ uint32_t num_fpr_registers;
- uint32_t last_gpr;
- uint32_t first_fpr;
- uint32_t last_fpr;
- uint32_t first_msa;
- uint32_t last_msa;
- };
+ uint32_t last_gpr;
+ uint32_t first_fpr;
+ uint32_t last_fpr;
+ uint32_t first_msa;
+ uint32_t last_msa;
+ };
- RegInfo m_reg_info;
+ RegInfo m_reg_info;
- GPR_linux_mips m_gpr;
+ GPR_linux_mips m_gpr;
- FPR_linux_mips m_fpr;
+ FPR_linux_mips m_fpr;
- MSA_linux_mips m_msa;
+ MSA_linux_mips m_msa;
- lldb::addr_t hw_addr_map[MAX_NUM_WP];
+ lldb::addr_t hw_addr_map[MAX_NUM_WP];
- IOVEC_mips m_iovec;
- };
+ IOVEC_mips m_iovec;
+};
} // namespace process_linux
} // namespace lldb_private
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp
index b09ad40..7ec4dc5 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp
@@ -30,99 +30,62 @@ using namespace lldb_private::process_linux;
// Private namespace.
// ----------------------------------------------------------------------------
-namespace
-{
- // s390x 64-bit general purpose registers.
- static const uint32_t g_gpr_regnums_s390x[] =
- {
- lldb_r0_s390x,
- lldb_r1_s390x,
- lldb_r2_s390x,
- lldb_r3_s390x,
- lldb_r4_s390x,
- lldb_r5_s390x,
- lldb_r6_s390x,
- lldb_r7_s390x,
- lldb_r8_s390x,
- lldb_r9_s390x,
- lldb_r10_s390x,
- lldb_r11_s390x,
- lldb_r12_s390x,
- lldb_r13_s390x,
- lldb_r14_s390x,
- lldb_r15_s390x,
- lldb_acr0_s390x,
- lldb_acr1_s390x,
- lldb_acr2_s390x,
- lldb_acr3_s390x,
- lldb_acr4_s390x,
- lldb_acr5_s390x,
- lldb_acr6_s390x,
- lldb_acr7_s390x,
- lldb_acr8_s390x,
- lldb_acr9_s390x,
- lldb_acr10_s390x,
- lldb_acr11_s390x,
- lldb_acr12_s390x,
- lldb_acr13_s390x,
- lldb_acr14_s390x,
- lldb_acr15_s390x,
- lldb_pswm_s390x,
- lldb_pswa_s390x,
- LLDB_INVALID_REGNUM // register sets need to end with this flag
- };
- static_assert((sizeof(g_gpr_regnums_s390x) / sizeof(g_gpr_regnums_s390x[0])) - 1 == k_num_gpr_registers_s390x,
- "g_gpr_regnums_s390x has wrong number of register infos");
-
- // s390x 64-bit floating point registers.
- static const uint32_t g_fpu_regnums_s390x[] =
- {
- lldb_f0_s390x,
- lldb_f1_s390x,
- lldb_f2_s390x,
- lldb_f3_s390x,
- lldb_f4_s390x,
- lldb_f5_s390x,
- lldb_f6_s390x,
- lldb_f7_s390x,
- lldb_f8_s390x,
- lldb_f9_s390x,
- lldb_f10_s390x,
- lldb_f11_s390x,
- lldb_f12_s390x,
- lldb_f13_s390x,
- lldb_f14_s390x,
- lldb_f15_s390x,
- lldb_fpc_s390x,
- LLDB_INVALID_REGNUM // register sets need to end with this flag
- };
- static_assert((sizeof(g_fpu_regnums_s390x) / sizeof(g_fpu_regnums_s390x[0])) - 1 == k_num_fpr_registers_s390x,
- "g_fpu_regnums_s390x has wrong number of register infos");
-
- // s390x Linux operating-system information.
- static const uint32_t g_linux_regnums_s390x[] =
- {
- lldb_orig_r2_s390x,
- lldb_last_break_s390x,
- lldb_system_call_s390x,
- LLDB_INVALID_REGNUM // register sets need to end with this flag
- };
- static_assert((sizeof(g_linux_regnums_s390x) / sizeof(g_linux_regnums_s390x[0])) - 1 == k_num_linux_registers_s390x,
- "g_linux_regnums_s390x has wrong number of register infos");
-
- // Number of register sets provided by this context.
- enum
- {
- k_num_register_sets = 3
- };
-
- // Register sets for s390x 64-bit.
- static const RegisterSet g_reg_sets_s390x[k_num_register_sets] =
- {
- { "General Purpose Registers", "gpr", k_num_gpr_registers_s390x, g_gpr_regnums_s390x },
- { "Floating Point Registers", "fpr", k_num_fpr_registers_s390x, g_fpu_regnums_s390x },
- { "Linux Operating System Data", "linux", k_num_linux_registers_s390x, g_linux_regnums_s390x },
- };
+namespace {
+// s390x 64-bit general purpose registers.
+static const uint32_t g_gpr_regnums_s390x[] = {
+ lldb_r0_s390x, lldb_r1_s390x, lldb_r2_s390x, lldb_r3_s390x,
+ lldb_r4_s390x, lldb_r5_s390x, lldb_r6_s390x, lldb_r7_s390x,
+ lldb_r8_s390x, lldb_r9_s390x, lldb_r10_s390x, lldb_r11_s390x,
+ lldb_r12_s390x, lldb_r13_s390x, lldb_r14_s390x, lldb_r15_s390x,
+ lldb_acr0_s390x, lldb_acr1_s390x, lldb_acr2_s390x, lldb_acr3_s390x,
+ lldb_acr4_s390x, lldb_acr5_s390x, lldb_acr6_s390x, lldb_acr7_s390x,
+ lldb_acr8_s390x, lldb_acr9_s390x, lldb_acr10_s390x, lldb_acr11_s390x,
+ lldb_acr12_s390x, lldb_acr13_s390x, lldb_acr14_s390x, lldb_acr15_s390x,
+ lldb_pswm_s390x, lldb_pswa_s390x,
+ LLDB_INVALID_REGNUM // register sets need to end with this flag
+};
+static_assert((sizeof(g_gpr_regnums_s390x) / sizeof(g_gpr_regnums_s390x[0])) -
+ 1 ==
+ k_num_gpr_registers_s390x,
+ "g_gpr_regnums_s390x has wrong number of register infos");
+
+// s390x 64-bit floating point registers.
+static const uint32_t g_fpu_regnums_s390x[] = {
+ lldb_f0_s390x, lldb_f1_s390x, lldb_f2_s390x, lldb_f3_s390x,
+ lldb_f4_s390x, lldb_f5_s390x, lldb_f6_s390x, lldb_f7_s390x,
+ lldb_f8_s390x, lldb_f9_s390x, lldb_f10_s390x, lldb_f11_s390x,
+ lldb_f12_s390x, lldb_f13_s390x, lldb_f14_s390x, lldb_f15_s390x,
+ lldb_fpc_s390x,
+ LLDB_INVALID_REGNUM // register sets need to end with this flag
+};
+static_assert((sizeof(g_fpu_regnums_s390x) / sizeof(g_fpu_regnums_s390x[0])) -
+ 1 ==
+ k_num_fpr_registers_s390x,
+ "g_fpu_regnums_s390x has wrong number of register infos");
+
+// s390x Linux operating-system information.
+static const uint32_t g_linux_regnums_s390x[] = {
+ lldb_orig_r2_s390x, lldb_last_break_s390x, lldb_system_call_s390x,
+ LLDB_INVALID_REGNUM // register sets need to end with this flag
+};
+static_assert((sizeof(g_linux_regnums_s390x) /
+ sizeof(g_linux_regnums_s390x[0])) -
+ 1 ==
+ k_num_linux_registers_s390x,
+ "g_linux_regnums_s390x has wrong number of register infos");
+
+// Number of register sets provided by this context.
+enum { k_num_register_sets = 3 };
+
+// Register sets for s390x 64-bit.
+static const RegisterSet g_reg_sets_s390x[k_num_register_sets] = {
+ {"General Purpose Registers", "gpr", k_num_gpr_registers_s390x,
+ g_gpr_regnums_s390x},
+ {"Floating Point Registers", "fpr", k_num_fpr_registers_s390x,
+ g_fpu_regnums_s390x},
+ {"Linux Operating System Data", "linux", k_num_linux_registers_s390x,
+ g_linux_regnums_s390x},
+};
}
#define REG_CONTEXT_SIZE (sizeof(s390_regs) + sizeof(s390_fp_regs) + 4)
@@ -131,15 +94,15 @@ namespace
// Required ptrace defines.
// ----------------------------------------------------------------------------
-#define NT_S390_LAST_BREAK 0x306 /* s390 breaking event address */
+#define NT_S390_LAST_BREAK 0x306 /* s390 breaking event address */
#define NT_S390_SYSTEM_CALL 0x307 /* s390 system call restart data */
NativeRegisterContextLinux *
-NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec &target_arch,
- NativeThreadProtocol &native_thread,
- uint32_t concrete_frame_idx)
-{
- return new NativeRegisterContextLinux_s390x(target_arch, native_thread, concrete_frame_idx);
+NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
+ const ArchSpec &target_arch, NativeThreadProtocol &native_thread,
+ uint32_t concrete_frame_idx) {
+ return new NativeRegisterContextLinux_s390x(target_arch, native_thread,
+ concrete_frame_idx);
}
// ----------------------------------------------------------------------------
@@ -147,570 +110,527 @@ NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec
// ----------------------------------------------------------------------------
static RegisterInfoInterface *
-CreateRegisterInfoInterface(const ArchSpec &target_arch)
-{
- assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
- "Register setting path assumes this is a 64-bit host");
- return new RegisterContextLinux_s390x(target_arch);
-}
-
-NativeRegisterContextLinux_s390x::NativeRegisterContextLinux_s390x(const ArchSpec &target_arch,
- NativeThreadProtocol &native_thread,
- uint32_t concrete_frame_idx)
- : NativeRegisterContextLinux(native_thread, concrete_frame_idx, CreateRegisterInfoInterface(target_arch))
-{
- // Set up data about ranges of valid registers.
- switch (target_arch.GetMachine())
- {
- case llvm::Triple::systemz:
- m_reg_info.num_registers = k_num_registers_s390x;
- m_reg_info.num_gpr_registers = k_num_gpr_registers_s390x;
- m_reg_info.num_fpr_registers = k_num_fpr_registers_s390x;
- m_reg_info.last_gpr = k_last_gpr_s390x;
- m_reg_info.first_fpr = k_first_fpr_s390x;
- m_reg_info.last_fpr = k_last_fpr_s390x;
- break;
- default:
- assert(false && "Unhandled target architecture.");
- break;
- }
-
- // Clear out the watchpoint state.
- m_watchpoint_addr = LLDB_INVALID_ADDRESS;
+CreateRegisterInfoInterface(const ArchSpec &target_arch) {
+ assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
+ "Register setting path assumes this is a 64-bit host");
+ return new RegisterContextLinux_s390x(target_arch);
+}
+
+NativeRegisterContextLinux_s390x::NativeRegisterContextLinux_s390x(
+ const ArchSpec &target_arch, NativeThreadProtocol &native_thread,
+ uint32_t concrete_frame_idx)
+ : NativeRegisterContextLinux(native_thread, concrete_frame_idx,
+ CreateRegisterInfoInterface(target_arch)) {
+ // Set up data about ranges of valid registers.
+ switch (target_arch.GetMachine()) {
+ case llvm::Triple::systemz:
+ m_reg_info.num_registers = k_num_registers_s390x;
+ m_reg_info.num_gpr_registers = k_num_gpr_registers_s390x;
+ m_reg_info.num_fpr_registers = k_num_fpr_registers_s390x;
+ m_reg_info.last_gpr = k_last_gpr_s390x;
+ m_reg_info.first_fpr = k_first_fpr_s390x;
+ m_reg_info.last_fpr = k_last_fpr_s390x;
+ break;
+ default:
+ assert(false && "Unhandled target architecture.");
+ break;
+ }
+
+ // Clear out the watchpoint state.
+ m_watchpoint_addr = LLDB_INVALID_ADDRESS;
+}
+
+uint32_t NativeRegisterContextLinux_s390x::GetRegisterSetCount() const {
+ uint32_t sets = 0;
+ for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) {
+ if (IsRegisterSetAvailable(set_index))
+ ++sets;
+ }
+
+ return sets;
+}
+
+uint32_t NativeRegisterContextLinux_s390x::GetUserRegisterCount() const {
+ uint32_t count = 0;
+ for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) {
+ const RegisterSet *set = GetRegisterSet(set_index);
+ if (set)
+ count += set->num_registers;
+ }
+ return count;
}
-uint32_t
-NativeRegisterContextLinux_s390x::GetRegisterSetCount() const
-{
- uint32_t sets = 0;
- for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index)
- {
- if (IsRegisterSetAvailable(set_index))
- ++sets;
- }
+const RegisterSet *
+NativeRegisterContextLinux_s390x::GetRegisterSet(uint32_t set_index) const {
+ if (!IsRegisterSetAvailable(set_index))
+ return nullptr;
- return sets;
-}
+ switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
+ case llvm::Triple::systemz:
+ return &g_reg_sets_s390x[set_index];
+ default:
+ assert(false && "Unhandled target architecture.");
+ return nullptr;
+ }
-uint32_t
-NativeRegisterContextLinux_s390x::GetUserRegisterCount() const
-{
- uint32_t count = 0;
- for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index)
- {
- const RegisterSet *set = GetRegisterSet(set_index);
- if (set)
- count += set->num_registers;
- }
- return count;
+ return nullptr;
}
-const RegisterSet *
-NativeRegisterContextLinux_s390x::GetRegisterSet(uint32_t set_index) const
-{
- if (!IsRegisterSetAvailable(set_index))
- return nullptr;
-
- switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine())
- {
- case llvm::Triple::systemz:
- return &g_reg_sets_s390x[set_index];
- default:
- assert(false && "Unhandled target architecture.");
- return nullptr;
- }
+bool NativeRegisterContextLinux_s390x::IsRegisterSetAvailable(
+ uint32_t set_index) const {
+ return set_index < k_num_register_sets;
+}
- return nullptr;
+bool NativeRegisterContextLinux_s390x::IsGPR(uint32_t reg_index) const {
+ // GPRs come first. "orig_r2" counts as GPR since it is part of the GPR
+ // register area.
+ return reg_index <= m_reg_info.last_gpr || reg_index == lldb_orig_r2_s390x;
}
-bool
-NativeRegisterContextLinux_s390x::IsRegisterSetAvailable(uint32_t set_index) const
-{
- return set_index < k_num_register_sets;
-}
-
-bool
-NativeRegisterContextLinux_s390x::IsGPR(uint32_t reg_index) const
-{
- // GPRs come first. "orig_r2" counts as GPR since it is part of the GPR register area.
- return reg_index <= m_reg_info.last_gpr || reg_index == lldb_orig_r2_s390x;
-}
-
-bool
-NativeRegisterContextLinux_s390x::IsFPR(uint32_t reg_index) const
-{
- return (m_reg_info.first_fpr <= reg_index && reg_index <= m_reg_info.last_fpr);
-}
-
-Error
-NativeRegisterContextLinux_s390x::ReadRegister(const RegisterInfo *reg_info, RegisterValue &reg_value)
-{
- if (!reg_info)
- return Error("reg_info NULL");
-
- const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
- if (reg == LLDB_INVALID_REGNUM)
- return Error("register \"%s\" is an internal-only lldb register, cannot read directly", reg_info->name);
-
- if (IsGPR(reg))
- {
- s390_regs regs;
- Error error = DoReadGPR(&regs, sizeof(regs));
- if (error.Fail())
- return error;
-
- uint8_t *src = (uint8_t *)&regs + reg_info->byte_offset;
- assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(regs));
- switch (reg_info->byte_size)
- {
- case 4:
- reg_value.SetUInt32(*(uint32_t *)src);
- break;
- case 8:
- reg_value.SetUInt64(*(uint64_t *)src);
- break;
- default:
- assert(false && "Unhandled data size.");
- return Error("unhandled byte size: %" PRIu32, reg_info->byte_size);
- }
- return Error();
- }
+bool NativeRegisterContextLinux_s390x::IsFPR(uint32_t reg_index) const {
+ return (m_reg_info.first_fpr <= reg_index &&
+ reg_index <= m_reg_info.last_fpr);
+}
- if (IsFPR(reg))
- {
- s390_fp_regs fp_regs;
- Error error = DoReadFPR(&fp_regs, sizeof(fp_regs));
- if (error.Fail())
- return error;
-
- // byte_offset is just the offset within FPR, not the whole user area.
- uint8_t *src = (uint8_t *)&fp_regs + reg_info->byte_offset;
- assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(fp_regs));
- switch (reg_info->byte_size)
- {
- case 4:
- reg_value.SetUInt32(*(uint32_t *)src);
- break;
- case 8:
- reg_value.SetUInt64(*(uint64_t *)src);
- break;
- default:
- assert(false && "Unhandled data size.");
- return Error("unhandled byte size: %" PRIu32, reg_info->byte_size);
- }
- return Error();
- }
+Error NativeRegisterContextLinux_s390x::ReadRegister(
+ const RegisterInfo *reg_info, RegisterValue &reg_value) {
+ if (!reg_info)
+ return Error("reg_info NULL");
- if (reg == lldb_last_break_s390x)
- {
- uint64_t last_break;
- Error error = DoReadRegisterSet(NT_S390_LAST_BREAK, &last_break, 8);
- if (error.Fail())
- return error;
+ const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+ if (reg == LLDB_INVALID_REGNUM)
+ return Error("register \"%s\" is an internal-only lldb register, cannot "
+ "read directly",
+ reg_info->name);
- reg_value.SetUInt64(last_break);
- return Error();
+ if (IsGPR(reg)) {
+ s390_regs regs;
+ Error error = DoReadGPR(&regs, sizeof(regs));
+ if (error.Fail())
+ return error;
+
+ uint8_t *src = (uint8_t *)&regs + reg_info->byte_offset;
+ assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(regs));
+ switch (reg_info->byte_size) {
+ case 4:
+ reg_value.SetUInt32(*(uint32_t *)src);
+ break;
+ case 8:
+ reg_value.SetUInt64(*(uint64_t *)src);
+ break;
+ default:
+ assert(false && "Unhandled data size.");
+ return Error("unhandled byte size: %" PRIu32, reg_info->byte_size);
}
+ return Error();
+ }
- if (reg == lldb_system_call_s390x)
- {
- uint32_t system_call;
- Error error = DoReadRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4);
- if (error.Fail())
- return error;
-
- reg_value.SetUInt32(system_call);
- return Error();
+ if (IsFPR(reg)) {
+ s390_fp_regs fp_regs;
+ Error error = DoReadFPR(&fp_regs, sizeof(fp_regs));
+ if (error.Fail())
+ return error;
+
+ // byte_offset is just the offset within FPR, not the whole user area.
+ uint8_t *src = (uint8_t *)&fp_regs + reg_info->byte_offset;
+ assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(fp_regs));
+ switch (reg_info->byte_size) {
+ case 4:
+ reg_value.SetUInt32(*(uint32_t *)src);
+ break;
+ case 8:
+ reg_value.SetUInt64(*(uint64_t *)src);
+ break;
+ default:
+ assert(false && "Unhandled data size.");
+ return Error("unhandled byte size: %" PRIu32, reg_info->byte_size);
}
+ return Error();
+ }
- return Error("failed - register wasn't recognized");
-}
-
-Error
-NativeRegisterContextLinux_s390x::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &reg_value)
-{
- if (!reg_info)
- return Error("reg_info NULL");
-
- const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
- if (reg == LLDB_INVALID_REGNUM)
- return Error("register \"%s\" is an internal-only lldb register, cannot write directly", reg_info->name);
-
- if (IsGPR(reg))
- {
- s390_regs regs;
- Error error = DoReadGPR(&regs, sizeof(regs));
- if (error.Fail())
- return error;
-
- uint8_t *dst = (uint8_t *)&regs + reg_info->byte_offset;
- assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(regs));
- switch (reg_info->byte_size)
- {
- case 4:
- *(uint32_t *)dst = reg_value.GetAsUInt32();
- break;
- case 8:
- *(uint64_t *)dst = reg_value.GetAsUInt64();
- break;
- default:
- assert(false && "Unhandled data size.");
- return Error("unhandled byte size: %" PRIu32, reg_info->byte_size);
- }
- return DoWriteGPR(&regs, sizeof(regs));
- }
+ if (reg == lldb_last_break_s390x) {
+ uint64_t last_break;
+ Error error = DoReadRegisterSet(NT_S390_LAST_BREAK, &last_break, 8);
+ if (error.Fail())
+ return error;
- if (IsFPR(reg))
- {
- s390_fp_regs fp_regs;
- Error error = DoReadFPR(&fp_regs, sizeof(fp_regs));
- if (error.Fail())
- return error;
-
- // byte_offset is just the offset within fp_regs, not the whole user area.
- uint8_t *dst = (uint8_t *)&fp_regs + reg_info->byte_offset;
- assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(fp_regs));
- switch (reg_info->byte_size)
- {
- case 4:
- *(uint32_t *)dst = reg_value.GetAsUInt32();
- break;
- case 8:
- *(uint64_t *)dst = reg_value.GetAsUInt64();
- break;
- default:
- assert(false && "Unhandled data size.");
- return Error("unhandled byte size: %" PRIu32, reg_info->byte_size);
- }
- return DoWriteFPR(&fp_regs, sizeof(fp_regs));
- }
+ reg_value.SetUInt64(last_break);
+ return Error();
+ }
- if (reg == lldb_last_break_s390x)
- {
- return Error("The last break address is read-only");
- }
+ if (reg == lldb_system_call_s390x) {
+ uint32_t system_call;
+ Error error = DoReadRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4);
+ if (error.Fail())
+ return error;
- if (reg == lldb_system_call_s390x)
- {
- uint32_t system_call = reg_value.GetAsUInt32();
- return DoWriteRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4);
- }
+ reg_value.SetUInt32(system_call);
+ return Error();
+ }
- return Error("failed - register wasn't recognized");
+ return Error("failed - register wasn't recognized");
}
-Error
-NativeRegisterContextLinux_s390x::ReadAllRegisterValues(lldb::DataBufferSP &data_sp)
-{
- Error error;
+Error NativeRegisterContextLinux_s390x::WriteRegister(
+ const RegisterInfo *reg_info, const RegisterValue &reg_value) {
+ if (!reg_info)
+ return Error("reg_info NULL");
- data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
- if (!data_sp)
- {
- error.SetErrorStringWithFormat("failed to allocate DataBufferHeap instance of size %" PRIu64, REG_CONTEXT_SIZE);
- return error;
- }
+ const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+ if (reg == LLDB_INVALID_REGNUM)
+ return Error("register \"%s\" is an internal-only lldb register, cannot "
+ "write directly",
+ reg_info->name);
- uint8_t *dst = data_sp->GetBytes();
- if (dst == nullptr)
- {
- error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64 " returned a null pointer",
- REG_CONTEXT_SIZE);
- return error;
+ if (IsGPR(reg)) {
+ s390_regs regs;
+ Error error = DoReadGPR(&regs, sizeof(regs));
+ if (error.Fail())
+ return error;
+
+ uint8_t *dst = (uint8_t *)&regs + reg_info->byte_offset;
+ assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(regs));
+ switch (reg_info->byte_size) {
+ case 4:
+ *(uint32_t *)dst = reg_value.GetAsUInt32();
+ break;
+ case 8:
+ *(uint64_t *)dst = reg_value.GetAsUInt64();
+ break;
+ default:
+ assert(false && "Unhandled data size.");
+ return Error("unhandled byte size: %" PRIu32, reg_info->byte_size);
}
+ return DoWriteGPR(&regs, sizeof(regs));
+ }
- error = DoReadGPR(dst, sizeof(s390_regs));
- dst += sizeof(s390_regs);
+ if (IsFPR(reg)) {
+ s390_fp_regs fp_regs;
+ Error error = DoReadFPR(&fp_regs, sizeof(fp_regs));
if (error.Fail())
- return error;
+ return error;
+
+ // byte_offset is just the offset within fp_regs, not the whole user area.
+ uint8_t *dst = (uint8_t *)&fp_regs + reg_info->byte_offset;
+ assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(fp_regs));
+ switch (reg_info->byte_size) {
+ case 4:
+ *(uint32_t *)dst = reg_value.GetAsUInt32();
+ break;
+ case 8:
+ *(uint64_t *)dst = reg_value.GetAsUInt64();
+ break;
+ default:
+ assert(false && "Unhandled data size.");
+ return Error("unhandled byte size: %" PRIu32, reg_info->byte_size);
+ }
+ return DoWriteFPR(&fp_regs, sizeof(fp_regs));
+ }
- error = DoReadFPR(dst, sizeof(s390_fp_regs));
- dst += sizeof(s390_fp_regs);
- if (error.Fail())
- return error;
+ if (reg == lldb_last_break_s390x) {
+ return Error("The last break address is read-only");
+ }
+
+ if (reg == lldb_system_call_s390x) {
+ uint32_t system_call = reg_value.GetAsUInt32();
+ return DoWriteRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4);
+ }
- // Ignore errors if the regset is unsupported (happens on older kernels).
- DoReadRegisterSet(NT_S390_SYSTEM_CALL, dst, 4);
- dst += 4;
+ return Error("failed - register wasn't recognized");
+}
- // To enable inferior function calls while the process is stopped in
- // an interrupted system call, we need to clear the system call flag.
- // It will be restored to its original value by WriteAllRegisterValues.
- // Again we ignore error if the regset is unsupported.
- uint32_t system_call = 0;
- DoWriteRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4);
+Error NativeRegisterContextLinux_s390x::ReadAllRegisterValues(
+ lldb::DataBufferSP &data_sp) {
+ Error error;
+ data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
+ if (!data_sp) {
+ error.SetErrorStringWithFormat(
+ "failed to allocate DataBufferHeap instance of size %" PRIu64,
+ REG_CONTEXT_SIZE);
return error;
-}
+ }
-Error
-NativeRegisterContextLinux_s390x::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp)
-{
- Error error;
+ uint8_t *dst = data_sp->GetBytes();
+ if (dst == nullptr) {
+ error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64
+ " returned a null pointer",
+ REG_CONTEXT_SIZE);
+ return error;
+ }
- if (!data_sp)
- {
- error.SetErrorStringWithFormat("NativeRegisterContextLinux_s390x::%s invalid data_sp provided", __FUNCTION__);
- return error;
- }
+ error = DoReadGPR(dst, sizeof(s390_regs));
+ dst += sizeof(s390_regs);
+ if (error.Fail())
+ return error;
- if (data_sp->GetByteSize() != REG_CONTEXT_SIZE)
- {
- error.SetErrorStringWithFormat(
- "NativeRegisterContextLinux_s390x::%s data_sp contained mismatched data size, expected %" PRIu64
- ", actual %" PRIu64,
- __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize());
- return error;
- }
+ error = DoReadFPR(dst, sizeof(s390_fp_regs));
+ dst += sizeof(s390_fp_regs);
+ if (error.Fail())
+ return error;
- uint8_t *src = data_sp->GetBytes();
- if (src == nullptr)
- {
- error.SetErrorStringWithFormat(
- "NativeRegisterContextLinux_s390x::%s DataBuffer::GetBytes() returned a null pointer", __FUNCTION__);
- return error;
- }
+ // Ignore errors if the regset is unsupported (happens on older kernels).
+ DoReadRegisterSet(NT_S390_SYSTEM_CALL, dst, 4);
+ dst += 4;
- error = DoWriteGPR(src, sizeof(s390_regs));
- src += sizeof(s390_regs);
- if (error.Fail())
- return error;
+ // To enable inferior function calls while the process is stopped in
+ // an interrupted system call, we need to clear the system call flag.
+ // It will be restored to its original value by WriteAllRegisterValues.
+ // Again we ignore error if the regset is unsupported.
+ uint32_t system_call = 0;
+ DoWriteRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4);
- error = DoWriteFPR(src, sizeof(s390_fp_regs));
- src += sizeof(s390_fp_regs);
- if (error.Fail())
- return error;
+ return error;
+}
- // Ignore errors if the regset is unsupported (happens on older kernels).
- DoWriteRegisterSet(NT_S390_SYSTEM_CALL, src, 4);
- src += 4;
+Error NativeRegisterContextLinux_s390x::WriteAllRegisterValues(
+ const lldb::DataBufferSP &data_sp) {
+ Error error;
+ if (!data_sp) {
+ error.SetErrorStringWithFormat(
+ "NativeRegisterContextLinux_s390x::%s invalid data_sp provided",
+ __FUNCTION__);
return error;
+ }
+
+ if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) {
+ error.SetErrorStringWithFormat(
+ "NativeRegisterContextLinux_s390x::%s data_sp contained mismatched "
+ "data size, expected %" PRIu64 ", actual %" PRIu64,
+ __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize());
+ return error;
+ }
+
+ uint8_t *src = data_sp->GetBytes();
+ if (src == nullptr) {
+ error.SetErrorStringWithFormat("NativeRegisterContextLinux_s390x::%s "
+ "DataBuffer::GetBytes() returned a null "
+ "pointer",
+ __FUNCTION__);
+ return error;
+ }
+
+ error = DoWriteGPR(src, sizeof(s390_regs));
+ src += sizeof(s390_regs);
+ if (error.Fail())
+ return error;
+
+ error = DoWriteFPR(src, sizeof(s390_fp_regs));
+ src += sizeof(s390_fp_regs);
+ if (error.Fail())
+ return error;
+
+ // Ignore errors if the regset is unsupported (happens on older kernels).
+ DoWriteRegisterSet(NT_S390_SYSTEM_CALL, src, 4);
+ src += 4;
+
+ return error;
}
-Error
-NativeRegisterContextLinux_s390x::DoReadRegisterValue(uint32_t offset, const char *reg_name, uint32_t size,
- RegisterValue &value)
-{
- return Error("DoReadRegisterValue unsupported");
+Error NativeRegisterContextLinux_s390x::DoReadRegisterValue(
+ uint32_t offset, const char *reg_name, uint32_t size,
+ RegisterValue &value) {
+ return Error("DoReadRegisterValue unsupported");
}
-Error
-NativeRegisterContextLinux_s390x::DoWriteRegisterValue(uint32_t offset, const char *reg_name,
- const RegisterValue &value)
-{
- return Error("DoWriteRegisterValue unsupported");
+Error NativeRegisterContextLinux_s390x::DoWriteRegisterValue(
+ uint32_t offset, const char *reg_name, const RegisterValue &value) {
+ return Error("DoWriteRegisterValue unsupported");
}
-Error
-NativeRegisterContextLinux_s390x::PeekUserArea(uint32_t offset, void *buf, size_t buf_size)
-{
- ptrace_area parea;
- parea.len = buf_size;
- parea.process_addr = (addr_t)buf;
- parea.kernel_addr = offset;
+Error NativeRegisterContextLinux_s390x::PeekUserArea(uint32_t offset, void *buf,
+ size_t buf_size) {
+ ptrace_area parea;
+ parea.len = buf_size;
+ parea.process_addr = (addr_t)buf;
+ parea.kernel_addr = offset;
- return NativeProcessLinux::PtraceWrapper(PTRACE_PEEKUSR_AREA, m_thread.GetID(), &parea);
+ return NativeProcessLinux::PtraceWrapper(PTRACE_PEEKUSR_AREA,
+ m_thread.GetID(), &parea);
}
-Error
-NativeRegisterContextLinux_s390x::PokeUserArea(uint32_t offset, const void *buf, size_t buf_size)
-{
- ptrace_area parea;
- parea.len = buf_size;
- parea.process_addr = (addr_t)buf;
- parea.kernel_addr = offset;
+Error NativeRegisterContextLinux_s390x::PokeUserArea(uint32_t offset,
+ const void *buf,
+ size_t buf_size) {
+ ptrace_area parea;
+ parea.len = buf_size;
+ parea.process_addr = (addr_t)buf;
+ parea.kernel_addr = offset;
- return NativeProcessLinux::PtraceWrapper(PTRACE_POKEUSR_AREA, m_thread.GetID(), &parea);
+ return NativeProcessLinux::PtraceWrapper(PTRACE_POKEUSR_AREA,
+ m_thread.GetID(), &parea);
}
-Error
-NativeRegisterContextLinux_s390x::DoReadGPR(void *buf, size_t buf_size)
-{
- assert(buf_size == sizeof(s390_regs));
- return PeekUserArea(offsetof(user_regs_struct, psw), buf, buf_size);
+Error NativeRegisterContextLinux_s390x::DoReadGPR(void *buf, size_t buf_size) {
+ assert(buf_size == sizeof(s390_regs));
+ return PeekUserArea(offsetof(user_regs_struct, psw), buf, buf_size);
}
-Error
-NativeRegisterContextLinux_s390x::DoWriteGPR(void *buf, size_t buf_size)
-{
- assert(buf_size == sizeof(s390_regs));
- return PokeUserArea(offsetof(user_regs_struct, psw), buf, buf_size);
+Error NativeRegisterContextLinux_s390x::DoWriteGPR(void *buf, size_t buf_size) {
+ assert(buf_size == sizeof(s390_regs));
+ return PokeUserArea(offsetof(user_regs_struct, psw), buf, buf_size);
}
-Error
-NativeRegisterContextLinux_s390x::DoReadFPR(void *buf, size_t buf_size)
-{
- assert(buf_size == sizeof(s390_fp_regs));
- return PeekUserArea(offsetof(user_regs_struct, fp_regs), buf, buf_size);
+Error NativeRegisterContextLinux_s390x::DoReadFPR(void *buf, size_t buf_size) {
+ assert(buf_size == sizeof(s390_fp_regs));
+ return PeekUserArea(offsetof(user_regs_struct, fp_regs), buf, buf_size);
}
-Error
-NativeRegisterContextLinux_s390x::DoWriteFPR(void *buf, size_t buf_size)
-{
- assert(buf_size == sizeof(s390_fp_regs));
- return PokeUserArea(offsetof(user_regs_struct, fp_regs), buf, buf_size);
+Error NativeRegisterContextLinux_s390x::DoWriteFPR(void *buf, size_t buf_size) {
+ assert(buf_size == sizeof(s390_fp_regs));
+ return PokeUserArea(offsetof(user_regs_struct, fp_regs), buf, buf_size);
}
-Error
-NativeRegisterContextLinux_s390x::DoReadRegisterSet(uint32_t regset, void *buf, size_t buf_size)
-{
- struct iovec iov;
- iov.iov_base = buf;
- iov.iov_len = buf_size;
+Error NativeRegisterContextLinux_s390x::DoReadRegisterSet(uint32_t regset,
+ void *buf,
+ size_t buf_size) {
+ struct iovec iov;
+ iov.iov_base = buf;
+ iov.iov_len = buf_size;
- return ReadRegisterSet(&iov, buf_size, regset);
+ return ReadRegisterSet(&iov, buf_size, regset);
}
-Error
-NativeRegisterContextLinux_s390x::DoWriteRegisterSet(uint32_t regset, const void *buf, size_t buf_size)
-{
- struct iovec iov;
- iov.iov_base = const_cast<void *>(buf);
- iov.iov_len = buf_size;
+Error NativeRegisterContextLinux_s390x::DoWriteRegisterSet(uint32_t regset,
+ const void *buf,
+ size_t buf_size) {
+ struct iovec iov;
+ iov.iov_base = const_cast<void *>(buf);
+ iov.iov_len = buf_size;
- return WriteRegisterSet(&iov, buf_size, regset);
+ return WriteRegisterSet(&iov, buf_size, regset);
}
-Error
-NativeRegisterContextLinux_s390x::IsWatchpointHit(uint32_t wp_index, bool &is_hit)
-{
- per_lowcore_bits per_lowcore;
+Error NativeRegisterContextLinux_s390x::IsWatchpointHit(uint32_t wp_index,
+ bool &is_hit) {
+ per_lowcore_bits per_lowcore;
- if (wp_index >= NumSupportedHardwareWatchpoints())
- return Error("Watchpoint index out of range");
-
- if (m_watchpoint_addr == LLDB_INVALID_ADDRESS)
- {
- is_hit = false;
- return Error();
- }
-
- Error error = PeekUserArea(offsetof(user_regs_struct, per_info.lowcore), &per_lowcore, sizeof(per_lowcore));
- if (error.Fail())
- {
- is_hit = false;
- return error;
- }
-
- is_hit = (per_lowcore.perc_storage_alteration == 1 && per_lowcore.perc_store_real_address == 0);
-
- if (is_hit)
- {
- // Do not report this watchpoint again.
- memset(&per_lowcore, 0, sizeof(per_lowcore));
- PokeUserArea(offsetof(user_regs_struct, per_info.lowcore), &per_lowcore, sizeof(per_lowcore));
- }
+ if (wp_index >= NumSupportedHardwareWatchpoints())
+ return Error("Watchpoint index out of range");
+ if (m_watchpoint_addr == LLDB_INVALID_ADDRESS) {
+ is_hit = false;
return Error();
-}
+ }
-Error
-NativeRegisterContextLinux_s390x::GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr)
-{
- uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
- for (wp_index = 0; wp_index < num_hw_wps; ++wp_index)
- {
- bool is_hit;
- Error error = IsWatchpointHit(wp_index, is_hit);
- if (error.Fail())
- {
- wp_index = LLDB_INVALID_INDEX32;
- return error;
- }
- else if (is_hit)
- {
- return error;
- }
+ Error error = PeekUserArea(offsetof(user_regs_struct, per_info.lowcore),
+ &per_lowcore, sizeof(per_lowcore));
+ if (error.Fail()) {
+ is_hit = false;
+ return error;
+ }
+
+ is_hit = (per_lowcore.perc_storage_alteration == 1 &&
+ per_lowcore.perc_store_real_address == 0);
+
+ if (is_hit) {
+ // Do not report this watchpoint again.
+ memset(&per_lowcore, 0, sizeof(per_lowcore));
+ PokeUserArea(offsetof(user_regs_struct, per_info.lowcore), &per_lowcore,
+ sizeof(per_lowcore));
+ }
+
+ return Error();
+}
+
+Error NativeRegisterContextLinux_s390x::GetWatchpointHitIndex(
+ uint32_t &wp_index, lldb::addr_t trap_addr) {
+ uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
+ for (wp_index = 0; wp_index < num_hw_wps; ++wp_index) {
+ bool is_hit;
+ Error error = IsWatchpointHit(wp_index, is_hit);
+ if (error.Fail()) {
+ wp_index = LLDB_INVALID_INDEX32;
+ return error;
+ } else if (is_hit) {
+ return error;
}
- wp_index = LLDB_INVALID_INDEX32;
- return Error();
+ }
+ wp_index = LLDB_INVALID_INDEX32;
+ return Error();
}
-Error
-NativeRegisterContextLinux_s390x::IsWatchpointVacant(uint32_t wp_index, bool &is_vacant)
-{
- if (wp_index >= NumSupportedHardwareWatchpoints())
- return Error("Watchpoint index out of range");
+Error NativeRegisterContextLinux_s390x::IsWatchpointVacant(uint32_t wp_index,
+ bool &is_vacant) {
+ if (wp_index >= NumSupportedHardwareWatchpoints())
+ return Error("Watchpoint index out of range");
- is_vacant = m_watchpoint_addr == LLDB_INVALID_ADDRESS;
+ is_vacant = m_watchpoint_addr == LLDB_INVALID_ADDRESS;
- return Error();
+ return Error();
}
-bool
-NativeRegisterContextLinux_s390x::ClearHardwareWatchpoint(uint32_t wp_index)
-{
- per_struct per_info;
+bool NativeRegisterContextLinux_s390x::ClearHardwareWatchpoint(
+ uint32_t wp_index) {
+ per_struct per_info;
- if (wp_index >= NumSupportedHardwareWatchpoints())
- return false;
+ if (wp_index >= NumSupportedHardwareWatchpoints())
+ return false;
- Error error = PeekUserArea(offsetof(user_regs_struct, per_info), &per_info, sizeof(per_info));
- if (error.Fail())
- return false;
+ Error error = PeekUserArea(offsetof(user_regs_struct, per_info), &per_info,
+ sizeof(per_info));
+ if (error.Fail())
+ return false;
- per_info.control_regs.bits.em_storage_alteration = 0;
- per_info.control_regs.bits.storage_alt_space_ctl = 0;
- per_info.starting_addr = 0;
- per_info.ending_addr = 0;
+ per_info.control_regs.bits.em_storage_alteration = 0;
+ per_info.control_regs.bits.storage_alt_space_ctl = 0;
+ per_info.starting_addr = 0;
+ per_info.ending_addr = 0;
- error = PokeUserArea(offsetof(user_regs_struct, per_info), &per_info, sizeof(per_info));
- if (error.Fail())
- return false;
+ error = PokeUserArea(offsetof(user_regs_struct, per_info), &per_info,
+ sizeof(per_info));
+ if (error.Fail())
+ return false;
- m_watchpoint_addr = LLDB_INVALID_ADDRESS;
- return true;
+ m_watchpoint_addr = LLDB_INVALID_ADDRESS;
+ return true;
}
-Error
-NativeRegisterContextLinux_s390x::ClearAllHardwareWatchpoints()
-{
- if (ClearHardwareWatchpoint(0))
- return Error();
- return Error("Clearing all hardware watchpoints failed.");
+Error NativeRegisterContextLinux_s390x::ClearAllHardwareWatchpoints() {
+ if (ClearHardwareWatchpoint(0))
+ return Error();
+ return Error("Clearing all hardware watchpoints failed.");
}
-uint32_t
-NativeRegisterContextLinux_s390x::SetHardwareWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags)
-{
- per_struct per_info;
+uint32_t NativeRegisterContextLinux_s390x::SetHardwareWatchpoint(
+ lldb::addr_t addr, size_t size, uint32_t watch_flags) {
+ per_struct per_info;
- if (watch_flags != 0x1)
- return LLDB_INVALID_INDEX32;
+ if (watch_flags != 0x1)
+ return LLDB_INVALID_INDEX32;
- if (m_watchpoint_addr != LLDB_INVALID_ADDRESS)
- return LLDB_INVALID_INDEX32;
+ if (m_watchpoint_addr != LLDB_INVALID_ADDRESS)
+ return LLDB_INVALID_INDEX32;
- Error error = PeekUserArea(offsetof(user_regs_struct, per_info), &per_info, sizeof(per_info));
- if (error.Fail())
- return LLDB_INVALID_INDEX32;
+ Error error = PeekUserArea(offsetof(user_regs_struct, per_info), &per_info,
+ sizeof(per_info));
+ if (error.Fail())
+ return LLDB_INVALID_INDEX32;
- per_info.control_regs.bits.em_storage_alteration = 1;
- per_info.control_regs.bits.storage_alt_space_ctl = 1;
- per_info.starting_addr = addr;
- per_info.ending_addr = addr + size - 1;
+ per_info.control_regs.bits.em_storage_alteration = 1;
+ per_info.control_regs.bits.storage_alt_space_ctl = 1;
+ per_info.starting_addr = addr;
+ per_info.ending_addr = addr + size - 1;
- error = PokeUserArea(offsetof(user_regs_struct, per_info), &per_info, sizeof(per_info));
- if (error.Fail())
- return LLDB_INVALID_INDEX32;
+ error = PokeUserArea(offsetof(user_regs_struct, per_info), &per_info,
+ sizeof(per_info));
+ if (error.Fail())
+ return LLDB_INVALID_INDEX32;
- m_watchpoint_addr = addr;
- return 0;
+ m_watchpoint_addr = addr;
+ return 0;
}
lldb::addr_t
-NativeRegisterContextLinux_s390x::GetWatchpointAddress(uint32_t wp_index)
-{
- if (wp_index >= NumSupportedHardwareWatchpoints())
- return LLDB_INVALID_ADDRESS;
- return m_watchpoint_addr;
+NativeRegisterContextLinux_s390x::GetWatchpointAddress(uint32_t wp_index) {
+ if (wp_index >= NumSupportedHardwareWatchpoints())
+ return LLDB_INVALID_ADDRESS;
+ return m_watchpoint_addr;
}
-uint32_t
-NativeRegisterContextLinux_s390x::NumSupportedHardwareWatchpoints()
-{
- return 1;
+uint32_t NativeRegisterContextLinux_s390x::NumSupportedHardwareWatchpoints() {
+ return 1;
}
#endif // defined(__s390x__) && defined(__linux__)
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.h b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.h
index 8cd4ab7..4bd7377 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.h
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.h
@@ -16,121 +16,96 @@
#include "Plugins/Process/Utility/RegisterContext_s390x.h"
#include "Plugins/Process/Utility/lldb-s390x-register-enums.h"
-namespace lldb_private
-{
-namespace process_linux
-{
+namespace lldb_private {
+namespace process_linux {
class NativeProcessLinux;
-class NativeRegisterContextLinux_s390x : public NativeRegisterContextLinux
-{
+class NativeRegisterContextLinux_s390x : public NativeRegisterContextLinux {
public:
- NativeRegisterContextLinux_s390x(const ArchSpec &target_arch, NativeThreadProtocol &native_thread,
- uint32_t concrete_frame_idx);
+ NativeRegisterContextLinux_s390x(const ArchSpec &target_arch,
+ NativeThreadProtocol &native_thread,
+ uint32_t concrete_frame_idx);
- uint32_t
- GetRegisterSetCount() const override;
+ uint32_t GetRegisterSetCount() const override;
- const RegisterSet *
- GetRegisterSet(uint32_t set_index) const override;
+ const RegisterSet *GetRegisterSet(uint32_t set_index) const override;
- uint32_t
- GetUserRegisterCount() const override;
+ uint32_t GetUserRegisterCount() const override;
- Error
- ReadRegister(const RegisterInfo *reg_info, RegisterValue &reg_value) override;
+ Error ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue &reg_value) override;
- Error
- WriteRegister(const RegisterInfo *reg_info, const RegisterValue &reg_value) override;
+ Error WriteRegister(const RegisterInfo *reg_info,
+ const RegisterValue &reg_value) override;
- Error
- ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
+ Error ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
- Error
- WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
+ Error WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
- Error
- IsWatchpointHit(uint32_t wp_index, bool &is_hit) override;
+ Error IsWatchpointHit(uint32_t wp_index, bool &is_hit) override;
- Error
- GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) override;
+ Error GetWatchpointHitIndex(uint32_t &wp_index,
+ lldb::addr_t trap_addr) override;
- Error
- IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) override;
+ Error IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) override;
- bool
- ClearHardwareWatchpoint(uint32_t wp_index) override;
+ bool ClearHardwareWatchpoint(uint32_t wp_index) override;
- Error
- ClearAllHardwareWatchpoints() override;
+ Error ClearAllHardwareWatchpoints() override;
- uint32_t
- SetHardwareWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags) override;
+ uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size,
+ uint32_t watch_flags) override;
- lldb::addr_t
- GetWatchpointAddress(uint32_t wp_index) override;
+ lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override;
- uint32_t
- NumSupportedHardwareWatchpoints() override;
+ uint32_t NumSupportedHardwareWatchpoints() override;
protected:
- Error
- DoReadRegisterValue(uint32_t offset, const char *reg_name, uint32_t size, RegisterValue &value) override;
+ Error DoReadRegisterValue(uint32_t offset, const char *reg_name,
+ uint32_t size, RegisterValue &value) override;
- Error
- DoWriteRegisterValue(uint32_t offset, const char *reg_name, const RegisterValue &value) override;
+ Error DoWriteRegisterValue(uint32_t offset, const char *reg_name,
+ const RegisterValue &value) override;
- Error
- DoReadGPR(void *buf, size_t buf_size) override;
+ Error DoReadGPR(void *buf, size_t buf_size) override;
- Error
- DoWriteGPR(void *buf, size_t buf_size) override;
+ Error DoWriteGPR(void *buf, size_t buf_size) override;
- Error
- DoReadFPR(void *buf, size_t buf_size) override;
+ Error DoReadFPR(void *buf, size_t buf_size) override;
- Error
- DoWriteFPR(void *buf, size_t buf_size) override;
+ Error DoWriteFPR(void *buf, size_t buf_size) override;
private:
- // Info about register ranges.
- struct RegInfo
- {
- uint32_t num_registers;
- uint32_t num_gpr_registers;
- uint32_t num_fpr_registers;
+ // Info about register ranges.
+ struct RegInfo {
+ uint32_t num_registers;
+ uint32_t num_gpr_registers;
+ uint32_t num_fpr_registers;
- uint32_t last_gpr;
- uint32_t first_fpr;
- uint32_t last_fpr;
- };
+ uint32_t last_gpr;
+ uint32_t first_fpr;
+ uint32_t last_fpr;
+ };
- // Private member variables.
- RegInfo m_reg_info;
- lldb::addr_t m_watchpoint_addr;
+ // Private member variables.
+ RegInfo m_reg_info;
+ lldb::addr_t m_watchpoint_addr;
- // Private member methods.
- bool
- IsRegisterSetAvailable(uint32_t set_index) const;
+ // Private member methods.
+ bool IsRegisterSetAvailable(uint32_t set_index) const;
- bool
- IsGPR(uint32_t reg_index) const;
+ bool IsGPR(uint32_t reg_index) const;
- bool
- IsFPR(uint32_t reg_index) const;
+ bool IsFPR(uint32_t reg_index) const;
- Error
- PeekUserArea(uint32_t offset, void *buf, size_t buf_size);
+ Error PeekUserArea(uint32_t offset, void *buf, size_t buf_size);
- Error
- PokeUserArea(uint32_t offset, const void *buf, size_t buf_size);
+ Error PokeUserArea(uint32_t offset, const void *buf, size_t buf_size);
- Error
- DoReadRegisterSet(uint32_t regset, void *buf, size_t buf_size);
+ Error DoReadRegisterSet(uint32_t regset, void *buf, size_t buf_size);
- Error
- DoWriteRegisterSet(uint32_t regset, const void *buf, size_t buf_size);
+ Error DoWriteRegisterSet(uint32_t regset, const void *buf, size_t buf_size);
};
} // namespace process_linux
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
index 2080d2e..369a803 100755
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
@@ -11,9 +11,9 @@
#include "NativeRegisterContextLinux_x86_64.h"
-#include "lldb/Core/Log.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"
@@ -27,297 +27,158 @@ using namespace lldb_private::process_linux;
// Private namespace.
// ----------------------------------------------------------------------------
-namespace
-{
- // x86 32-bit general purpose registers.
- const uint32_t
- g_gpr_regnums_i386[] =
- {
- lldb_eax_i386,
- lldb_ebx_i386,
- lldb_ecx_i386,
- lldb_edx_i386,
- lldb_edi_i386,
- lldb_esi_i386,
- lldb_ebp_i386,
- lldb_esp_i386,
- lldb_eip_i386,
- lldb_eflags_i386,
- lldb_cs_i386,
- lldb_fs_i386,
- lldb_gs_i386,
- lldb_ss_i386,
- lldb_ds_i386,
- lldb_es_i386,
- lldb_ax_i386,
- lldb_bx_i386,
- lldb_cx_i386,
- lldb_dx_i386,
- lldb_di_i386,
- lldb_si_i386,
- lldb_bp_i386,
- lldb_sp_i386,
- lldb_ah_i386,
- lldb_bh_i386,
- lldb_ch_i386,
- lldb_dh_i386,
- lldb_al_i386,
- lldb_bl_i386,
- lldb_cl_i386,
- lldb_dl_i386,
- LLDB_INVALID_REGNUM // register sets need to end with this flag
- };
- static_assert((sizeof(g_gpr_regnums_i386) / sizeof(g_gpr_regnums_i386[0])) - 1 == k_num_gpr_registers_i386,
- "g_gpr_regnums_i386 has wrong number of register infos");
-
- // x86 32-bit floating point registers.
- const uint32_t
- g_fpu_regnums_i386[] =
- {
- lldb_fctrl_i386,
- lldb_fstat_i386,
- lldb_ftag_i386,
- lldb_fop_i386,
- lldb_fiseg_i386,
- lldb_fioff_i386,
- lldb_foseg_i386,
- lldb_fooff_i386,
- lldb_mxcsr_i386,
- lldb_mxcsrmask_i386,
- lldb_st0_i386,
- lldb_st1_i386,
- lldb_st2_i386,
- lldb_st3_i386,
- lldb_st4_i386,
- lldb_st5_i386,
- lldb_st6_i386,
- lldb_st7_i386,
- lldb_mm0_i386,
- lldb_mm1_i386,
- lldb_mm2_i386,
- lldb_mm3_i386,
- lldb_mm4_i386,
- lldb_mm5_i386,
- lldb_mm6_i386,
- lldb_mm7_i386,
- lldb_xmm0_i386,
- lldb_xmm1_i386,
- lldb_xmm2_i386,
- lldb_xmm3_i386,
- lldb_xmm4_i386,
- lldb_xmm5_i386,
- lldb_xmm6_i386,
- lldb_xmm7_i386,
- LLDB_INVALID_REGNUM // register sets need to end with this flag
- };
- static_assert((sizeof(g_fpu_regnums_i386) / sizeof(g_fpu_regnums_i386[0])) - 1 == k_num_fpr_registers_i386,
- "g_fpu_regnums_i386 has wrong number of register infos");
-
- // x86 32-bit AVX registers.
- const uint32_t
- g_avx_regnums_i386[] =
- {
- lldb_ymm0_i386,
- lldb_ymm1_i386,
- lldb_ymm2_i386,
- lldb_ymm3_i386,
- lldb_ymm4_i386,
- lldb_ymm5_i386,
- lldb_ymm6_i386,
- lldb_ymm7_i386,
- LLDB_INVALID_REGNUM // register sets need to end with this flag
- };
- static_assert((sizeof(g_avx_regnums_i386) / sizeof(g_avx_regnums_i386[0])) - 1 == k_num_avx_registers_i386,
- " g_avx_regnums_i386 has wrong number of register infos");
-
- // x86 64-bit general purpose registers.
- static const
- uint32_t g_gpr_regnums_x86_64[] =
- {
- lldb_rax_x86_64,
- lldb_rbx_x86_64,
- lldb_rcx_x86_64,
- lldb_rdx_x86_64,
- lldb_rdi_x86_64,
- lldb_rsi_x86_64,
- lldb_rbp_x86_64,
- lldb_rsp_x86_64,
- lldb_r8_x86_64,
- lldb_r9_x86_64,
- lldb_r10_x86_64,
- lldb_r11_x86_64,
- lldb_r12_x86_64,
- lldb_r13_x86_64,
- lldb_r14_x86_64,
- lldb_r15_x86_64,
- lldb_rip_x86_64,
- lldb_rflags_x86_64,
- lldb_cs_x86_64,
- lldb_fs_x86_64,
- lldb_gs_x86_64,
- lldb_ss_x86_64,
- lldb_ds_x86_64,
- lldb_es_x86_64,
- lldb_eax_x86_64,
- lldb_ebx_x86_64,
- lldb_ecx_x86_64,
- lldb_edx_x86_64,
- lldb_edi_x86_64,
- lldb_esi_x86_64,
- lldb_ebp_x86_64,
- lldb_esp_x86_64,
- lldb_r8d_x86_64, // Low 32 bits or r8
- lldb_r9d_x86_64, // Low 32 bits or r9
- lldb_r10d_x86_64, // Low 32 bits or r10
- lldb_r11d_x86_64, // Low 32 bits or r11
- lldb_r12d_x86_64, // Low 32 bits or r12
- lldb_r13d_x86_64, // Low 32 bits or r13
- lldb_r14d_x86_64, // Low 32 bits or r14
- lldb_r15d_x86_64, // Low 32 bits or r15
- lldb_ax_x86_64,
- lldb_bx_x86_64,
- lldb_cx_x86_64,
- lldb_dx_x86_64,
- lldb_di_x86_64,
- lldb_si_x86_64,
- lldb_bp_x86_64,
- lldb_sp_x86_64,
- lldb_r8w_x86_64, // Low 16 bits or r8
- lldb_r9w_x86_64, // Low 16 bits or r9
- lldb_r10w_x86_64, // Low 16 bits or r10
- lldb_r11w_x86_64, // Low 16 bits or r11
- lldb_r12w_x86_64, // Low 16 bits or r12
- lldb_r13w_x86_64, // Low 16 bits or r13
- lldb_r14w_x86_64, // Low 16 bits or r14
- lldb_r15w_x86_64, // Low 16 bits or r15
- lldb_ah_x86_64,
- lldb_bh_x86_64,
- lldb_ch_x86_64,
- lldb_dh_x86_64,
- lldb_al_x86_64,
- lldb_bl_x86_64,
- lldb_cl_x86_64,
- lldb_dl_x86_64,
- lldb_dil_x86_64,
- lldb_sil_x86_64,
- lldb_bpl_x86_64,
- lldb_spl_x86_64,
- lldb_r8l_x86_64, // Low 8 bits or r8
- lldb_r9l_x86_64, // Low 8 bits or r9
- lldb_r10l_x86_64, // Low 8 bits or r10
- lldb_r11l_x86_64, // Low 8 bits or r11
- lldb_r12l_x86_64, // Low 8 bits or r12
- lldb_r13l_x86_64, // Low 8 bits or r13
- lldb_r14l_x86_64, // Low 8 bits or r14
- lldb_r15l_x86_64, // Low 8 bits or r15
- LLDB_INVALID_REGNUM // register sets need to end with this flag
- };
- static_assert((sizeof(g_gpr_regnums_x86_64) / sizeof(g_gpr_regnums_x86_64[0])) - 1 == k_num_gpr_registers_x86_64,
- "g_gpr_regnums_x86_64 has wrong number of register infos");
-
- // x86 64-bit floating point registers.
- static const uint32_t
- g_fpu_regnums_x86_64[] =
- {
- lldb_fctrl_x86_64,
- lldb_fstat_x86_64,
- lldb_ftag_x86_64,
- lldb_fop_x86_64,
- lldb_fiseg_x86_64,
- lldb_fioff_x86_64,
- lldb_foseg_x86_64,
- lldb_fooff_x86_64,
- lldb_mxcsr_x86_64,
- lldb_mxcsrmask_x86_64,
- lldb_st0_x86_64,
- lldb_st1_x86_64,
- lldb_st2_x86_64,
- lldb_st3_x86_64,
- lldb_st4_x86_64,
- lldb_st5_x86_64,
- lldb_st6_x86_64,
- lldb_st7_x86_64,
- lldb_mm0_x86_64,
- lldb_mm1_x86_64,
- lldb_mm2_x86_64,
- lldb_mm3_x86_64,
- lldb_mm4_x86_64,
- lldb_mm5_x86_64,
- lldb_mm6_x86_64,
- lldb_mm7_x86_64,
- lldb_xmm0_x86_64,
- lldb_xmm1_x86_64,
- lldb_xmm2_x86_64,
- lldb_xmm3_x86_64,
- lldb_xmm4_x86_64,
- lldb_xmm5_x86_64,
- lldb_xmm6_x86_64,
- lldb_xmm7_x86_64,
- lldb_xmm8_x86_64,
- lldb_xmm9_x86_64,
- lldb_xmm10_x86_64,
- lldb_xmm11_x86_64,
- lldb_xmm12_x86_64,
- lldb_xmm13_x86_64,
- lldb_xmm14_x86_64,
- lldb_xmm15_x86_64,
- LLDB_INVALID_REGNUM // register sets need to end with this flag
- };
- static_assert((sizeof(g_fpu_regnums_x86_64) / sizeof(g_fpu_regnums_x86_64[0])) - 1 == k_num_fpr_registers_x86_64,
- "g_fpu_regnums_x86_64 has wrong number of register infos");
-
- // x86 64-bit AVX registers.
- static const uint32_t
- g_avx_regnums_x86_64[] =
- {
- lldb_ymm0_x86_64,
- lldb_ymm1_x86_64,
- lldb_ymm2_x86_64,
- lldb_ymm3_x86_64,
- lldb_ymm4_x86_64,
- lldb_ymm5_x86_64,
- lldb_ymm6_x86_64,
- lldb_ymm7_x86_64,
- lldb_ymm8_x86_64,
- lldb_ymm9_x86_64,
- lldb_ymm10_x86_64,
- lldb_ymm11_x86_64,
- lldb_ymm12_x86_64,
- lldb_ymm13_x86_64,
- lldb_ymm14_x86_64,
- lldb_ymm15_x86_64,
- LLDB_INVALID_REGNUM // register sets need to end with this flag
- };
- static_assert((sizeof(g_avx_regnums_x86_64) / sizeof(g_avx_regnums_x86_64[0])) - 1 == k_num_avx_registers_x86_64,
- "g_avx_regnums_x86_64 has wrong number of register infos");
-
- // Number of register sets provided by this context.
- enum
- {
- k_num_extended_register_sets = 1,
- k_num_register_sets = 3
- };
-
- // Register sets for x86 32-bit.
- static const RegisterSet
- g_reg_sets_i386[k_num_register_sets] =
- {
- { "General Purpose Registers", "gpr", k_num_gpr_registers_i386, g_gpr_regnums_i386 },
- { "Floating Point Registers", "fpu", k_num_fpr_registers_i386, g_fpu_regnums_i386 },
- { "Advanced Vector Extensions", "avx", k_num_avx_registers_i386, g_avx_regnums_i386 }
- };
-
- // Register sets for x86 64-bit.
- static const RegisterSet
- g_reg_sets_x86_64[k_num_register_sets] =
- {
- { "General Purpose Registers", "gpr", k_num_gpr_registers_x86_64, g_gpr_regnums_x86_64 },
- { "Floating Point Registers", "fpu", k_num_fpr_registers_x86_64, g_fpu_regnums_x86_64 },
- { "Advanced Vector Extensions", "avx", k_num_avx_registers_x86_64, g_avx_regnums_x86_64 }
- };
+namespace {
+// x86 32-bit general purpose registers.
+const uint32_t g_gpr_regnums_i386[] = {
+ lldb_eax_i386, lldb_ebx_i386, lldb_ecx_i386, lldb_edx_i386,
+ lldb_edi_i386, lldb_esi_i386, lldb_ebp_i386, lldb_esp_i386,
+ lldb_eip_i386, lldb_eflags_i386, lldb_cs_i386, lldb_fs_i386,
+ lldb_gs_i386, lldb_ss_i386, lldb_ds_i386, lldb_es_i386,
+ lldb_ax_i386, lldb_bx_i386, lldb_cx_i386, lldb_dx_i386,
+ lldb_di_i386, lldb_si_i386, lldb_bp_i386, lldb_sp_i386,
+ lldb_ah_i386, lldb_bh_i386, lldb_ch_i386, lldb_dh_i386,
+ lldb_al_i386, lldb_bl_i386, lldb_cl_i386, lldb_dl_i386,
+ LLDB_INVALID_REGNUM // register sets need to end with this flag
+};
+static_assert((sizeof(g_gpr_regnums_i386) / sizeof(g_gpr_regnums_i386[0])) -
+ 1 ==
+ k_num_gpr_registers_i386,
+ "g_gpr_regnums_i386 has wrong number of register infos");
+
+// x86 32-bit floating point registers.
+const uint32_t g_fpu_regnums_i386[] = {
+ lldb_fctrl_i386, lldb_fstat_i386, lldb_ftag_i386, lldb_fop_i386,
+ lldb_fiseg_i386, lldb_fioff_i386, lldb_foseg_i386, lldb_fooff_i386,
+ lldb_mxcsr_i386, lldb_mxcsrmask_i386, lldb_st0_i386, lldb_st1_i386,
+ lldb_st2_i386, lldb_st3_i386, lldb_st4_i386, lldb_st5_i386,
+ lldb_st6_i386, lldb_st7_i386, lldb_mm0_i386, lldb_mm1_i386,
+ lldb_mm2_i386, lldb_mm3_i386, lldb_mm4_i386, lldb_mm5_i386,
+ lldb_mm6_i386, lldb_mm7_i386, lldb_xmm0_i386, lldb_xmm1_i386,
+ lldb_xmm2_i386, lldb_xmm3_i386, lldb_xmm4_i386, lldb_xmm5_i386,
+ lldb_xmm6_i386, lldb_xmm7_i386,
+ LLDB_INVALID_REGNUM // register sets need to end with this flag
+};
+static_assert((sizeof(g_fpu_regnums_i386) / sizeof(g_fpu_regnums_i386[0])) -
+ 1 ==
+ k_num_fpr_registers_i386,
+ "g_fpu_regnums_i386 has wrong number of register infos");
+
+// x86 32-bit AVX registers.
+const uint32_t g_avx_regnums_i386[] = {
+ lldb_ymm0_i386, lldb_ymm1_i386, lldb_ymm2_i386, lldb_ymm3_i386,
+ lldb_ymm4_i386, lldb_ymm5_i386, lldb_ymm6_i386, lldb_ymm7_i386,
+ LLDB_INVALID_REGNUM // register sets need to end with this flag
+};
+static_assert((sizeof(g_avx_regnums_i386) / sizeof(g_avx_regnums_i386[0])) -
+ 1 ==
+ k_num_avx_registers_i386,
+ " g_avx_regnums_i386 has wrong number of register infos");
+
+// x86 64-bit general purpose registers.
+static const uint32_t g_gpr_regnums_x86_64[] = {
+ lldb_rax_x86_64, lldb_rbx_x86_64, lldb_rcx_x86_64, lldb_rdx_x86_64,
+ lldb_rdi_x86_64, lldb_rsi_x86_64, lldb_rbp_x86_64, lldb_rsp_x86_64,
+ lldb_r8_x86_64, lldb_r9_x86_64, lldb_r10_x86_64, lldb_r11_x86_64,
+ lldb_r12_x86_64, lldb_r13_x86_64, lldb_r14_x86_64, lldb_r15_x86_64,
+ lldb_rip_x86_64, lldb_rflags_x86_64, lldb_cs_x86_64, lldb_fs_x86_64,
+ lldb_gs_x86_64, lldb_ss_x86_64, lldb_ds_x86_64, lldb_es_x86_64,
+ lldb_eax_x86_64, lldb_ebx_x86_64, lldb_ecx_x86_64, lldb_edx_x86_64,
+ lldb_edi_x86_64, lldb_esi_x86_64, lldb_ebp_x86_64, lldb_esp_x86_64,
+ lldb_r8d_x86_64, // Low 32 bits or r8
+ lldb_r9d_x86_64, // Low 32 bits or r9
+ lldb_r10d_x86_64, // Low 32 bits or r10
+ lldb_r11d_x86_64, // Low 32 bits or r11
+ lldb_r12d_x86_64, // Low 32 bits or r12
+ lldb_r13d_x86_64, // Low 32 bits or r13
+ lldb_r14d_x86_64, // Low 32 bits or r14
+ lldb_r15d_x86_64, // Low 32 bits or r15
+ lldb_ax_x86_64, lldb_bx_x86_64, lldb_cx_x86_64, lldb_dx_x86_64,
+ lldb_di_x86_64, lldb_si_x86_64, lldb_bp_x86_64, lldb_sp_x86_64,
+ lldb_r8w_x86_64, // Low 16 bits or r8
+ lldb_r9w_x86_64, // Low 16 bits or r9
+ lldb_r10w_x86_64, // Low 16 bits or r10
+ lldb_r11w_x86_64, // Low 16 bits or r11
+ lldb_r12w_x86_64, // Low 16 bits or r12
+ lldb_r13w_x86_64, // Low 16 bits or r13
+ lldb_r14w_x86_64, // Low 16 bits or r14
+ lldb_r15w_x86_64, // Low 16 bits or r15
+ lldb_ah_x86_64, lldb_bh_x86_64, lldb_ch_x86_64, lldb_dh_x86_64,
+ lldb_al_x86_64, lldb_bl_x86_64, lldb_cl_x86_64, lldb_dl_x86_64,
+ lldb_dil_x86_64, lldb_sil_x86_64, lldb_bpl_x86_64, lldb_spl_x86_64,
+ lldb_r8l_x86_64, // Low 8 bits or r8
+ lldb_r9l_x86_64, // Low 8 bits or r9
+ lldb_r10l_x86_64, // Low 8 bits or r10
+ lldb_r11l_x86_64, // Low 8 bits or r11
+ lldb_r12l_x86_64, // Low 8 bits or r12
+ lldb_r13l_x86_64, // Low 8 bits or r13
+ lldb_r14l_x86_64, // Low 8 bits or r14
+ lldb_r15l_x86_64, // Low 8 bits or r15
+ LLDB_INVALID_REGNUM // register sets need to end with this flag
+};
+static_assert((sizeof(g_gpr_regnums_x86_64) / sizeof(g_gpr_regnums_x86_64[0])) -
+ 1 ==
+ k_num_gpr_registers_x86_64,
+ "g_gpr_regnums_x86_64 has wrong number of register infos");
+
+// x86 64-bit floating point registers.
+static const uint32_t g_fpu_regnums_x86_64[] = {
+ lldb_fctrl_x86_64, lldb_fstat_x86_64, lldb_ftag_x86_64,
+ lldb_fop_x86_64, lldb_fiseg_x86_64, lldb_fioff_x86_64,
+ lldb_foseg_x86_64, lldb_fooff_x86_64, lldb_mxcsr_x86_64,
+ lldb_mxcsrmask_x86_64, lldb_st0_x86_64, lldb_st1_x86_64,
+ lldb_st2_x86_64, lldb_st3_x86_64, lldb_st4_x86_64,
+ lldb_st5_x86_64, lldb_st6_x86_64, lldb_st7_x86_64,
+ lldb_mm0_x86_64, lldb_mm1_x86_64, lldb_mm2_x86_64,
+ lldb_mm3_x86_64, lldb_mm4_x86_64, lldb_mm5_x86_64,
+ lldb_mm6_x86_64, lldb_mm7_x86_64, lldb_xmm0_x86_64,
+ lldb_xmm1_x86_64, lldb_xmm2_x86_64, lldb_xmm3_x86_64,
+ lldb_xmm4_x86_64, lldb_xmm5_x86_64, lldb_xmm6_x86_64,
+ lldb_xmm7_x86_64, lldb_xmm8_x86_64, lldb_xmm9_x86_64,
+ lldb_xmm10_x86_64, lldb_xmm11_x86_64, lldb_xmm12_x86_64,
+ lldb_xmm13_x86_64, lldb_xmm14_x86_64, lldb_xmm15_x86_64,
+ LLDB_INVALID_REGNUM // register sets need to end with this flag
+};
+static_assert((sizeof(g_fpu_regnums_x86_64) / sizeof(g_fpu_regnums_x86_64[0])) -
+ 1 ==
+ k_num_fpr_registers_x86_64,
+ "g_fpu_regnums_x86_64 has wrong number of register infos");
+
+// x86 64-bit AVX registers.
+static const uint32_t g_avx_regnums_x86_64[] = {
+ lldb_ymm0_x86_64, lldb_ymm1_x86_64, lldb_ymm2_x86_64, lldb_ymm3_x86_64,
+ lldb_ymm4_x86_64, lldb_ymm5_x86_64, lldb_ymm6_x86_64, lldb_ymm7_x86_64,
+ lldb_ymm8_x86_64, lldb_ymm9_x86_64, lldb_ymm10_x86_64, lldb_ymm11_x86_64,
+ lldb_ymm12_x86_64, lldb_ymm13_x86_64, lldb_ymm14_x86_64, lldb_ymm15_x86_64,
+ LLDB_INVALID_REGNUM // register sets need to end with this flag
+};
+static_assert((sizeof(g_avx_regnums_x86_64) / sizeof(g_avx_regnums_x86_64[0])) -
+ 1 ==
+ k_num_avx_registers_x86_64,
+ "g_avx_regnums_x86_64 has wrong number of register infos");
+
+// Number of register sets provided by this context.
+enum { k_num_extended_register_sets = 1, k_num_register_sets = 3 };
+
+// Register sets for x86 32-bit.
+static const RegisterSet g_reg_sets_i386[k_num_register_sets] = {
+ {"General Purpose Registers", "gpr", k_num_gpr_registers_i386,
+ g_gpr_regnums_i386},
+ {"Floating Point Registers", "fpu", k_num_fpr_registers_i386,
+ g_fpu_regnums_i386},
+ {"Advanced Vector Extensions", "avx", k_num_avx_registers_i386,
+ g_avx_regnums_i386}};
+
+// Register sets for x86 64-bit.
+static const RegisterSet g_reg_sets_x86_64[k_num_register_sets] = {
+ {"General Purpose Registers", "gpr", k_num_gpr_registers_x86_64,
+ g_gpr_regnums_x86_64},
+ {"Floating Point Registers", "fpu", k_num_fpr_registers_x86_64,
+ g_fpu_regnums_x86_64},
+ {"Advanced Vector Extensions", "avx", k_num_avx_registers_x86_64,
+ g_avx_regnums_x86_64}};
}
-#define REG_CONTEXT_SIZE (GetRegisterInfoInterface ().GetGPRSize () + sizeof(FPR))
+#define REG_CONTEXT_SIZE (GetRegisterInfoInterface().GetGPRSize() + sizeof(FPR))
// ----------------------------------------------------------------------------
// Required ptrace defines.
@@ -331,909 +192,890 @@ namespace
#define NT_PRXFPREG 0x46e62b7f
#endif
-NativeRegisterContextLinux*
-NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch,
- NativeThreadProtocol &native_thread,
- uint32_t concrete_frame_idx)
-{
- return new NativeRegisterContextLinux_x86_64(target_arch, native_thread, concrete_frame_idx);
+NativeRegisterContextLinux *
+NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
+ const ArchSpec &target_arch, NativeThreadProtocol &native_thread,
+ uint32_t concrete_frame_idx) {
+ return new NativeRegisterContextLinux_x86_64(target_arch, native_thread,
+ concrete_frame_idx);
}
// ----------------------------------------------------------------------------
// NativeRegisterContextLinux_x86_64 members.
// ----------------------------------------------------------------------------
-static RegisterInfoInterface*
-CreateRegisterInfoInterface(const ArchSpec& target_arch)
-{
- if (HostInfo::GetArchitecture().GetAddressByteSize() == 4)
- {
- // 32-bit hosts run with a RegisterContextLinux_i386 context.
- return new RegisterContextLinux_i386(target_arch);
- }
- else
- {
- assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
- "Register setting path assumes this is a 64-bit host");
- // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the x86_64 register context.
- return new RegisterContextLinux_x86_64 (target_arch);
- }
+static RegisterInfoInterface *
+CreateRegisterInfoInterface(const ArchSpec &target_arch) {
+ if (HostInfo::GetArchitecture().GetAddressByteSize() == 4) {
+ // 32-bit hosts run with a RegisterContextLinux_i386 context.
+ return new RegisterContextLinux_i386(target_arch);
+ } else {
+ assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
+ "Register setting path assumes this is a 64-bit host");
+ // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the
+ // x86_64 register context.
+ return new RegisterContextLinux_x86_64(target_arch);
+ }
}
-NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64 (const ArchSpec& target_arch,
- NativeThreadProtocol &native_thread,
- uint32_t concrete_frame_idx) :
- NativeRegisterContextLinux (native_thread, concrete_frame_idx, CreateRegisterInfoInterface(target_arch)),
- m_fpr_type (eFPRTypeNotValid),
- m_fpr (),
- m_iovec (),
- m_ymm_set (),
- m_reg_info (),
- m_gpr_x86_64 ()
-{
- // Set up data about ranges of valid registers.
- switch (target_arch.GetMachine ())
- {
- case llvm::Triple::x86:
- m_reg_info.num_registers = k_num_registers_i386;
- m_reg_info.num_gpr_registers = k_num_gpr_registers_i386;
- m_reg_info.num_fpr_registers = k_num_fpr_registers_i386;
- m_reg_info.num_avx_registers = k_num_avx_registers_i386;
- m_reg_info.last_gpr = k_last_gpr_i386;
- m_reg_info.first_fpr = k_first_fpr_i386;
- m_reg_info.last_fpr = k_last_fpr_i386;
- m_reg_info.first_st = lldb_st0_i386;
- m_reg_info.last_st = lldb_st7_i386;
- m_reg_info.first_mm = lldb_mm0_i386;
- m_reg_info.last_mm = lldb_mm7_i386;
- m_reg_info.first_xmm = lldb_xmm0_i386;
- m_reg_info.last_xmm = lldb_xmm7_i386;
- m_reg_info.first_ymm = lldb_ymm0_i386;
- m_reg_info.last_ymm = lldb_ymm7_i386;
- m_reg_info.first_dr = lldb_dr0_i386;
- m_reg_info.gpr_flags = lldb_eflags_i386;
- break;
- case llvm::Triple::x86_64:
- m_reg_info.num_registers = k_num_registers_x86_64;
- m_reg_info.num_gpr_registers = k_num_gpr_registers_x86_64;
- m_reg_info.num_fpr_registers = k_num_fpr_registers_x86_64;
- m_reg_info.num_avx_registers = k_num_avx_registers_x86_64;
- m_reg_info.last_gpr = k_last_gpr_x86_64;
- m_reg_info.first_fpr = k_first_fpr_x86_64;
- m_reg_info.last_fpr = k_last_fpr_x86_64;
- m_reg_info.first_st = lldb_st0_x86_64;
- m_reg_info.last_st = lldb_st7_x86_64;
- m_reg_info.first_mm = lldb_mm0_x86_64;
- m_reg_info.last_mm = lldb_mm7_x86_64;
- m_reg_info.first_xmm = lldb_xmm0_x86_64;
- m_reg_info.last_xmm = lldb_xmm15_x86_64;
- m_reg_info.first_ymm = lldb_ymm0_x86_64;
- m_reg_info.last_ymm = lldb_ymm15_x86_64;
- m_reg_info.first_dr = lldb_dr0_x86_64;
- m_reg_info.gpr_flags = lldb_rflags_x86_64;
- break;
- default:
- assert(false && "Unhandled target architecture.");
- break;
- }
-
- // Initialize m_iovec to point to the buffer and buffer size
- // using the conventions of Berkeley style UIO structures, as required
- // by PTRACE extensions.
- m_iovec.iov_base = &m_fpr.xstate.xsave;
- m_iovec.iov_len = sizeof(m_fpr.xstate.xsave);
-
- // Clear out the FPR state.
- ::memset(&m_fpr, 0, sizeof(FPR));
-
- // Store byte offset of fctrl (i.e. first register of FPR)
- const RegisterInfo *reg_info_fctrl = GetRegisterInfoByName("fctrl");
- m_fctrl_offset_in_userarea = reg_info_fctrl->byte_offset;
+NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64(
+ const ArchSpec &target_arch, NativeThreadProtocol &native_thread,
+ uint32_t concrete_frame_idx)
+ : NativeRegisterContextLinux(native_thread, concrete_frame_idx,
+ CreateRegisterInfoInterface(target_arch)),
+ m_fpr_type(eFPRTypeNotValid), m_fpr(), m_iovec(), m_ymm_set(),
+ m_reg_info(), m_gpr_x86_64() {
+ // Set up data about ranges of valid registers.
+ switch (target_arch.GetMachine()) {
+ case llvm::Triple::x86:
+ m_reg_info.num_registers = k_num_registers_i386;
+ m_reg_info.num_gpr_registers = k_num_gpr_registers_i386;
+ m_reg_info.num_fpr_registers = k_num_fpr_registers_i386;
+ m_reg_info.num_avx_registers = k_num_avx_registers_i386;
+ m_reg_info.last_gpr = k_last_gpr_i386;
+ m_reg_info.first_fpr = k_first_fpr_i386;
+ m_reg_info.last_fpr = k_last_fpr_i386;
+ m_reg_info.first_st = lldb_st0_i386;
+ m_reg_info.last_st = lldb_st7_i386;
+ m_reg_info.first_mm = lldb_mm0_i386;
+ m_reg_info.last_mm = lldb_mm7_i386;
+ m_reg_info.first_xmm = lldb_xmm0_i386;
+ m_reg_info.last_xmm = lldb_xmm7_i386;
+ m_reg_info.first_ymm = lldb_ymm0_i386;
+ m_reg_info.last_ymm = lldb_ymm7_i386;
+ m_reg_info.first_dr = lldb_dr0_i386;
+ m_reg_info.gpr_flags = lldb_eflags_i386;
+ break;
+ case llvm::Triple::x86_64:
+ m_reg_info.num_registers = k_num_registers_x86_64;
+ m_reg_info.num_gpr_registers = k_num_gpr_registers_x86_64;
+ m_reg_info.num_fpr_registers = k_num_fpr_registers_x86_64;
+ m_reg_info.num_avx_registers = k_num_avx_registers_x86_64;
+ m_reg_info.last_gpr = k_last_gpr_x86_64;
+ m_reg_info.first_fpr = k_first_fpr_x86_64;
+ m_reg_info.last_fpr = k_last_fpr_x86_64;
+ m_reg_info.first_st = lldb_st0_x86_64;
+ m_reg_info.last_st = lldb_st7_x86_64;
+ m_reg_info.first_mm = lldb_mm0_x86_64;
+ m_reg_info.last_mm = lldb_mm7_x86_64;
+ m_reg_info.first_xmm = lldb_xmm0_x86_64;
+ m_reg_info.last_xmm = lldb_xmm15_x86_64;
+ m_reg_info.first_ymm = lldb_ymm0_x86_64;
+ m_reg_info.last_ymm = lldb_ymm15_x86_64;
+ m_reg_info.first_dr = lldb_dr0_x86_64;
+ m_reg_info.gpr_flags = lldb_rflags_x86_64;
+ break;
+ default:
+ assert(false && "Unhandled target architecture.");
+ break;
+ }
+
+ // Initialize m_iovec to point to the buffer and buffer size
+ // using the conventions of Berkeley style UIO structures, as required
+ // by PTRACE extensions.
+ m_iovec.iov_base = &m_fpr.xstate.xsave;
+ m_iovec.iov_len = sizeof(m_fpr.xstate.xsave);
+
+ // Clear out the FPR state.
+ ::memset(&m_fpr, 0, sizeof(FPR));
+
+ // Store byte offset of fctrl (i.e. first register of FPR)
+ const RegisterInfo *reg_info_fctrl = GetRegisterInfoByName("fctrl");
+ m_fctrl_offset_in_userarea = reg_info_fctrl->byte_offset;
}
// CONSIDER after local and llgs debugging are merged, register set support can
// be moved into a base x86-64 class with IsRegisterSetAvailable made virtual.
-uint32_t
-NativeRegisterContextLinux_x86_64::GetRegisterSetCount () const
-{
- uint32_t sets = 0;
- for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index)
- {
- if (IsRegisterSetAvailable (set_index))
- ++sets;
- }
-
- return sets;
+uint32_t NativeRegisterContextLinux_x86_64::GetRegisterSetCount() const {
+ uint32_t sets = 0;
+ for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) {
+ if (IsRegisterSetAvailable(set_index))
+ ++sets;
+ }
+
+ return sets;
}
-uint32_t
-NativeRegisterContextLinux_x86_64::GetUserRegisterCount() const
-{
- uint32_t count = 0;
- for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index)
- {
- const RegisterSet* set = GetRegisterSet(set_index);
- if (set)
- count += set->num_registers;
- }
- return count;
+uint32_t NativeRegisterContextLinux_x86_64::GetUserRegisterCount() const {
+ uint32_t count = 0;
+ for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) {
+ const RegisterSet *set = GetRegisterSet(set_index);
+ if (set)
+ count += set->num_registers;
+ }
+ return count;
}
const RegisterSet *
-NativeRegisterContextLinux_x86_64::GetRegisterSet (uint32_t set_index) const
-{
- if (!IsRegisterSetAvailable (set_index))
- return nullptr;
-
- switch (GetRegisterInfoInterface ().GetTargetArchitecture ().GetMachine ())
- {
- case llvm::Triple::x86:
- return &g_reg_sets_i386[set_index];
- case llvm::Triple::x86_64:
- return &g_reg_sets_x86_64[set_index];
- default:
- assert (false && "Unhandled target architecture.");
- return nullptr;
- }
+NativeRegisterContextLinux_x86_64::GetRegisterSet(uint32_t set_index) const {
+ if (!IsRegisterSetAvailable(set_index))
+ return nullptr;
+ switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
+ case llvm::Triple::x86:
+ return &g_reg_sets_i386[set_index];
+ case llvm::Triple::x86_64:
+ return &g_reg_sets_x86_64[set_index];
+ default:
+ assert(false && "Unhandled target architecture.");
return nullptr;
-}
+ }
-Error
-NativeRegisterContextLinux_x86_64::ReadRegister (const RegisterInfo *reg_info, RegisterValue &reg_value)
-{
- Error error;
+ return nullptr;
+}
- if (!reg_info)
- {
- error.SetErrorString ("reg_info NULL");
- return error;
- }
+Error NativeRegisterContextLinux_x86_64::ReadRegister(
+ const RegisterInfo *reg_info, RegisterValue &reg_value) {
+ Error error;
- const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
- if (reg == LLDB_INVALID_REGNUM)
- {
- // This is likely an internal register for lldb use only and should not be directly queried.
- error.SetErrorStringWithFormat ("register \"%s\" is an internal-only lldb register, cannot read directly", reg_info->name);
- return error;
- }
+ if (!reg_info) {
+ error.SetErrorString("reg_info NULL");
+ return error;
+ }
+
+ const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+ if (reg == LLDB_INVALID_REGNUM) {
+ // This is likely an internal register for lldb use only and should not be
+ // directly queried.
+ error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb "
+ "register, cannot read directly",
+ reg_info->name);
+ return error;
+ }
- if (IsFPR(reg, GetFPRType()))
- {
- error = ReadFPR();
- if (error.Fail())
- return error;
+ if (IsFPR(reg, GetFPRType())) {
+ error = ReadFPR();
+ if (error.Fail())
+ return error;
+ } else {
+ uint32_t full_reg = reg;
+ bool is_subreg = reg_info->invalidate_regs &&
+ (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
+
+ if (is_subreg) {
+ // Read the full aligned 64-bit register.
+ full_reg = reg_info->invalidate_regs[0];
}
- else
- {
- uint32_t full_reg = reg;
- bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
-
- if (is_subreg)
- {
- // Read the full aligned 64-bit register.
- full_reg = reg_info->invalidate_regs[0];
- }
- error = ReadRegisterRaw(full_reg, reg_value);
+ error = ReadRegisterRaw(full_reg, reg_value);
- if (error.Success ())
- {
- // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right.
- if (is_subreg && (reg_info->byte_offset & 0x1))
- reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8);
+ if (error.Success()) {
+ // If our read was not aligned (for ah,bh,ch,dh), shift our returned value
+ // one byte to the right.
+ if (is_subreg && (reg_info->byte_offset & 0x1))
+ reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8);
- // If our return byte size was greater than the return value reg size, then
- // use the type specified by reg_info rather than the uint64_t default
- if (reg_value.GetByteSize() > reg_info->byte_size)
- reg_value.SetType(reg_info);
- }
- return error;
+ // If our return byte size was greater than the return value reg size,
+ // then
+ // use the type specified by reg_info rather than the uint64_t default
+ if (reg_value.GetByteSize() > reg_info->byte_size)
+ reg_value.SetType(reg_info);
}
-
- if (reg_info->encoding == lldb::eEncodingVector)
- {
- lldb::ByteOrder byte_order = GetByteOrder();
-
- if (byte_order != lldb::eByteOrderInvalid)
- {
- if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st)
- reg_value.SetBytes(m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_st].bytes, reg_info->byte_size, byte_order);
- if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm)
- reg_value.SetBytes(m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_mm].bytes, reg_info->byte_size, byte_order);
- if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm)
- reg_value.SetBytes(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_xmm].bytes, reg_info->byte_size, byte_order);
- if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm)
- {
- // Concatenate ymm using the register halves in xmm.bytes and ymmh.bytes
- if (GetFPRType() == eFPRTypeXSAVE && CopyXSTATEtoYMM(reg, byte_order))
- reg_value.SetBytes(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, reg_info->byte_size, byte_order);
- else
- {
- error.SetErrorString ("failed to copy ymm register value");
- return error;
- }
- }
-
- if (reg_value.GetType() != RegisterValue::eTypeBytes)
- error.SetErrorString ("write failed - type was expected to be RegisterValue::eTypeBytes");
-
- return error;
+ return error;
+ }
+
+ if (reg_info->encoding == lldb::eEncodingVector) {
+ lldb::ByteOrder byte_order = GetByteOrder();
+
+ if (byte_order != lldb::eByteOrderInvalid) {
+ if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st)
+ reg_value.SetBytes(
+ m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_st].bytes,
+ reg_info->byte_size, byte_order);
+ if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm)
+ reg_value.SetBytes(
+ m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_mm].bytes,
+ reg_info->byte_size, byte_order);
+ if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm)
+ reg_value.SetBytes(
+ m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_xmm].bytes,
+ reg_info->byte_size, byte_order);
+ if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm) {
+ // Concatenate ymm using the register halves in xmm.bytes and ymmh.bytes
+ if (GetFPRType() == eFPRTypeXSAVE && CopyXSTATEtoYMM(reg, byte_order))
+ reg_value.SetBytes(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes,
+ reg_info->byte_size, byte_order);
+ else {
+ error.SetErrorString("failed to copy ymm register value");
+ return error;
}
+ }
- error.SetErrorString ("byte order is invalid");
- return error;
- }
+ if (reg_value.GetType() != RegisterValue::eTypeBytes)
+ error.SetErrorString(
+ "write failed - type was expected to be RegisterValue::eTypeBytes");
- // Get pointer to m_fpr.xstate.fxsave variable and set the data from it.
-
- // Byte offsets of all registers are calculated wrt 'UserArea' structure.
- // However, ReadFPR() reads fpu registers {using ptrace(PTRACE_GETFPREGS,..)}
- // and stores them in 'm_fpr' (of type FPR structure). To extract values of fpu
- // registers, m_fpr should be read at byte offsets calculated wrt to FPR structure.
-
- // Since, FPR structure is also one of the member of UserArea structure.
- // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) - byte_offset(fctrl wrt UserArea)
- assert ( (reg_info->byte_offset - m_fctrl_offset_in_userarea) < sizeof(m_fpr));
- uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset - m_fctrl_offset_in_userarea;
- switch (reg_info->byte_size)
- {
- case 1:
- reg_value.SetUInt8(*(uint8_t *)src);
- break;
- case 2:
- reg_value.SetUInt16(*(uint16_t *)src);
- break;
- case 4:
- reg_value.SetUInt32(*(uint32_t *)src);
- break;
- case 8:
- reg_value.SetUInt64(*(uint64_t *)src);
- break;
- default:
- assert(false && "Unhandled data size.");
- error.SetErrorStringWithFormat ("unhandled byte size: %" PRIu32, reg_info->byte_size);
- break;
+ return error;
}
+ error.SetErrorString("byte order is invalid");
return error;
+ }
+
+ // Get pointer to m_fpr.xstate.fxsave variable and set the data from it.
+
+ // Byte offsets of all registers are calculated wrt 'UserArea' structure.
+ // However, ReadFPR() reads fpu registers {using ptrace(PTRACE_GETFPREGS,..)}
+ // and stores them in 'm_fpr' (of type FPR structure). To extract values of
+ // fpu
+ // registers, m_fpr should be read at byte offsets calculated wrt to FPR
+ // structure.
+
+ // Since, FPR structure is also one of the member of UserArea structure.
+ // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) -
+ // byte_offset(fctrl wrt UserArea)
+ assert((reg_info->byte_offset - m_fctrl_offset_in_userarea) < sizeof(m_fpr));
+ uint8_t *src =
+ (uint8_t *)&m_fpr + reg_info->byte_offset - m_fctrl_offset_in_userarea;
+ switch (reg_info->byte_size) {
+ case 1:
+ reg_value.SetUInt8(*(uint8_t *)src);
+ break;
+ case 2:
+ reg_value.SetUInt16(*(uint16_t *)src);
+ break;
+ case 4:
+ reg_value.SetUInt32(*(uint32_t *)src);
+ break;
+ case 8:
+ reg_value.SetUInt64(*(uint64_t *)src);
+ break;
+ default:
+ assert(false && "Unhandled data size.");
+ error.SetErrorStringWithFormat("unhandled byte size: %" PRIu32,
+ reg_info->byte_size);
+ break;
+ }
+
+ return error;
}
-Error
-NativeRegisterContextLinux_x86_64::WriteRegister (const RegisterInfo *reg_info, const RegisterValue &reg_value)
-{
- assert (reg_info && "reg_info is null");
-
- const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB];
- if (reg_index == LLDB_INVALID_REGNUM)
- return Error ("no lldb regnum for %s", reg_info && reg_info->name ? reg_info->name : "<unknown register>");
-
- if (IsGPR(reg_index))
- return WriteRegisterRaw(reg_index, reg_value);
-
- if (IsFPR(reg_index, GetFPRType()))
- {
- if (reg_info->encoding == lldb::eEncodingVector)
- {
- if (reg_index >= m_reg_info.first_st && reg_index <= m_reg_info.last_st)
- ::memcpy (m_fpr.xstate.fxsave.stmm[reg_index - m_reg_info.first_st].bytes, reg_value.GetBytes(), reg_value.GetByteSize());
-
- if (reg_index >= m_reg_info.first_mm && reg_index <= m_reg_info.last_mm)
- ::memcpy (m_fpr.xstate.fxsave.stmm[reg_index - m_reg_info.first_mm].bytes, reg_value.GetBytes(), reg_value.GetByteSize());
-
- if (reg_index >= m_reg_info.first_xmm && reg_index <= m_reg_info.last_xmm)
- ::memcpy (m_fpr.xstate.fxsave.xmm[reg_index - m_reg_info.first_xmm].bytes, reg_value.GetBytes(), reg_value.GetByteSize());
-
- if (reg_index >= m_reg_info.first_ymm && reg_index <= m_reg_info.last_ymm)
- {
- if (GetFPRType() != eFPRTypeXSAVE)
- return Error ("target processor does not support AVX");
-
- // Store ymm register content, and split into the register halves in xmm.bytes and ymmh.bytes
- ::memcpy (m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes, reg_value.GetBytes(), reg_value.GetByteSize());
- if (!CopyYMMtoXSTATE(reg_index, GetByteOrder()))
- return Error ("CopyYMMtoXSTATE() failed");
- }
- }
- else
- {
- // Get pointer to m_fpr.xstate.fxsave variable and set the data to it.
-
- // Byte offsets of all registers are calculated wrt 'UserArea' structure.
- // However, WriteFPR() takes m_fpr (of type FPR structure) and writes only fpu
- // registers using ptrace(PTRACE_SETFPREGS,..) API. Hence fpu registers should
- // be written in m_fpr at byte offsets calculated wrt FPR structure.
-
- // Since, FPR structure is also one of the member of UserArea structure.
- // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) - byte_offset(fctrl wrt UserArea)
- assert ( (reg_info->byte_offset - m_fctrl_offset_in_userarea) < sizeof(m_fpr));
- uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset - m_fctrl_offset_in_userarea;
- switch (reg_info->byte_size)
- {
- case 1:
- *(uint8_t *)dst = reg_value.GetAsUInt8();
- break;
- case 2:
- *(uint16_t *)dst = reg_value.GetAsUInt16();
- break;
- case 4:
- *(uint32_t *)dst = reg_value.GetAsUInt32();
- break;
- case 8:
- *(uint64_t *)dst = reg_value.GetAsUInt64();
- break;
- default:
- assert(false && "Unhandled data size.");
- return Error ("unhandled register data size %" PRIu32, reg_info->byte_size);
- }
- }
+Error NativeRegisterContextLinux_x86_64::WriteRegister(
+ const RegisterInfo *reg_info, const RegisterValue &reg_value) {
+ assert(reg_info && "reg_info is null");
+
+ const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB];
+ if (reg_index == LLDB_INVALID_REGNUM)
+ return Error("no lldb regnum for %s", reg_info && reg_info->name
+ ? reg_info->name
+ : "<unknown register>");
+
+ if (IsGPR(reg_index))
+ return WriteRegisterRaw(reg_index, reg_value);
+
+ if (IsFPR(reg_index, GetFPRType())) {
+ if (reg_info->encoding == lldb::eEncodingVector) {
+ if (reg_index >= m_reg_info.first_st && reg_index <= m_reg_info.last_st)
+ ::memcpy(
+ m_fpr.xstate.fxsave.stmm[reg_index - m_reg_info.first_st].bytes,
+ reg_value.GetBytes(), reg_value.GetByteSize());
+
+ if (reg_index >= m_reg_info.first_mm && reg_index <= m_reg_info.last_mm)
+ ::memcpy(
+ m_fpr.xstate.fxsave.stmm[reg_index - m_reg_info.first_mm].bytes,
+ reg_value.GetBytes(), reg_value.GetByteSize());
+
+ if (reg_index >= m_reg_info.first_xmm && reg_index <= m_reg_info.last_xmm)
+ ::memcpy(
+ m_fpr.xstate.fxsave.xmm[reg_index - m_reg_info.first_xmm].bytes,
+ reg_value.GetBytes(), reg_value.GetByteSize());
+
+ if (reg_index >= m_reg_info.first_ymm &&
+ reg_index <= m_reg_info.last_ymm) {
+ if (GetFPRType() != eFPRTypeXSAVE)
+ return Error("target processor does not support AVX");
+
+ // Store ymm register content, and split into the register halves in
+ // xmm.bytes and ymmh.bytes
+ ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes,
+ reg_value.GetBytes(), reg_value.GetByteSize());
+ if (!CopyYMMtoXSTATE(reg_index, GetByteOrder()))
+ return Error("CopyYMMtoXSTATE() failed");
+ }
+ } else {
+ // Get pointer to m_fpr.xstate.fxsave variable and set the data to it.
+
+ // Byte offsets of all registers are calculated wrt 'UserArea' structure.
+ // However, WriteFPR() takes m_fpr (of type FPR structure) and writes only
+ // fpu
+ // registers using ptrace(PTRACE_SETFPREGS,..) API. Hence fpu registers
+ // should
+ // be written in m_fpr at byte offsets calculated wrt FPR structure.
+
+ // Since, FPR structure is also one of the member of UserArea structure.
+ // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) -
+ // byte_offset(fctrl wrt UserArea)
+ assert((reg_info->byte_offset - m_fctrl_offset_in_userarea) <
+ sizeof(m_fpr));
+ uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset -
+ m_fctrl_offset_in_userarea;
+ switch (reg_info->byte_size) {
+ case 1:
+ *(uint8_t *)dst = reg_value.GetAsUInt8();
+ break;
+ case 2:
+ *(uint16_t *)dst = reg_value.GetAsUInt16();
+ break;
+ case 4:
+ *(uint32_t *)dst = reg_value.GetAsUInt32();
+ break;
+ case 8:
+ *(uint64_t *)dst = reg_value.GetAsUInt64();
+ break;
+ default:
+ assert(false && "Unhandled data size.");
+ return Error("unhandled register data size %" PRIu32,
+ reg_info->byte_size);
+ }
+ }
- Error error = WriteFPR();
- if (error.Fail())
- return error;
+ Error error = WriteFPR();
+ if (error.Fail())
+ return error;
- if (IsAVX(reg_index))
- {
- if (!CopyYMMtoXSTATE(reg_index, GetByteOrder()))
- return Error ("CopyYMMtoXSTATE() failed");
- }
- return Error ();
+ if (IsAVX(reg_index)) {
+ if (!CopyYMMtoXSTATE(reg_index, GetByteOrder()))
+ return Error("CopyYMMtoXSTATE() failed");
}
- return Error ("failed - register wasn't recognized to be a GPR or an FPR, write strategy unknown");
+ return Error();
+ }
+ return Error("failed - register wasn't recognized to be a GPR or an FPR, "
+ "write strategy unknown");
}
-Error
-NativeRegisterContextLinux_x86_64::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
-{
- Error error;
+Error NativeRegisterContextLinux_x86_64::ReadAllRegisterValues(
+ lldb::DataBufferSP &data_sp) {
+ Error error;
- data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
- if (!data_sp)
- {
- error.SetErrorStringWithFormat ("failed to allocate DataBufferHeap instance of size %" PRIu64, REG_CONTEXT_SIZE);
- return error;
- }
+ data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
+ if (!data_sp) {
+ error.SetErrorStringWithFormat(
+ "failed to allocate DataBufferHeap instance of size %" PRIu64,
+ REG_CONTEXT_SIZE);
+ return error;
+ }
- error = ReadGPR();
- if (error.Fail())
- return error;
+ error = ReadGPR();
+ if (error.Fail())
+ return error;
- error = ReadFPR();
- if (error.Fail())
- return error;
+ error = ReadFPR();
+ if (error.Fail())
+ return error;
- uint8_t *dst = data_sp->GetBytes ();
- if (dst == nullptr)
- {
- error.SetErrorStringWithFormat ("DataBufferHeap instance of size %" PRIu64 " returned a null pointer", REG_CONTEXT_SIZE);
+ uint8_t *dst = data_sp->GetBytes();
+ if (dst == nullptr) {
+ error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64
+ " returned a null pointer",
+ REG_CONTEXT_SIZE);
+ return error;
+ }
+
+ ::memcpy(dst, &m_gpr_x86_64, GetRegisterInfoInterface().GetGPRSize());
+ dst += GetRegisterInfoInterface().GetGPRSize();
+ if (GetFPRType() == eFPRTypeFXSAVE)
+ ::memcpy(dst, &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave));
+ else if (GetFPRType() == eFPRTypeXSAVE) {
+ lldb::ByteOrder byte_order = GetByteOrder();
+
+ // Assemble the YMM register content from the register halves.
+ for (uint32_t reg = m_reg_info.first_ymm; reg <= m_reg_info.last_ymm;
+ ++reg) {
+ if (!CopyXSTATEtoYMM(reg, byte_order)) {
+ error.SetErrorStringWithFormat("NativeRegisterContextLinux_x86_64::%s "
+ "CopyXSTATEtoYMM() failed for reg num "
+ "%" PRIu32,
+ __FUNCTION__, reg);
return error;
+ }
}
- ::memcpy (dst, &m_gpr_x86_64, GetRegisterInfoInterface ().GetGPRSize ());
- dst += GetRegisterInfoInterface ().GetGPRSize ();
- if (GetFPRType () == eFPRTypeFXSAVE)
- ::memcpy (dst, &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave));
- else if (GetFPRType () == eFPRTypeXSAVE)
- {
- lldb::ByteOrder byte_order = GetByteOrder ();
-
- // Assemble the YMM register content from the register halves.
- for (uint32_t reg = m_reg_info.first_ymm; reg <= m_reg_info.last_ymm; ++reg)
- {
- if (!CopyXSTATEtoYMM (reg, byte_order))
- {
- error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s CopyXSTATEtoYMM() failed for reg num %" PRIu32, __FUNCTION__, reg);
- return error;
- }
- }
-
- // Copy the extended register state including the assembled ymm registers.
- ::memcpy (dst, &m_fpr, sizeof (m_fpr));
- }
- else
- {
- assert (false && "how do we save the floating point registers?");
- error.SetErrorString ("unsure how to save the floating point registers");
- }
- /** The following code is specific to Linux x86 based architectures,
- * where the register orig_eax (32 bit)/orig_rax (64 bit) is set to
- * -1 to solve the bug 23659, such a setting prevents the automatic
- * decrement of the instruction pointer which was causing the SIGILL
- * exception.
- * **/
-
- RegisterValue value((uint64_t) -1);
- const RegisterInfo *reg_info = GetRegisterInfoInterface().GetDynamicRegisterInfo("orig_eax");
- if (reg_info == nullptr)
- reg_info = GetRegisterInfoInterface().GetDynamicRegisterInfo("orig_rax");
-
- if (reg_info != nullptr)
- return DoWriteRegisterValue(reg_info->byte_offset,reg_info->name,value);
-
- return error;
+ // Copy the extended register state including the assembled ymm registers.
+ ::memcpy(dst, &m_fpr, sizeof(m_fpr));
+ } else {
+ assert(false && "how do we save the floating point registers?");
+ error.SetErrorString("unsure how to save the floating point registers");
+ }
+ /** The following code is specific to Linux x86 based architectures,
+ * where the register orig_eax (32 bit)/orig_rax (64 bit) is set to
+ * -1 to solve the bug 23659, such a setting prevents the automatic
+ * decrement of the instruction pointer which was causing the SIGILL
+ * exception.
+ * **/
+
+ RegisterValue value((uint64_t)-1);
+ const RegisterInfo *reg_info =
+ GetRegisterInfoInterface().GetDynamicRegisterInfo("orig_eax");
+ if (reg_info == nullptr)
+ reg_info = GetRegisterInfoInterface().GetDynamicRegisterInfo("orig_rax");
+
+ if (reg_info != nullptr)
+ return DoWriteRegisterValue(reg_info->byte_offset, reg_info->name, value);
+
+ return error;
}
-Error
-NativeRegisterContextLinux_x86_64::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
-{
- Error error;
-
- if (!data_sp)
- {
- error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s invalid data_sp provided", __FUNCTION__);
- return error;
- }
+Error NativeRegisterContextLinux_x86_64::WriteAllRegisterValues(
+ const lldb::DataBufferSP &data_sp) {
+ Error error;
- if (data_sp->GetByteSize () != REG_CONTEXT_SIZE)
- {
- error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched data size, expected %" PRIu64 ", actual %" PRIu64, __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize ());
- return error;
- }
+ if (!data_sp) {
+ error.SetErrorStringWithFormat(
+ "NativeRegisterContextLinux_x86_64::%s invalid data_sp provided",
+ __FUNCTION__);
+ return error;
+ }
+ if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) {
+ error.SetErrorStringWithFormat(
+ "NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched "
+ "data size, expected %" PRIu64 ", actual %" PRIu64,
+ __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize());
+ return error;
+ }
+
+ uint8_t *src = data_sp->GetBytes();
+ if (src == nullptr) {
+ error.SetErrorStringWithFormat("NativeRegisterContextLinux_x86_64::%s "
+ "DataBuffer::GetBytes() returned a null "
+ "pointer",
+ __FUNCTION__);
+ return error;
+ }
+ ::memcpy(&m_gpr_x86_64, src, GetRegisterInfoInterface().GetGPRSize());
- uint8_t *src = data_sp->GetBytes ();
- if (src == nullptr)
- {
- error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s DataBuffer::GetBytes() returned a null pointer", __FUNCTION__);
- return error;
- }
- ::memcpy (&m_gpr_x86_64, src, GetRegisterInfoInterface ().GetGPRSize ());
+ error = WriteGPR();
+ if (error.Fail())
+ return error;
- error = WriteGPR();
- if (error.Fail())
- return error;
+ src += GetRegisterInfoInterface().GetGPRSize();
+ if (GetFPRType() == eFPRTypeFXSAVE)
+ ::memcpy(&m_fpr.xstate.fxsave, src, sizeof(m_fpr.xstate.fxsave));
+ else if (GetFPRType() == eFPRTypeXSAVE)
+ ::memcpy(&m_fpr.xstate.xsave, src, sizeof(m_fpr.xstate.xsave));
- src += GetRegisterInfoInterface ().GetGPRSize ();
- if (GetFPRType () == eFPRTypeFXSAVE)
- ::memcpy (&m_fpr.xstate.fxsave, src, sizeof(m_fpr.xstate.fxsave));
- else if (GetFPRType () == eFPRTypeXSAVE)
- ::memcpy (&m_fpr.xstate.xsave, src, sizeof(m_fpr.xstate.xsave));
+ error = WriteFPR();
+ if (error.Fail())
+ return error;
- error = WriteFPR();
- if (error.Fail())
+ if (GetFPRType() == eFPRTypeXSAVE) {
+ lldb::ByteOrder byte_order = GetByteOrder();
+
+ // Parse the YMM register content from the register halves.
+ for (uint32_t reg = m_reg_info.first_ymm; reg <= m_reg_info.last_ymm;
+ ++reg) {
+ if (!CopyYMMtoXSTATE(reg, byte_order)) {
+ error.SetErrorStringWithFormat("NativeRegisterContextLinux_x86_64::%s "
+ "CopyYMMtoXSTATE() failed for reg num "
+ "%" PRIu32,
+ __FUNCTION__, reg);
return error;
-
- if (GetFPRType() == eFPRTypeXSAVE)
- {
- lldb::ByteOrder byte_order = GetByteOrder();
-
- // Parse the YMM register content from the register halves.
- for (uint32_t reg = m_reg_info.first_ymm; reg <= m_reg_info.last_ymm; ++reg)
- {
- if (!CopyYMMtoXSTATE (reg, byte_order))
- {
- error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s CopyYMMtoXSTATE() failed for reg num %" PRIu32, __FUNCTION__, reg);
- return error;
- }
- }
+ }
}
+ }
- return error;
+ return error;
}
-bool
-NativeRegisterContextLinux_x86_64::IsRegisterSetAvailable (uint32_t set_index) const
-{
- // Note: Extended register sets are assumed to be at the end of g_reg_sets.
- uint32_t num_sets = k_num_register_sets - k_num_extended_register_sets;
+bool NativeRegisterContextLinux_x86_64::IsRegisterSetAvailable(
+ uint32_t set_index) const {
+ // Note: Extended register sets are assumed to be at the end of g_reg_sets.
+ uint32_t num_sets = k_num_register_sets - k_num_extended_register_sets;
- if (GetFPRType () == eFPRTypeXSAVE)
- {
- // AVX is the first extended register set.
- ++num_sets;
- }
- return (set_index < num_sets);
+ if (GetFPRType() == eFPRTypeXSAVE) {
+ // AVX is the first extended register set.
+ ++num_sets;
+ }
+ return (set_index < num_sets);
}
-bool
-NativeRegisterContextLinux_x86_64::IsGPR(uint32_t reg_index) const
-{
- // GPRs come first.
- return reg_index <= m_reg_info.last_gpr;
+bool NativeRegisterContextLinux_x86_64::IsGPR(uint32_t reg_index) const {
+ // GPRs come first.
+ return reg_index <= m_reg_info.last_gpr;
}
NativeRegisterContextLinux_x86_64::FPRType
-NativeRegisterContextLinux_x86_64::GetFPRType () const
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (m_fpr_type == eFPRTypeNotValid)
- {
- // TODO: Use assembly to call cpuid on the inferior and query ebx or ecx.
-
- // Try and see if AVX register retrieval works.
- m_fpr_type = eFPRTypeXSAVE;
- if (const_cast<NativeRegisterContextLinux_x86_64*>(this)->ReadFPR().Fail())
- {
- // Fall back to general floating point with no AVX support.
- m_fpr_type = eFPRTypeFXSAVE;
-
- // Check if FXSAVE area can be read.
- if (const_cast<NativeRegisterContextLinux_x86_64*>(this)->ReadFPR().Fail())
- {
- if (log)
- log->Printf("NativeRegisterContextLinux_x86_64::%s ptrace APIs failed to read XSAVE/FXSAVE area", __FUNCTION__);
- }
- }
+NativeRegisterContextLinux_x86_64::GetFPRType() const {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (m_fpr_type == eFPRTypeNotValid) {
+ // TODO: Use assembly to call cpuid on the inferior and query ebx or ecx.
+
+ // Try and see if AVX register retrieval works.
+ m_fpr_type = eFPRTypeXSAVE;
+ if (const_cast<NativeRegisterContextLinux_x86_64 *>(this)
+ ->ReadFPR()
+ .Fail()) {
+ // Fall back to general floating point with no AVX support.
+ m_fpr_type = eFPRTypeFXSAVE;
+
+ // Check if FXSAVE area can be read.
+ if (const_cast<NativeRegisterContextLinux_x86_64 *>(this)
+ ->ReadFPR()
+ .Fail()) {
+ if (log)
+ log->Printf("NativeRegisterContextLinux_x86_64::%s ptrace APIs "
+ "failed to read XSAVE/FXSAVE area",
+ __FUNCTION__);
+ }
}
- return m_fpr_type;
+ }
+ return m_fpr_type;
}
-bool
-NativeRegisterContextLinux_x86_64::IsFPR(uint32_t reg_index) const
-{
- return (m_reg_info.first_fpr <= reg_index && reg_index <= m_reg_info.last_fpr);
+bool NativeRegisterContextLinux_x86_64::IsFPR(uint32_t reg_index) const {
+ return (m_reg_info.first_fpr <= reg_index &&
+ reg_index <= m_reg_info.last_fpr);
}
-bool
-NativeRegisterContextLinux_x86_64::IsFPR(uint32_t reg_index, FPRType fpr_type) const
-{
- bool generic_fpr = IsFPR(reg_index);
+bool NativeRegisterContextLinux_x86_64::IsFPR(uint32_t reg_index,
+ FPRType fpr_type) const {
+ bool generic_fpr = IsFPR(reg_index);
- if (fpr_type == eFPRTypeXSAVE)
- return generic_fpr || IsAVX(reg_index);
- return generic_fpr;
+ if (fpr_type == eFPRTypeXSAVE)
+ return generic_fpr || IsAVX(reg_index);
+ return generic_fpr;
}
-Error
-NativeRegisterContextLinux_x86_64::WriteFPR()
-{
- const FPRType fpr_type = GetFPRType ();
- const lldb_private::ArchSpec& target_arch = GetRegisterInfoInterface().GetTargetArchitecture();
- switch (fpr_type)
- {
- case FPRType::eFPRTypeFXSAVE:
- // For 32-bit inferiors on x86_32/x86_64 architectures,
- // FXSAVE area can be written using PTRACE_SETREGSET ptrace api
- // For 64-bit inferiors on x86_64 architectures,
- // FXSAVE area can be written using PTRACE_SETFPREGS ptrace api
- switch (target_arch.GetMachine ())
- {
- case llvm::Triple::x86:
- return WriteRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave), NT_PRXFPREG);
- case llvm::Triple::x86_64:
- return NativeRegisterContextLinux::WriteFPR();
- default:
- assert(false && "Unhandled target architecture.");
- break;
- }
- case FPRType::eFPRTypeXSAVE:
- return WriteRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE);
+Error NativeRegisterContextLinux_x86_64::WriteFPR() {
+ const FPRType fpr_type = GetFPRType();
+ const lldb_private::ArchSpec &target_arch =
+ GetRegisterInfoInterface().GetTargetArchitecture();
+ switch (fpr_type) {
+ case FPRType::eFPRTypeFXSAVE:
+ // For 32-bit inferiors on x86_32/x86_64 architectures,
+ // FXSAVE area can be written using PTRACE_SETREGSET ptrace api
+ // For 64-bit inferiors on x86_64 architectures,
+ // FXSAVE area can be written using PTRACE_SETFPREGS ptrace api
+ switch (target_arch.GetMachine()) {
+ case llvm::Triple::x86:
+ return WriteRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave),
+ NT_PRXFPREG);
+ case llvm::Triple::x86_64:
+ return NativeRegisterContextLinux::WriteFPR();
default:
- return Error("Unrecognized FPR type");
+ assert(false && "Unhandled target architecture.");
+ break;
}
+ case FPRType::eFPRTypeXSAVE:
+ return WriteRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave),
+ NT_X86_XSTATE);
+ default:
+ return Error("Unrecognized FPR type");
+ }
}
-bool
-NativeRegisterContextLinux_x86_64::IsAVX(uint32_t reg_index) const
-{
- return (m_reg_info.first_ymm <= reg_index && reg_index <= m_reg_info.last_ymm);
+bool NativeRegisterContextLinux_x86_64::IsAVX(uint32_t reg_index) const {
+ return (m_reg_info.first_ymm <= reg_index &&
+ reg_index <= m_reg_info.last_ymm);
}
-bool
-NativeRegisterContextLinux_x86_64::CopyXSTATEtoYMM (uint32_t reg_index, lldb::ByteOrder byte_order)
-{
- if (!IsAVX (reg_index))
- return false;
-
- if (byte_order == lldb::eByteOrderLittle)
- {
- ::memcpy (m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes,
- m_fpr.xstate.fxsave.xmm[reg_index - m_reg_info.first_ymm].bytes,
- sizeof (XMMReg));
- ::memcpy (m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes + sizeof (XMMReg),
- m_fpr.xstate.xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes,
- sizeof (YMMHReg));
- return true;
- }
-
- if (byte_order == lldb::eByteOrderBig)
- {
- ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes + sizeof (XMMReg),
- m_fpr.xstate.fxsave.xmm[reg_index - m_reg_info.first_ymm].bytes,
- sizeof (XMMReg));
- ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes,
- m_fpr.xstate.xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes,
- sizeof (YMMHReg));
- return true;
- }
- return false; // unsupported or invalid byte order
-
+bool NativeRegisterContextLinux_x86_64::CopyXSTATEtoYMM(
+ uint32_t reg_index, lldb::ByteOrder byte_order) {
+ if (!IsAVX(reg_index))
+ return false;
+
+ if (byte_order == lldb::eByteOrderLittle) {
+ ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes,
+ m_fpr.xstate.fxsave.xmm[reg_index - m_reg_info.first_ymm].bytes,
+ sizeof(XMMReg));
+ ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes +
+ sizeof(XMMReg),
+ m_fpr.xstate.xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes,
+ sizeof(YMMHReg));
+ return true;
+ }
+
+ if (byte_order == lldb::eByteOrderBig) {
+ ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes +
+ sizeof(XMMReg),
+ m_fpr.xstate.fxsave.xmm[reg_index - m_reg_info.first_ymm].bytes,
+ sizeof(XMMReg));
+ ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes,
+ m_fpr.xstate.xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes,
+ sizeof(YMMHReg));
+ return true;
+ }
+ return false; // unsupported or invalid byte order
}
-bool
-NativeRegisterContextLinux_x86_64::CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order)
-{
- if (!IsAVX(reg))
- return false;
-
- if (byte_order == lldb::eByteOrderLittle)
- {
- ::memcpy(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes,
- m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes,
- sizeof(XMMReg));
- ::memcpy(m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes,
- m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg),
- sizeof(YMMHReg));
- return true;
- }
-
- if (byte_order == lldb::eByteOrderBig)
- {
- ::memcpy(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes,
- m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg),
- sizeof(XMMReg));
- ::memcpy(m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes,
- m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes,
- sizeof(YMMHReg));
- return true;
- }
- return false; // unsupported or invalid byte order
+bool NativeRegisterContextLinux_x86_64::CopyYMMtoXSTATE(
+ uint32_t reg, lldb::ByteOrder byte_order) {
+ if (!IsAVX(reg))
+ return false;
+
+ if (byte_order == lldb::eByteOrderLittle) {
+ ::memcpy(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes,
+ m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, sizeof(XMMReg));
+ ::memcpy(m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes,
+ m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg),
+ sizeof(YMMHReg));
+ return true;
+ }
+
+ if (byte_order == lldb::eByteOrderBig) {
+ ::memcpy(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes,
+ m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg),
+ sizeof(XMMReg));
+ ::memcpy(m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes,
+ m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, sizeof(YMMHReg));
+ return true;
+ }
+ return false; // unsupported or invalid byte order
}
-void*
-NativeRegisterContextLinux_x86_64::GetFPRBuffer()
-{
- const FPRType fpr_type = GetFPRType ();
- switch (fpr_type)
- {
- case FPRType::eFPRTypeFXSAVE:
- return &m_fpr.xstate.fxsave;
- case FPRType::eFPRTypeXSAVE:
- return &m_iovec;
- default:
- return nullptr;
- }
+void *NativeRegisterContextLinux_x86_64::GetFPRBuffer() {
+ const FPRType fpr_type = GetFPRType();
+ switch (fpr_type) {
+ case FPRType::eFPRTypeFXSAVE:
+ return &m_fpr.xstate.fxsave;
+ case FPRType::eFPRTypeXSAVE:
+ return &m_iovec;
+ default:
+ return nullptr;
+ }
}
-size_t
-NativeRegisterContextLinux_x86_64::GetFPRSize()
-{
- const FPRType fpr_type = GetFPRType ();
- switch (fpr_type)
- {
- case FPRType::eFPRTypeFXSAVE:
- return sizeof(m_fpr.xstate.fxsave);
- case FPRType::eFPRTypeXSAVE:
- return sizeof(m_iovec);
- default:
- return 0;
- }
+size_t NativeRegisterContextLinux_x86_64::GetFPRSize() {
+ const FPRType fpr_type = GetFPRType();
+ switch (fpr_type) {
+ case FPRType::eFPRTypeFXSAVE:
+ return sizeof(m_fpr.xstate.fxsave);
+ case FPRType::eFPRTypeXSAVE:
+ return sizeof(m_iovec);
+ default:
+ return 0;
+ }
}
-Error
-NativeRegisterContextLinux_x86_64::ReadFPR ()
-{
- const FPRType fpr_type = GetFPRType ();
- const lldb_private::ArchSpec& target_arch = GetRegisterInfoInterface().GetTargetArchitecture();
- switch (fpr_type)
- {
- case FPRType::eFPRTypeFXSAVE:
- // For 32-bit inferiors on x86_32/x86_64 architectures,
- // FXSAVE area can be read using PTRACE_GETREGSET ptrace api
- // For 64-bit inferiors on x86_64 architectures,
- // FXSAVE area can be read using PTRACE_GETFPREGS ptrace api
- switch (target_arch.GetMachine ())
- {
- case llvm::Triple::x86:
- return ReadRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave), NT_PRXFPREG);
- case llvm::Triple::x86_64:
- return NativeRegisterContextLinux::ReadFPR();
- default:
- assert(false && "Unhandled target architecture.");
- break;
- }
- case FPRType::eFPRTypeXSAVE:
- return ReadRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE);
+Error NativeRegisterContextLinux_x86_64::ReadFPR() {
+ const FPRType fpr_type = GetFPRType();
+ const lldb_private::ArchSpec &target_arch =
+ GetRegisterInfoInterface().GetTargetArchitecture();
+ switch (fpr_type) {
+ case FPRType::eFPRTypeFXSAVE:
+ // For 32-bit inferiors on x86_32/x86_64 architectures,
+ // FXSAVE area can be read using PTRACE_GETREGSET ptrace api
+ // For 64-bit inferiors on x86_64 architectures,
+ // FXSAVE area can be read using PTRACE_GETFPREGS ptrace api
+ switch (target_arch.GetMachine()) {
+ case llvm::Triple::x86:
+ return ReadRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave), NT_PRXFPREG);
+ case llvm::Triple::x86_64:
+ return NativeRegisterContextLinux::ReadFPR();
default:
- return Error("Unrecognized FPR type");
+ assert(false && "Unhandled target architecture.");
+ break;
}
+ case FPRType::eFPRTypeXSAVE:
+ return ReadRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE);
+ default:
+ return Error("Unrecognized FPR type");
+ }
}
-Error
-NativeRegisterContextLinux_x86_64::IsWatchpointHit(uint32_t wp_index, bool &is_hit)
-{
- if (wp_index >= NumSupportedHardwareWatchpoints())
- return Error("Watchpoint index out of range");
+Error NativeRegisterContextLinux_x86_64::IsWatchpointHit(uint32_t wp_index,
+ bool &is_hit) {
+ if (wp_index >= NumSupportedHardwareWatchpoints())
+ return Error("Watchpoint index out of range");
- RegisterValue reg_value;
- Error error = ReadRegisterRaw(m_reg_info.first_dr + 6, reg_value);
- if (error.Fail())
- {
- is_hit = false;
- return error;
- }
+ RegisterValue reg_value;
+ Error error = ReadRegisterRaw(m_reg_info.first_dr + 6, reg_value);
+ if (error.Fail()) {
+ is_hit = false;
+ return error;
+ }
- uint64_t status_bits = reg_value.GetAsUInt64();
+ uint64_t status_bits = reg_value.GetAsUInt64();
- is_hit = status_bits & (1 << wp_index);
+ is_hit = status_bits & (1 << wp_index);
- return error;
+ return error;
}
-Error
-NativeRegisterContextLinux_x86_64::GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) {
- uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
- for (wp_index = 0; wp_index < num_hw_wps; ++wp_index)
- {
- bool is_hit;
- Error error = IsWatchpointHit(wp_index, is_hit);
- if (error.Fail()) {
- wp_index = LLDB_INVALID_INDEX32;
- return error;
- } else if (is_hit) {
- return error;
- }
+Error NativeRegisterContextLinux_x86_64::GetWatchpointHitIndex(
+ uint32_t &wp_index, lldb::addr_t trap_addr) {
+ uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
+ for (wp_index = 0; wp_index < num_hw_wps; ++wp_index) {
+ bool is_hit;
+ Error error = IsWatchpointHit(wp_index, is_hit);
+ if (error.Fail()) {
+ wp_index = LLDB_INVALID_INDEX32;
+ return error;
+ } else if (is_hit) {
+ return error;
}
- wp_index = LLDB_INVALID_INDEX32;
- return Error();
+ }
+ wp_index = LLDB_INVALID_INDEX32;
+ return Error();
}
-Error
-NativeRegisterContextLinux_x86_64::IsWatchpointVacant(uint32_t wp_index, bool &is_vacant)
-{
- if (wp_index >= NumSupportedHardwareWatchpoints())
- return Error ("Watchpoint index out of range");
+Error NativeRegisterContextLinux_x86_64::IsWatchpointVacant(uint32_t wp_index,
+ bool &is_vacant) {
+ if (wp_index >= NumSupportedHardwareWatchpoints())
+ return Error("Watchpoint index out of range");
- RegisterValue reg_value;
- Error error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value);
- if (error.Fail())
- {
- is_vacant = false;
- return error;
- }
+ RegisterValue reg_value;
+ Error error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value);
+ if (error.Fail()) {
+ is_vacant = false;
+ return error;
+ }
- uint64_t control_bits = reg_value.GetAsUInt64();
+ uint64_t control_bits = reg_value.GetAsUInt64();
- is_vacant = !(control_bits & (1 << (2 * wp_index)));
+ is_vacant = !(control_bits & (1 << (2 * wp_index)));
- return error;
+ return error;
}
-Error
-NativeRegisterContextLinux_x86_64::SetHardwareWatchpointWithIndex(
- lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) {
+Error NativeRegisterContextLinux_x86_64::SetHardwareWatchpointWithIndex(
+ lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) {
- if (wp_index >= NumSupportedHardwareWatchpoints())
- return Error ("Watchpoint index out of range");
+ if (wp_index >= NumSupportedHardwareWatchpoints())
+ return Error("Watchpoint index out of range");
- // Read only watchpoints aren't supported on x86_64. Fall back to read/write waitchpoints instead.
- // TODO: Add logic to detect when a write happens and ignore that watchpoint hit.
- if (watch_flags == 0x2)
- watch_flags = 0x3;
+ // Read only watchpoints aren't supported on x86_64. Fall back to read/write
+ // waitchpoints instead.
+ // TODO: Add logic to detect when a write happens and ignore that watchpoint
+ // hit.
+ if (watch_flags == 0x2)
+ watch_flags = 0x3;
- if (watch_flags != 0x1 && watch_flags != 0x3)
- return Error ("Invalid read/write bits for watchpoint");
+ if (watch_flags != 0x1 && watch_flags != 0x3)
+ return Error("Invalid read/write bits for watchpoint");
- if (size != 1 && size != 2 && size != 4 && size != 8)
- return Error ("Invalid size for watchpoint");
+ if (size != 1 && size != 2 && size != 4 && size != 8)
+ return Error("Invalid size for watchpoint");
- bool is_vacant;
- Error error = IsWatchpointVacant (wp_index, is_vacant);
- if (error.Fail()) return error;
- if (!is_vacant) return Error("Watchpoint index not vacant");
-
- RegisterValue reg_value;
- error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value);
- if (error.Fail()) return error;
+ bool is_vacant;
+ Error error = IsWatchpointVacant(wp_index, is_vacant);
+ if (error.Fail())
+ return error;
+ if (!is_vacant)
+ return Error("Watchpoint index not vacant");
- // for watchpoints 0, 1, 2, or 3, respectively,
- // set bits 1, 3, 5, or 7
- uint64_t enable_bit = 1 << (2 * wp_index);
+ RegisterValue reg_value;
+ error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value);
+ if (error.Fail())
+ return error;
- // set bits 16-17, 20-21, 24-25, or 28-29
- // with 0b01 for write, and 0b11 for read/write
- uint64_t rw_bits = watch_flags << (16 + 4 * wp_index);
+ // for watchpoints 0, 1, 2, or 3, respectively,
+ // set bits 1, 3, 5, or 7
+ uint64_t enable_bit = 1 << (2 * wp_index);
- // set bits 18-19, 22-23, 26-27, or 30-31
- // with 0b00, 0b01, 0b10, or 0b11
- // for 1, 2, 8 (if supported), or 4 bytes, respectively
- uint64_t size_bits = (size == 8 ? 0x2 : size - 1) << (18 + 4 * wp_index);
+ // set bits 16-17, 20-21, 24-25, or 28-29
+ // with 0b01 for write, and 0b11 for read/write
+ uint64_t rw_bits = watch_flags << (16 + 4 * wp_index);
- uint64_t bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
+ // set bits 18-19, 22-23, 26-27, or 30-31
+ // with 0b00, 0b01, 0b10, or 0b11
+ // for 1, 2, 8 (if supported), or 4 bytes, respectively
+ uint64_t size_bits = (size == 8 ? 0x2 : size - 1) << (18 + 4 * wp_index);
- uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
+ uint64_t bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
- control_bits |= enable_bit | rw_bits | size_bits;
+ uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
- error = WriteRegisterRaw(m_reg_info.first_dr + wp_index, RegisterValue(addr));
- if (error.Fail()) return error;
+ control_bits |= enable_bit | rw_bits | size_bits;
- error = WriteRegisterRaw(m_reg_info.first_dr + 7, RegisterValue(control_bits));
- if (error.Fail()) return error;
+ error = WriteRegisterRaw(m_reg_info.first_dr + wp_index, RegisterValue(addr));
+ if (error.Fail())
+ return error;
- error.Clear();
+ error =
+ WriteRegisterRaw(m_reg_info.first_dr + 7, RegisterValue(control_bits));
+ if (error.Fail())
return error;
+
+ error.Clear();
+ return error;
}
-bool
-NativeRegisterContextLinux_x86_64::ClearHardwareWatchpoint(uint32_t wp_index)
-{
- if (wp_index >= NumSupportedHardwareWatchpoints())
- return false;
-
- RegisterValue reg_value;
-
- // for watchpoints 0, 1, 2, or 3, respectively,
- // clear bits 0, 1, 2, or 3 of the debug status register (DR6)
- Error error = ReadRegisterRaw(m_reg_info.first_dr + 6, reg_value);
- if (error.Fail()) return false;
- uint64_t bit_mask = 1 << wp_index;
- uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask;
- error = WriteRegisterRaw(m_reg_info.first_dr + 6, RegisterValue(status_bits));
- if (error.Fail()) return false;
-
- // for watchpoints 0, 1, 2, or 3, respectively,
- // clear bits {0-1,16-19}, {2-3,20-23}, {4-5,24-27}, or {6-7,28-31}
- // of the debug control register (DR7)
- error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value);
- if (error.Fail()) return false;
- bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
- uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
- return WriteRegisterRaw(m_reg_info.first_dr + 7, RegisterValue(control_bits)).Success();
+bool NativeRegisterContextLinux_x86_64::ClearHardwareWatchpoint(
+ uint32_t wp_index) {
+ if (wp_index >= NumSupportedHardwareWatchpoints())
+ return false;
+
+ RegisterValue reg_value;
+
+ // for watchpoints 0, 1, 2, or 3, respectively,
+ // clear bits 0, 1, 2, or 3 of the debug status register (DR6)
+ Error error = ReadRegisterRaw(m_reg_info.first_dr + 6, reg_value);
+ if (error.Fail())
+ return false;
+ uint64_t bit_mask = 1 << wp_index;
+ uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask;
+ error = WriteRegisterRaw(m_reg_info.first_dr + 6, RegisterValue(status_bits));
+ if (error.Fail())
+ return false;
+
+ // for watchpoints 0, 1, 2, or 3, respectively,
+ // clear bits {0-1,16-19}, {2-3,20-23}, {4-5,24-27}, or {6-7,28-31}
+ // of the debug control register (DR7)
+ error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value);
+ if (error.Fail())
+ return false;
+ bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
+ uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
+ return WriteRegisterRaw(m_reg_info.first_dr + 7, RegisterValue(control_bits))
+ .Success();
}
-Error
-NativeRegisterContextLinux_x86_64::ClearAllHardwareWatchpoints()
-{
- RegisterValue reg_value;
-
- // clear bits {0-4} of the debug status register (DR6)
- Error error = ReadRegisterRaw(m_reg_info.first_dr + 6, reg_value);
- if (error.Fail()) return error;
- uint64_t bit_mask = 0xF;
- uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask;
- error = WriteRegisterRaw(m_reg_info.first_dr + 6, RegisterValue(status_bits));
- if (error.Fail()) return error;
-
- // clear bits {0-7,16-31} of the debug control register (DR7)
- error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value);
- if (error.Fail()) return error;
- bit_mask = 0xFF | (0xFFFF << 16);
- uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
- return WriteRegisterRaw(m_reg_info.first_dr + 7, RegisterValue(control_bits));
+Error NativeRegisterContextLinux_x86_64::ClearAllHardwareWatchpoints() {
+ RegisterValue reg_value;
+
+ // clear bits {0-4} of the debug status register (DR6)
+ Error error = ReadRegisterRaw(m_reg_info.first_dr + 6, reg_value);
+ if (error.Fail())
+ return error;
+ uint64_t bit_mask = 0xF;
+ uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask;
+ error = WriteRegisterRaw(m_reg_info.first_dr + 6, RegisterValue(status_bits));
+ if (error.Fail())
+ return error;
+
+ // clear bits {0-7,16-31} of the debug control register (DR7)
+ error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value);
+ if (error.Fail())
+ return error;
+ bit_mask = 0xFF | (0xFFFF << 16);
+ uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
+ return WriteRegisterRaw(m_reg_info.first_dr + 7, RegisterValue(control_bits));
}
-uint32_t
-NativeRegisterContextLinux_x86_64::SetHardwareWatchpoint(
- lldb::addr_t addr, size_t size, uint32_t watch_flags)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
- const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
- for (uint32_t wp_index = 0; wp_index < num_hw_watchpoints; ++wp_index)
- {
- bool is_vacant;
- Error error = IsWatchpointVacant(wp_index, is_vacant);
- if (is_vacant)
- {
- error = SetHardwareWatchpointWithIndex(addr, size, watch_flags, wp_index);
- if (error.Success())
- return wp_index;
- }
- if (error.Fail() && log)
- {
- log->Printf("NativeRegisterContextLinux_x86_64::%s Error: %s",
- __FUNCTION__, error.AsCString());
- }
+uint32_t NativeRegisterContextLinux_x86_64::SetHardwareWatchpoint(
+ lldb::addr_t addr, size_t size, uint32_t watch_flags) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+ const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
+ for (uint32_t wp_index = 0; wp_index < num_hw_watchpoints; ++wp_index) {
+ bool is_vacant;
+ Error error = IsWatchpointVacant(wp_index, is_vacant);
+ if (is_vacant) {
+ error = SetHardwareWatchpointWithIndex(addr, size, watch_flags, wp_index);
+ if (error.Success())
+ return wp_index;
+ }
+ if (error.Fail() && log) {
+ log->Printf("NativeRegisterContextLinux_x86_64::%s Error: %s",
+ __FUNCTION__, error.AsCString());
}
- return LLDB_INVALID_INDEX32;
+ }
+ return LLDB_INVALID_INDEX32;
}
lldb::addr_t
-NativeRegisterContextLinux_x86_64::GetWatchpointAddress(uint32_t wp_index)
-{
- if (wp_index >= NumSupportedHardwareWatchpoints())
- return LLDB_INVALID_ADDRESS;
- RegisterValue reg_value;
- if (ReadRegisterRaw(m_reg_info.first_dr + wp_index, reg_value).Fail())
- return LLDB_INVALID_ADDRESS;
- return reg_value.GetAsUInt64();
+NativeRegisterContextLinux_x86_64::GetWatchpointAddress(uint32_t wp_index) {
+ if (wp_index >= NumSupportedHardwareWatchpoints())
+ return LLDB_INVALID_ADDRESS;
+ RegisterValue reg_value;
+ if (ReadRegisterRaw(m_reg_info.first_dr + wp_index, reg_value).Fail())
+ return LLDB_INVALID_ADDRESS;
+ return reg_value.GetAsUInt64();
}
-uint32_t
-NativeRegisterContextLinux_x86_64::NumSupportedHardwareWatchpoints ()
-{
- // Available debug address registers: dr0, dr1, dr2, dr3
- return 4;
+uint32_t NativeRegisterContextLinux_x86_64::NumSupportedHardwareWatchpoints() {
+ // Available debug address registers: dr0, dr1, dr2, dr3
+ return 4;
}
#endif // defined(__i386__) || defined(__x86_64__)
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h
index b04be4b..2378c77 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h
@@ -19,149 +19,116 @@
namespace lldb_private {
namespace process_linux {
- class NativeProcessLinux;
+class NativeProcessLinux;
- class NativeRegisterContextLinux_x86_64 : public NativeRegisterContextLinux
- {
- public:
- NativeRegisterContextLinux_x86_64 (const ArchSpec& target_arch,
- NativeThreadProtocol &native_thread,
- uint32_t concrete_frame_idx);
+class NativeRegisterContextLinux_x86_64 : public NativeRegisterContextLinux {
+public:
+ NativeRegisterContextLinux_x86_64(const ArchSpec &target_arch,
+ NativeThreadProtocol &native_thread,
+ uint32_t concrete_frame_idx);
- uint32_t
- GetRegisterSetCount () const override;
+ uint32_t GetRegisterSetCount() const override;
- const RegisterSet *
- GetRegisterSet (uint32_t set_index) const override;
+ const RegisterSet *GetRegisterSet(uint32_t set_index) const override;
- uint32_t
- GetUserRegisterCount() const override;
+ uint32_t GetUserRegisterCount() const override;
- Error
- ReadRegister (const RegisterInfo *reg_info, RegisterValue &reg_value) override;
+ Error ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue &reg_value) override;
- Error
- WriteRegister (const RegisterInfo *reg_info, const RegisterValue &reg_value) override;
+ Error WriteRegister(const RegisterInfo *reg_info,
+ const RegisterValue &reg_value) override;
- Error
- ReadAllRegisterValues (lldb::DataBufferSP &data_sp) override;
+ Error ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
- Error
- WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) override;
+ Error WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
- Error
- IsWatchpointHit(uint32_t wp_index, bool &is_hit) override;
+ Error IsWatchpointHit(uint32_t wp_index, bool &is_hit) override;
- Error
- GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) override;
+ Error GetWatchpointHitIndex(uint32_t &wp_index,
+ lldb::addr_t trap_addr) override;
- Error
- IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) override;
+ Error IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) override;
- bool
- ClearHardwareWatchpoint(uint32_t wp_index) override;
+ bool ClearHardwareWatchpoint(uint32_t wp_index) override;
- Error
- ClearAllHardwareWatchpoints () override;
+ Error ClearAllHardwareWatchpoints() override;
- Error
- SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size,
- uint32_t watch_flags, uint32_t wp_index);
+ Error SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size,
+ uint32_t watch_flags, uint32_t wp_index);
- uint32_t
- SetHardwareWatchpoint(lldb::addr_t addr, size_t size,
- uint32_t watch_flags) override;
+ uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size,
+ uint32_t watch_flags) override;
- lldb::addr_t
- GetWatchpointAddress(uint32_t wp_index) override;
+ lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override;
- uint32_t
- NumSupportedHardwareWatchpoints() override;
+ uint32_t NumSupportedHardwareWatchpoints() override;
- protected:
- void*
- GetGPRBuffer() override { return &m_gpr_x86_64; }
+protected:
+ void *GetGPRBuffer() override { return &m_gpr_x86_64; }
- void*
- GetFPRBuffer() override;
+ void *GetFPRBuffer() override;
- size_t
- GetFPRSize() override;
+ size_t GetFPRSize() override;
- Error
- ReadFPR() override;
+ Error ReadFPR() override;
- Error
- WriteFPR() override;
+ Error WriteFPR() override;
- private:
+private:
+ // Private member types.
+ enum FPRType { eFPRTypeNotValid = 0, eFPRTypeFXSAVE, eFPRTypeXSAVE };
- // Private member types.
- enum FPRType
- {
- eFPRTypeNotValid = 0,
- eFPRTypeFXSAVE,
- eFPRTypeXSAVE
- };
+ // Info about register ranges.
+ struct RegInfo {
+ uint32_t num_registers;
+ uint32_t num_gpr_registers;
+ uint32_t num_fpr_registers;
+ uint32_t num_avx_registers;
- // Info about register ranges.
- struct RegInfo
- {
- uint32_t num_registers;
- uint32_t num_gpr_registers;
- uint32_t num_fpr_registers;
- uint32_t num_avx_registers;
+ uint32_t last_gpr;
+ uint32_t first_fpr;
+ uint32_t last_fpr;
- uint32_t last_gpr;
- uint32_t first_fpr;
- uint32_t last_fpr;
+ uint32_t first_st;
+ uint32_t last_st;
+ uint32_t first_mm;
+ uint32_t last_mm;
+ uint32_t first_xmm;
+ uint32_t last_xmm;
+ uint32_t first_ymm;
+ uint32_t last_ymm;
- uint32_t first_st;
- uint32_t last_st;
- uint32_t first_mm;
- uint32_t last_mm;
- uint32_t first_xmm;
- uint32_t last_xmm;
- uint32_t first_ymm;
- uint32_t last_ymm;
+ uint32_t first_dr;
+ uint32_t gpr_flags;
+ };
- uint32_t first_dr;
- uint32_t gpr_flags;
- };
+ // Private member variables.
+ mutable FPRType m_fpr_type;
+ FPR m_fpr;
+ IOVEC m_iovec;
+ YMM m_ymm_set;
+ RegInfo m_reg_info;
+ uint64_t m_gpr_x86_64[k_num_gpr_registers_x86_64];
+ uint32_t m_fctrl_offset_in_userarea;
- // Private member variables.
- mutable FPRType m_fpr_type;
- FPR m_fpr;
- IOVEC m_iovec;
- YMM m_ymm_set;
- RegInfo m_reg_info;
- uint64_t m_gpr_x86_64[k_num_gpr_registers_x86_64];
- uint32_t m_fctrl_offset_in_userarea;
+ // Private member methods.
+ bool IsRegisterSetAvailable(uint32_t set_index) const;
- // Private member methods.
- bool IsRegisterSetAvailable (uint32_t set_index) const;
+ bool IsGPR(uint32_t reg_index) const;
- bool
- IsGPR(uint32_t reg_index) const;
+ FPRType GetFPRType() const;
- FPRType
- GetFPRType () const;
+ bool IsFPR(uint32_t reg_index) const;
- bool
- IsFPR(uint32_t reg_index) const;
+ bool IsFPR(uint32_t reg_index, FPRType fpr_type) const;
- bool
- IsFPR(uint32_t reg_index, FPRType fpr_type) const;
+ bool CopyXSTATEtoYMM(uint32_t reg_index, lldb::ByteOrder byte_order);
- bool
- CopyXSTATEtoYMM (uint32_t reg_index, lldb::ByteOrder byte_order);
+ bool CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order);
- bool
- CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order);
-
- bool
- IsAVX (uint32_t reg_index) const;
- };
+ bool IsAVX(uint32_t reg_index) const;
+};
} // namespace process_linux
} // namespace lldb_private
diff --git a/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp
index 6509022..ebe80da 100644
--- a/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp
@@ -29,481 +29,454 @@
#include <sys/syscall.h>
// Try to define a macro to encapsulate the tgkill syscall
-#define tgkill(pid, tid, sig) \
- syscall(__NR_tgkill, static_cast< ::pid_t>(pid), static_cast< ::pid_t>(tid), sig)
+#define tgkill(pid, tid, sig) \
+ syscall(__NR_tgkill, static_cast<::pid_t>(pid), static_cast<::pid_t>(tid), \
+ sig)
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::process_linux;
-namespace
-{
- void LogThreadStopInfo (Log &log, const ThreadStopInfo &stop_info, const char *const header)
- {
- switch (stop_info.reason)
- {
- case eStopReasonNone:
- log.Printf ("%s: %s no stop reason", __FUNCTION__, header);
- return;
- case eStopReasonTrace:
- log.Printf ("%s: %s trace, stopping signal 0x%" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo);
- return;
- case eStopReasonBreakpoint:
- log.Printf ("%s: %s breakpoint, stopping signal 0x%" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo);
- return;
- case eStopReasonWatchpoint:
- log.Printf ("%s: %s watchpoint, stopping signal 0x%" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo);
- return;
- case eStopReasonSignal:
- log.Printf ("%s: %s signal 0x%02" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo);
- return;
- case eStopReasonException:
- log.Printf ("%s: %s exception type 0x%02" PRIx64, __FUNCTION__, header, stop_info.details.exception.type);
- return;
- case eStopReasonExec:
- log.Printf ("%s: %s exec, stopping signal 0x%" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo);
- return;
- case eStopReasonPlanComplete:
- log.Printf ("%s: %s plan complete", __FUNCTION__, header);
- return;
- case eStopReasonThreadExiting:
- log.Printf ("%s: %s thread exiting", __FUNCTION__, header);
- return;
- case eStopReasonInstrumentation:
- log.Printf ("%s: %s instrumentation", __FUNCTION__, header);
- return;
- default:
- log.Printf ("%s: %s invalid stop reason %" PRIu32, __FUNCTION__, header, static_cast<uint32_t> (stop_info.reason));
- }
- }
+namespace {
+void LogThreadStopInfo(Log &log, const ThreadStopInfo &stop_info,
+ const char *const header) {
+ switch (stop_info.reason) {
+ case eStopReasonNone:
+ log.Printf("%s: %s no stop reason", __FUNCTION__, header);
+ return;
+ case eStopReasonTrace:
+ log.Printf("%s: %s trace, stopping signal 0x%" PRIx32, __FUNCTION__, header,
+ stop_info.details.signal.signo);
+ return;
+ case eStopReasonBreakpoint:
+ log.Printf("%s: %s breakpoint, stopping signal 0x%" PRIx32, __FUNCTION__,
+ header, stop_info.details.signal.signo);
+ return;
+ case eStopReasonWatchpoint:
+ log.Printf("%s: %s watchpoint, stopping signal 0x%" PRIx32, __FUNCTION__,
+ header, stop_info.details.signal.signo);
+ return;
+ case eStopReasonSignal:
+ log.Printf("%s: %s signal 0x%02" PRIx32, __FUNCTION__, header,
+ stop_info.details.signal.signo);
+ return;
+ case eStopReasonException:
+ log.Printf("%s: %s exception type 0x%02" PRIx64, __FUNCTION__, header,
+ stop_info.details.exception.type);
+ return;
+ case eStopReasonExec:
+ log.Printf("%s: %s exec, stopping signal 0x%" PRIx32, __FUNCTION__, header,
+ stop_info.details.signal.signo);
+ return;
+ case eStopReasonPlanComplete:
+ log.Printf("%s: %s plan complete", __FUNCTION__, header);
+ return;
+ case eStopReasonThreadExiting:
+ log.Printf("%s: %s thread exiting", __FUNCTION__, header);
+ return;
+ case eStopReasonInstrumentation:
+ log.Printf("%s: %s instrumentation", __FUNCTION__, header);
+ return;
+ default:
+ log.Printf("%s: %s invalid stop reason %" PRIu32, __FUNCTION__, header,
+ static_cast<uint32_t>(stop_info.reason));
+ }
}
-
-NativeThreadLinux::NativeThreadLinux (NativeProcessLinux *process, lldb::tid_t tid) :
- NativeThreadProtocol (process, tid),
- m_state (StateType::eStateInvalid),
- 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();
+NativeThreadLinux::NativeThreadLinux(NativeProcessLinux *process,
+ lldb::tid_t tid)
+ : NativeThreadProtocol(process, tid), m_state(StateType::eStateInvalid),
+ 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();
}
-lldb::StateType
-NativeThreadLinux::GetState ()
-{
- return m_state;
-}
+lldb::StateType NativeThreadLinux::GetState() { return m_state; }
+
+bool NativeThreadLinux::GetStopReason(ThreadStopInfo &stop_info,
+ std::string &description) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
+
+ description.clear();
+
+ switch (m_state) {
+ case eStateStopped:
+ case eStateCrashed:
+ case eStateExited:
+ case eStateSuspended:
+ case eStateUnloaded:
+ if (log)
+ LogThreadStopInfo(*log, m_stop_info, "m_stop_info in thread:");
+ stop_info = m_stop_info;
+ description = m_stop_description;
+ if (log)
+ LogThreadStopInfo(*log, stop_info, "returned stop_info:");
+ return true;
-bool
-NativeThreadLinux::GetStopReason (ThreadStopInfo &stop_info, std::string& description)
-{
- Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
-
- description.clear();
-
- switch (m_state)
- {
- case eStateStopped:
- case eStateCrashed:
- case eStateExited:
- case eStateSuspended:
- case eStateUnloaded:
- if (log)
- LogThreadStopInfo (*log, m_stop_info, "m_stop_info in thread:");
- stop_info = m_stop_info;
- description = m_stop_description;
- if (log)
- LogThreadStopInfo (*log, stop_info, "returned stop_info:");
-
- return true;
-
- case eStateInvalid:
- case eStateConnected:
- case eStateAttaching:
- case eStateLaunching:
- case eStateRunning:
- case eStateStepping:
- case eStateDetached:
- if (log)
- {
- log->Printf ("NativeThreadLinux::%s tid %" PRIu64 " in state %s cannot answer stop reason",
- __FUNCTION__, GetID (), StateAsCString (m_state));
- }
- return false;
+ case eStateInvalid:
+ case eStateConnected:
+ case eStateAttaching:
+ case eStateLaunching:
+ case eStateRunning:
+ case eStateStepping:
+ case eStateDetached:
+ if (log) {
+ log->Printf("NativeThreadLinux::%s tid %" PRIu64
+ " in state %s cannot answer stop reason",
+ __FUNCTION__, GetID(), StateAsCString(m_state));
}
- llvm_unreachable("unhandled StateType!");
+ return false;
+ }
+ llvm_unreachable("unhandled StateType!");
}
-NativeRegisterContextSP
-NativeThreadLinux::GetRegisterContext ()
-{
- // Return the register context if we already created it.
- if (m_reg_context_sp)
- return m_reg_context_sp;
+NativeRegisterContextSP NativeThreadLinux::GetRegisterContext() {
+ // Return the register context if we already created it.
+ if (m_reg_context_sp)
+ return m_reg_context_sp;
- NativeProcessProtocolSP m_process_sp = m_process_wp.lock ();
- if (!m_process_sp)
- return NativeRegisterContextSP ();
+ NativeProcessProtocolSP m_process_sp = m_process_wp.lock();
+ if (!m_process_sp)
+ return NativeRegisterContextSP();
- ArchSpec target_arch;
- if (!m_process_sp->GetArchitecture (target_arch))
- return NativeRegisterContextSP ();
+ ArchSpec target_arch;
+ if (!m_process_sp->GetArchitecture(target_arch))
+ return NativeRegisterContextSP();
- const uint32_t concrete_frame_idx = 0;
- m_reg_context_sp.reset (NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(target_arch,
- *this,
- concrete_frame_idx));
+ const uint32_t concrete_frame_idx = 0;
+ m_reg_context_sp.reset(
+ NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
+ target_arch, *this, concrete_frame_idx));
- return m_reg_context_sp;
+ return m_reg_context_sp;
}
-Error
-NativeThreadLinux::SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware)
-{
- if (!hardware)
- return Error ("not implemented");
- if (m_state == eStateLaunching)
- return Error ();
- Error error = RemoveWatchpoint(addr);
- if (error.Fail()) return error;
- NativeRegisterContextSP reg_ctx = GetRegisterContext ();
- uint32_t wp_index =
- reg_ctx->SetHardwareWatchpoint (addr, size, watch_flags);
- if (wp_index == LLDB_INVALID_INDEX32)
- return Error ("Setting hardware watchpoint failed.");
- m_watchpoint_index_map.insert({addr, wp_index});
- return Error ();
+Error NativeThreadLinux::SetWatchpoint(lldb::addr_t addr, size_t size,
+ uint32_t watch_flags, bool hardware) {
+ if (!hardware)
+ return Error("not implemented");
+ if (m_state == eStateLaunching)
+ return Error();
+ Error error = RemoveWatchpoint(addr);
+ if (error.Fail())
+ return error;
+ NativeRegisterContextSP reg_ctx = GetRegisterContext();
+ uint32_t wp_index = reg_ctx->SetHardwareWatchpoint(addr, size, watch_flags);
+ if (wp_index == LLDB_INVALID_INDEX32)
+ return Error("Setting hardware watchpoint failed.");
+ m_watchpoint_index_map.insert({addr, wp_index});
+ return Error();
}
-Error
-NativeThreadLinux::RemoveWatchpoint (lldb::addr_t addr)
-{
- auto wp = m_watchpoint_index_map.find(addr);
- if (wp == m_watchpoint_index_map.end())
- return Error ();
- uint32_t wp_index = wp->second;
- m_watchpoint_index_map.erase(wp);
- if (GetRegisterContext()->ClearHardwareWatchpoint(wp_index))
- return Error ();
- return Error ("Clearing hardware watchpoint failed.");
+Error NativeThreadLinux::RemoveWatchpoint(lldb::addr_t addr) {
+ auto wp = m_watchpoint_index_map.find(addr);
+ if (wp == m_watchpoint_index_map.end())
+ return Error();
+ uint32_t wp_index = wp->second;
+ m_watchpoint_index_map.erase(wp);
+ if (GetRegisterContext()->ClearHardwareWatchpoint(wp_index))
+ return Error();
+ return Error("Clearing hardware watchpoint failed.");
}
-Error
-NativeThreadLinux::Resume(uint32_t signo)
-{
- const StateType new_state = StateType::eStateRunning;
- MaybeLogStateChange (new_state);
- m_state = new_state;
-
- m_stop_info.reason = StopReason::eStopReasonNone;
- m_stop_description.clear();
-
- // If watchpoints have been set, but none on this thread,
- // then this is a new thread. So set all existing watchpoints.
- if (m_watchpoint_index_map.empty())
- {
- NativeProcessLinux &process = GetProcess();
-
- const auto &watchpoint_map = process.GetWatchpointMap();
- GetRegisterContext()->ClearAllHardwareWatchpoints();
- for (const auto &pair : watchpoint_map)
- {
- const auto &wp = pair.second;
- SetWatchpoint(wp.m_addr, wp.m_size, wp.m_watch_flags, wp.m_hardware);
- }
- }
+Error NativeThreadLinux::Resume(uint32_t signo) {
+ const StateType new_state = StateType::eStateRunning;
+ MaybeLogStateChange(new_state);
+ m_state = new_state;
- intptr_t data = 0;
+ m_stop_info.reason = StopReason::eStopReasonNone;
+ m_stop_description.clear();
- if (signo != LLDB_INVALID_SIGNAL_NUMBER)
- data = signo;
+ // If watchpoints have been set, but none on this thread,
+ // then this is a new thread. So set all existing watchpoints.
+ if (m_watchpoint_index_map.empty()) {
+ NativeProcessLinux &process = GetProcess();
- return NativeProcessLinux::PtraceWrapper(PTRACE_CONT, GetID(), nullptr, reinterpret_cast<void *>(data));
-}
+ const auto &watchpoint_map = process.GetWatchpointMap();
+ GetRegisterContext()->ClearAllHardwareWatchpoints();
+ for (const auto &pair : watchpoint_map) {
+ const auto &wp = pair.second;
+ SetWatchpoint(wp.m_addr, wp.m_size, wp.m_watch_flags, wp.m_hardware);
+ }
+ }
-void
-NativeThreadLinux::MaybePrepareSingleStepWorkaround()
-{
- if (!SingleStepWorkaroundNeeded())
- return;
+ intptr_t data = 0;
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
+ if (signo != LLDB_INVALID_SIGNAL_NUMBER)
+ data = signo;
- 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;
- }
+ return NativeProcessLinux::PtraceWrapper(PTRACE_CONT, GetID(), nullptr,
+ reinterpret_cast<void *>(data));
+}
- 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::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());
- }
+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();
-
- intptr_t data = 0;
- if (signo != LLDB_INVALID_SIGNAL_NUMBER)
- data = signo;
-
- // If hardware single-stepping is not supported, we just do a continue. The breakpoint on the
- // next instruction has been setup in NativeProcessLinux::Resume.
- return NativeProcessLinux::PtraceWrapper(GetProcess().SupportHardwareSingleStepping() ? PTRACE_SINGLESTEP
- : PTRACE_CONT,
- m_tid, nullptr, reinterpret_cast<void *>(data));
+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();
+
+ intptr_t data = 0;
+ if (signo != LLDB_INVALID_SIGNAL_NUMBER)
+ data = signo;
+
+ // If hardware single-stepping is not supported, we just do a continue. The
+ // breakpoint on the
+ // next instruction has been setup in NativeProcessLinux::Resume.
+ return NativeProcessLinux::PtraceWrapper(
+ GetProcess().SupportHardwareSingleStepping() ? PTRACE_SINGLESTEP
+ : PTRACE_CONT,
+ m_tid, nullptr, reinterpret_cast<void *>(data));
}
-void
-NativeThreadLinux::SetStoppedBySignal(uint32_t signo, const siginfo_t *info)
-{
- Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
- if (log)
- log->Printf ("NativeThreadLinux::%s called with signal 0x%02" PRIx32, __FUNCTION__, signo);
-
- SetStopped();
-
- m_stop_info.reason = StopReason::eStopReasonSignal;
- m_stop_info.details.signal.signo = signo;
-
- m_stop_description.clear();
- if (info)
- {
- switch (signo)
- {
- case SIGSEGV:
- case SIGBUS:
- case SIGFPE:
- case SIGILL:
- //In case of MIPS64 target, SI_KERNEL is generated for invalid 64bit address.
- const auto reason = (info->si_signo == SIGBUS && info->si_code == SI_KERNEL) ?
- CrashReason::eInvalidAddress : GetCrashReason(*info);
- m_stop_description = GetCrashReasonString(reason, reinterpret_cast<uintptr_t>(info->si_addr));
- break;
- }
+void NativeThreadLinux::SetStoppedBySignal(uint32_t signo,
+ const siginfo_t *info) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
+ if (log)
+ log->Printf("NativeThreadLinux::%s called with signal 0x%02" PRIx32,
+ __FUNCTION__, signo);
+
+ SetStopped();
+
+ m_stop_info.reason = StopReason::eStopReasonSignal;
+ m_stop_info.details.signal.signo = signo;
+
+ m_stop_description.clear();
+ if (info) {
+ switch (signo) {
+ case SIGSEGV:
+ case SIGBUS:
+ case SIGFPE:
+ case SIGILL:
+ // In case of MIPS64 target, SI_KERNEL is generated for invalid 64bit
+ // address.
+ const auto reason =
+ (info->si_signo == SIGBUS && info->si_code == SI_KERNEL)
+ ? CrashReason::eInvalidAddress
+ : GetCrashReason(*info);
+ m_stop_description = GetCrashReasonString(
+ reason, reinterpret_cast<uintptr_t>(info->si_addr));
+ break;
}
+ }
}
-bool
-NativeThreadLinux::IsStopped (int *signo)
-{
- if (!StateIsStoppedState (m_state, false))
- return false;
-
- // If we are stopped by a signal, return the signo.
- if (signo &&
- m_state == StateType::eStateStopped &&
- m_stop_info.reason == StopReason::eStopReasonSignal)
- {
- *signo = m_stop_info.details.signal.signo;
- }
+bool NativeThreadLinux::IsStopped(int *signo) {
+ if (!StateIsStoppedState(m_state, false))
+ return false;
- // Regardless, we are stopped.
- return true;
+ // If we are stopped by a signal, return the signo.
+ if (signo && m_state == StateType::eStateStopped &&
+ m_stop_info.reason == StopReason::eStopReasonSignal) {
+ *signo = m_stop_info.details.signal.signo;
+ }
+
+ // Regardless, we are stopped.
+ return true;
}
-void
-NativeThreadLinux::SetStopped()
-{
- if (m_state == StateType::eStateStepping)
- MaybeCleanupSingleStepWorkaround();
+void NativeThreadLinux::SetStopped() {
+ if (m_state == StateType::eStateStepping)
+ MaybeCleanupSingleStepWorkaround();
- const StateType new_state = StateType::eStateStopped;
- MaybeLogStateChange(new_state);
- m_state = new_state;
- m_stop_description.clear();
+ const StateType new_state = StateType::eStateStopped;
+ MaybeLogStateChange(new_state);
+ m_state = new_state;
+ m_stop_description.clear();
}
-void
-NativeThreadLinux::SetStoppedByExec ()
-{
- Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
- if (log)
- log->Printf ("NativeThreadLinux::%s()", __FUNCTION__);
+void NativeThreadLinux::SetStoppedByExec() {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
+ if (log)
+ log->Printf("NativeThreadLinux::%s()", __FUNCTION__);
- SetStopped();
+ SetStopped();
- m_stop_info.reason = StopReason::eStopReasonExec;
- m_stop_info.details.signal.signo = SIGSTOP;
+ m_stop_info.reason = StopReason::eStopReasonExec;
+ m_stop_info.details.signal.signo = SIGSTOP;
}
-void
-NativeThreadLinux::SetStoppedByBreakpoint ()
-{
- SetStopped();
+void NativeThreadLinux::SetStoppedByBreakpoint() {
+ SetStopped();
- m_stop_info.reason = StopReason::eStopReasonBreakpoint;
- m_stop_info.details.signal.signo = SIGTRAP;
- m_stop_description.clear();
+ m_stop_info.reason = StopReason::eStopReasonBreakpoint;
+ m_stop_info.details.signal.signo = SIGTRAP;
+ m_stop_description.clear();
}
-void
-NativeThreadLinux::SetStoppedByWatchpoint (uint32_t wp_index)
-{
- SetStopped();
+void NativeThreadLinux::SetStoppedByWatchpoint(uint32_t wp_index) {
+ SetStopped();
- lldbassert(wp_index != LLDB_INVALID_INDEX32 &&
- "wp_index cannot be invalid");
+ lldbassert(wp_index != LLDB_INVALID_INDEX32 && "wp_index cannot be invalid");
- std::ostringstream ostr;
- ostr << GetRegisterContext()->GetWatchpointAddress(wp_index) << " ";
- ostr << wp_index;
+ std::ostringstream ostr;
+ ostr << GetRegisterContext()->GetWatchpointAddress(wp_index) << " ";
+ ostr << wp_index;
- /*
- * MIPS: Last 3bits of the watchpoint address are masked by the kernel. For example:
- * 'n' is at 0x120010d00 and 'm' is 0x120010d04. When a watchpoint is set at 'm', then
- * watch exception is generated even when 'n' is read/written. To handle this case,
- * find the base address of the load/store instruction and append it in the stop-info
- * packet.
- */
- ostr << " " << GetRegisterContext()->GetWatchpointHitAddress(wp_index);
+ /*
+ * MIPS: Last 3bits of the watchpoint address are masked by the kernel. For
+ * example:
+ * 'n' is at 0x120010d00 and 'm' is 0x120010d04. When a watchpoint is set at
+ * 'm', then
+ * watch exception is generated even when 'n' is read/written. To handle this
+ * case,
+ * find the base address of the load/store instruction and append it in the
+ * stop-info
+ * packet.
+ */
+ ostr << " " << GetRegisterContext()->GetWatchpointHitAddress(wp_index);
- m_stop_description = ostr.str();
+ m_stop_description = ostr.str();
- m_stop_info.reason = StopReason::eStopReasonWatchpoint;
- m_stop_info.details.signal.signo = SIGTRAP;
+ m_stop_info.reason = StopReason::eStopReasonWatchpoint;
+ m_stop_info.details.signal.signo = SIGTRAP;
}
-bool
-NativeThreadLinux::IsStoppedAtBreakpoint ()
-{
- return GetState () == StateType::eStateStopped &&
- m_stop_info.reason == StopReason::eStopReasonBreakpoint;
+bool NativeThreadLinux::IsStoppedAtBreakpoint() {
+ return GetState() == StateType::eStateStopped &&
+ m_stop_info.reason == StopReason::eStopReasonBreakpoint;
}
-bool
-NativeThreadLinux::IsStoppedAtWatchpoint ()
-{
- return GetState () == StateType::eStateStopped &&
- m_stop_info.reason == StopReason::eStopReasonWatchpoint;
+bool NativeThreadLinux::IsStoppedAtWatchpoint() {
+ return GetState() == StateType::eStateStopped &&
+ m_stop_info.reason == StopReason::eStopReasonWatchpoint;
}
-void
-NativeThreadLinux::SetStoppedByTrace ()
-{
- SetStopped();
+void NativeThreadLinux::SetStoppedByTrace() {
+ SetStopped();
- m_stop_info.reason = StopReason::eStopReasonTrace;
- m_stop_info.details.signal.signo = SIGTRAP;
+ m_stop_info.reason = StopReason::eStopReasonTrace;
+ m_stop_info.details.signal.signo = SIGTRAP;
}
-void
-NativeThreadLinux::SetStoppedWithNoReason ()
-{
- SetStopped();
+void NativeThreadLinux::SetStoppedWithNoReason() {
+ SetStopped();
- m_stop_info.reason = StopReason::eStopReasonNone;
- m_stop_info.details.signal.signo = 0;
+ m_stop_info.reason = StopReason::eStopReasonNone;
+ m_stop_info.details.signal.signo = 0;
}
-void
-NativeThreadLinux::SetExited ()
-{
- const StateType new_state = StateType::eStateExited;
- MaybeLogStateChange (new_state);
- m_state = new_state;
+void NativeThreadLinux::SetExited() {
+ const StateType new_state = StateType::eStateExited;
+ MaybeLogStateChange(new_state);
+ m_state = new_state;
- m_stop_info.reason = StopReason::eStopReasonThreadExiting;
+ m_stop_info.reason = StopReason::eStopReasonThreadExiting;
}
-Error
-NativeThreadLinux::RequestStop ()
-{
- Log* log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
+Error NativeThreadLinux::RequestStop() {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
- NativeProcessLinux &process = GetProcess();
+ NativeProcessLinux &process = GetProcess();
+
+ lldb::pid_t pid = process.GetID();
+ lldb::tid_t tid = GetID();
- lldb::pid_t pid = process.GetID();
- lldb::tid_t tid = GetID();
+ if (log)
+ log->Printf("NativeThreadLinux::%s requesting thread stop(pid: %" PRIu64
+ ", tid: %" PRIu64 ")",
+ __FUNCTION__, pid, tid);
+ Error err;
+ errno = 0;
+ if (::tgkill(pid, tid, SIGSTOP) != 0) {
+ err.SetErrorToErrno();
if (log)
- log->Printf ("NativeThreadLinux::%s requesting thread stop(pid: %" PRIu64 ", tid: %" PRIu64 ")", __FUNCTION__, pid, tid);
-
- Error err;
- errno = 0;
- if (::tgkill (pid, tid, SIGSTOP) != 0)
- {
- err.SetErrorToErrno ();
- if (log)
- log->Printf ("NativeThreadLinux::%s tgkill(%" PRIu64 ", %" PRIu64 ", SIGSTOP) failed: %s", __FUNCTION__, pid, tid, err.AsCString ());
- }
+ log->Printf("NativeThreadLinux::%s tgkill(%" PRIu64 ", %" PRIu64
+ ", SIGSTOP) failed: %s",
+ __FUNCTION__, pid, tid, err.AsCString());
+ }
- return err;
+ return err;
}
-void
-NativeThreadLinux::MaybeLogStateChange (lldb::StateType new_state)
-{
- Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
- // If we're not logging, we're done.
- if (!log)
- return;
-
- // If this is a state change to the same state, we're done.
- lldb::StateType old_state = m_state;
- if (new_state == old_state)
- return;
-
- NativeProcessProtocolSP m_process_sp = m_process_wp.lock ();
- lldb::pid_t pid = m_process_sp ? m_process_sp->GetID () : LLDB_INVALID_PROCESS_ID;
-
- // Log it.
- log->Printf ("NativeThreadLinux: thread (pid=%" PRIu64 ", tid=%" PRIu64 ") changing from state %s to %s", pid, GetID (), StateAsCString (old_state), StateAsCString (new_state));
+void NativeThreadLinux::MaybeLogStateChange(lldb::StateType new_state) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
+ // If we're not logging, we're done.
+ if (!log)
+ return;
+
+ // If this is a state change to the same state, we're done.
+ lldb::StateType old_state = m_state;
+ if (new_state == old_state)
+ return;
+
+ NativeProcessProtocolSP m_process_sp = m_process_wp.lock();
+ lldb::pid_t pid =
+ m_process_sp ? m_process_sp->GetID() : LLDB_INVALID_PROCESS_ID;
+
+ // Log it.
+ log->Printf("NativeThreadLinux: thread (pid=%" PRIu64 ", tid=%" PRIu64
+ ") changing from state %s to %s",
+ pid, GetID(), StateAsCString(old_state),
+ StateAsCString(new_state));
}
-NativeProcessLinux &
-NativeThreadLinux::GetProcess()
-{
- auto process_sp = std::static_pointer_cast<NativeProcessLinux>(NativeThreadProtocol::GetProcess());
- assert(process_sp);
- return *process_sp;
+NativeProcessLinux &NativeThreadLinux::GetProcess() {
+ auto process_sp = std::static_pointer_cast<NativeProcessLinux>(
+ NativeThreadProtocol::GetProcess());
+ assert(process_sp);
+ return *process_sp;
}
diff --git a/lldb/source/Plugins/Process/Linux/NativeThreadLinux.h b/lldb/source/Plugins/Process/Linux/NativeThreadLinux.h
index f1b6a6e..f170bb1 100644
--- a/lldb/source/Plugins/Process/Linux/NativeThreadLinux.h
+++ b/lldb/source/Plugins/Process/Linux/NativeThreadLinux.h
@@ -10,8 +10,8 @@
#ifndef liblldb_NativeThreadLinux_H_
#define liblldb_NativeThreadLinux_H_
-#include "lldb/lldb-private-forward.h"
#include "lldb/Host/common/NativeThreadProtocol.h"
+#include "lldb/lldb-private-forward.h"
#include <sched.h>
@@ -22,118 +22,95 @@
namespace lldb_private {
namespace process_linux {
- class NativeProcessLinux;
+class NativeProcessLinux;
- class NativeThreadLinux : public NativeThreadProtocol
- {
- friend class NativeProcessLinux;
+class NativeThreadLinux : public NativeThreadProtocol {
+ friend class NativeProcessLinux;
- public:
- NativeThreadLinux (NativeProcessLinux *process, lldb::tid_t tid);
+public:
+ NativeThreadLinux(NativeProcessLinux *process, lldb::tid_t tid);
- // ---------------------------------------------------------------------
- // NativeThreadProtocol Interface
- // ---------------------------------------------------------------------
- std::string
- GetName() override;
+ // ---------------------------------------------------------------------
+ // NativeThreadProtocol Interface
+ // ---------------------------------------------------------------------
+ std::string GetName() override;
- lldb::StateType
- GetState () override;
+ lldb::StateType GetState() override;
- bool
- GetStopReason (ThreadStopInfo &stop_info, std::string& description) override;
+ bool GetStopReason(ThreadStopInfo &stop_info,
+ std::string &description) override;
- NativeRegisterContextSP
- GetRegisterContext () override;
+ NativeRegisterContextSP GetRegisterContext() override;
- Error
- SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware) override;
+ Error SetWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags,
+ bool hardware) override;
- Error
- RemoveWatchpoint (lldb::addr_t addr) override;
+ Error RemoveWatchpoint(lldb::addr_t addr) override;
- private:
- // ---------------------------------------------------------------------
- // Interface for friend classes
- // ---------------------------------------------------------------------
+private:
+ // ---------------------------------------------------------------------
+ // Interface for friend classes
+ // ---------------------------------------------------------------------
- /// Resumes the thread. If @p signo is anything but
- /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread.
- Error
- Resume(uint32_t signo);
+ /// Resumes the thread. If @p signo is anything but
+ /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread.
+ Error Resume(uint32_t signo);
- /// Single steps the thread. If @p signo is anything but
- /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread.
- Error
- SingleStep(uint32_t signo);
+ /// Single steps the thread. If @p signo is anything but
+ /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread.
+ Error SingleStep(uint32_t signo);
- void
- SetStoppedBySignal(uint32_t signo, const siginfo_t *info = nullptr);
+ void SetStoppedBySignal(uint32_t signo, const siginfo_t *info = nullptr);
- /// Return true if the thread is stopped.
- /// If stopped by a signal, indicate the signo in the signo argument.
- /// Otherwise, return LLDB_INVALID_SIGNAL_NUMBER.
- bool
- IsStopped (int *signo);
+ /// Return true if the thread is stopped.
+ /// If stopped by a signal, indicate the signo in the signo argument.
+ /// Otherwise, return LLDB_INVALID_SIGNAL_NUMBER.
+ bool IsStopped(int *signo);
- void
- SetStoppedByExec ();
+ void SetStoppedByExec();
- void
- SetStoppedByBreakpoint ();
+ void SetStoppedByBreakpoint();
- void
- SetStoppedByWatchpoint (uint32_t wp_index);
+ void SetStoppedByWatchpoint(uint32_t wp_index);
- bool
- IsStoppedAtBreakpoint ();
+ bool IsStoppedAtBreakpoint();
- bool
- IsStoppedAtWatchpoint ();
+ bool IsStoppedAtWatchpoint();
- void
- SetStoppedByTrace ();
+ void SetStoppedByTrace();
- void
- SetStoppedWithNoReason ();
+ void SetStoppedWithNoReason();
- void
- SetExited ();
+ void SetExited();
- Error
- RequestStop ();
+ Error RequestStop();
- // ---------------------------------------------------------------------
- // Private interface
- // ---------------------------------------------------------------------
- void
- MaybeLogStateChange (lldb::StateType new_state);
+ // ---------------------------------------------------------------------
+ // Private interface
+ // ---------------------------------------------------------------------
+ void MaybeLogStateChange(lldb::StateType new_state);
- NativeProcessLinux &
- GetProcess();
+ NativeProcessLinux &GetProcess();
- void
- SetStopped();
+ void SetStopped();
- inline void
- MaybePrepareSingleStepWorkaround();
+ inline void MaybePrepareSingleStepWorkaround();
- inline void
- MaybeCleanupSingleStepWorkaround();
+ inline void MaybeCleanupSingleStepWorkaround();
- // ---------------------------------------------------------------------
- // Member Variables
- // ---------------------------------------------------------------------
- lldb::StateType m_state;
- ThreadStopInfo m_stop_info;
- NativeRegisterContextSP m_reg_context_sp;
- 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.
- };
+ // ---------------------------------------------------------------------
+ // Member Variables
+ // ---------------------------------------------------------------------
+ lldb::StateType m_state;
+ ThreadStopInfo m_stop_info;
+ NativeRegisterContextSP m_reg_context_sp;
+ 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.
+};
- typedef std::shared_ptr<NativeThreadLinux> NativeThreadLinuxSP;
+typedef std::shared_ptr<NativeThreadLinux> NativeThreadLinuxSP;
} // namespace process_linux
} // namespace lldb_private
diff --git a/lldb/source/Plugins/Process/Linux/ProcFileReader.cpp b/lldb/source/Plugins/Process/Linux/ProcFileReader.cpp
index 4d1f231..a1bb7a6 100644
--- a/lldb/source/Plugins/Process/Linux/ProcFileReader.cpp
+++ b/lldb/source/Plugins/Process/Linux/ProcFileReader.cpp
@@ -26,83 +26,78 @@
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);
+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;
}
- }
-
- 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;
- }
+ bytes_read += status;
- // 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;
+ if (avail - status == 0)
+ buf_ap->SetByteSize(2 * buf_ap->GetByteSize());
+ }
- 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);
+ 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/lldb/source/Plugins/Process/Linux/ProcFileReader.h b/lldb/source/Plugins/Process/Linux/ProcFileReader.h
index 7b38124..dcdb355 100644
--- a/lldb/source/Plugins/Process/Linux/ProcFileReader.h
+++ b/lldb/source/Plugins/Process/Linux/ProcFileReader.h
@@ -18,18 +18,18 @@
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);
- };
+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
diff --git a/lldb/source/Plugins/Process/Linux/Procfs.h b/lldb/source/Plugins/Process/Linux/Procfs.h
index cad433f..1d9c9db 100644
--- a/lldb/source/Plugins/Process/Linux/Procfs.h
+++ b/lldb/source/Plugins/Process/Linux/Procfs.h
@@ -13,19 +13,19 @@
#include <sys/ptrace.h>
#ifdef __ANDROID__
-#if defined (__arm64__) || defined (__aarch64__)
+#if defined(__arm64__) || defined(__aarch64__)
typedef unsigned long elf_greg_t;
-typedef elf_greg_t elf_gregset_t[(sizeof (struct user_pt_regs) / sizeof(elf_greg_t))];
+typedef elf_greg_t
+ elf_gregset_t[(sizeof(struct user_pt_regs) / sizeof(elf_greg_t))];
typedef struct user_fpsimd_state elf_fpregset_t;
#ifndef NT_FPREGSET
- #define NT_FPREGSET NT_PRFPREG
+#define NT_FPREGSET NT_PRFPREG
#endif // NT_FPREGSET
-#elif defined (__mips__)
+#elif defined(__mips__)
#ifndef NT_FPREGSET
- #define NT_FPREGSET NT_PRFPREG
+#define NT_FPREGSET NT_PRFPREG
#endif // NT_FPREGSET
#endif
-#else // __ANDROID__
+#else // __ANDROID__
#include <sys/procfs.h>
#endif // __ANDROID__
-
diff --git a/lldb/source/Plugins/Process/Linux/SingleStepCheck.cpp b/lldb/source/Plugins/Process/Linux/SingleStepCheck.cpp
index 8c557d4..b23c1bd 100644
--- a/lldb/source/Plugins/Process/Linux/SingleStepCheck.cpp
+++ b/lldb/source/Plugins/Process/Linux/SingleStepCheck.cpp
@@ -25,153 +25,142 @@
using namespace lldb_private::process_linux;
#if defined(__arm64__) || defined(__aarch64__)
-namespace
-{
-
-void LLVM_ATTRIBUTE_NORETURN
-Child()
-{
- if (ptrace(PTRACE_TRACEME, 0, nullptr, nullptr) == -1)
- _exit(1);
-
- // We just do an endless loop SIGSTOPPING ourselves until killed. The tracer will fiddle with our cpu
- // affinities and monitor the behaviour.
- for (;;)
- {
- raise(SIGSTOP);
-
- // Generate a bunch of instructions here, so that a single-step does not land in the
- // raise() accidentally. If single-stepping works, we will be spinning in this loop. If
- // it doesn't, we'll land in the raise() call above.
- for (volatile unsigned i = 0; i < CPU_SETSIZE; ++i)
- ;
- }
+namespace {
+
+void LLVM_ATTRIBUTE_NORETURN Child() {
+ if (ptrace(PTRACE_TRACEME, 0, nullptr, nullptr) == -1)
+ _exit(1);
+
+ // We just do an endless loop SIGSTOPPING ourselves until killed. The tracer
+ // will fiddle with our cpu
+ // affinities and monitor the behaviour.
+ for (;;) {
+ raise(SIGSTOP);
+
+ // Generate a bunch of instructions here, so that a single-step does not
+ // land in the
+ // raise() accidentally. If single-stepping works, we will be spinning in
+ // this loop. If
+ // it doesn't, we'll land in the raise() call above.
+ for (volatile unsigned i = 0; i < CPU_SETSIZE; ++i)
+ ;
+ }
}
-struct ChildDeleter
-{
- ::pid_t pid;
+struct ChildDeleter {
+ ::pid_t pid;
- ~ChildDeleter()
- {
- int status;
- kill(pid, SIGKILL); // Kill the child.
- waitpid(pid, &status, __WALL); // Pick up the remains.
- }
+ ~ChildDeleter() {
+ int status;
+ kill(pid, SIGKILL); // Kill the child.
+ waitpid(pid, &status, __WALL); // Pick up the remains.
+ }
};
} // end anonymous namespace
-bool
-impl::SingleStepWorkaroundNeeded()
-{
- // 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;
- ::pid_t child_pid = fork();
- if (child_pid == -1)
- {
- if (log)
- {
- error.SetErrorToErrno();
- log->Printf("%s failed to fork(): %s", __FUNCTION__, error.AsCString());
- }
- return false;
+bool impl::SingleStepWorkaroundNeeded() {
+ // 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;
+ ::pid_t child_pid = fork();
+ if (child_pid == -1) {
+ if (log) {
+ error.SetErrorToErrno();
+ log->Printf("%s failed to fork(): %s", __FUNCTION__, error.AsCString());
+ }
+ return false;
+ }
+ if (child_pid == 0)
+ Child();
+
+ ChildDeleter child_deleter{child_pid};
+ cpu_set_t available_cpus;
+ if (sched_getaffinity(child_pid, sizeof available_cpus, &available_cpus) ==
+ -1) {
+ if (log) {
+ error.SetErrorToErrno();
+ log->Printf("%s failed to get available cpus: %s", __FUNCTION__,
+ error.AsCString());
+ }
+ 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());
}
- if (child_pid == 0)
- Child();
-
- ChildDeleter child_deleter{child_pid};
- cpu_set_t available_cpus;
- if (sched_getaffinity(child_pid, sizeof available_cpus, &available_cpus) == -1)
- {
- if (log)
- {
- error.SetErrorToErrno();
- log->Printf("%s failed to get available cpus: %s", __FUNCTION__, error.AsCString());
- }
- return false;
+ return false;
+ }
+
+ unsigned cpu;
+ for (cpu = 0; cpu < CPU_SETSIZE; ++cpu) {
+ if (!CPU_ISSET(cpu, &available_cpus))
+ continue;
+
+ cpu_set_t cpus;
+ CPU_ZERO(&cpus);
+ CPU_SET(cpu, &cpus);
+ if (sched_setaffinity(child_pid, sizeof cpus, &cpus) == -1) {
+ if (log) {
+ error.SetErrorToErrno();
+ log->Printf("%s failed to switch to cpu %u: %s", __FUNCTION__, cpu,
+ error.AsCString());
+ }
+ continue;
}
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());
- }
- return false;
+ error = NativeProcessLinux::PtraceWrapper(PTRACE_SINGLESTEP, child_pid);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("%s single step failed: %s", __FUNCTION__,
+ error.AsCString());
+ break;
}
- unsigned cpu;
- for (cpu = 0; cpu < CPU_SETSIZE; ++cpu)
- {
- if (!CPU_ISSET(cpu, &available_cpus))
- continue;
-
- cpu_set_t cpus;
- CPU_ZERO(&cpus);
- CPU_SET(cpu, &cpus);
- if (sched_setaffinity(child_pid, sizeof cpus, &cpus) == -1)
- {
- if (log)
- {
- error.SetErrorToErrno();
- log->Printf("%s failed to switch to cpu %u: %s", __FUNCTION__, cpu, error.AsCString());
- }
- continue;
- }
-
- int status;
- error = NativeProcessLinux::PtraceWrapper(PTRACE_SINGLESTEP, child_pid);
- if (error.Fail())
- {
- if (log)
- log->Printf("%s single step failed: %s", __FUNCTION__, error.AsCString());
- 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());
- }
- break;
- }
- if (WSTOPSIG(status) != SIGTRAP)
- {
- if (log)
- log->Printf("%s single stepping on cpu %d failed with status %x", __FUNCTION__, cpu, status);
- 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());
+ }
+ 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__);
- // No point in trying to fiddle with the affinities, just give it our best shot and see how it goes.
- return false;
+ if (WSTOPSIG(status) != SIGTRAP) {
+ if (log)
+ log->Printf("%s single stepping on cpu %d failed with status %x",
+ __FUNCTION__, 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__);
+ // No point in trying to fiddle with the affinities, just give it our best
+ // shot and see how it goes.
+ return false;
+ }
- return cpu != CPU_SETSIZE;
+ return cpu != CPU_SETSIZE;
}
#else // !arm64
-bool
-impl::SingleStepWorkaroundNeeded()
-{
- return false;
-}
+bool impl::SingleStepWorkaroundNeeded() { return false; }
#endif
diff --git a/lldb/source/Plugins/Process/Linux/SingleStepCheck.h b/lldb/source/Plugins/Process/Linux/SingleStepCheck.h
index f83f7c9..6e3310d 100644
--- a/lldb/source/Plugins/Process/Linux/SingleStepCheck.h
+++ b/lldb/source/Plugins/Process/Linux/SingleStepCheck.h
@@ -10,30 +10,29 @@
#ifndef liblldb_SingleStepCheck_H_
#define liblldb_SingleStepCheck_H_
-namespace lldb_private
-{
-namespace process_linux
-{
+namespace lldb_private {
+namespace process_linux {
-namespace impl
-{
-extern bool
-SingleStepWorkaroundNeeded();
+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
+// 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
// the boot cpu.
//
-// The underlying issue has been fixed in android N and linux 4.4. This code can be removed once
+// 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;
+inline bool SingleStepWorkaroundNeeded() {
+ static bool value = impl::SingleStepWorkaroundNeeded();
+ return value;
}
} // end namespace process_linux
} // end namespace lldb_private