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