[lldb-dev] [PATCH 2/2] Support debugging yourself on Linux.
eatnumber1 at google.com
eatnumber1 at google.com
Fri Sep 26 09:56:48 PDT 2014
From: Russell Harmon <eatnumber1 at google.com>
---
source/Plugins/Process/Linux/CMakeLists.txt | 2 +
source/Plugins/Process/Linux/ProcessMonitor.cpp | 16 ++
source/Plugins/Process/Linux/ProcessMonitor.h | 25 +--
.../Plugins/Process/Linux/ProcessMonitorOther.cpp | 6 +-
source/Plugins/Process/Linux/ProcessMonitorOther.h | 2 -
.../Plugins/Process/Linux/ProcessMonitorSelf.cpp | 237 +++++++++++++++++++++
source/Plugins/Process/Linux/ProcessMonitorSelf.h | 164 ++++++++++++++
source/Plugins/Process/POSIX/ProcessPOSIX.cpp | 9 +-
8 files changed, 439 insertions(+), 22 deletions(-)
create mode 100644 source/Plugins/Process/Linux/ProcessMonitor.cpp
create mode 100644 source/Plugins/Process/Linux/ProcessMonitorSelf.cpp
create mode 100644 source/Plugins/Process/Linux/ProcessMonitorSelf.h
diff --git a/source/Plugins/Process/Linux/CMakeLists.txt b/source/Plugins/Process/Linux/CMakeLists.txt
index 9b04315..021828e 100644
--- a/source/Plugins/Process/Linux/CMakeLists.txt
+++ b/source/Plugins/Process/Linux/CMakeLists.txt
@@ -9,7 +9,9 @@ add_lldb_library(lldbPluginProcessLinux
NativeRegisterContextLinux_x86_64.cpp
NativeThreadLinux.cpp
ProcessLinux.cpp
+ ProcessMonitor.cpp
ProcessMonitorOther.cpp
+ ProcessMonitorSelf.cpp
ProcFileReader.cpp
LinuxThread.cpp
)
diff --git a/source/Plugins/Process/Linux/ProcessMonitor.cpp b/source/Plugins/Process/Linux/ProcessMonitor.cpp
new file mode 100644
index 0000000..780d20a
--- /dev/null
+++ b/source/Plugins/Process/Linux/ProcessMonitor.cpp
@@ -0,0 +1,16 @@
+//===-- ProcessMonitor.cpp ------------------------------------ -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ProcessPOSIX.h"
+#include "ProcessLinux.h"
+#include "ProcessMonitor.h"
+
+ProcessMonitor::ProcessMonitor(ProcessPOSIX *process)
+ : m_process(static_cast<ProcessLinux *>(process))
+{}
diff --git a/source/Plugins/Process/Linux/ProcessMonitor.h b/source/Plugins/Process/Linux/ProcessMonitor.h
index 96ddf28..1c3c9d3 100644
--- a/source/Plugins/Process/Linux/ProcessMonitor.h
+++ b/source/Plugins/Process/Linux/ProcessMonitor.h
@@ -22,12 +22,9 @@
namespace lldb_private
{
class Error;
-class Module;
-class Scalar;
} // End lldb_private namespace.
class ProcessLinux;
-class Operation;
/// @class ProcessMonitor
/// @brief Manages communication with the inferior (debugee) process.
@@ -44,12 +41,18 @@ class Operation;
class ProcessMonitor
{
public:
- virtual ~ProcessMonitor() {};
+ ProcessMonitor(ProcessPOSIX *process);
+
+ virtual ~ProcessMonitor() {}
/// Provides the process number of debugee.
virtual lldb::pid_t
GetPID() const = 0;
+ /// Returns the process associated with this ProcessMonitorOther.
+ ProcessLinux &
+ GetProcess() { return *m_process; }
+
/// Returns a file descriptor to the controlling terminal of the inferior
/// process.
///
@@ -125,17 +128,6 @@ public:
virtual bool
ReadThreadPointer(lldb::tid_t tid, lldb::addr_t &value) = 0;
- /// Writes a siginfo_t structure corresponding to the given thread ID to the
- /// memory region pointed to by @p siginfo.
- virtual bool
- GetSignalInfo(lldb::tid_t tid, void *siginfo, int &ptrace_err) = 0;
-
- /// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG)
- /// corresponding to the given thread IDto the memory pointed to by @p
- /// message.
- virtual bool
- GetEventMessage(lldb::tid_t tid, unsigned long *message) = 0;
-
/// Resumes the given thread. If @p signo is anything but
/// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread.
virtual bool
@@ -164,6 +156,9 @@ public:
// Waits for the initial stop message from a new thread.
virtual bool
WaitForInitialTIDStop(lldb::tid_t tid) = 0;
+
+protected:
+ ProcessLinux *m_process;
};
#endif // #ifndef liblldb_ProcessMonitor_H_
diff --git a/source/Plugins/Process/Linux/ProcessMonitorOther.cpp b/source/Plugins/Process/Linux/ProcessMonitorOther.cpp
index 6ba900d..d151663 100644
--- a/source/Plugins/Process/Linux/ProcessMonitorOther.cpp
+++ b/source/Plugins/Process/Linux/ProcessMonitorOther.cpp
@@ -1008,8 +1008,7 @@ ProcessMonitorOther::ProcessMonitorOther(ProcessPOSIX *process,
const char *stderr_path,
const char *working_dir,
lldb_private::Error &error)
- : ProcessMonitor(),
- m_process(static_cast<ProcessLinux *>(process)),
+ : ProcessMonitor(process),
m_operation_thread(LLDB_INVALID_HOST_THREAD),
m_monitor_thread(LLDB_INVALID_HOST_THREAD),
m_pid(LLDB_INVALID_PROCESS_ID),
@@ -1062,8 +1061,7 @@ WAIT_AGAIN:
ProcessMonitorOther::ProcessMonitorOther(ProcessPOSIX *process,
lldb::pid_t pid,
lldb_private::Error &error)
- : ProcessMonitor(),
- m_process(static_cast<ProcessLinux *>(process)),
+ : ProcessMonitor(process),
m_operation_thread(LLDB_INVALID_HOST_THREAD),
m_monitor_thread(LLDB_INVALID_HOST_THREAD),
m_pid(LLDB_INVALID_PROCESS_ID),
diff --git a/source/Plugins/Process/Linux/ProcessMonitorOther.h b/source/Plugins/Process/Linux/ProcessMonitorOther.h
index 7a61cc2..d5dc087 100644
--- a/source/Plugins/Process/Linux/ProcessMonitorOther.h
+++ b/source/Plugins/Process/Linux/ProcessMonitorOther.h
@@ -194,8 +194,6 @@ public:
WaitForInitialTIDStop(lldb::tid_t tid);
private:
- ProcessLinux *m_process;
-
lldb::thread_t m_operation_thread;
lldb::thread_t m_monitor_thread;
lldb::pid_t m_pid;
diff --git a/source/Plugins/Process/Linux/ProcessMonitorSelf.cpp b/source/Plugins/Process/Linux/ProcessMonitorSelf.cpp
new file mode 100644
index 0000000..79e2833
--- /dev/null
+++ b/source/Plugins/Process/Linux/ProcessMonitorSelf.cpp
@@ -0,0 +1,237 @@
+//===-- ProcessMonitorSelf.cpp ------------------------------------ -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-python.h"
+
+// C Includes
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <stddef.h>
+
+// C++ Includes
+// Self libraries and framework includes
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Utility/PseudoTerminal.h"
+
+#include "POSIXThread.h"
+#include "ProcessLinux.h"
+#include "ProcessPOSIXLog.h"
+#include "ProcessMonitorSelf.h"
+
+using namespace lldb_private;
+
+ProcessMonitorSelf::ProcessMonitorSelf(ProcessPOSIX *process,
+ lldb_private::Error &error)
+ : ProcessMonitor(process),
+ m_terminal_fd(-1)
+{
+ // TODO: Determine a better size for this buffer
+ // TODO: Do something reasonable if stderr is not open on the same terminal
+ // as stdout.
+ char buf[1024];
+ int err = ttyname_r(STDOUT_FILENO, buf, 1024);
+ if (err != 0) {
+ // TODO: Handle the error
+ assert(false);
+ }
+
+ int fd = open(buf, O_RDONLY);
+ if (fd == -1) {
+ // TODO: Handle the error
+ assert(false);
+ }
+
+ m_terminal_fd = fd;
+
+ process->SendMessage(ProcessMessage::Attach(GetPID()));
+}
+
+ProcessMonitorSelf::~ProcessMonitorSelf() {
+ // TODO: Handle errors on close
+ close(m_terminal_fd);
+}
+
+/// Provides the process number of debugee.
+lldb::pid_t
+ProcessMonitorSelf::GetPID() const
+{
+ return getpid();
+}
+
+/// Returns a file descriptor to the controlling terminal of the inferior
+/// process.
+///
+/// Reads from this file descriptor yield both the standard output and
+/// standard error of this debugee. Even if stderr and stdout were
+/// redirected on launch it may still happen that data is available on this
+/// descriptor (if the inferior process opens /dev/tty, for example).
+///
+/// If this monitor was attached to an existing process this method returns
+/// -1.
+int
+ProcessMonitorSelf::GetTerminalFD() const {
+ return m_terminal_fd;
+}
+
+/// Reads @p size bytes from address @vm_adder in the inferior process
+/// address space.
+///
+/// This method is provided to implement Process::DoReadMemory.
+size_t
+ProcessMonitorSelf::ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
+ lldb_private::Error &error)
+{
+ memcpy(buf, (void *) vm_addr, size);
+ return size;
+}
+
+/// Writes @p size bytes from address @p vm_adder in the inferior process
+/// address space.
+///
+/// This method is provided to implement Process::DoWriteMemory.
+size_t
+ProcessMonitorSelf::WriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size,
+ lldb_private::Error &error)
+{
+ memcpy((void *) vm_addr, buf, size);
+ return size;
+}
+
+/// Reads the contents from the register identified by the given (architecture
+/// dependent) offset.
+///
+/// This method is provided for use by RegisterContextLinux derivatives.
+bool
+ProcessMonitorSelf::ReadRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name,
+ unsigned size, lldb_private::RegisterValue &value)
+{
+ assert(false);
+}
+
+/// Writes the given value to the register identified by the given
+/// (architecture dependent) offset.
+///
+/// This method is provided for use by RegisterContextLinux derivatives.
+bool
+ProcessMonitorSelf::WriteRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name,
+ const lldb_private::RegisterValue &value)
+{
+ assert(false);
+}
+
+/// Reads all general purpose registers into the specified buffer.
+bool
+ProcessMonitorSelf::ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size)
+{
+ assert(false);
+}
+
+/// Reads generic floating point registers into the specified buffer.
+bool
+ProcessMonitorSelf::ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size)
+{
+ assert(false);
+}
+
+/// Reads the specified register set into the specified buffer.
+/// For instance, the extended floating-point register set.
+bool
+ProcessMonitorSelf::ReadRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset)
+{
+ assert(false);
+}
+
+/// Writes all general purpose registers into the specified buffer.
+bool
+ProcessMonitorSelf::WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size)
+{
+ assert(false);
+}
+
+/// Writes generic floating point registers into the specified buffer.
+bool
+ProcessMonitorSelf::WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size)
+{
+ assert(false);
+}
+
+/// Writes the specified register set into the specified buffer.
+/// For instance, the extended floating-point register set.
+bool
+ProcessMonitorSelf::WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset)
+{
+ assert(false);
+}
+
+/// Reads the value of the thread-specific pointer for a given thread ID.
+bool
+ProcessMonitorSelf::ReadThreadPointer(lldb::tid_t tid, lldb::addr_t &value)
+{
+ assert(false);
+}
+
+/// Resumes the given thread. If @p signo is anything but
+/// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread.
+bool
+ProcessMonitorSelf::Resume(lldb::tid_t tid, uint32_t signo)
+{
+ assert(false);
+}
+
+/// Single steps the given thread. If @p signo is anything but
+/// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread.
+bool
+ProcessMonitorSelf::SingleStep(lldb::tid_t tid, uint32_t signo)
+{
+ assert(false);
+}
+
+/// Terminate the traced process.
+bool
+ProcessMonitorSelf::Kill()
+{
+ exit(EXIT_SUCCESS);
+}
+
+lldb_private::Error
+ProcessMonitorSelf::Detach(lldb::tid_t tid)
+{
+ return Error();
+}
+
+/// Stops the monitoring the child process thread.
+void
+ProcessMonitorSelf::StopMonitor()
+{}
+
+/// Stops the requested thread and waits for the stop signal.
+bool
+ProcessMonitorSelf::StopThread(lldb::tid_t tid)
+{
+ assert(false);
+}
+
+// Waits for the initial stop message from a new thread.
+bool
+ProcessMonitorSelf::WaitForInitialTIDStop(lldb::tid_t tid)
+{
+ assert(false);
+}
diff --git a/source/Plugins/Process/Linux/ProcessMonitorSelf.h b/source/Plugins/Process/Linux/ProcessMonitorSelf.h
new file mode 100644
index 0000000..4b4a4e4
--- /dev/null
+++ b/source/Plugins/Process/Linux/ProcessMonitorSelf.h
@@ -0,0 +1,164 @@
+//===-- ProcessMonitorSelf.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_ProcessMonitorSelf_H_
+#define liblldb_ProcessMonitorSelf_H_
+
+// C Includes
+#include <semaphore.h>
+#include <signal.h>
+
+// C++ Includes
+// Self libraries and framework includes
+#include "lldb/lldb-types.h"
+#include "lldb/Host/Mutex.h"
+
+#include "ProcessMonitor.h"
+
+namespace lldb_private
+{
+class Error;
+class Module;
+class Scalar;
+} // End lldb_private namespace.
+
+class ProcessLinux;
+class Operation;
+
+/// @class ProcessMonitorSelf
+/// @brief Manages communication with the inferior (debugee) process.
+///
+/// Upon construction, this class prepares and launches an inferior process for
+/// debugging.
+///
+/// Changes in the inferior process state are propagated to the associated
+/// ProcessLinux instance by calling ProcessLinux::SendMessage with the
+/// appropriate ProcessMessage events.
+///
+/// A purposely minimal set of operations are provided to interrogate and change
+/// the inferior process state.
+class ProcessMonitorSelf : public ProcessMonitor
+{
+public:
+ ProcessMonitorSelf(ProcessPOSIX *process, lldb_private::Error &error);
+ ~ProcessMonitorSelf();
+
+ /// Provides the process number of debugee.
+ lldb::pid_t
+ GetPID() const;
+
+ /// Returns a file descriptor to the controlling terminal of the inferior
+ /// process.
+ ///
+ /// Reads from this file descriptor yield both the standard output and
+ /// standard error of this debugee. Even if stderr and stdout were
+ /// redirected on launch it may still happen that data is available on this
+ /// descriptor (if the inferior process opens /dev/tty, for example).
+ ///
+ /// If this monitor was attached to an existing process this method returns
+ /// -1.
+ int
+ GetTerminalFD() const;
+
+ /// Reads @p size bytes from address @vm_adder in the inferior process
+ /// address space.
+ ///
+ /// This method is provided to implement Process::DoReadMemory.
+ size_t
+ ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
+ lldb_private::Error &error);
+
+ /// Writes @p size bytes from address @p vm_adder in the inferior process
+ /// address space.
+ ///
+ /// This method is provided to implement Process::DoWriteMemory.
+ size_t
+ WriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size,
+ lldb_private::Error &error);
+
+ /// Reads the contents from the register identified by the given (architecture
+ /// dependent) offset.
+ ///
+ /// This method is provided for use by RegisterContextLinux derivatives.
+ bool
+ ReadRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name,
+ unsigned size, lldb_private::RegisterValue &value);
+
+ /// Writes the given value to the register identified by the given
+ /// (architecture dependent) offset.
+ ///
+ /// This method is provided for use by RegisterContextLinux derivatives.
+ bool
+ WriteRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name,
+ const lldb_private::RegisterValue &value);
+
+ /// Reads all general purpose registers into the specified buffer.
+ bool
+ ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size);
+
+ /// Reads generic floating point registers into the specified buffer.
+ bool
+ ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size);
+
+ /// Reads the specified register set into the specified buffer.
+ /// For instance, the extended floating-point register set.
+ bool
+ ReadRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset);
+
+ /// Writes all general purpose registers into the specified buffer.
+ bool
+ WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size);
+
+ /// Writes generic floating point registers into the specified buffer.
+ bool
+ WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size);
+
+ /// Writes the specified register set into the specified buffer.
+ /// For instance, the extended floating-point register set.
+ bool
+ WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset);
+
+ /// Reads the value of the thread-specific pointer for a given thread ID.
+ bool
+ ReadThreadPointer(lldb::tid_t tid, lldb::addr_t &value);
+
+ /// Resumes the given thread. If @p signo is anything but
+ /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread.
+ bool
+ Resume(lldb::tid_t tid, uint32_t signo);
+
+ /// Single steps the given thread. If @p signo is anything but
+ /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread.
+ bool
+ SingleStep(lldb::tid_t tid, uint32_t signo);
+
+ /// Terminate the traced process.
+ bool
+ Kill();
+
+ lldb_private::Error
+ Detach(lldb::tid_t tid);
+
+ /// Stops the monitoring the child process thread.
+ void
+ StopMonitor();
+
+ /// Stops the requested thread and waits for the stop signal.
+ bool
+ StopThread(lldb::tid_t tid);
+
+ // Waits for the initial stop message from a new thread.
+ bool
+ WaitForInitialTIDStop(lldb::tid_t tid);
+
+private:
+ int m_terminal_fd;
+};
+
+#endif // #ifndef liblldb_ProcessMonitorSelf_H_
diff --git a/source/Plugins/Process/POSIX/ProcessPOSIX.cpp b/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
index 8333f01..fef629e 100644
--- a/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
+++ b/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
@@ -11,6 +11,8 @@
// C Includes
#include <errno.h>
+#include <sys/types.h>
+#include <unistd.h>
// C++ Includes
// Other libraries and framework includes
@@ -30,6 +32,7 @@
#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
#include "ProcessMonitor.h"
#include "ProcessMonitorOther.h"
+#include "ProcessMonitorSelf.h"
#include "POSIXThread.h"
using namespace lldb;
@@ -124,7 +127,11 @@ ProcessPOSIX::DoAttachToProcessWithID(lldb::pid_t pid)
if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
log->Printf ("ProcessPOSIX::%s(pid = %" PRIi64 ")", __FUNCTION__, GetID());
- m_monitor = new ProcessMonitorOther(this, pid, error);
+ if ((::pid_t) pid == getpid()) {
+ m_monitor = new ProcessMonitorSelf(this, error);
+ } else {
+ m_monitor = new ProcessMonitorOther(this, pid, error);
+ }
if (!error.Success())
return error;
--
2.1.0.rc2.206.gedb03e5
More information about the lldb-dev
mailing list