[Lldb-commits] [lldb] r242391 - Revert "[NativeProcessLinux] Integrate MainLoop"
Pavel Labath
labath at google.com
Thu Jul 16 01:45:04 PDT 2015
Author: labath
Date: Thu Jul 16 03:45:03 2015
New Revision: 242391
URL: http://llvm.org/viewvc/llvm-project?rev=242391&view=rev
Log:
Revert "[NativeProcessLinux] Integrate MainLoop"
This seems to be causing major slowdows on the android buildbot. Reverting while I investigate.
Modified:
lldb/trunk/include/lldb/Host/common/NativeProcessProtocol.h
lldb/trunk/source/Host/common/NativeProcessProtocol.cpp
lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp
lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h
lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp
lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp
lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
Modified: lldb/trunk/include/lldb/Host/common/NativeProcessProtocol.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/common/NativeProcessProtocol.h?rev=242391&r1=242390&r2=242391&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Host/common/NativeProcessProtocol.h (original)
+++ lldb/trunk/include/lldb/Host/common/NativeProcessProtocol.h Thu Jul 16 03:45:03 2015
@@ -16,7 +16,6 @@
#include "lldb/lldb-types.h"
#include "lldb/Core/Error.h"
#include "lldb/Host/Mutex.h"
-#include "lldb/Host/MainLoop.h"
#include "llvm/ADT/StringRef.h"
#include "NativeBreakpointList.h"
@@ -285,6 +284,10 @@ namespace lldb_private
bool
UnregisterNativeDelegate (NativeDelegate &native_delegate);
+ // Called before termination of NativeProcessProtocol's instance.
+ virtual void
+ Terminate ();
+
virtual Error
GetLoadedModuleFileSpec(const char* module_path, FileSpec& file_spec) = 0;
@@ -304,11 +307,6 @@ namespace lldb_private
/// inferior. Must outlive the NativeProcessProtocol
/// instance.
///
- /// @param[in] mainloop
- /// The mainloop instance with which the process can register
- /// callbacks. Must outlive the NativeProcessProtocol
- /// instance.
- ///
/// @param[out] process_sp
/// On successful return from the method, this parameter
/// contains the shared pointer to the
@@ -322,7 +320,6 @@ namespace lldb_private
static Error
Launch (ProcessLaunchInfo &launch_info,
NativeDelegate &native_delegate,
- MainLoop &mainloop,
NativeProcessProtocolSP &process_sp);
//------------------------------------------------------------------
@@ -338,11 +335,6 @@ namespace lldb_private
/// inferior. Must outlive the NativeProcessProtocol
/// instance.
///
- /// @param[in] mainloop
- /// The mainloop instance with which the process can register
- /// callbacks. Must outlive the NativeProcessProtocol
- /// instance.
- ///
/// @param[out] process_sp
/// On successful return from the method, this parameter
/// contains the shared pointer to the
@@ -356,7 +348,6 @@ namespace lldb_private
static Error
Attach (lldb::pid_t pid,
NativeDelegate &native_delegate,
- MainLoop &mainloop,
NativeProcessProtocolSP &process_sp);
protected:
Modified: lldb/trunk/source/Host/common/NativeProcessProtocol.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/NativeProcessProtocol.cpp?rev=242391&r1=242390&r2=242391&view=diff
==============================================================================
--- lldb/trunk/source/Host/common/NativeProcessProtocol.cpp (original)
+++ lldb/trunk/source/Host/common/NativeProcessProtocol.cpp Thu Jul 16 03:45:03 2015
@@ -436,6 +436,12 @@ NativeProcessProtocol::DoStopIDBumped (u
// Default implementation does nothing.
}
+void
+NativeProcessProtocol::Terminate ()
+{
+ // Default implementation does nothing.
+}
+
#ifndef __linux__
// These need to be implemented to support lldb-gdb-server on a given platform. Stubs are
// provided to make the rest of the code link on non-supported platforms.
@@ -443,7 +449,6 @@ NativeProcessProtocol::DoStopIDBumped (u
Error
NativeProcessProtocol::Launch (ProcessLaunchInfo &launch_info,
NativeDelegate &native_delegate,
- MainLoop &mainloop,
NativeProcessProtocolSP &process_sp)
{
llvm_unreachable("Platform has no NativeProcessProtocol support");
@@ -452,7 +457,6 @@ NativeProcessProtocol::Launch (ProcessLa
Error
NativeProcessProtocol::Attach (lldb::pid_t pid,
NativeDelegate &native_delegate,
- MainLoop &mainloop,
NativeProcessProtocolSP &process_sp)
{
llvm_unreachable("Platform has no NativeProcessProtocol support");
Modified: lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp?rev=242391&r1=242390&r2=242391&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp Thu Jul 16 03:45:03 2015
@@ -11,6 +11,7 @@
// C Includes
#include <errno.h>
+#include <semaphore.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
@@ -212,8 +213,157 @@ namespace
}
}
- static constexpr unsigned k_ptrace_word_size = sizeof(void*);
- static_assert(sizeof(long) >= k_ptrace_word_size, "Size of long must be larger than ptrace word size");
+ //------------------------------------------------------------------------------
+ // Static implementations of NativeProcessLinux::ReadMemory and
+ // NativeProcessLinux::WriteMemory. This enables mutual recursion between these
+ // functions without needed to go thru the thread funnel.
+
+ Error
+ DoReadMemory(
+ lldb::pid_t pid,
+ lldb::addr_t vm_addr,
+ void *buf,
+ size_t size,
+ size_t &bytes_read)
+ {
+ // ptrace word size is determined by the host, not the child
+ static const unsigned word_size = sizeof(void*);
+ 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(%" PRIu64 ", %d, %p, %p, %zd, _)", __FUNCTION__,
+ pid, word_size, (void*)vm_addr, buf, size);
+
+ assert(sizeof(data) >= word_size);
+ for (bytes_read = 0; bytes_read < size; bytes_read += remainder)
+ {
+ Error error = NativeProcessLinux::PtraceWrapper(PTRACE_PEEKDATA, pid, (void*)vm_addr, nullptr, 0, &data);
+ if (error.Fail())
+ {
+ if (log)
+ ProcessPOSIXLog::DecNestLevel();
+ return error;
+ }
+
+ remainder = size - bytes_read;
+ remainder = remainder > word_size ? word_size : remainder;
+
+ // Copy the data into our buffer
+ for (unsigned i = 0; i < remainder; ++i)
+ dst[i] = ((data >> i*8) & 0xFF);
+
+ 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() [%p]:0x%lx (0x%lx)", __FUNCTION__,
+ (void*)vm_addr, print_dst, (unsigned long)data);
+ }
+ vm_addr += word_size;
+ dst += word_size;
+ }
+
+ if (log)
+ ProcessPOSIXLog::DecNestLevel();
+ return Error();
+ }
+
+ Error
+ DoWriteMemory(
+ lldb::pid_t pid,
+ lldb::addr_t vm_addr,
+ const void *buf,
+ size_t size,
+ size_t &bytes_written)
+ {
+ // ptrace word size is determined by the host, not the child
+ static const unsigned word_size = sizeof(void*);
+ const unsigned char *src = static_cast<const unsigned char*>(buf);
+ size_t remainder;
+ Error error;
+
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL));
+ if (log)
+ ProcessPOSIXLog::IncNestLevel();
+ if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY))
+ log->Printf ("NativeProcessLinux::%s(%" PRIu64 ", %u, %p, %p, %" PRIu64 ")", __FUNCTION__,
+ pid, word_size, (void*)vm_addr, buf, size);
+
+ for (bytes_written = 0; bytes_written < size; bytes_written += remainder)
+ {
+ remainder = size - bytes_written;
+ remainder = remainder > word_size ? word_size : remainder;
+
+ if (remainder == word_size)
+ {
+ unsigned long data = 0;
+ assert(sizeof(data) >= word_size);
+ for (unsigned i = 0; i < word_size; ++i)
+ data |= (unsigned long)src[i] << i*8;
+
+ 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*)vm_addr, *(const unsigned long*)src, data);
+
+ error = NativeProcessLinux::PtraceWrapper(PTRACE_POKEDATA, pid, (void*)vm_addr, (void*)data);
+ if (error.Fail())
+ {
+ if (log)
+ ProcessPOSIXLog::DecNestLevel();
+ return error;
+ }
+ }
+ else
+ {
+ unsigned char buff[8];
+ size_t bytes_read;
+ error = DoReadMemory(pid, vm_addr, buff, word_size, bytes_read);
+ if (error.Fail())
+ {
+ if (log)
+ ProcessPOSIXLog::DecNestLevel();
+ return error;
+ }
+
+ memcpy(buff, src, remainder);
+
+ size_t bytes_written_rec;
+ error = DoWriteMemory(pid, vm_addr, buff, word_size, bytes_written_rec);
+ if (error.Fail())
+ {
+ if (log)
+ ProcessPOSIXLog::DecNestLevel();
+ return error;
+ }
+
+ if (log && ProcessPOSIXLog::AtTopNestLevel() &&
+ (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) ||
+ (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) &&
+ size <= POSIX_LOG_MEMORY_SHORT_BYTES)))
+ log->Printf ("NativeProcessLinux::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__,
+ (void*)vm_addr, *(const unsigned long*)src, *(unsigned long*)buff);
+ }
+
+ vm_addr += word_size;
+ src += word_size;
+ }
+ if (log)
+ ProcessPOSIXLog::DecNestLevel();
+ return error;
+ }
} // end of anonymous namespace
// Simple helper function to ensure flags are enabled on the given file
@@ -239,6 +389,406 @@ EnsureFDFlags(int fd, int flags)
return error;
}
+// This class encapsulates the privileged thread which performs all ptrace and wait operations on
+// the inferior. The thread consists of a main loop which waits for events and processes them
+// - SIGCHLD (delivered over a signalfd file descriptor): These signals notify us of events in
+// the inferior process. Upon receiving this signal we do a waitpid to get more information
+// and dispatch to NativeProcessLinux::MonitorCallback.
+// - requests for ptrace operations: These initiated via the DoOperation method, which funnels
+// them to the Monitor thread via m_operation member. The Monitor thread is signaled over a
+// pipe, and the completion of the operation is signalled over the semaphore.
+// - thread exit event: this is signaled from the Monitor destructor by closing the write end
+// of the command pipe.
+class NativeProcessLinux::Monitor
+{
+private:
+ // The initial monitor operation (launch or attach). It returns a inferior process id.
+ std::unique_ptr<InitialOperation> m_initial_operation_up;
+
+ ::pid_t m_child_pid = -1;
+ NativeProcessLinux * m_native_process;
+
+ enum { READ, WRITE };
+ int m_pipefd[2] = {-1, -1};
+ int m_signal_fd = -1;
+ HostThread m_thread;
+
+ // current operation which must be executed on the priviliged thread
+ Mutex m_operation_mutex;
+ const Operation *m_operation = nullptr;
+ sem_t m_operation_sem;
+ Error m_operation_error;
+
+ unsigned m_operation_nesting_level = 0;
+
+ static constexpr char operation_command = 'o';
+ static constexpr char begin_block_command = '{';
+ static constexpr char end_block_command = '}';
+
+ void
+ HandleSignals();
+
+ void
+ HandleWait();
+
+ // Returns true if the thread should exit.
+ bool
+ HandleCommands();
+
+ void
+ MainLoop();
+
+ static void *
+ RunMonitor(void *arg);
+
+ Error
+ WaitForAck();
+
+ void
+ BeginOperationBlock()
+ {
+ write(m_pipefd[WRITE], &begin_block_command, sizeof operation_command);
+ WaitForAck();
+ }
+
+ void
+ EndOperationBlock()
+ {
+ write(m_pipefd[WRITE], &end_block_command, sizeof operation_command);
+ WaitForAck();
+ }
+
+public:
+ Monitor(const InitialOperation &initial_operation,
+ NativeProcessLinux *native_process)
+ : m_initial_operation_up(new InitialOperation(initial_operation)),
+ m_native_process(native_process)
+ {
+ sem_init(&m_operation_sem, 0, 0);
+ }
+
+ ~Monitor();
+
+ Error
+ Initialize();
+
+ void
+ Terminate();
+
+ Error
+ DoOperation(const Operation &op);
+
+ class ScopedOperationLock {
+ Monitor &m_monitor;
+
+ public:
+ ScopedOperationLock(Monitor &monitor)
+ : m_monitor(monitor)
+ { m_monitor.BeginOperationBlock(); }
+
+ ~ScopedOperationLock()
+ { m_monitor.EndOperationBlock(); }
+ };
+};
+constexpr char NativeProcessLinux::Monitor::operation_command;
+constexpr char NativeProcessLinux::Monitor::begin_block_command;
+constexpr char NativeProcessLinux::Monitor::end_block_command;
+
+Error
+NativeProcessLinux::Monitor::Initialize()
+{
+ Error error;
+
+ // We get a SIGCHLD every time something interesting happens with the inferior. We shall be
+ // listening for these signals over a signalfd file descriptors. This allows us to wait for
+ // multiple kinds of events with select.
+ sigset_t signals;
+ sigemptyset(&signals);
+ sigaddset(&signals, SIGCHLD);
+ m_signal_fd = signalfd(-1, &signals, SFD_NONBLOCK | SFD_CLOEXEC);
+ if (m_signal_fd < 0)
+ {
+ return Error("NativeProcessLinux::Monitor::%s failed due to signalfd failure. Monitoring the inferior will be impossible: %s",
+ __FUNCTION__, strerror(errno));
+
+ }
+
+ if (pipe2(m_pipefd, O_CLOEXEC) == -1)
+ {
+ error.SetErrorToErrno();
+ return error;
+ }
+
+ if ((error = EnsureFDFlags(m_pipefd[READ], O_NONBLOCK)).Fail()) {
+ return error;
+ }
+
+ static const char g_thread_name[] = "lldb.process.nativelinux.monitor";
+ m_thread = ThreadLauncher::LaunchThread(g_thread_name, Monitor::RunMonitor, this, nullptr);
+ if (!m_thread.IsJoinable())
+ return Error("Failed to create monitor thread for NativeProcessLinux.");
+
+ // Wait for initial operation to complete.
+ return WaitForAck();
+}
+
+Error
+NativeProcessLinux::Monitor::DoOperation(const Operation &op)
+{
+ if (m_thread.EqualsThread(pthread_self())) {
+ // If we're on the Monitor thread, we can simply execute the operation.
+ return op();
+ }
+
+ // Otherwise we need to pass the operation to the Monitor thread so it can handle it.
+ Mutex::Locker lock(m_operation_mutex);
+
+ m_operation = &op;
+
+ // notify the thread that an operation is ready to be processed
+ write(m_pipefd[WRITE], &operation_command, sizeof operation_command);
+
+ return WaitForAck();
+}
+
+void
+NativeProcessLinux::Monitor::Terminate()
+{
+ if (m_pipefd[WRITE] >= 0)
+ {
+ close(m_pipefd[WRITE]);
+ m_pipefd[WRITE] = -1;
+ }
+ if (m_thread.IsJoinable())
+ m_thread.Join(nullptr);
+}
+
+NativeProcessLinux::Monitor::~Monitor()
+{
+ Terminate();
+ if (m_pipefd[READ] >= 0)
+ close(m_pipefd[READ]);
+ if (m_signal_fd >= 0)
+ close(m_signal_fd);
+ sem_destroy(&m_operation_sem);
+}
+
+void
+NativeProcessLinux::Monitor::HandleSignals()
+{
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ // We don't really care about the content of the SIGCHLD siginfo structure, as we will get
+ // all the information from waitpid(). We just need to read all the signals so that we can
+ // sleep next time we reach select().
+ while (true)
+ {
+ signalfd_siginfo info;
+ ssize_t size = read(m_signal_fd, &info, sizeof info);
+ if (size == -1)
+ {
+ if (errno == EAGAIN || errno == EWOULDBLOCK)
+ break; // We are done.
+ if (errno == EINTR)
+ continue;
+ if (log)
+ log->Printf("NativeProcessLinux::Monitor::%s reading from signalfd file descriptor failed: %s",
+ __FUNCTION__, strerror(errno));
+ break;
+ }
+ if (size != sizeof info)
+ {
+ // We got incomplete information structure. This should not happen, let's just log
+ // that.
+ if (log)
+ log->Printf("NativeProcessLinux::Monitor::%s reading from signalfd file descriptor returned incomplete data: "
+ "structure size is %zd, read returned %zd bytes",
+ __FUNCTION__, sizeof info, size);
+ break;
+ }
+ if (log)
+ log->Printf("NativeProcessLinux::Monitor::%s received signal %s(%d).", __FUNCTION__,
+ Host::GetSignalAsCString(info.ssi_signo), info.ssi_signo);
+ }
+}
+
+void
+NativeProcessLinux::Monitor::HandleWait()
+{
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ // Process all pending waitpid notifications.
+ while (true)
+ {
+ int status = -1;
+ ::pid_t wait_pid = waitpid(-1, &status, __WALL | __WNOTHREAD | WNOHANG);
+
+ if (wait_pid == 0)
+ break; // We are done.
+
+ if (wait_pid == -1)
+ {
+ if (errno == EINTR)
+ continue;
+
+ if (log)
+ log->Printf("NativeProcessLinux::Monitor::%s waitpid (-1, &status, __WALL | __WNOTHREAD | WNOHANG) failed: %s",
+ __FUNCTION__, strerror(errno));
+ break;
+ }
+
+ bool exited = false;
+ int signal = 0;
+ int exit_status = 0;
+ const char *status_cstr = NULL;
+ if (WIFSTOPPED(status))
+ {
+ signal = WSTOPSIG(status);
+ status_cstr = "STOPPED";
+ }
+ else if (WIFEXITED(status))
+ {
+ exit_status = WEXITSTATUS(status);
+ status_cstr = "EXITED";
+ exited = true;
+ }
+ else if (WIFSIGNALED(status))
+ {
+ signal = WTERMSIG(status);
+ status_cstr = "SIGNALED";
+ if (wait_pid == m_child_pid) {
+ exited = true;
+ exit_status = -1;
+ }
+ }
+ else
+ status_cstr = "(\?\?\?)";
+
+ if (log)
+ log->Printf("NativeProcessLinux::Monitor::%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);
+
+ m_native_process->MonitorCallback (wait_pid, exited, signal, exit_status);
+ }
+}
+
+bool
+NativeProcessLinux::Monitor::HandleCommands()
+{
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ while (true)
+ {
+ char command = 0;
+ ssize_t size = read(m_pipefd[READ], &command, sizeof command);
+ if (size == -1)
+ {
+ if (errno == EAGAIN || errno == EWOULDBLOCK)
+ return false;
+ if (errno == EINTR)
+ continue;
+ if (log)
+ log->Printf("NativeProcessLinux::Monitor::%s exiting because read from command file descriptor failed: %s", __FUNCTION__, strerror(errno));
+ return true;
+ }
+ if (size == 0) // end of file - write end closed
+ {
+ if (log)
+ log->Printf("NativeProcessLinux::Monitor::%s exit command received, exiting...", __FUNCTION__);
+ assert(m_operation_nesting_level == 0 && "Unbalanced begin/end block commands detected");
+ return true; // We are done.
+ }
+
+ switch (command)
+ {
+ case operation_command:
+ m_operation_error = (*m_operation)();
+ break;
+ case begin_block_command:
+ ++m_operation_nesting_level;
+ break;
+ case end_block_command:
+ assert(m_operation_nesting_level > 0);
+ --m_operation_nesting_level;
+ break;
+ default:
+ if (log)
+ log->Printf("NativeProcessLinux::Monitor::%s received unknown command '%c'",
+ __FUNCTION__, command);
+ }
+
+ // notify calling thread that the command has been processed
+ sem_post(&m_operation_sem);
+ }
+}
+
+void
+NativeProcessLinux::Monitor::MainLoop()
+{
+ ::pid_t child_pid = (*m_initial_operation_up)(m_operation_error);
+ m_initial_operation_up.reset();
+ m_child_pid = child_pid;
+ sem_post(&m_operation_sem);
+
+ while (true)
+ {
+ fd_set fds;
+ FD_ZERO(&fds);
+ // Only process waitpid events if we are outside of an operation block. Any pending
+ // events will be processed after we leave the block.
+ if (m_operation_nesting_level == 0)
+ FD_SET(m_signal_fd, &fds);
+ FD_SET(m_pipefd[READ], &fds);
+
+ int max_fd = std::max(m_signal_fd, m_pipefd[READ]) + 1;
+ int r = select(max_fd, &fds, nullptr, nullptr, nullptr);
+ if (r < 0)
+ {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf("NativeProcessLinux::Monitor::%s exiting because select failed: %s",
+ __FUNCTION__, strerror(errno));
+ return;
+ }
+
+ if (FD_ISSET(m_pipefd[READ], &fds))
+ {
+ if (HandleCommands())
+ return;
+ }
+
+ if (FD_ISSET(m_signal_fd, &fds))
+ {
+ HandleSignals();
+ HandleWait();
+ }
+ }
+}
+
+Error
+NativeProcessLinux::Monitor::WaitForAck()
+{
+ Error error;
+ while (sem_wait(&m_operation_sem) != 0)
+ {
+ if (errno == EINTR)
+ continue;
+
+ error.SetErrorToErrno();
+ return error;
+ }
+
+ return m_operation_error;
+}
+
+void *
+NativeProcessLinux::Monitor::RunMonitor(void *arg)
+{
+ static_cast<Monitor *>(arg)->MainLoop();
+ return nullptr;
+}
+
+
NativeProcessLinux::LaunchArgs::LaunchArgs(Module *module,
char const **argv,
char const **envp,
@@ -269,7 +819,6 @@ Error
NativeProcessProtocol::Launch (
ProcessLaunchInfo &launch_info,
NativeProcessProtocol::NativeDelegate &native_delegate,
- MainLoop &mainloop,
NativeProcessProtocolSP &native_process_sp)
{
Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
@@ -356,7 +905,6 @@ NativeProcessProtocol::Launch (
}
std::static_pointer_cast<NativeProcessLinux> (native_process_sp)->LaunchInferior (
- mainloop,
exe_module_sp.get(),
launch_info.GetArguments ().GetConstArgumentVector (),
launch_info.GetEnvironmentEntries ().GetConstArgumentVector (),
@@ -384,7 +932,6 @@ Error
NativeProcessProtocol::Attach (
lldb::pid_t pid,
NativeProcessProtocol::NativeDelegate &native_delegate,
- MainLoop &mainloop,
NativeProcessProtocolSP &native_process_sp)
{
Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
@@ -411,7 +958,7 @@ NativeProcessProtocol::Attach (
return error;
}
- native_process_linux_sp->AttachToInferior (mainloop, pid, error);
+ native_process_linux_sp->AttachToInferior (pid, error);
if (!error.Success ())
return error;
@@ -432,9 +979,12 @@ NativeProcessLinux::NativeProcessLinux (
{
}
+//------------------------------------------------------------------------------
+// NativeProcessLinux spawns a new thread which performs all operations on the inferior process.
+// Refer to Monitor and Operation classes to see why this is necessary.
+//------------------------------------------------------------------------------
void
NativeProcessLinux::LaunchInferior (
- MainLoop &mainloop,
Module *module,
const char *argv[],
const char *envp[],
@@ -445,11 +995,6 @@ NativeProcessLinux::LaunchInferior (
const ProcessLaunchInfo &launch_info,
Error &error)
{
- m_sigchld_handle = mainloop.RegisterSignal(SIGCHLD,
- [this] (MainLoopBase &) { SigchldHandler(); }, error);
- if (! m_sigchld_handle)
- return;
-
if (module)
m_arch = module->GetArchitecture ();
@@ -463,21 +1008,18 @@ NativeProcessLinux::LaunchInferior (
working_dir,
launch_info));
- Launch(args.get(), error);
+ StartMonitorThread ([&] (Error &e) { return Launch(args.get(), e); }, error);
+ if (!error.Success ())
+ return;
}
void
-NativeProcessLinux::AttachToInferior (MainLoop &mainloop, lldb::pid_t pid, Error &error)
+NativeProcessLinux::AttachToInferior (lldb::pid_t pid, Error &error)
{
Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
if (log)
log->Printf ("NativeProcessLinux::%s (pid = %" PRIi64 ")", __FUNCTION__, pid);
- m_sigchld_handle = mainloop.RegisterSignal(SIGCHLD,
- [this] (MainLoopBase &) { SigchldHandler(); }, error);
- if (! m_sigchld_handle)
- return;
-
// We can use the Host for everything except the ResolveExecutable portion.
PlatformSP platform_sp = Platform::GetHostPlatform ();
if (!platform_sp)
@@ -515,7 +1057,15 @@ NativeProcessLinux::AttachToInferior (Ma
m_pid = pid;
SetState(eStateAttaching);
- Attach(pid, error);
+ StartMonitorThread ([=] (Error &e) { return Attach(pid, e); }, error);
+ if (!error.Success ())
+ return;
+}
+
+void
+NativeProcessLinux::Terminate ()
+{
+ m_monitor_up->Terminate();
}
::pid_t
@@ -1737,6 +2287,7 @@ NativeProcessLinux::Resume (const Resume
bool software_single_step = !SupportHardwareSingleStepping();
+ Monitor::ScopedOperationLock monitor_lock(*m_monitor_up);
Mutex::Locker locker (m_threads_mutex);
if (software_single_step)
@@ -1856,7 +2407,7 @@ NativeProcessLinux::Detach ()
error = Detach (GetID ());
// Stop monitoring the inferior.
- m_sigchld_handle.reset();
+ m_monitor_up->Terminate();
// No error.
return error;
@@ -1891,6 +2442,7 @@ NativeProcessLinux::Interrupt ()
if (log)
log->Printf ("NativeProcessLinux::%s selecting running thread for interrupt target", __FUNCTION__);
+ Monitor::ScopedOperationLock monitor_lock(*m_monitor_up);
Mutex::Locker locker (m_threads_mutex);
for (auto thread_sp : m_threads)
@@ -2546,6 +3098,24 @@ NativeProcessLinux::GetCrashReasonForSIG
#endif
Error
+NativeProcessLinux::SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware)
+{
+ // The base SetWatchpoint will end up executing monitor operations. Let's lock the monitor
+ // for it.
+ Monitor::ScopedOperationLock monitor_lock(*m_monitor_up);
+ return NativeProcessProtocol::SetWatchpoint(addr, size, watch_flags, hardware);
+}
+
+Error
+NativeProcessLinux::RemoveWatchpoint (lldb::addr_t addr)
+{
+ // The base RemoveWatchpoint will end up executing monitor operations. Let's lock the monitor
+ // for it.
+ Monitor::ScopedOperationLock monitor_lock(*m_monitor_up);
+ return NativeProcessProtocol::RemoveWatchpoint(addr);
+}
+
+Error
NativeProcessLinux::ReadMemory (lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read)
{
if (ProcessVmReadvSupported()) {
@@ -2574,52 +3144,7 @@ NativeProcessLinux::ReadMemory (lldb::ad
// the call failed for some reason, let's retry the read using ptrace api.
}
- unsigned char *dst = static_cast<unsigned char*>(buf);
- size_t remainder;
- long data;
-
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL));
- if (log)
- ProcessPOSIXLog::IncNestLevel();
- if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY))
- log->Printf ("NativeProcessLinux::%s(%p, %p, %zd, _)", __FUNCTION__, (void*)addr, buf, size);
-
- for (bytes_read = 0; bytes_read < size; bytes_read += remainder)
- {
- Error error = NativeProcessLinux::PtraceWrapper(PTRACE_PEEKDATA, GetID(), (void*)addr, nullptr, 0, &data);
- if (error.Fail())
- {
- if (log)
- ProcessPOSIXLog::DecNestLevel();
- return error;
- }
-
- remainder = size - bytes_read;
- remainder = remainder > k_ptrace_word_size ? k_ptrace_word_size : remainder;
-
- // Copy the data into our buffer
- for (unsigned i = 0; i < remainder; ++i)
- dst[i] = ((data >> i*8) & 0xFF);
-
- 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() [%p]:0x%lx (0x%lx)", __FUNCTION__,
- (void*)addr, print_dst, (unsigned long)data);
- }
- addr += k_ptrace_word_size;
- dst += k_ptrace_word_size;
- }
-
- if (log)
- ProcessPOSIXLog::DecNestLevel();
- return Error();
+ return DoOperation([&] { return DoReadMemory(GetID(), addr, buf, size, bytes_read); });
}
Error
@@ -2633,79 +3158,7 @@ NativeProcessLinux::ReadMemoryWithoutTra
Error
NativeProcessLinux::WriteMemory(lldb::addr_t addr, const void *buf, size_t size, size_t &bytes_written)
{
- const unsigned char *src = static_cast<const unsigned char*>(buf);
- size_t remainder;
- Error error;
-
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL));
- if (log)
- ProcessPOSIXLog::IncNestLevel();
- if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY))
- log->Printf ("NativeProcessLinux::%s(%p, %p, %" PRIu64 ")", __FUNCTION__, (void*)addr, buf, size);
-
- for (bytes_written = 0; bytes_written < size; bytes_written += remainder)
- {
- remainder = size - bytes_written;
- remainder = remainder > k_ptrace_word_size ? k_ptrace_word_size : remainder;
-
- if (remainder == k_ptrace_word_size)
- {
- unsigned long data = 0;
- for (unsigned i = 0; i < k_ptrace_word_size; ++i)
- data |= (unsigned long)src[i] << i*8;
-
- if (log && ProcessPOSIXLog::AtTopNestLevel() &&
- (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) ||
- (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) &&
- size <= POSIX_LOG_MEMORY_SHORT_BYTES)))
- log->Printf ("NativeProcessLinux::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__,
- (void*)addr, *(const unsigned long*)src, data);
-
- error = NativeProcessLinux::PtraceWrapper(PTRACE_POKEDATA, GetID(), (void*)addr, (void*)data);
- if (error.Fail())
- {
- if (log)
- ProcessPOSIXLog::DecNestLevel();
- return error;
- }
- }
- else
- {
- unsigned char buff[8];
- size_t bytes_read;
- error = ReadMemory(addr, buff, k_ptrace_word_size, bytes_read);
- if (error.Fail())
- {
- if (log)
- ProcessPOSIXLog::DecNestLevel();
- return error;
- }
-
- memcpy(buff, src, remainder);
-
- size_t bytes_written_rec;
- error = WriteMemory(addr, buff, k_ptrace_word_size, bytes_written_rec);
- if (error.Fail())
- {
- if (log)
- ProcessPOSIXLog::DecNestLevel();
- return error;
- }
-
- if (log && ProcessPOSIXLog::AtTopNestLevel() &&
- (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) ||
- (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) &&
- size <= POSIX_LOG_MEMORY_SHORT_BYTES)))
- log->Printf ("NativeProcessLinux::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__,
- (void*)addr, *(const unsigned long*)src, *(unsigned long*)buff);
- }
-
- addr += k_ptrace_word_size;
- src += k_ptrace_word_size;
- }
- if (log)
- ProcessPOSIXLog::DecNestLevel();
- return error;
+ return DoOperation([&] { return DoWriteMemory(GetID(), addr, buf, size, bytes_written); });
}
Error
@@ -2724,7 +3177,7 @@ NativeProcessLinux::Resume (lldb::tid_t
if (signo != LLDB_INVALID_SIGNAL_NUMBER)
data = signo;
- Error error = PtraceWrapper(PTRACE_CONT, tid, nullptr, (void*)data);
+ Error error = DoOperation([&] { return PtraceWrapper(PTRACE_CONT, tid, nullptr, (void*)data); });
if (log)
log->Printf ("NativeProcessLinux::%s() resuming thread = %" PRIu64 " result = %s", __FUNCTION__, tid, error.Success() ? "true" : "false");
@@ -2739,19 +3192,19 @@ NativeProcessLinux::SingleStep(lldb::tid
if (signo != LLDB_INVALID_SIGNAL_NUMBER)
data = signo;
- return PtraceWrapper(PTRACE_SINGLESTEP, tid, nullptr, (void*)data);
+ return DoOperation([&] { return PtraceWrapper(PTRACE_SINGLESTEP, tid, nullptr, (void*)data); });
}
Error
NativeProcessLinux::GetSignalInfo(lldb::tid_t tid, void *siginfo)
{
- return PtraceWrapper(PTRACE_GETSIGINFO, tid, nullptr, siginfo);
+ return DoOperation([&] { return PtraceWrapper(PTRACE_GETSIGINFO, tid, nullptr, siginfo); });
}
Error
NativeProcessLinux::GetEventMessage(lldb::tid_t tid, unsigned long *message)
{
- return PtraceWrapper(PTRACE_GETEVENTMSG, tid, nullptr, message);
+ return DoOperation([&] { return PtraceWrapper(PTRACE_GETEVENTMSG, tid, nullptr, message); });
}
Error
@@ -2760,7 +3213,7 @@ NativeProcessLinux::Detach(lldb::tid_t t
if (tid == LLDB_INVALID_THREAD_ID)
return Error();
- return PtraceWrapper(PTRACE_DETACH, tid);
+ return DoOperation([&] { return PtraceWrapper(PTRACE_DETACH, tid); });
}
bool
@@ -2777,6 +3230,16 @@ NativeProcessLinux::DupDescriptor(const
return (close(target_fd) == -1) ? false : true;
}
+void
+NativeProcessLinux::StartMonitorThread(const InitialOperation &initial_operation, Error &error)
+{
+ m_monitor_up.reset(new Monitor(initial_operation, this));
+ error = m_monitor_up->Initialize();
+ if (error.Fail()) {
+ m_monitor_up.reset();
+ }
+}
+
bool
NativeProcessLinux::HasThreadNoLock (lldb::tid_t thread_id)
{
@@ -3245,65 +3708,10 @@ NativeProcessLinux::ThreadWasCreated (ll
}
}
-void
-NativeProcessLinux::SigchldHandler()
+Error
+NativeProcessLinux::DoOperation(const Operation &op)
{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- // Process all pending waitpid notifications.
- while (true)
- {
- int status = -1;
- ::pid_t wait_pid = waitpid(-1, &status, __WALL | __WNOTHREAD | WNOHANG);
-
- if (wait_pid == 0)
- break; // We are done.
-
- if (wait_pid == -1)
- {
- if (errno == EINTR)
- continue;
-
- Error error(errno, eErrorTypePOSIX);
- if (log)
- log->Printf("NativeProcessLinux::%s waitpid (-1, &status, __WALL | __WNOTHREAD | WNOHANG) failed: %s",
- __FUNCTION__, error.AsCString());
- break;
- }
-
- bool exited = false;
- int signal = 0;
- int exit_status = 0;
- const char *status_cstr = nullptr;
- if (WIFSTOPPED(status))
- {
- signal = WSTOPSIG(status);
- status_cstr = "STOPPED";
- }
- else if (WIFEXITED(status))
- {
- exit_status = WEXITSTATUS(status);
- status_cstr = "EXITED";
- exited = true;
- }
- else if (WIFSIGNALED(status))
- {
- signal = WTERMSIG(status);
- status_cstr = "SIGNALED";
- if (wait_pid == static_cast<::pid_t>(GetID())) {
- exited = true;
- exit_status = -1;
- }
- }
- else
- status_cstr = "(\?\?\?)";
-
- if (log)
- log->Printf("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);
-
- MonitorCallback (wait_pid, exited, signal, exit_status);
- }
+ return m_monitor_up->DoOperation(op);
}
// Wrapper for ptrace to catch errors and log calls.
Modified: lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h?rev=242391&r1=242390&r2=242391&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h Thu Jul 16 03:45:03 2015
@@ -43,16 +43,25 @@ namespace process_linux {
friend Error
NativeProcessProtocol::Launch (ProcessLaunchInfo &launch_info,
NativeDelegate &native_delegate,
- MainLoop &mainloop,
NativeProcessProtocolSP &process_sp);
friend Error
NativeProcessProtocol::Attach (lldb::pid_t pid,
- NativeProcessProtocol::NativeDelegate &native_delegate,
- MainLoop &mainloop,
- NativeProcessProtocolSP &process_sp);
+ NativeProcessProtocol::NativeDelegate &native_delegate,
+ NativeProcessProtocolSP &native_process_sp);
public:
+ //------------------------------------------------------------------------------
+ /// @class Operation
+ /// @brief Represents a NativeProcessLinux operation.
+ ///
+ /// Under Linux, it is not possible to ptrace() from any other thread but the
+ /// one that spawned or attached to the process from the start. Therefore, when
+ /// a NativeProcessLinux is asked to deliver or change the state of an inferior
+ /// process the operation must be "funneled" to a specific thread to perform the
+ /// task.
+ typedef std::function<Error()> Operation;
+
// ---------------------------------------------------------------------
// NativeProcessProtocol Interface
// ---------------------------------------------------------------------
@@ -104,9 +113,18 @@ namespace process_linux {
Error
SetBreakpoint (lldb::addr_t addr, uint32_t size, bool hardware) override;
+ Error
+ SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware) override;
+
+ Error
+ RemoveWatchpoint (lldb::addr_t addr) override;
+
void
DoStopIDBumped (uint32_t newBumpId) override;
+ void
+ Terminate () override;
+
Error
GetLoadedModuleFileSpec(const char* module_path, FileSpec& file_spec) override;
@@ -116,6 +134,9 @@ namespace process_linux {
// ---------------------------------------------------------------------
// Interface used by NativeRegisterContext-derived classes.
// ---------------------------------------------------------------------
+ Error
+ DoOperation(const Operation &op);
+
static Error
PtraceWrapper(int req,
lldb::pid_t pid,
@@ -133,9 +154,12 @@ namespace process_linux {
private:
- MainLoop::SignalHandleUP m_sigchld_handle;
+ class Monitor;
+
ArchSpec m_arch;
+ std::unique_ptr<Monitor> m_monitor_up;
+
LazyBool m_supports_mem_region;
std::vector<MemoryRegionInfo> m_mem_region_cache;
Mutex m_mem_region_cache_mutex;
@@ -182,7 +206,6 @@ namespace process_linux {
/// implementation of Process::DoLaunch.
void
LaunchInferior (
- MainLoop &mainloop,
Module *module,
char const *argv[],
char const *envp[],
@@ -196,7 +219,10 @@ namespace process_linux {
/// Attaches to an existing process. Forms the
/// implementation of Process::DoAttach
void
- AttachToInferior (MainLoop &mainloop, lldb::pid_t pid, Error &error);
+ AttachToInferior (lldb::pid_t pid, Error &error);
+
+ void
+ StartMonitorThread(const InitialOperation &operation, Error &error);
::pid_t
Launch(LaunchArgs *args, Error &error);
@@ -344,9 +370,6 @@ namespace process_linux {
void
ThreadWasCreated (lldb::tid_t tid);
- void
- SigchldHandler();
-
// Member variables.
PendingNotificationUP m_pending_notification_up;
};
Modified: lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp?rev=242391&r1=242390&r2=242391&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp Thu Jul 16 03:45:03 2015
@@ -50,7 +50,14 @@ NativeRegisterContextLinux::ReadRegister
if (!reg_info)
return Error("register %" PRIu32 " not found", reg_index);
- return DoReadRegisterValue(reg_info->byte_offset, reg_info->name, reg_info->byte_size, reg_value);
+ NativeProcessProtocolSP process_sp(m_thread.GetProcess());
+ if (!process_sp)
+ return Error("NativeProcessProtocol is NULL");
+
+ NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
+ return process_p->DoOperation([&] {
+ return DoReadRegisterValue(reg_info->byte_offset, reg_info->name, reg_info->byte_size, reg_value);
+ });
}
Error
@@ -101,70 +108,111 @@ NativeRegisterContextLinux::WriteRegiste
}
}
+ NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+ if (!process_sp)
+ return Error("NativeProcessProtocol is NULL");
+
const RegisterInfo *const register_to_write_info_p = GetRegisterInfoAtIndex (reg_to_write);
assert (register_to_write_info_p && "register to write does not have valid RegisterInfo");
if (!register_to_write_info_p)
return Error("NativeRegisterContextLinux::%s failed to get RegisterInfo for write register index %" PRIu32, __FUNCTION__, reg_to_write);
- return DoWriteRegisterValue(reg_info->byte_offset, reg_info->name, reg_value);
+ NativeProcessLinux* process_p = static_cast<NativeProcessLinux*> (process_sp.get ());
+ return process_p->DoOperation([&] {
+ return DoWriteRegisterValue(reg_info->byte_offset, reg_info->name, reg_value);
+ });
}
Error
NativeRegisterContextLinux::ReadGPR()
{
+ NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+ if (!process_sp)
+ return Error("NativeProcessProtocol is NULL");
+
void* buf = GetGPRBuffer();
if (!buf)
return Error("GPR buffer is NULL");
size_t buf_size = GetGPRSize();
- return DoReadGPR(buf, buf_size);
+ NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
+ return process_p->DoOperation([&] { return DoReadGPR(buf, buf_size); });
}
Error
NativeRegisterContextLinux::WriteGPR()
{
+ NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+ if (!process_sp)
+ return Error("NativeProcessProtocol is NULL");
+
void* buf = GetGPRBuffer();
if (!buf)
return Error("GPR buffer is NULL");
size_t buf_size = GetGPRSize();
- return DoWriteGPR(buf, buf_size);
+ NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
+ return process_p->DoOperation([&] { return DoWriteGPR(buf, buf_size); });
}
Error
NativeRegisterContextLinux::ReadFPR()
{
+ NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+ if (!process_sp)
+ return Error("NativeProcessProtocol is NULL");
+
void* buf = GetFPRBuffer();
if (!buf)
return Error("GPR buffer is NULL");
size_t buf_size = GetFPRSize();
- return DoReadFPR(buf, buf_size);
+ NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
+ return process_p->DoOperation([&] { return DoReadFPR(buf, buf_size); });
}
Error
NativeRegisterContextLinux::WriteFPR()
{
+ NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+ if (!process_sp)
+ return Error("NativeProcessProtocol is NULL");
+
void* buf = GetFPRBuffer();
if (!buf)
return Error("GPR buffer is NULL");
size_t buf_size = GetFPRSize();
- return DoWriteFPR(buf, buf_size);
+ NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
+ return process_p->DoOperation([&] { return DoWriteFPR(buf, buf_size); });
}
Error
NativeRegisterContextLinux::ReadRegisterSet(void *buf, size_t buf_size, unsigned int regset)
{
- return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_thread.GetID(),
- static_cast<void *>(®set), buf, buf_size);
+ NativeProcessProtocolSP process_sp (m_thread.GetProcess());
+ if (!process_sp)
+ return Error("NativeProcessProtocol is NULL");
+ NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
+
+ return process_p->DoOperation([&] {
+ return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_thread.GetID(),
+ static_cast<void *>(®set), buf, buf_size);
+ });
}
Error
NativeRegisterContextLinux::WriteRegisterSet(void *buf, size_t buf_size, unsigned int regset)
{
- return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(),
- static_cast<void *>(®set), buf, buf_size);
+ NativeProcessProtocolSP process_sp (m_thread.GetProcess());
+ if (!process_sp)
+ return Error("NativeProcessProtocol is NULL");
+ NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
+
+ return process_p->DoOperation([&] {
+ return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(),
+ static_cast<void *>(®set), buf, buf_size);
+ });
}
Error
Modified: lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp?rev=242391&r1=242390&r2=242391&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp Thu Jul 16 03:45:03 2015
@@ -715,23 +715,29 @@ Error
NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo(unsigned int &watch_count,
unsigned int &break_count)
{
+ NativeProcessProtocolSP process_sp (m_thread.GetProcess());
+ if (!process_sp)
+ return Error("NativeProcessProtocol is NULL");
+ NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*>(process_sp.get());
::pid_t tid = m_thread.GetID();
- int regset = NT_ARM_HW_WATCH;
- struct iovec ioVec;
- struct user_hwdebug_state dreg_state;
- Error error;
-
- ioVec.iov_base = &dreg_state;
- ioVec.iov_len = sizeof (dreg_state);
- error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, &ioVec, ioVec.iov_len);
- watch_count = dreg_state.dbg_info & 0xff;
-
- regset = NT_ARM_HW_BREAK;
- error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, &ioVec, ioVec.iov_len);
- break_count = dreg_state.dbg_info & 0xff;
+ return process_p->DoOperation([&] {
+ int regset = NT_ARM_HW_WATCH;
+ struct iovec ioVec;
+ struct user_hwdebug_state dreg_state;
+ Error error;
+
+ ioVec.iov_base = &dreg_state;
+ ioVec.iov_len = sizeof (dreg_state);
+ error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, &ioVec, ioVec.iov_len);
+ watch_count = dreg_state.dbg_info & 0xff;
+
+ regset = NT_ARM_HW_BREAK;
+ error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, &ioVec, ioVec.iov_len);
+ break_count = dreg_state.dbg_info & 0xff;
- return error;
+ return error;
+ });
}
Error
@@ -740,26 +746,33 @@ NativeRegisterContextLinux_arm64::WriteH
int type,
int count)
{
- struct iovec ioVec;
- struct user_hwdebug_state dreg_state;
- Error error;
-
- memset (&dreg_state, 0, sizeof (dreg_state));
- ioVec.iov_base = &dreg_state;
- ioVec.iov_len = sizeof (dreg_state);
-
- if (type == 0)
- type = NT_ARM_HW_WATCH;
- else
- type = NT_ARM_HW_BREAK;
-
- for (int i = 0; i < count; i++)
- {
- dreg_state.dbg_regs[i].addr = addr_buf[i];
- dreg_state.dbg_regs[i].ctrl = cntrl_buf[i];
- }
+ NativeProcessProtocolSP process_sp (m_thread.GetProcess());
+ if (!process_sp)
+ return Error("NativeProcessProtocol is NULL");
+ NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*>(process_sp.get());
+
+ return process_p->DoOperation([&] {
+ struct iovec ioVec;
+ struct user_hwdebug_state dreg_state;
+ Error error;
+
+ memset (&dreg_state, 0, sizeof (dreg_state));
+ ioVec.iov_base = &dreg_state;
+ ioVec.iov_len = sizeof (dreg_state);
+
+ if (type == 0)
+ type = NT_ARM_HW_WATCH;
+ else
+ type = NT_ARM_HW_BREAK;
+
+ for (int i = 0; i < count; i++)
+ {
+ dreg_state.dbg_regs[i].addr = addr_buf[i];
+ dreg_state.dbg_regs[i].ctrl = cntrl_buf[i];
+ }
- return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), &type, &ioVec, ioVec.iov_len);
+ return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), &type, &ioVec, ioVec.iov_len);
+ });
}
Error
Modified: lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp?rev=242391&r1=242390&r2=242391&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp Thu Jul 16 03:45:03 2015
@@ -877,13 +877,19 @@ NativeRegisterContextLinux_mips64::IsWat
// reading the current state of watch regs
struct pt_watch_regs watch_readback;
- Error error = DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(&watch_readback));
+ NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+ NativeProcessLinux *const process_p = static_cast<NativeProcessLinux*> (process_sp.get ());
+ Error error = process_p->DoOperation([&] {
+ return DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(&watch_readback));
+ });
if (GetWatchHi (&watch_readback, wp_index) & (IRW))
{
// clear hit flag in watchhi
SetWatchHi (&watch_readback, wp_index, (GetWatchHi (&watch_readback, wp_index) & ~(IRW)));
- DoWriteWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(&watch_readback));
+ process_p->DoOperation([&] {
+ return DoWriteWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(&watch_readback));
+ });
is_hit = true;
return error;
@@ -924,7 +930,11 @@ NativeRegisterContextLinux_mips64::Clear
struct pt_watch_regs regs;
// First reading the current state of watch regs
- DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void*>(®s));
+ NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+ NativeProcessLinux *const process_p = static_cast<NativeProcessLinux*> (process_sp.get ());
+ process_p->DoOperation([&] {
+ return DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void*>(®s));
+ });
if (regs.style == pt_watch_style_mips32)
{
@@ -939,7 +949,9 @@ NativeRegisterContextLinux_mips64::Clear
regs.mips64.watch_masks[wp_index] = default_watch_regs.mips64.watch_masks[wp_index];
}
- Error error = DoWriteWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(®s));
+ Error error = process_p->DoOperation([&] {
+ return DoWriteWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(®s));
+ });
if(!error.Fail())
{
hw_addr_map[wp_index] = LLDB_INVALID_ADDRESS;
@@ -951,7 +963,11 @@ NativeRegisterContextLinux_mips64::Clear
Error
NativeRegisterContextLinux_mips64::ClearAllHardwareWatchpoints()
{
- return DoWriteWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(&default_watch_regs));
+ NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+ NativeProcessLinux *const process_p = static_cast<NativeProcessLinux *> (process_sp.get ());
+ return process_p->DoOperation([&] {
+ return DoWriteWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(&default_watch_regs));
+ });
}
Error
@@ -970,7 +986,11 @@ NativeRegisterContextLinux_mips64::SetHa
struct pt_watch_regs regs;
// First reading the current state of watch regs
- DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(®s));
+ NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+ NativeProcessLinux *const process_p = static_cast<NativeProcessLinux*> (process_sp.get ());
+ process_p->DoOperation([&] {
+ return DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(®s));
+ });
// Try if a new watch point fits in this state
int index = GetVacantWatchIndex (®s, addr, size, watch_flags, NumSupportedHardwareWatchpoints());
@@ -981,7 +1001,9 @@ NativeRegisterContextLinux_mips64::SetHa
// It fits, so we go ahead with updating the state of watch regs
- DoWriteWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(®s));
+ process_p->DoOperation([&] {
+ return DoWriteWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(®s));
+ });
// Storing exact address
hw_addr_map[index] = addr;
@@ -1005,7 +1027,17 @@ NativeRegisterContextLinux_mips64::NumSu
static int num_valid = 0;
if (!num_valid)
{
- DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(®s));
+ NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+ if (!process_sp)
+ {
+ printf ("NativeProcessProtocol is NULL");
+ return 0;
+ }
+
+ NativeProcessLinux *const process_p = static_cast<NativeProcessLinux*> (process_sp.get ());
+ process_p->DoOperation([&] {
+ return DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(®s));
+ });
default_watch_regs = regs; // Keeping default watch regs values for future use
switch (regs.style)
{
Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp?rev=242391&r1=242390&r2=242391&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp Thu Jul 16 03:45:03 2015
@@ -96,6 +96,20 @@ GDBRemoteCommunicationServerLLGS::GDBRem
RegisterPacketHandlers();
}
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+GDBRemoteCommunicationServerLLGS::~GDBRemoteCommunicationServerLLGS()
+{
+ Mutex::Locker locker (m_debugged_process_mutex);
+
+ if (m_debugged_process_sp)
+ {
+ m_debugged_process_sp->Terminate ();
+ m_debugged_process_sp.reset ();
+ }
+}
+
void
GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers()
{
@@ -209,7 +223,6 @@ GDBRemoteCommunicationServerLLGS::Launch
error = NativeProcessProtocol::Launch(
m_process_launch_info,
*this,
- m_mainloop,
m_debugged_process_sp);
}
@@ -295,7 +308,7 @@ GDBRemoteCommunicationServerLLGS::Attach
}
// Try to attach.
- error = NativeProcessProtocol::Attach(pid, *this, m_mainloop, m_debugged_process_sp);
+ error = NativeProcessProtocol::Attach(pid, *this, m_debugged_process_sp);
if (!error.Success ())
{
fprintf (stderr, "%s: failed to attach to process %" PRIu64 ": %s", __FUNCTION__, pid, error.AsCString ());
Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h?rev=242391&r1=242390&r2=242391&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h Thu Jul 16 03:45:03 2015
@@ -42,6 +42,9 @@ public:
//------------------------------------------------------------------
GDBRemoteCommunicationServerLLGS(const lldb::PlatformSP& platform_sp, MainLoop &mainloop);
+ virtual
+ ~GDBRemoteCommunicationServerLLGS();
+
//------------------------------------------------------------------
/// Specify the program to launch and its arguments.
///
More information about the lldb-commits
mailing list