diff options
Diffstat (limited to 'lldb/source/Plugins/Process')
5 files changed, 111 insertions, 1 deletions
diff --git a/lldb/source/Plugins/Process/Linux/ProcessMonitor.cpp b/lldb/source/Plugins/Process/Linux/ProcessMonitor.cpp index a0cda3485c6..bda0cb33097 100644 --- a/lldb/source/Plugins/Process/Linux/ProcessMonitor.cpp +++ b/lldb/source/Plugins/Process/Linux/ProcessMonitor.cpp @@ -19,6 +19,7 @@ #include <sys/socket.h> #include <sys/syscall.h> #include <sys/types.h> +#include <sys/user.h> #include <sys/wait.h> // C++ Includes @@ -46,6 +47,19 @@ #ifndef PTRACE_SETREGSET #define PTRACE_SETREGSET 0x4205 #endif +#ifndef PTRACE_GET_THREAD_AREA + #define PTRACE_GET_THREAD_AREA 25 +#endif +#ifndef PTRACE_ARCH_PRCTL + #define PTRACE_ARCH_PRCTL 30 +#endif +#ifndef ARCH_GET_FS + #define ARCH_SET_GS 0x1001 + #define ARCH_SET_FS 0x1002 + #define ARCH_GET_FS 0x1003 + #define ARCH_GET_GS 0x1004 +#endif + // Support hardware breakpoints in case it has not been defined #ifndef TRAP_HWBKPT @@ -703,6 +717,74 @@ WriteRegisterSetOperation::Execute(ProcessMonitor *monitor) } //------------------------------------------------------------------------------ +/// @class ReadThreadPointerOperation +/// @brief Implements ProcessMonitor::ReadThreadPointer. +class ReadThreadPointerOperation : public Operation +{ +public: + ReadThreadPointerOperation(lldb::tid_t tid, lldb::addr_t *addr, bool &result) + : m_tid(tid), m_addr(addr), m_result(result) + { } + + void Execute(ProcessMonitor *monitor); + +private: + lldb::tid_t m_tid; + lldb::addr_t *m_addr; + bool &m_result; +}; + +void +ReadThreadPointerOperation::Execute(ProcessMonitor *monitor) +{ + Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS)); + if (log) + log->Printf ("ProcessMonitor::%s()", __FUNCTION__); + + // The process for getting the thread area on Linux is + // somewhat... obscure. There's several different ways depending on + // what arch you're on, and what kernel version you have. + + const ArchSpec& arch = monitor->GetProcess().GetTarget().GetArchitecture(); + switch(arch.GetMachine()) + { + case llvm::Triple::x86: + { + // Find the GS register location for our host architecture. + size_t gs_user_offset = offsetof(struct user, regs); +#ifdef __x86_64__ + gs_user_offset += offsetof(struct user_regs_struct, gs); +#endif +#ifdef __i386__ + gs_user_offset += offsetof(struct user_regs_struct, xgs); +#endif + + // Read the GS register value to get the selector. + errno = 0; + long gs = PTRACE(PTRACE_PEEKUSER, m_tid, (void*)gs_user_offset, NULL, 0); + if (errno) + { + m_result = false; + break; + } + + // Read the LDT base for that selector. + uint32_t tmp[4]; + m_result = (PTRACE(PTRACE_GET_THREAD_AREA, m_tid, (void *)(gs >> 3), &tmp, 0) == 0); + *m_addr = tmp[1]; + break; + } + case llvm::Triple::x86_64: + // Read the FS register base. + m_result = (PTRACE(PTRACE_ARCH_PRCTL, m_tid, m_addr, (void *)ARCH_GET_FS, 0) == 0); + break; + default: + m_result = false; + break; + } +} + +//------------------------------------------------------------------------------ /// @class ResumeOperation /// @brief Implements ProcessMonitor::Resume. class ResumeOperation : public Operation @@ -2106,6 +2188,15 @@ ProcessMonitor::WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, un } bool +ProcessMonitor::ReadThreadPointer(lldb::tid_t tid, lldb::addr_t &value) +{ + bool result; + ReadThreadPointerOperation op(tid, &value, result); + DoOperation(&op); + return result; +} + +bool ProcessMonitor::Resume(lldb::tid_t tid, uint32_t signo) { bool result; diff --git a/lldb/source/Plugins/Process/Linux/ProcessMonitor.h b/lldb/source/Plugins/Process/Linux/ProcessMonitor.h index 3729e257feb..a087140f407 100644 --- a/lldb/source/Plugins/Process/Linux/ProcessMonitor.h +++ b/lldb/source/Plugins/Process/Linux/ProcessMonitor.h @@ -147,6 +147,10 @@ public: 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); + /// Writes a siginfo_t structure corresponding to the given thread ID to the /// memory region pointed to by @p siginfo. bool diff --git a/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp b/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp index db68875723c..16399748c54 100644 --- a/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp +++ b/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp @@ -230,6 +230,17 @@ POSIXThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame) return reg_ctx_sp; } +lldb::addr_t +POSIXThread::GetThreadPointer () +{ + ProcessMonitor &monitor = GetMonitor(); + addr_t addr; + if (monitor.ReadThreadPointer (GetID(), addr)) + return addr; + else + return LLDB_INVALID_ADDRESS; +} + bool POSIXThread::CalculateStopInfo() { diff --git a/lldb/source/Plugins/Process/POSIX/POSIXThread.h b/lldb/source/Plugins/Process/POSIX/POSIXThread.h index 5490f1f1ea5..51d6645f209 100644 --- a/lldb/source/Plugins/Process/POSIX/POSIXThread.h +++ b/lldb/source/Plugins/Process/POSIX/POSIXThread.h @@ -59,6 +59,9 @@ public: virtual lldb::RegisterContextSP CreateRegisterContextForFrame (lldb_private::StackFrame *frame); + virtual lldb::addr_t + GetThreadPointer (); + //-------------------------------------------------------------------------- // These functions provide a mapping from the register offset // back to the register index or name for use in debugging or log diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp index 2a01d6a92d9..c19aec3a02c 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp @@ -1196,7 +1196,8 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat DataExtractor dwarfdata (unwindplan_regloc.GetDWARFExpressionBytes(), unwindplan_regloc.GetDWARFExpressionLength(), process->GetByteOrder(), process->GetAddressByteSize()); - DWARFExpression dwarfexpr (dwarfdata, 0, unwindplan_regloc.GetDWARFExpressionLength()); + ModuleSP opcode_ctx; + DWARFExpression dwarfexpr (opcode_ctx, dwarfdata, 0, unwindplan_regloc.GetDWARFExpressionLength()); dwarfexpr.SetRegisterKind (unwindplan_registerkind); Value result; Error error; |