Index: lldb/trunk/source/Plugins/Process/Linux/CMakeLists.txt =================================================================== --- lldb/trunk/source/Plugins/Process/Linux/CMakeLists.txt +++ lldb/trunk/source/Plugins/Process/Linux/CMakeLists.txt @@ -7,6 +7,7 @@ add_lldb_library(lldbPluginProcessLinux LinuxThread.cpp NativeProcessLinux.cpp + NativeRegisterContextLinux.cpp NativeRegisterContextLinux_arm.cpp NativeRegisterContextLinux_arm64.cpp NativeRegisterContextLinux_x86_64.cpp @@ -16,4 +17,3 @@ ProcessMonitor.cpp ProcFileReader.cpp ) - Index: lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h =================================================================== --- lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h +++ lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h @@ -60,6 +60,37 @@ NativeProcessProtocol::NativeDelegate &native_delegate, NativeProcessProtocolSP &native_process_sp); + //------------------------------------------------------------------------------ + /// @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. The Operation class provides an abstract base for all services the + /// NativeProcessLinux must perform via the single virtual function Execute, thus + /// encapsulating the code that needs to run in the privileged context. + class Operation + { + public: + Operation () : m_error() { } + + virtual + ~Operation() {} + + virtual void + Execute (NativeProcessLinux *process) = 0; + + const Error & + GetError () const { return m_error; } + + protected: + Error m_error; + }; + + typedef std::unique_ptr OperationUP; + // --------------------------------------------------------------------- // NativeProcessProtocol Interface // --------------------------------------------------------------------- @@ -123,64 +154,20 @@ void Terminate () override; + Error + GetLoadedModuleFileSpec(const char* module_path, FileSpec& file_spec) override; + // --------------------------------------------------------------------- // Interface used by NativeRegisterContext-derived classes. // --------------------------------------------------------------------- - - /// Reads the contents from the register identified by the given (architecture - /// dependent) offset. - /// - /// This method is provided for use by RegisterContextLinux derivatives. - Error - ReadRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name, - unsigned size, 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. Error - WriteRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name, - const RegisterValue &value); + DoOperation(Operation* op); - /// Reads all general purpose registers into the specified buffer. Error - ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size); + DoOperation(OperationUP op) { return DoOperation(op.get()); } - /// Reads generic floating point registers into the specified buffer. - Error - ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size); - - /// Reads hardware breakpoints and watchpoints capability information. - Error - ReadHardwareDebugInfo (lldb::tid_t tid, unsigned int &watch_count , - unsigned int &break_count); - - /// Write hardware breakpoint/watchpoint control and address registers. - Error - WriteHardwareDebugRegs (lldb::tid_t tid, lldb::addr_t *addr_buf, - uint32_t *cntrl_buf, int type, int count); - - /// Reads the specified register set into the specified buffer. - /// For instance, the extended floating-point register set. - Error - ReadRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset); - - /// Writes all general purpose registers into the specified buffer. - Error - WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size); - - /// Writes generic floating point registers into the specified buffer. - Error - 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. - Error - WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset); - - Error - GetLoadedModuleFileSpec(const char* module_path, FileSpec& file_spec) override; + static long + PtraceWrapper(int req, lldb::pid_t pid, void *addr, void *data, size_t data_size, Error& error); protected: // --------------------------------------------------------------------- Index: lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -61,11 +61,6 @@ #include #include -#if defined (__arm64__) || defined (__aarch64__) -// NT_PRSTATUS and NT_FPREGSET definition -#include -#endif - #include "lldb/Host/linux/Personality.h" #include "lldb/Host/linux/Ptrace.h" #include "lldb/Host/linux/Signalfd.h" @@ -78,16 +73,6 @@ #define TRAP_HWBKPT 4 #endif -// We disable the tracing of ptrace calls for integration builds to -// avoid the additional indirection and checks. -#ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION -#define PTRACE(req, pid, addr, data, data_size, error) \ - PtraceWrapper((req), (pid), (addr), (data), (data_size), (error), #req, __FILE__, __LINE__) -#else -#define PTRACE(req, pid, addr, data, data_size, error) \ - PtraceWrapper((req), (pid), (addr), (data), (data_size), (error)) -#endif - using namespace lldb; using namespace lldb_private; using namespace lldb_private::process_linux; @@ -204,72 +189,6 @@ } } - // Wrapper for ptrace to catch errors and log calls. - // Note that ptrace sets errno on error because -1 can be a valid result (i.e. for PTRACE_PEEK*) - long - PtraceWrapper(int req, lldb::pid_t pid, void *addr, void *data, size_t data_size, Error& error, - const char* reqName, const char* file, int line) - { - long int result; - - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PTRACE)); - - PtraceDisplayBytes(req, data, data_size); - - error.Clear(); - errno = 0; - if (req == PTRACE_GETREGSET || req == PTRACE_SETREGSET) - result = ptrace(static_cast<__ptrace_request>(req), static_cast< ::pid_t>(pid), *(unsigned int *)addr, data); - else - result = ptrace(static_cast<__ptrace_request>(req), static_cast< ::pid_t>(pid), addr, data); - - if (result == -1) - error.SetErrorToErrno(); - - if (log) - log->Printf("ptrace(%s, %" PRIu64 ", %p, %p, %zu)=%lX called from file %s line %d", - reqName, pid, addr, data, data_size, result, file, line); - - PtraceDisplayBytes(req, data, data_size); - - if (log && error.GetError() != 0) - { - const char* str; - switch (error.GetError()) - { - case ESRCH: str = "ESRCH"; break; - case EINVAL: str = "EINVAL"; break; - case EBUSY: str = "EBUSY"; break; - case EPERM: str = "EPERM"; break; - default: str = error.AsCString(); - } - log->Printf("ptrace() failed; errno=%d (%s)", error.GetError(), str); - } - - return result; - } - -#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION - // Wrapper for ptrace when logging is not required. - // Sets errno to 0 prior to calling ptrace. - long - PtraceWrapper(int req, lldb::pid_t pid, void *addr, void *data, size_t data_size, Error& error) - { - long result = 0; - - error.Clear(); - errno = 0; - if (req == PTRACE_GETREGSET || req == PTRACE_SETREGSET) - result = ptrace(static_cast<__ptrace_request>(req), static_cast< ::pid_t>(pid), *(unsigned int *)addr, data); - else - result = ptrace(static_cast<__ptrace_request>(req), static_cast< ::pid_t>(pid), addr, data); - - if (result == -1) - error.SetErrorToErrno(); - return result; - } -#endif - //------------------------------------------------------------------------------ // Static implementations of NativeProcessLinux::ReadMemory and // NativeProcessLinux::WriteMemory. This enables mutual recursion between these @@ -300,7 +219,7 @@ assert(sizeof(data) >= word_size); for (bytes_read = 0; bytes_read < size; bytes_read += remainder) { - data = PTRACE(PTRACE_PEEKDATA, pid, (void*)vm_addr, nullptr, 0, error); + data = NativeProcessLinux::PtraceWrapper(PTRACE_PEEKDATA, pid, (void*)vm_addr, nullptr, 0, error); if (error.Fail()) { if (log) @@ -377,7 +296,7 @@ log->Printf ("NativeProcessLinux::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__, (void*)vm_addr, *(const unsigned long*)src, data); - if (PTRACE(PTRACE_POKEDATA, pid, (void*)vm_addr, (void*)data, 0, error)) + if (NativeProcessLinux::PtraceWrapper(PTRACE_POKEDATA, pid, (void*)vm_addr, (void*)data, 0, error)) { if (log) ProcessPOSIXLog::DecNestLevel(); @@ -422,38 +341,9 @@ } //------------------------------------------------------------------------------ - /// @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. The Operation class provides an abstract base for all services the - /// NativeProcessLinux must perform via the single virtual function Execute, thus - /// encapsulating the code that needs to run in the privileged context. - class Operation - { - public: - Operation () : m_error() { } - - virtual - ~Operation() {} - - virtual void - Execute (NativeProcessLinux *process) = 0; - - const Error & - GetError () const { return m_error; } - - protected: - Error m_error; - }; - - //------------------------------------------------------------------------------ /// @class ReadOperation /// @brief Implements NativeProcessLinux::ReadMemory. - class ReadOperation : public Operation + class ReadOperation : public NativeProcessLinux::Operation { public: ReadOperation( @@ -487,7 +377,7 @@ //------------------------------------------------------------------------------ /// @class WriteOperation /// @brief Implements NativeProcessLinux::WriteMemory. - class WriteOperation : public Operation + class WriteOperation : public NativeProcessLinux::Operation { public: WriteOperation( @@ -519,463 +409,9 @@ } //------------------------------------------------------------------------------ - /// @class ReadRegOperation - /// @brief Implements NativeProcessLinux::ReadRegisterValue. - class ReadRegOperation : public Operation - { - public: - ReadRegOperation(lldb::tid_t tid, uint32_t offset, const char *reg_name, - RegisterValue &value) - : m_tid(tid), - m_offset(static_cast (offset)), - m_reg_name(reg_name), - m_value(value) - { } - - void Execute(NativeProcessLinux *monitor) override; - - private: - lldb::tid_t m_tid; - uintptr_t m_offset; - const char *m_reg_name; - RegisterValue &m_value; - }; - - void - ReadRegOperation::Execute(NativeProcessLinux *monitor) - { -#if defined (__arm64__) || defined (__aarch64__) - if (m_offset > sizeof(struct user_pt_regs)) - { - uintptr_t offset = m_offset - sizeof(struct user_pt_regs); - if (offset > sizeof(struct user_fpsimd_state)) - { - m_error.SetErrorString("invalid offset value"); - return; - } - elf_fpregset_t regs; - int regset = NT_FPREGSET; - struct iovec ioVec; - - ioVec.iov_base = ®s; - ioVec.iov_len = sizeof regs; - PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, sizeof regs, m_error); - if (m_error.Success()) - { - ArchSpec arch; - if (monitor->GetArchitecture(arch)) - m_value.SetBytes((void *)(((unsigned char *)(®s)) + offset), 16, arch.GetByteOrder()); - else - m_error.SetErrorString("failed to get architecture"); - } - } - else - { - elf_gregset_t regs; - int regset = NT_PRSTATUS; - struct iovec ioVec; - - ioVec.iov_base = ®s; - ioVec.iov_len = sizeof regs; - PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, sizeof regs, m_error); - if (m_error.Success()) - { - ArchSpec arch; - if (monitor->GetArchitecture(arch)) - m_value.SetBytes((void *)(((unsigned char *)(regs)) + m_offset), 8, arch.GetByteOrder()); - else - m_error.SetErrorString("failed to get architecture"); - } - } -#elif defined (__mips__) - elf_gregset_t regs; - PTRACE(PTRACE_GETREGS, m_tid, NULL, ®s, sizeof regs, m_error); - if (m_error.Success()) - { - lldb_private::ArchSpec arch; - if (monitor->GetArchitecture(arch)) - m_value.SetBytes((void *)(((unsigned char *)(regs)) + m_offset), 8, arch.GetByteOrder()); - else - m_error.SetErrorString("failed to get architecture"); - } -#else - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS)); - - lldb::addr_t data = static_cast(PTRACE(PTRACE_PEEKUSER, m_tid, (void*)m_offset, nullptr, 0, m_error)); - if (m_error.Success()) - m_value = data; - - if (log) - log->Printf ("NativeProcessLinux::%s() reg %s: 0x%" PRIx64, __FUNCTION__, - m_reg_name, data); -#endif - } - - //------------------------------------------------------------------------------ - /// @class WriteRegOperation - /// @brief Implements NativeProcessLinux::WriteRegisterValue. - class WriteRegOperation : public Operation - { - public: - WriteRegOperation(lldb::tid_t tid, unsigned offset, const char *reg_name, - const RegisterValue &value) - : m_tid(tid), - m_offset(offset), - m_reg_name(reg_name), - m_value(value) - { } - - void Execute(NativeProcessLinux *monitor) override; - - private: - lldb::tid_t m_tid; - uintptr_t m_offset; - const char *m_reg_name; - const RegisterValue &m_value; - }; - - void - WriteRegOperation::Execute(NativeProcessLinux *monitor) - { -#if defined (__arm64__) || defined (__aarch64__) - if (m_offset > sizeof(struct user_pt_regs)) - { - uintptr_t offset = m_offset - sizeof(struct user_pt_regs); - if (offset > sizeof(struct user_fpsimd_state)) - { - m_error.SetErrorString("invalid offset value"); - return; - } - elf_fpregset_t regs; - int regset = NT_FPREGSET; - struct iovec ioVec; - - ioVec.iov_base = ®s; - ioVec.iov_len = sizeof regs; - PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, sizeof regs, m_error); - if (m_error.Success()) - { - ::memcpy((void *)(((unsigned char *)(®s)) + offset), m_value.GetBytes(), 16); - PTRACE(PTRACE_SETREGSET, m_tid, ®set, &ioVec, sizeof regs, m_error); - } - } - else - { - elf_gregset_t regs; - int regset = NT_PRSTATUS; - struct iovec ioVec; - - ioVec.iov_base = ®s; - ioVec.iov_len = sizeof regs; - PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, sizeof regs, m_error); - if (m_error.Success()) - { - ::memcpy((void *)(((unsigned char *)(®s)) + m_offset), m_value.GetBytes(), 8); - PTRACE(PTRACE_SETREGSET, m_tid, ®set, &ioVec, sizeof regs, m_error); - } - } -#elif defined (__mips__) - elf_gregset_t regs; - PTRACE(PTRACE_GETREGS, m_tid, NULL, ®s, sizeof regs, m_error); - if (m_error.Success()) - { - ::memcpy((void *)(((unsigned char *)(®s)) + m_offset), m_value.GetBytes(), 8); - PTRACE(PTRACE_SETREGS, m_tid, NULL, ®s, sizeof regs, m_error); - } -#else - void* buf; - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS)); - - buf = (void*) m_value.GetAsUInt64(); - - if (log) - log->Printf ("NativeProcessLinux::%s() reg %s: %p", __FUNCTION__, m_reg_name, buf); - PTRACE(PTRACE_POKEUSER, m_tid, (void*)m_offset, buf, 0, m_error); -#endif - } - - //------------------------------------------------------------------------------ - /// @class ReadGPROperation - /// @brief Implements NativeProcessLinux::ReadGPR. - class ReadGPROperation : public Operation - { - public: - ReadGPROperation(lldb::tid_t tid, void *buf, size_t buf_size) - : m_tid(tid), m_buf(buf), m_buf_size(buf_size) - { } - - void Execute(NativeProcessLinux *monitor) override; - - private: - lldb::tid_t m_tid; - void *m_buf; - size_t m_buf_size; - }; - - void - ReadGPROperation::Execute(NativeProcessLinux *monitor) - { -#if defined (__arm64__) || defined (__aarch64__) - int regset = NT_PRSTATUS; - struct iovec ioVec; - - ioVec.iov_base = m_buf; - ioVec.iov_len = m_buf_size; - PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, m_buf_size, m_error); -#else - PTRACE(PTRACE_GETREGS, m_tid, nullptr, m_buf, m_buf_size, m_error); -#endif - } - - //------------------------------------------------------------------------------ - /// @class ReadFPROperation - /// @brief Implements NativeProcessLinux::ReadFPR. - class ReadFPROperation : public Operation - { - public: - ReadFPROperation(lldb::tid_t tid, void *buf, size_t buf_size) - : m_tid(tid), - m_buf(buf), - m_buf_size(buf_size) - { } - - void Execute(NativeProcessLinux *monitor) override; - - private: - lldb::tid_t m_tid; - void *m_buf; - size_t m_buf_size; - }; - - void - ReadFPROperation::Execute(NativeProcessLinux *monitor) - { -#if defined (__arm64__) || defined (__aarch64__) - int regset = NT_FPREGSET; - struct iovec ioVec; - - ioVec.iov_base = m_buf; - ioVec.iov_len = m_buf_size; - PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, m_buf_size, m_error); -#else - PTRACE(PTRACE_GETFPREGS, m_tid, nullptr, m_buf, m_buf_size, m_error); -#endif - } - - //------------------------------------------------------------------------------ - /// @class ReadDBGROperation - /// @brief Implements NativeProcessLinux::ReadHardwareDebugInfo. - class ReadDBGROperation : public Operation - { - public: - ReadDBGROperation(lldb::tid_t tid, unsigned int &count_wp, unsigned int &count_bp) - : m_tid(tid), - m_count_wp(count_wp), - m_count_bp(count_bp) - { } - - void Execute(NativeProcessLinux *monitor) override; - - private: - lldb::tid_t m_tid; - unsigned int &m_count_wp; - unsigned int &m_count_bp; - }; - - void - ReadDBGROperation::Execute(NativeProcessLinux *monitor) - { -#if defined (__arm64__) || defined (__aarch64__) - int regset = NT_ARM_HW_WATCH; - struct iovec ioVec; - struct user_hwdebug_state dreg_state; - - ioVec.iov_base = &dreg_state; - ioVec.iov_len = sizeof (dreg_state); - - PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, ioVec.iov_len, m_error); - - m_count_wp = dreg_state.dbg_info & 0xff; - regset = NT_ARM_HW_BREAK; - - PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, ioVec.iov_len, m_error); - m_count_bp = dreg_state.dbg_info & 0xff; -#endif - } - - - //------------------------------------------------------------------------------ - /// @class ReadRegisterSetOperation - /// @brief Implements NativeProcessLinux::ReadRegisterSet. - class ReadRegisterSetOperation : public Operation - { - public: - ReadRegisterSetOperation(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset) - : m_tid(tid), m_buf(buf), m_buf_size(buf_size), m_regset(regset) - { } - - void Execute(NativeProcessLinux *monitor) override; - - private: - lldb::tid_t m_tid; - void *m_buf; - size_t m_buf_size; - const unsigned int m_regset; - }; - - void - ReadRegisterSetOperation::Execute(NativeProcessLinux *monitor) - { - PTRACE(PTRACE_GETREGSET, m_tid, (void *)&m_regset, m_buf, m_buf_size, m_error); - } - - //------------------------------------------------------------------------------ - /// @class WriteGPROperation - /// @brief Implements NativeProcessLinux::WriteGPR. - class WriteGPROperation : public Operation - { - public: - WriteGPROperation(lldb::tid_t tid, void *buf, size_t buf_size) - : m_tid(tid), m_buf(buf), m_buf_size(buf_size) - { } - - void Execute(NativeProcessLinux *monitor) override; - - private: - lldb::tid_t m_tid; - void *m_buf; - size_t m_buf_size; - }; - - void - WriteGPROperation::Execute(NativeProcessLinux *monitor) - { -#if defined (__arm64__) || defined (__aarch64__) - int regset = NT_PRSTATUS; - struct iovec ioVec; - - ioVec.iov_base = m_buf; - ioVec.iov_len = m_buf_size; - PTRACE(PTRACE_SETREGSET, m_tid, ®set, &ioVec, m_buf_size, m_error); -#else - PTRACE(PTRACE_SETREGS, m_tid, NULL, m_buf, m_buf_size, m_error); -#endif - } - - //------------------------------------------------------------------------------ - /// @class WriteFPROperation - /// @brief Implements NativeProcessLinux::WriteFPR. - class WriteFPROperation : public Operation - { - public: - WriteFPROperation(lldb::tid_t tid, void *buf, size_t buf_size) - : m_tid(tid), m_buf(buf), m_buf_size(buf_size) - { } - - void Execute(NativeProcessLinux *monitor) override; - - private: - lldb::tid_t m_tid; - void *m_buf; - size_t m_buf_size; - }; - - void - WriteFPROperation::Execute(NativeProcessLinux *monitor) - { -#if defined (__arm64__) || defined (__aarch64__) - int regset = NT_FPREGSET; - struct iovec ioVec; - - ioVec.iov_base = m_buf; - ioVec.iov_len = m_buf_size; - PTRACE(PTRACE_SETREGSET, m_tid, ®set, &ioVec, m_buf_size, m_error); -#else - PTRACE(PTRACE_SETFPREGS, m_tid, NULL, m_buf, m_buf_size, m_error); -#endif - } - - //------------------------------------------------------------------------------ - /// @class WriteDBGROperation - /// @brief Implements NativeProcessLinux::WriteHardwareDebugRegs. - class WriteDBGROperation : public Operation - { - public: - WriteDBGROperation(lldb::tid_t tid, lldb::addr_t *addr_buf, - uint32_t *cntrl_buf, int type, int count) - : m_tid(tid), - m_address(addr_buf), - m_control(cntrl_buf), - m_type(type), - m_count(count) - { } - - void Execute(NativeProcessLinux *monitor) override; - - private: - lldb::tid_t m_tid; - lldb::addr_t * m_address; - uint32_t * m_control; - int m_type; - int m_count; - }; - - void - WriteDBGROperation::Execute(NativeProcessLinux *monitor) - { -#if defined (__arm64__) || defined (__aarch64__) - struct iovec ioVec; - struct user_hwdebug_state dreg_state; - - memset (&dreg_state, 0, sizeof (dreg_state)); - ioVec.iov_base = &dreg_state; - ioVec.iov_len = sizeof (dreg_state); - - if (m_type == 0) - m_type = NT_ARM_HW_WATCH; - else - m_type = NT_ARM_HW_BREAK; - - for (int i = 0; i < m_count; i++) - { - dreg_state.dbg_regs[i].addr = m_address[i]; - dreg_state.dbg_regs[i].ctrl = m_control[i]; - } - - PTRACE(PTRACE_SETREGSET, m_tid, &m_type, &ioVec, ioVec.iov_len, m_error); -#endif - } - - - //------------------------------------------------------------------------------ - /// @class WriteRegisterSetOperation - /// @brief Implements NativeProcessLinux::WriteRegisterSet. - class WriteRegisterSetOperation : public Operation - { - public: - WriteRegisterSetOperation(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset) - : m_tid(tid), m_buf(buf), m_buf_size(buf_size), m_regset(regset) - { } - - void Execute(NativeProcessLinux *monitor) override; - - private: - lldb::tid_t m_tid; - void *m_buf; - size_t m_buf_size; - const unsigned int m_regset; - }; - - void - WriteRegisterSetOperation::Execute(NativeProcessLinux *monitor) - { - PTRACE(PTRACE_SETREGSET, m_tid, (void *)&m_regset, m_buf, m_buf_size, m_error); - } - - //------------------------------------------------------------------------------ /// @class ResumeOperation /// @brief Implements NativeProcessLinux::Resume. - class ResumeOperation : public Operation + class ResumeOperation : public NativeProcessLinux::Operation { public: ResumeOperation(lldb::tid_t tid, uint32_t signo) : @@ -996,7 +432,7 @@ if (m_signo != LLDB_INVALID_SIGNAL_NUMBER) data = m_signo; - PTRACE(PTRACE_CONT, m_tid, nullptr, (void*)data, 0, m_error); + NativeProcessLinux::PtraceWrapper(PTRACE_CONT, m_tid, nullptr, (void*)data, 0, m_error); if (m_error.Fail()) { Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); @@ -1009,7 +445,7 @@ //------------------------------------------------------------------------------ /// @class SingleStepOperation /// @brief Implements NativeProcessLinux::SingleStep. - class SingleStepOperation : public Operation + class SingleStepOperation : public NativeProcessLinux::Operation { public: SingleStepOperation(lldb::tid_t tid, uint32_t signo) @@ -1030,13 +466,13 @@ if (m_signo != LLDB_INVALID_SIGNAL_NUMBER) data = m_signo; - PTRACE(PTRACE_SINGLESTEP, m_tid, nullptr, (void*)data, 0, m_error); + NativeProcessLinux::PtraceWrapper(PTRACE_SINGLESTEP, m_tid, nullptr, (void*)data, 0, m_error); } //------------------------------------------------------------------------------ /// @class SiginfoOperation /// @brief Implements NativeProcessLinux::GetSignalInfo. - class SiginfoOperation : public Operation + class SiginfoOperation : public NativeProcessLinux::Operation { public: SiginfoOperation(lldb::tid_t tid, void *info) @@ -1052,13 +488,13 @@ void SiginfoOperation::Execute(NativeProcessLinux *monitor) { - PTRACE(PTRACE_GETSIGINFO, m_tid, nullptr, m_info, 0, m_error); + NativeProcessLinux::PtraceWrapper(PTRACE_GETSIGINFO, m_tid, nullptr, m_info, 0, m_error); } //------------------------------------------------------------------------------ /// @class EventMessageOperation /// @brief Implements NativeProcessLinux::GetEventMessage. - class EventMessageOperation : public Operation + class EventMessageOperation : public NativeProcessLinux::Operation { public: EventMessageOperation(lldb::tid_t tid, unsigned long *message) @@ -1074,10 +510,10 @@ void EventMessageOperation::Execute(NativeProcessLinux *monitor) { - PTRACE(PTRACE_GETEVENTMSG, m_tid, nullptr, m_message, 0, m_error); + NativeProcessLinux::PtraceWrapper(PTRACE_GETEVENTMSG, m_tid, nullptr, m_message, 0, m_error); } - class DetachOperation : public Operation + class DetachOperation : public NativeProcessLinux::Operation { public: DetachOperation(lldb::tid_t tid) : m_tid(tid) { } @@ -1091,7 +527,7 @@ void DetachOperation::Execute(NativeProcessLinux *monitor) { - PTRACE(PTRACE_DETACH, m_tid, nullptr, 0, 0, m_error); + NativeProcessLinux::PtraceWrapper(PTRACE_DETACH, m_tid, nullptr, 0, 0, m_error); } } // end of anonymous namespace @@ -1833,7 +1269,7 @@ // send log info to parent re: launch status, in place of the log lines removed here. // Start tracing this child that is about to exec. - PTRACE(PTRACE_TRACEME, 0, nullptr, nullptr, 0, error); + NativeProcessLinux::PtraceWrapper(PTRACE_TRACEME, 0, nullptr, nullptr, 0, error); if (error.Fail()) exit(ePtraceFailed); @@ -2070,7 +1506,7 @@ // Attach to the requested process. // An attach will cause the thread to stop with a SIGSTOP. - PTRACE(PTRACE_ATTACH, tid, nullptr, nullptr, 0, error); + NativeProcessLinux::PtraceWrapper(PTRACE_ATTACH, tid, nullptr, nullptr, 0, error); if (error.Fail()) { // No such thread. The thread may have exited. @@ -2162,7 +1598,7 @@ ptrace_opts |= PTRACE_O_TRACEEXEC; Error error; - PTRACE(PTRACE_SETOPTIONS, pid, nullptr, (void*)ptrace_opts, 0, error); + NativeProcessLinux::PtraceWrapper(PTRACE_SETOPTIONS, pid, nullptr, (void*)ptrace_opts, 0, error); return error; } @@ -3842,88 +3278,6 @@ } Error -NativeProcessLinux::ReadRegisterValue(lldb::tid_t tid, uint32_t offset, const char* reg_name, - uint32_t size, RegisterValue &value) -{ - ReadRegOperation op(tid, offset, reg_name, value); - m_monitor_up->DoOperation(&op); - return op.GetError(); -} - -Error -NativeProcessLinux::WriteRegisterValue(lldb::tid_t tid, unsigned offset, - const char* reg_name, const RegisterValue &value) -{ - WriteRegOperation op(tid, offset, reg_name, value); - m_monitor_up->DoOperation(&op); - return op.GetError(); -} - -Error -NativeProcessLinux::ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size) -{ - ReadGPROperation op(tid, buf, buf_size); - m_monitor_up->DoOperation(&op); - return op.GetError(); -} - -Error -NativeProcessLinux::ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size) -{ - ReadFPROperation op(tid, buf, buf_size); - m_monitor_up->DoOperation(&op); - return op.GetError(); -} - -Error -NativeProcessLinux::ReadRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset) -{ - ReadRegisterSetOperation op(tid, buf, buf_size, regset); - m_monitor_up->DoOperation(&op); - return op.GetError(); -} - -Error -NativeProcessLinux::ReadHardwareDebugInfo (lldb::tid_t tid, unsigned int &watch_count , unsigned int &break_count) -{ - ReadDBGROperation op(tid, watch_count, break_count); - m_monitor_up->DoOperation(&op); - return op.GetError(); -} - -Error -NativeProcessLinux::WriteHardwareDebugRegs (lldb::tid_t tid, lldb::addr_t *addr_buf, uint32_t *cntrl_buf, int type, int count) -{ - WriteDBGROperation op(tid, addr_buf, cntrl_buf, type, count); - m_monitor_up->DoOperation(&op); - return op.GetError(); -} - -Error -NativeProcessLinux::WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size) -{ - WriteGPROperation op(tid, buf, buf_size); - m_monitor_up->DoOperation(&op); - return op.GetError(); -} - -Error -NativeProcessLinux::WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size) -{ - WriteFPROperation op(tid, buf, buf_size); - m_monitor_up->DoOperation(&op); - return op.GetError(); -} - -Error -NativeProcessLinux::WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset) -{ - WriteRegisterSetOperation op(tid, buf, buf_size, regset); - m_monitor_up->DoOperation(&op); - return op.GetError(); -} - -Error NativeProcessLinux::Resume (lldb::tid_t tid, uint32_t signo) { Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); @@ -4431,3 +3785,53 @@ thread_sp->RequestStop(); } } + +Error +NativeProcessLinux::DoOperation(Operation* op) +{ + m_monitor_up->DoOperation(op); + return op->GetError(); +} + +// Wrapper for ptrace to catch errors and log calls. +// Note that ptrace sets errno on error because -1 can be a valid result (i.e. for PTRACE_PEEK*) +long +NativeProcessLinux::PtraceWrapper(int req, lldb::pid_t pid, void *addr, void *data, size_t data_size, Error& error) +{ + long int result; + + Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PTRACE)); + + PtraceDisplayBytes(req, data, data_size); + + error.Clear(); + errno = 0; + if (req == PTRACE_GETREGSET || req == PTRACE_SETREGSET) + result = ptrace(static_cast<__ptrace_request>(req), static_cast< ::pid_t>(pid), *(unsigned int *)addr, data); + else + result = ptrace(static_cast<__ptrace_request>(req), static_cast< ::pid_t>(pid), addr, data); + + if (result == -1) + error.SetErrorToErrno(); + + if (log) + log->Printf("ptrace(%d, %" PRIu64 ", %p, %p, %zu)=%lX", req, pid, addr, data, data_size, result); + + PtraceDisplayBytes(req, data, data_size); + + if (log && error.GetError() != 0) + { + const char* str; + switch (error.GetError()) + { + case ESRCH: str = "ESRCH"; break; + case EINVAL: str = "EINVAL"; break; + case EBUSY: str = "EBUSY"; break; + case EPERM: str = "EPERM"; break; + default: str = error.AsCString(); + } + log->Printf("ptrace() failed; errno=%d (%s)", error.GetError(), str); + } + + return result; +} Index: lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux.h =================================================================== --- lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux.h +++ lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux.h @@ -0,0 +1,105 @@ +//===-- NativeRegisterContextLinux.h ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#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" + +namespace lldb_private { +namespace process_linux { + +class NativeRegisterContextLinux : public NativeRegisterContextRegisterInfo +{ +public: + NativeRegisterContextLinux(NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx, + RegisterInfoInterface *reg_info_interface_p); + + // This function is implemented in the NativeRegisterContextLinux_* subclasses to create a new + // instance of the host specific NativeRegisterContextLinux. The implementations can't collide + // as only one NativeRegisterContextLinux_* variant should be compiled into the final + // executable. + static NativeRegisterContextLinux* + CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch, + NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx); + +protected: + lldb::ByteOrder + GetByteOrder() const; + + virtual Error + ReadRegisterRaw(uint32_t reg_index, RegisterValue& reg_value); + + virtual Error + WriteRegisterRaw(uint32_t reg_index, const RegisterValue& reg_value); + + virtual Error + ReadRegisterSet(void *buf, size_t buf_size, unsigned int regset); + + virtual Error + WriteRegisterSet(void *buf, size_t buf_size, unsigned int regset); + + virtual Error + ReadGPR(); + + virtual Error + WriteGPR(); + + virtual Error + ReadFPR(); + + virtual Error + WriteFPR(); + + virtual void* + GetGPRBuffer() { return nullptr; }; + + virtual size_t + GetGPRSize() { return GetRegisterInfoInterface().GetGPRSize(); } + + virtual void* + GetFPRBuffer() { return nullptr; } + + virtual size_t + GetFPRSize() { return 0; } + + virtual NativeProcessLinux::OperationUP + GetReadRegisterValueOperation(uint32_t offset, + const char* reg_name, + uint32_t size, + RegisterValue &value); + + virtual NativeProcessLinux::OperationUP + GetWriteRegisterValueOperation(uint32_t offset, + const char* reg_name, + const RegisterValue &value); + + virtual NativeProcessLinux::OperationUP + GetReadGPROperation(void *buf, size_t buf_size); + + virtual NativeProcessLinux::OperationUP + GetWriteGPROperation(void *buf, size_t buf_size); + + virtual NativeProcessLinux::OperationUP + GetReadFPROperation(void *buf, size_t buf_size); + + virtual NativeProcessLinux::OperationUP + GetWriteFPROperation(void *buf, size_t buf_size); +}; + +} // namespace process_linux +} // namespace lldb_private + +#endif // #ifndef lldb_NativeRegisterContextLinux_h + Index: lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp +++ lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp @@ -0,0 +1,452 @@ +//===-- NativeRegisterContextLinux.cpp --------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "NativeRegisterContextLinux.h" + +#include "lldb/Core/RegisterValue.h" +#include "lldb/Host/common/NativeProcessProtocol.h" +#include "lldb/Host/common/NativeThreadProtocol.h" +#include "lldb/Host/linux/Ptrace.h" + +#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" + +using namespace lldb_private; +using namespace lldb_private::process_linux; + +namespace +{ + +class ReadRegOperation : public NativeProcessLinux::Operation +{ +public: + ReadRegOperation(lldb::tid_t tid, uint32_t offset, const char *reg_name, RegisterValue &value) : + m_tid(tid), + m_offset(static_cast(offset)), + m_reg_name(reg_name), + m_value(value) + { } + + void + Execute(NativeProcessLinux *monitor) override; + +private: + lldb::tid_t m_tid; + uintptr_t m_offset; + const char *m_reg_name; + RegisterValue &m_value; +}; + +class WriteRegOperation : public NativeProcessLinux::Operation +{ +public: + WriteRegOperation(lldb::tid_t tid, unsigned offset, const char *reg_name, const RegisterValue &value) : + m_tid(tid), + m_offset(offset), + m_reg_name(reg_name), + m_value(value) + { } + + void + Execute(NativeProcessLinux *monitor) override; + +private: + lldb::tid_t m_tid; + uintptr_t m_offset; + const char *m_reg_name; + const RegisterValue &m_value; +}; + +class ReadGPROperation : public NativeProcessLinux::Operation +{ +public: + ReadGPROperation(lldb::tid_t tid, void *buf, size_t buf_size) : + m_tid(tid), m_buf(buf), m_buf_size(buf_size) + { } + + void Execute(NativeProcessLinux *monitor) override; + +private: + lldb::tid_t m_tid; + void *m_buf; + size_t m_buf_size; +}; + +class WriteGPROperation : public NativeProcessLinux::Operation +{ +public: + WriteGPROperation(lldb::tid_t tid, void *buf, size_t buf_size) : + m_tid(tid), m_buf(buf), m_buf_size(buf_size) + { } + + void Execute(NativeProcessLinux *monitor) override; + +private: + lldb::tid_t m_tid; + void *m_buf; + size_t m_buf_size; +}; + +class ReadFPROperation : public NativeProcessLinux::Operation +{ +public: + ReadFPROperation(lldb::tid_t tid, void *buf, size_t buf_size) : + m_tid(tid), m_buf(buf), m_buf_size(buf_size) + { } + + void Execute(NativeProcessLinux *monitor) override; + +private: + lldb::tid_t m_tid; + void *m_buf; + size_t m_buf_size; +}; + +class WriteFPROperation : public NativeProcessLinux::Operation +{ +public: + WriteFPROperation(lldb::tid_t tid, void *buf, size_t buf_size) : + m_tid(tid), m_buf(buf), m_buf_size(buf_size) + { } + + void Execute(NativeProcessLinux *monitor) override; + +private: + lldb::tid_t m_tid; + void *m_buf; + size_t m_buf_size; +}; + +class ReadRegisterSetOperation : public NativeProcessLinux::Operation +{ +public: + ReadRegisterSetOperation(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset) : + m_tid(tid), m_buf(buf), m_buf_size(buf_size), m_regset(regset) + { } + + void Execute(NativeProcessLinux *monitor) override; + +private: + lldb::tid_t m_tid; + void *m_buf; + size_t m_buf_size; + const unsigned int m_regset; +}; + +class WriteRegisterSetOperation : public NativeProcessLinux::Operation +{ +public: + WriteRegisterSetOperation(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset) : + m_tid(tid), m_buf(buf), m_buf_size(buf_size), m_regset(regset) + { } + + void Execute(NativeProcessLinux *monitor) override; + +private: + lldb::tid_t m_tid; + void *m_buf; + size_t m_buf_size; + const unsigned int m_regset; +}; + +} // end of anonymous namespace + +void +ReadRegOperation::Execute(NativeProcessLinux *monitor) +{ + Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS)); + + lldb::addr_t data = static_cast(NativeProcessLinux::PtraceWrapper(PTRACE_PEEKUSER, m_tid, (void*)m_offset, nullptr, 0, m_error)); + if (m_error.Success()) + m_value = data; + + if (log) + log->Printf ("NativeProcessLinux::%s() reg %s: 0x%" PRIx64, __FUNCTION__, m_reg_name, data); +} + +void +WriteRegOperation::Execute(NativeProcessLinux *monitor) +{ + Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS)); + + void* buf = (void*)m_value.GetAsUInt64(); + + if (log) + log->Printf ("NativeProcessLinux::%s() reg %s: %p", __FUNCTION__, m_reg_name, buf); + NativeProcessLinux::PtraceWrapper(PTRACE_POKEUSER, m_tid, (void*)m_offset, buf, 0, m_error); +} + +void +ReadGPROperation::Execute(NativeProcessLinux *monitor) +{ + NativeProcessLinux::PtraceWrapper(PTRACE_GETREGS, m_tid, nullptr, m_buf, m_buf_size, m_error); +} + +void +WriteGPROperation::Execute(NativeProcessLinux *monitor) +{ + NativeProcessLinux::PtraceWrapper(PTRACE_SETREGS, m_tid, nullptr, m_buf, m_buf_size, m_error); +} + +void +ReadFPROperation::Execute(NativeProcessLinux *monitor) +{ + NativeProcessLinux::PtraceWrapper(PTRACE_GETFPREGS, m_tid, nullptr, m_buf, m_buf_size, m_error); +} + +void +WriteFPROperation::Execute(NativeProcessLinux *monitor) +{ + NativeProcessLinux::PtraceWrapper(PTRACE_SETFPREGS, m_tid, nullptr, m_buf, m_buf_size, m_error); +} + +void +ReadRegisterSetOperation::Execute(NativeProcessLinux *monitor) +{ + NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, (void *)&m_regset, m_buf, m_buf_size, m_error); +} + +void +WriteRegisterSetOperation::Execute(NativeProcessLinux *monitor) +{ + NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_tid, (void *)&m_regset, m_buf, m_buf_size, m_error); +} + +NativeRegisterContextLinux::NativeRegisterContextLinux(NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx, + RegisterInfoInterface *reg_info_interface_p) : + NativeRegisterContextRegisterInfo(native_thread, concrete_frame_idx, reg_info_interface_p) +{} + +lldb::ByteOrder +NativeRegisterContextLinux::GetByteOrder() const +{ + // Get the target process whose privileged thread was used for the register read. + lldb::ByteOrder byte_order = lldb::eByteOrderInvalid; + + NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); + if (!process_sp) + return byte_order; + + if (!process_sp->GetByteOrder (byte_order)) + { + // FIXME log here + } + + return byte_order; +} + +Error +NativeRegisterContextLinux::ReadRegisterRaw(uint32_t reg_index, RegisterValue ®_value) +{ + const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(reg_index); + if (!reg_info) + return Error("register %" PRIu32 " not found", reg_index); + + NativeProcessProtocolSP process_sp(m_thread.GetProcess()); + if (!process_sp) + return Error("NativeProcessProtocol is NULL"); + + NativeProcessLinux* process_p = static_cast(process_sp.get()); + return process_p->DoOperation(GetReadRegisterValueOperation(reg_info->byte_offset, + reg_info->name, + reg_info->byte_size, + reg_value)); +} + +Error +NativeRegisterContextLinux::WriteRegisterRaw(uint32_t reg_index, const RegisterValue ®_value) +{ + uint32_t reg_to_write = reg_index; + RegisterValue value_to_write = reg_value; + + // Check if this is a subregister of a full register. + const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_index); + if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) + { + Error error; + + RegisterValue full_value; + uint32_t full_reg = reg_info->invalidate_regs[0]; + const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg); + + // Read the full register. + error = ReadRegister(full_reg_info, full_value); + if (error.Fail ()) + return error; + + lldb::ByteOrder byte_order = GetByteOrder(); + uint8_t dst[RegisterValue::kMaxRegisterByteSize]; + + // Get the bytes for the full register. + const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info, + dst, + sizeof(dst), + byte_order, + error); + if (error.Success() && dest_size) + { + uint8_t src[RegisterValue::kMaxRegisterByteSize]; + + // Get the bytes for the source data. + const uint32_t src_size = reg_value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error); + if (error.Success() && src_size && (src_size < dest_size)) + { + // Copy the src bytes to the destination. + memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size); + // Set this full register as the value to write. + value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order); + value_to_write.SetType(full_reg_info); + reg_to_write = full_reg; + } + } + } + + 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); + + NativeProcessLinux* process_p = static_cast (process_sp.get ()); + return process_p->DoOperation(GetWriteRegisterValueOperation(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(); + + NativeProcessLinux* process_p = static_cast(process_sp.get()); + return process_p->DoOperation(GetReadGPROperation(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(); + + NativeProcessLinux* process_p = static_cast(process_sp.get()); + return process_p->DoOperation(GetWriteGPROperation(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(); + + NativeProcessLinux* process_p = static_cast(process_sp.get()); + return process_p->DoOperation(GetReadFPROperation(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(); + + NativeProcessLinux* process_p = static_cast(process_sp.get()); + return process_p->DoOperation(GetWriteFPROperation(buf, buf_size)); +} + +Error +NativeRegisterContextLinux::ReadRegisterSet(void *buf, size_t buf_size, unsigned int regset) +{ + NativeProcessProtocolSP process_sp (m_thread.GetProcess()); + if (!process_sp) + return Error("NativeProcessProtocol is NULL"); + NativeProcessLinux* process_p = static_cast(process_sp.get()); + + ReadRegisterSetOperation op(m_thread.GetID(), buf, buf_size, regset); + return process_p->DoOperation(&op); +} + +Error +NativeRegisterContextLinux::WriteRegisterSet(void *buf, size_t buf_size, unsigned int regset) +{ + NativeProcessProtocolSP process_sp (m_thread.GetProcess()); + if (!process_sp) + return Error("NativeProcessProtocol is NULL"); + NativeProcessLinux* process_p = static_cast(process_sp.get()); + + WriteRegisterSetOperation op(m_thread.GetID(), buf, buf_size, regset); + return process_p->DoOperation(&op); +} + +NativeProcessLinux::OperationUP +NativeRegisterContextLinux::GetReadRegisterValueOperation(uint32_t offset, + const char* reg_name, + uint32_t size, + RegisterValue &value) +{ + return NativeProcessLinux::OperationUP(new ReadRegOperation(m_thread.GetID(), offset, reg_name, value)); +} + +NativeProcessLinux::OperationUP +NativeRegisterContextLinux::GetWriteRegisterValueOperation(uint32_t offset, + const char* reg_name, + const RegisterValue &value) +{ + return NativeProcessLinux::OperationUP(new WriteRegOperation(m_thread.GetID(), offset, reg_name, value)); +} + +NativeProcessLinux::OperationUP +NativeRegisterContextLinux::GetReadGPROperation(void *buf, size_t buf_size) +{ + return NativeProcessLinux::OperationUP(new ReadGPROperation(m_thread.GetID(), buf, buf_size)); +} + +NativeProcessLinux::OperationUP +NativeRegisterContextLinux::GetWriteGPROperation(void *buf, size_t buf_size) +{ + return NativeProcessLinux::OperationUP(new WriteGPROperation(m_thread.GetID(), buf, buf_size)); +} + +NativeProcessLinux::OperationUP +NativeRegisterContextLinux::GetReadFPROperation(void *buf, size_t buf_size) +{ + return NativeProcessLinux::OperationUP(new ReadFPROperation(m_thread.GetID(), buf, buf_size)); +} + +NativeProcessLinux::OperationUP +NativeRegisterContextLinux::GetWriteFPROperation(void *buf, size_t buf_size) +{ + return NativeProcessLinux::OperationUP(new WriteFPROperation(m_thread.GetID(), buf, buf_size)); +} Index: lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h =================================================================== --- lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h +++ lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h @@ -7,11 +7,12 @@ // //===----------------------------------------------------------------------===// +#if defined(__arm__) // arm register context only needed on arm devices #ifndef lldb_NativeRegisterContextLinux_arm_h #define lldb_NativeRegisterContextLinux_arm_h -#include "lldb/Host/common/NativeRegisterContextRegisterInfo.h" +#include "Plugins/Process/Linux/NativeRegisterContextLinux.h" #include "Plugins/Process/Utility/lldb-arm-register-enums.h" namespace lldb_private { @@ -19,10 +20,12 @@ class NativeProcessLinux; - class NativeRegisterContextLinux_arm : public NativeRegisterContextRegisterInfo + class NativeRegisterContextLinux_arm : public NativeRegisterContextLinux { public: - NativeRegisterContextLinux_arm (NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx, RegisterInfoInterface *reg_info_interface_p); + NativeRegisterContextLinux_arm (const ArchSpec& target_arch, + NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx); uint32_t GetRegisterSetCount () const override; @@ -45,6 +48,16 @@ Error WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) override; + protected: + void* + GetGPRBuffer() override { return &m_gpr_arm; } + + void* + GetFPRBuffer() override { return &m_fpr; } + + size_t + GetFPRSize() override { return sizeof(m_fpr); } + private: struct RegInfo { @@ -85,31 +98,7 @@ IsGPR(unsigned reg) const; bool - ReadGPR (); - - bool - WriteGPR (); - - bool IsFPR(unsigned reg) const; - - bool - ReadFPR (); - - bool - WriteFPR (); - - Error - ReadRegisterRaw (uint32_t reg_index, RegisterValue ®_value); - - Error - WriteRegisterRaw (uint32_t reg_index, const RegisterValue ®_value); - - lldb::ByteOrder - GetByteOrder() const; - - size_t - GetGPRSize() const; }; } // namespace process_linux @@ -117,3 +106,4 @@ #endif // #ifndef lldb_NativeRegisterContextLinux_arm_h +#endif // defined(__arm__) Index: lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp +++ lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp @@ -7,15 +7,15 @@ // //===----------------------------------------------------------------------===// +#if defined(__arm__) + #include "NativeRegisterContextLinux_arm.h" -#include "lldb/lldb-private-forward.h" #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/Error.h" #include "lldb/Core/RegisterValue.h" -#include "lldb/Host/common/NativeProcessProtocol.h" -#include "lldb/Host/common/NativeThreadProtocol.h" -#include "Plugins/Process/Linux/NativeProcessLinux.h" + +#include "Plugins/Process/Utility/RegisterContextLinux_arm.h" #define REG_CONTEXT_SIZE (GetGPRSize() + sizeof (m_fpr)) @@ -105,13 +105,20 @@ { "Floating Point Registers", "fpu", k_num_fpr_registers_arm, g_fpu_regnums_arm } }; -NativeRegisterContextLinux_arm::NativeRegisterContextLinux_arm ( - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx, - RegisterInfoInterface *reg_info_interface_p) : - NativeRegisterContextRegisterInfo (native_thread, concrete_frame_idx, reg_info_interface_p) +NativeRegisterContextLinux* +NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch, + NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx) +{ + return new NativeRegisterContextLinux_arm(target_arch, native_thread, concrete_frame_idx); +} + +NativeRegisterContextLinux_arm::NativeRegisterContextLinux_arm (const ArchSpec& target_arch, + NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx) : + NativeRegisterContextLinux (native_thread, concrete_frame_idx, new RegisterContextLinux_arm(target_arch)) { - switch (reg_info_interface_p->m_target_arch.GetMachine()) + switch (target_arch.GetMachine()) { case llvm::Triple::arm: m_reg_info.num_registers = k_num_registers_arm; @@ -172,11 +179,9 @@ if (IsFPR(reg)) { - if (!ReadFPR()) - { - error.SetErrorString ("failed to read floating point register"); + error = ReadFPR(); + if (error.Fail()) return error; - } } else { @@ -262,10 +267,9 @@ return Error ("unhandled register data size %" PRIu32, reg_info->byte_size); } - if (!WriteFPR()) - { - return Error ("NativeRegisterContextLinux_arm::WriteRegister: WriteFPR failed"); - } + Error error = WriteFPR(); + if (error.Fail()) + return error; return Error (); } @@ -282,17 +286,13 @@ if (!data_sp) return Error ("failed to allocate DataBufferHeap instance of size %" PRIu64, (uint64_t)REG_CONTEXT_SIZE); - if (!ReadGPR ()) - { - error.SetErrorString ("ReadGPR() failed"); + error = ReadGPR(); + if (error.Fail()) return error; - } - if (!ReadFPR ()) - { - error.SetErrorString ("ReadFPR() failed"); + error = ReadFPR(); + if (error.Fail()) return error; - } uint8_t *dst = data_sp->GetBytes (); if (dst == nullptr) @@ -334,120 +334,20 @@ } ::memcpy (&m_gpr_arm, src, GetRegisterInfoInterface ().GetGPRSize ()); - if (!WriteGPR ()) - { - error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s WriteGPR() failed", __FUNCTION__); + error = WriteGPR(); + if (error.Fail()) return error; - } src += GetRegisterInfoInterface ().GetGPRSize (); ::memcpy (&m_fpr, src, sizeof(m_fpr)); - if (!WriteFPR ()) - { - error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s WriteFPR() failed", __FUNCTION__); + error = WriteFPR(); + if (error.Fail()) return error; - } return error; } -Error -NativeRegisterContextLinux_arm::WriteRegisterRaw (uint32_t reg_index, const RegisterValue ®_value) -{ - Error error; - - uint32_t reg_to_write = reg_index; - RegisterValue value_to_write = reg_value; - - // Check if this is a subregister of a full register. - const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_index); - if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) - { - RegisterValue full_value; - uint32_t full_reg = reg_info->invalidate_regs[0]; - const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg); - - // Read the full register. - error = ReadRegister(full_reg_info, full_value); - if (error.Fail ()) - return error; - - lldb::ByteOrder byte_order = GetByteOrder(); - uint8_t dst[RegisterValue::kMaxRegisterByteSize]; - - // Get the bytes for the full register. - const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info, - dst, - sizeof(dst), - byte_order, - error); - if (error.Success() && dest_size) - { - uint8_t src[RegisterValue::kMaxRegisterByteSize]; - - // Get the bytes for the source data. - const uint32_t src_size = reg_value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error); - if (error.Success() && src_size && (src_size < dest_size)) - { - // Copy the src bytes to the destination. - memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size); - // Set this full register as the value to write. - value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order); - value_to_write.SetType(full_reg_info); - reg_to_write = full_reg; - } - } - } - - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (!process_sp) - { - error.SetErrorString ("NativeProcessProtocol is NULL"); - return error; - } - - 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) - { - error.SetErrorStringWithFormat ("NativeRegisterContextLinux_arm::%s failed to get RegisterInfo for write register index %" PRIu32, __FUNCTION__, reg_to_write); - return error; - } - - NativeProcessLinux *const process_p = reinterpret_cast (process_sp.get ()); - return process_p->WriteRegisterValue(m_thread.GetID(), - register_to_write_info_p->byte_offset, - register_to_write_info_p->name, - value_to_write); -} - -Error -NativeRegisterContextLinux_arm::ReadRegisterRaw (uint32_t reg_index, RegisterValue ®_value) -{ - Error error; - const RegisterInfo *const reg_info = GetRegisterInfoAtIndex (reg_index); - if (!reg_info) - { - error.SetErrorStringWithFormat ("register %" PRIu32 " not found", reg_index); - return error; - } - - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (!process_sp) - { - error.SetErrorString ("NativeProcessProtocol is NULL"); - return error; - } - - NativeProcessLinux *const process_p = reinterpret_cast (process_sp.get ()); - return process_p->ReadRegisterValue(m_thread.GetID(), - reg_info->byte_offset, - reg_info->name, - reg_info->byte_size, - reg_value); -} - bool NativeRegisterContextLinux_arm::IsGPR(unsigned reg) const { @@ -455,75 +355,9 @@ } bool -NativeRegisterContextLinux_arm::ReadGPR() -{ - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (!process_sp) - return false; - NativeProcessLinux *const process_p = reinterpret_cast (process_sp.get ()); - - return process_p->ReadGPR (m_thread.GetID (), &m_gpr_arm, GetRegisterInfoInterface ().GetGPRSize ()).Success(); -} - -bool -NativeRegisterContextLinux_arm::WriteGPR() -{ - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (!process_sp) - return false; - NativeProcessLinux *const process_p = reinterpret_cast (process_sp.get ()); - - return process_p->WriteGPR (m_thread.GetID (), &m_gpr_arm, GetRegisterInfoInterface ().GetGPRSize ()).Success(); -} - -bool NativeRegisterContextLinux_arm::IsFPR(unsigned reg) const { return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); } -bool -NativeRegisterContextLinux_arm::ReadFPR () -{ - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (!process_sp) - return false; - - NativeProcessLinux *const process_p = reinterpret_cast (process_sp.get ()); - return process_p->ReadFPR (m_thread.GetID (), &m_fpr, sizeof (m_fpr)).Success(); -} - -bool -NativeRegisterContextLinux_arm::WriteFPR () -{ - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (!process_sp) - return false; - - NativeProcessLinux *const process_p = reinterpret_cast (process_sp.get ()); - return process_p->WriteFPR (m_thread.GetID (), &m_fpr, sizeof (m_fpr)).Success(); -} - -lldb::ByteOrder -NativeRegisterContextLinux_arm::GetByteOrder() const -{ - // Get the target process whose privileged thread was used for the register read. - lldb::ByteOrder byte_order = lldb::eByteOrderInvalid; - - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (!process_sp) - return byte_order; - - if (!process_sp->GetByteOrder (byte_order)) - { - // FIXME log here - } - - return byte_order; -} - -size_t -NativeRegisterContextLinux_arm::GetGPRSize() const -{ - return GetRegisterInfoInterface().GetGPRSize(); -} +#endif // defined(__arm__) Index: lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h =================================================================== --- lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h +++ lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h @@ -7,11 +7,12 @@ // //===----------------------------------------------------------------------===// +#if defined (__arm64__) || defined (__aarch64__) #ifndef lldb_NativeRegisterContextLinux_arm64_h #define lldb_NativeRegisterContextLinux_arm64_h -#include "lldb/Host/common/NativeRegisterContextRegisterInfo.h" +#include "Plugins/Process/Linux/NativeRegisterContextLinux.h" #include "Plugins/Process/Utility/lldb-arm64-register-enums.h" namespace lldb_private { @@ -19,12 +20,12 @@ class NativeProcessLinux; - class NativeRegisterContextLinux_arm64 : public NativeRegisterContextRegisterInfo + class NativeRegisterContextLinux_arm64 : public NativeRegisterContextLinux { public: - NativeRegisterContextLinux_arm64 (NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx, - RegisterInfoInterface *reg_info_interface_p); + NativeRegisterContextLinux_arm64 (const ArchSpec& target_arch, + NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx); uint32_t GetRegisterSetCount () const override; @@ -72,15 +73,45 @@ lldb::addr_t GetWatchpointAddress (uint32_t wp_index) override; - bool - HardwareSingleStep (bool enable) override; - uint32_t GetWatchpointSize(uint32_t wp_index); bool WatchpointIsEnabled(uint32_t wp_index); + protected: + NativeProcessLinux::OperationUP + GetReadRegisterValueOperation(uint32_t offset, + const char* reg_name, + uint32_t size, + RegisterValue &value) override; + + NativeProcessLinux::OperationUP + GetWriteRegisterValueOperation(uint32_t offset, + const char* reg_name, + const RegisterValue &value) override; + + NativeProcessLinux::OperationUP + GetReadGPROperation(void *buf, size_t buf_size) override; + + NativeProcessLinux::OperationUP + GetWriteGPROperation(void *buf, size_t buf_size) override; + + NativeProcessLinux::OperationUP + GetReadFPROperation(void *buf, size_t buf_size) override; + + NativeProcessLinux::OperationUP + GetWriteFPROperation(void *buf, size_t buf_size) override; + + void* + GetGPRBuffer() override { return &m_gpr_arm64; } + + void* + GetFPRBuffer() override { return &m_fpr; } + + size_t + GetFPRSize() override { return sizeof(m_fpr); } + private: struct RegInfo { @@ -135,31 +166,13 @@ IsGPR(unsigned reg) const; bool - ReadGPR (); - - bool - WriteGPR (); - - bool IsFPR(unsigned reg) const; - bool - ReadFPR (); - - bool - WriteFPR (); - Error - ReadRegisterRaw (uint32_t reg_index, RegisterValue ®_value); + ReadHardwareDebugInfo(unsigned int &watch_count , unsigned int &break_count); Error - WriteRegisterRaw (uint32_t reg_index, const RegisterValue ®_value); - - lldb::ByteOrder - GetByteOrder() const; - - size_t - GetGPRSize() const; + WriteHardwareDebugRegs(lldb::addr_t *addr_buf, uint32_t *cntrl_buf, int type, int count); }; } // namespace process_linux @@ -167,3 +180,4 @@ #endif // #ifndef lldb_NativeRegisterContextLinux_arm64_h +#endif // defined (__arm64__) || defined (__aarch64__) Index: lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp +++ lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp @@ -7,19 +7,31 @@ // //===----------------------------------------------------------------------===// +#if defined (__arm64__) || defined (__aarch64__) + #include "NativeRegisterContextLinux_arm64.h" -#include "lldb/lldb-private-forward.h" +// C Includes +// C++ Includes + +// Other libraries and framework includes #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/Error.h" -#include "lldb/Core/StreamString.h" +#include "lldb/Core/Log.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Host/common/NativeProcessProtocol.h" -#include "lldb/Host/common/NativeThreadProtocol.h" + #include "Plugins/Process/Linux/NativeProcessLinux.h" -#include "lldb/Core/Log.h" +#include "Plugins/Process/Linux/Procfs.h" +#include "Plugins/Process/Utility/RegisterContextLinux_arm64.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 +// NT_PRSTATUS and NT_FPREGSET definition +#include -#define REG_CONTEXT_SIZE (GetGPRSize() + sizeof (m_fpr)) +#define REG_CONTEXT_SIZE (GetGPRSize() + GetFPRSize()) using namespace lldb; using namespace lldb_private; @@ -125,13 +137,341 @@ { "Floating Point Registers", "fpu", k_num_fpr_registers_arm64, g_fpu_regnums_arm64 } }; -NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64 ( - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx, - RegisterInfoInterface *reg_info_interface_p) : - NativeRegisterContextRegisterInfo (native_thread, concrete_frame_idx, reg_info_interface_p) +namespace +{ + +class ReadRegOperation : public NativeProcessLinux::Operation +{ +public: + ReadRegOperation(lldb::tid_t tid, uint32_t offset, const char *reg_name, RegisterValue &value) : + m_tid(tid), + m_offset(static_cast(offset)), + m_reg_name(reg_name), + m_value(value) + { } + + void + Execute(NativeProcessLinux *monitor) override; + +private: + lldb::tid_t m_tid; + uintptr_t m_offset; + const char *m_reg_name; + RegisterValue &m_value; +}; + +class WriteRegOperation : public NativeProcessLinux::Operation +{ +public: + WriteRegOperation(lldb::tid_t tid, unsigned offset, const char *reg_name, const RegisterValue &value) : + m_tid(tid), + m_offset(offset), + m_reg_name(reg_name), + m_value(value) + { } + + void + Execute(NativeProcessLinux *monitor) override; + +private: + lldb::tid_t m_tid; + uintptr_t m_offset; + const char *m_reg_name; + const RegisterValue &m_value; +}; + +class ReadGPROperation : public NativeProcessLinux::Operation +{ +public: + ReadGPROperation(lldb::tid_t tid, void *buf, size_t buf_size) + : m_tid(tid), m_buf(buf), m_buf_size(buf_size) + { } + + void Execute(NativeProcessLinux *monitor) override; + +private: + lldb::tid_t m_tid; + void *m_buf; + size_t m_buf_size; +}; + +class WriteGPROperation : public NativeProcessLinux::Operation +{ +public: + WriteGPROperation(lldb::tid_t tid, void *buf, size_t buf_size) : + m_tid(tid), m_buf(buf), m_buf_size(buf_size) + { } + + void Execute(NativeProcessLinux *monitor) override; + +private: + lldb::tid_t m_tid; + void *m_buf; + size_t m_buf_size; +}; + +class ReadFPROperation : public NativeProcessLinux::Operation +{ +public: + ReadFPROperation(lldb::tid_t tid, void *buf, size_t buf_size) + : m_tid(tid), + m_buf(buf), + m_buf_size(buf_size) + { } + + void Execute(NativeProcessLinux *monitor) override; + +private: + lldb::tid_t m_tid; + void *m_buf; + size_t m_buf_size; +}; + +class WriteFPROperation : public NativeProcessLinux::Operation +{ +public: + WriteFPROperation(lldb::tid_t tid, void *buf, size_t buf_size) + : m_tid(tid), m_buf(buf), m_buf_size(buf_size) + { } + + void Execute(NativeProcessLinux *monitor) override; + +private: + lldb::tid_t m_tid; + void *m_buf; + size_t m_buf_size; +}; + +class ReadDBGROperation : public NativeProcessLinux::Operation +{ +public: + ReadDBGROperation(lldb::tid_t tid, unsigned int &count_wp, unsigned int &count_bp) + : m_tid(tid), + m_count_wp(count_wp), + m_count_bp(count_bp) + { } + + void Execute(NativeProcessLinux *monitor) override; + +private: + lldb::tid_t m_tid; + unsigned int &m_count_wp; + unsigned int &m_count_bp; +}; + +class WriteDBGROperation : public NativeProcessLinux::Operation +{ +public: + WriteDBGROperation(lldb::tid_t tid, lldb::addr_t *addr_buf, + uint32_t *cntrl_buf, int type, int count) + : m_tid(tid), + m_address(addr_buf), + m_control(cntrl_buf), + m_type(type), + m_count(count) + { } + + void Execute(NativeProcessLinux *monitor) override; + +private: + lldb::tid_t m_tid; + lldb::addr_t * m_address; + uint32_t * m_control; + int m_type; + int m_count; +}; + +} // end of anonymous namespace + +void +ReadRegOperation::Execute(NativeProcessLinux *monitor) +{ + if (m_offset > sizeof(struct user_pt_regs)) + { + uintptr_t offset = m_offset - sizeof(struct user_pt_regs); + if (offset > sizeof(struct user_fpsimd_state)) + { + m_error.SetErrorString("invalid offset value"); + return; + } + elf_fpregset_t regs; + int regset = NT_FPREGSET; + struct iovec ioVec; + + ioVec.iov_base = ®s; + ioVec.iov_len = sizeof regs; + NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, ®set, &ioVec, sizeof regs, m_error); + if (m_error.Success()) + { + ArchSpec arch; + if (monitor->GetArchitecture(arch)) + m_value.SetBytes((void *)(((unsigned char *)(®s)) + offset), 16, arch.GetByteOrder()); + else + m_error.SetErrorString("failed to get architecture"); + } + } + else + { + elf_gregset_t regs; + int regset = NT_PRSTATUS; + struct iovec ioVec; + + ioVec.iov_base = ®s; + ioVec.iov_len = sizeof regs; + NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, ®set, &ioVec, sizeof regs, m_error); + if (m_error.Success()) + { + ArchSpec arch; + if (monitor->GetArchitecture(arch)) + m_value.SetBytes((void *)(((unsigned char *)(regs)) + m_offset), 8, arch.GetByteOrder()); + else + m_error.SetErrorString("failed to get architecture"); + } + } +} + +void +WriteRegOperation::Execute(NativeProcessLinux *monitor) +{ + if (m_offset > sizeof(struct user_pt_regs)) + { + uintptr_t offset = m_offset - sizeof(struct user_pt_regs); + if (offset > sizeof(struct user_fpsimd_state)) + { + m_error.SetErrorString("invalid offset value"); + return; + } + elf_fpregset_t regs; + int regset = NT_FPREGSET; + struct iovec ioVec; + + ioVec.iov_base = ®s; + ioVec.iov_len = sizeof regs; + NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, ®set, &ioVec, sizeof regs, m_error); + if (m_error.Success()) + { + ::memcpy((void *)(((unsigned char *)(®s)) + offset), m_value.GetBytes(), 16); + NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_tid, ®set, &ioVec, sizeof regs, m_error); + } + } + else + { + elf_gregset_t regs; + int regset = NT_PRSTATUS; + struct iovec ioVec; + + ioVec.iov_base = ®s; + ioVec.iov_len = sizeof regs; + NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, ®set, &ioVec, sizeof regs, m_error); + if (m_error.Success()) + { + ::memcpy((void *)(((unsigned char *)(®s)) + m_offset), m_value.GetBytes(), 8); + NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_tid, ®set, &ioVec, sizeof regs, m_error); + } + } +} + +void +ReadGPROperation::Execute(NativeProcessLinux *monitor) +{ + int regset = NT_PRSTATUS; + struct iovec ioVec; + + ioVec.iov_base = m_buf; + ioVec.iov_len = m_buf_size; + NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, ®set, &ioVec, m_buf_size, m_error); +} + +void +WriteGPROperation::Execute(NativeProcessLinux *monitor) { - switch (reg_info_interface_p->m_target_arch.GetMachine()) + int regset = NT_PRSTATUS; + struct iovec ioVec; + + ioVec.iov_base = m_buf; + ioVec.iov_len = m_buf_size; + NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_tid, ®set, &ioVec, m_buf_size, m_error); +} + +void +ReadFPROperation::Execute(NativeProcessLinux *monitor) +{ + int regset = NT_FPREGSET; + struct iovec ioVec; + + ioVec.iov_base = m_buf; + ioVec.iov_len = m_buf_size; + NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, ®set, &ioVec, m_buf_size, m_error); +} + +void +WriteFPROperation::Execute(NativeProcessLinux *monitor) +{ + int regset = NT_FPREGSET; + struct iovec ioVec; + + ioVec.iov_base = m_buf; + ioVec.iov_len = m_buf_size; + NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_tid, ®set, &ioVec, m_buf_size, m_error); +} + +void +ReadDBGROperation::Execute(NativeProcessLinux *monitor) +{ + int regset = NT_ARM_HW_WATCH; + struct iovec ioVec; + struct user_hwdebug_state dreg_state; + + ioVec.iov_base = &dreg_state; + ioVec.iov_len = sizeof (dreg_state); + + NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, ®set, &ioVec, ioVec.iov_len, m_error); + + m_count_wp = dreg_state.dbg_info & 0xff; + regset = NT_ARM_HW_BREAK; + + NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, ®set, &ioVec, ioVec.iov_len, m_error); + m_count_bp = dreg_state.dbg_info & 0xff; +} + +void +WriteDBGROperation::Execute(NativeProcessLinux *monitor) +{ + struct iovec ioVec; + struct user_hwdebug_state dreg_state; + + memset (&dreg_state, 0, sizeof (dreg_state)); + ioVec.iov_base = &dreg_state; + ioVec.iov_len = sizeof (dreg_state); + + if (m_type == 0) + m_type = NT_ARM_HW_WATCH; + else + m_type = NT_ARM_HW_BREAK; + + for (int i = 0; i < m_count; i++) + { + dreg_state.dbg_regs[i].addr = m_address[i]; + dreg_state.dbg_regs[i].ctrl = m_control[i]; + } + + NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_tid, &m_type, &ioVec, ioVec.iov_len, m_error); +} + +NativeRegisterContextLinux* +NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch, + NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx) +{ + return new NativeRegisterContextLinux_arm64(target_arch, native_thread, concrete_frame_idx); +} + +NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64 (const ArchSpec& target_arch, + NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx) : + NativeRegisterContextLinux (native_thread, concrete_frame_idx, new RegisterContextLinux_arm64(target_arch)) +{ + switch (target_arch.GetMachine()) { case llvm::Triple::aarch64: m_reg_info.num_registers = k_num_registers_arm64; @@ -189,11 +529,9 @@ if (IsFPR(reg)) { - if (!ReadFPR()) - { - error.SetErrorString ("failed to read floating point register"); + error = ReadFPR(); + if (error.Fail()) return error; - } } else { @@ -279,10 +617,9 @@ return Error ("unhandled register data size %" PRIu32, reg_info->byte_size); } - if (!WriteFPR()) - { - return Error ("NativeRegisterContextLinux_arm64::WriteRegister: WriteFPR failed"); - } + Error error = WriteFPR(); + if (error.Fail()) + return error; return Error (); } @@ -299,17 +636,13 @@ if (!data_sp) return Error ("failed to allocate DataBufferHeap instance of size %" PRIu64, REG_CONTEXT_SIZE); - if (!ReadGPR ()) - { - error.SetErrorString ("ReadGPR() failed"); + error = ReadGPR(); + if (error.Fail()) return error; - } - if (!ReadFPR ()) - { - error.SetErrorString ("ReadFPR() failed"); + error = ReadFPR(); + if (error.Fail()) return error; - } uint8_t *dst = data_sp->GetBytes (); if (dst == nullptr) @@ -351,120 +684,20 @@ } ::memcpy (&m_gpr_arm64, src, GetRegisterInfoInterface ().GetGPRSize ()); - if (!WriteGPR ()) - { - error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s WriteGPR() failed", __FUNCTION__); + error = WriteGPR(); + if (error.Fail()) return error; - } src += GetRegisterInfoInterface ().GetGPRSize (); ::memcpy (&m_fpr, src, sizeof(m_fpr)); - if (!WriteFPR ()) - { - error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s WriteFPR() failed", __FUNCTION__); + error = WriteFPR(); + if (error.Fail()) return error; - } return error; } -Error -NativeRegisterContextLinux_arm64::WriteRegisterRaw (uint32_t reg_index, const RegisterValue ®_value) -{ - Error error; - - uint32_t reg_to_write = reg_index; - RegisterValue value_to_write = reg_value; - - // Check if this is a subregister of a full register. - const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_index); - if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) - { - RegisterValue full_value; - uint32_t full_reg = reg_info->invalidate_regs[0]; - const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg); - - // Read the full register. - error = ReadRegister(full_reg_info, full_value); - if (error.Fail ()) - return error; - - lldb::ByteOrder byte_order = GetByteOrder(); - uint8_t dst[RegisterValue::kMaxRegisterByteSize]; - - // Get the bytes for the full register. - const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info, - dst, - sizeof(dst), - byte_order, - error); - if (error.Success() && dest_size) - { - uint8_t src[RegisterValue::kMaxRegisterByteSize]; - - // Get the bytes for the source data. - const uint32_t src_size = reg_value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error); - if (error.Success() && src_size && (src_size < dest_size)) - { - // Copy the src bytes to the destination. - memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size); - // Set this full register as the value to write. - value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order); - value_to_write.SetType(full_reg_info); - reg_to_write = full_reg; - } - } - } - - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (!process_sp) - { - error.SetErrorString ("NativeProcessProtocol is NULL"); - return error; - } - - 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) - { - error.SetErrorStringWithFormat ("NativeRegisterContextLinux_arm64::%s failed to get RegisterInfo for write register index %" PRIu32, __FUNCTION__, reg_to_write); - return error; - } - - NativeProcessLinux *const process_p = reinterpret_cast (process_sp.get ()); - return process_p->WriteRegisterValue(m_thread.GetID(), - register_to_write_info_p->byte_offset, - register_to_write_info_p->name, - value_to_write); -} - -Error -NativeRegisterContextLinux_arm64::ReadRegisterRaw (uint32_t reg_index, RegisterValue ®_value) -{ - Error error; - const RegisterInfo *const reg_info = GetRegisterInfoAtIndex (reg_index); - if (!reg_info) - { - error.SetErrorStringWithFormat ("register %" PRIu32 " not found", reg_index); - return error; - } - - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (!process_sp) - { - error.SetErrorString ("NativeProcessProtocol is NULL"); - return error; - } - - NativeProcessLinux *const process_p = reinterpret_cast (process_sp.get ()); - return process_p->ReadRegisterValue(m_thread.GetID(), - reg_info->byte_offset, - reg_info->name, - reg_info->byte_size, - reg_value); -} - bool NativeRegisterContextLinux_arm64::IsGPR(unsigned reg) const { @@ -472,79 +705,11 @@ } bool -NativeRegisterContextLinux_arm64::ReadGPR() -{ - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (!process_sp) - return false; - NativeProcessLinux *const process_p = reinterpret_cast (process_sp.get ()); - - return process_p->ReadGPR (m_thread.GetID (), &m_gpr_arm64, GetRegisterInfoInterface ().GetGPRSize ()).Success(); -} - -bool -NativeRegisterContextLinux_arm64::WriteGPR() -{ - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (!process_sp) - return false; - NativeProcessLinux *const process_p = reinterpret_cast (process_sp.get ()); - - return process_p->WriteGPR (m_thread.GetID (), &m_gpr_arm64, GetRegisterInfoInterface ().GetGPRSize ()).Success(); -} - -bool NativeRegisterContextLinux_arm64::IsFPR(unsigned reg) const { return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); } -bool -NativeRegisterContextLinux_arm64::ReadFPR () -{ - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (!process_sp) - return false; - - NativeProcessLinux *const process_p = reinterpret_cast (process_sp.get ()); - return process_p->ReadFPR (m_thread.GetID (), &m_fpr, sizeof (m_fpr)).Success(); -} - -bool -NativeRegisterContextLinux_arm64::WriteFPR () -{ - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (!process_sp) - return false; - - NativeProcessLinux *const process_p = reinterpret_cast (process_sp.get ()); - return process_p->WriteFPR (m_thread.GetID (), &m_fpr, sizeof (m_fpr)).Success(); -} - -lldb::ByteOrder -NativeRegisterContextLinux_arm64::GetByteOrder() const -{ - // Get the target process whose privileged thread was used for the register read. - lldb::ByteOrder byte_order = lldb::eByteOrderInvalid; - - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (!process_sp) - return byte_order; - - if (!process_sp->GetByteOrder (byte_order)) - { - // FIXME log here - } - - return byte_order; -} - -size_t -NativeRegisterContextLinux_arm64::GetGPRSize() const -{ - return GetRegisterInfoInterface().GetGPRSize(); -} - uint32_t NativeRegisterContextLinux_arm64::SetHardwareBreakpoint (lldb::addr_t addr, size_t size) { @@ -557,12 +722,10 @@ if (!process_sp) return false; - NativeProcessLinux *const process_p = reinterpret_cast (process_sp.get ()); // Check if our hardware breakpoint and watchpoint information is updated. if (m_refresh_hwdebug_info) { - process_p->ReadHardwareDebugInfo (m_thread.GetID (), m_max_hwp_supported, - m_max_hbp_supported); + ReadHardwareDebugInfo (m_max_hwp_supported, m_max_hbp_supported); m_refresh_hwdebug_info = false; } @@ -668,12 +831,11 @@ if (!process_sp) return false; - NativeProcessLinux *const process_p = reinterpret_cast (process_sp.get ()); + // Check if our hardware breakpoint and watchpoint information is updated. if (m_refresh_hwdebug_info) { - process_p->ReadHardwareDebugInfo (m_thread.GetID (), m_max_hwp_supported, - m_max_hbp_supported); + ReadHardwareDebugInfo (m_max_hwp_supported, m_max_hbp_supported); m_refresh_hwdebug_info = false; } @@ -724,8 +886,7 @@ m_hwp_regs[wp_index].refcount = 1; // PTRACE call to set corresponding watchpoint register. - process_p->WriteHardwareDebugRegs(m_thread.GetID (), &addr, - &control_value, 0, wp_index); + WriteHardwareDebugRegs(&addr, &control_value, 0, wp_index); } else m_hwp_regs[wp_index].refcount++; @@ -745,8 +906,6 @@ if (!process_sp) return false; - NativeProcessLinux *const process_p = reinterpret_cast (process_sp.get ()); - if (wp_index >= m_max_hwp_supported) return false; @@ -763,10 +922,7 @@ m_hwp_regs[wp_index].refcount = 0; //TODO: PTRACE CALL HERE for an UPDATE - process_p->WriteHardwareDebugRegs(m_thread.GetID (), - &m_hwp_regs[wp_index].address, - &m_hwp_regs[wp_index].control, - 0, wp_index); + WriteHardwareDebugRegs(&m_hwp_regs[wp_index].address, &m_hwp_regs[wp_index].control, 0, wp_index); return true; } @@ -788,8 +944,6 @@ if (!process_sp) return ml_error; - NativeProcessLinux *const process_p = reinterpret_cast (process_sp.get ()); - for (uint32_t i = 0; i < m_max_hwp_supported; i++) { if (m_hwp_regs[i].control & 0x01) @@ -798,10 +952,7 @@ m_hwp_regs[i].address = 0; m_hwp_regs[i].refcount = 0; - process_p->WriteHardwareDebugRegs(m_thread.GetID (), - &m_hwp_regs[i].address, - &m_hwp_regs[i].control, - 0, i); + WriteHardwareDebugRegs(&m_hwp_regs[i].address, &m_hwp_regs[i].control, 0, i); } } @@ -887,13 +1038,73 @@ return LLDB_INVALID_ADDRESS; } -bool -NativeRegisterContextLinux_arm64::HardwareSingleStep (bool enable) +Error +NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo(unsigned int &watch_count, + unsigned int &break_count) { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); + NativeProcessProtocolSP process_sp (m_thread.GetProcess()); + if (!process_sp) + return Error("NativeProcessProtocol is NULL"); + NativeProcessLinux *const process_p = reinterpret_cast(process_sp.get()); - if (log) - log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); + ReadDBGROperation op(m_thread.GetID(), watch_count, break_count); + return process_p->DoOperation(&op); +} - return false; +Error +NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(lldb::addr_t *addr_buf, + uint32_t *cntrl_buf, + int type, + int count) +{ + NativeProcessProtocolSP process_sp (m_thread.GetProcess()); + if (!process_sp) + return Error("NativeProcessProtocol is NULL"); + NativeProcessLinux *const process_p = reinterpret_cast(process_sp.get()); + + WriteDBGROperation op(m_thread.GetID(), addr_buf, cntrl_buf, type, count); + return process_p->DoOperation(&op); +} + +NativeProcessLinux::OperationUP +NativeRegisterContextLinux_arm64::GetReadRegisterValueOperation(uint32_t offset, + const char* reg_name, + uint32_t size, + RegisterValue &value) +{ + return NativeProcessLinux::OperationUP(new ReadRegOperation(m_thread.GetID(), offset, reg_name, value)); +} + +NativeProcessLinux::OperationUP +NativeRegisterContextLinux_arm64::GetWriteRegisterValueOperation(uint32_t offset, + const char* reg_name, + const RegisterValue &value) +{ + return NativeProcessLinux::OperationUP(new WriteRegOperation(m_thread.GetID(), offset, reg_name, value)); +} + +NativeProcessLinux::OperationUP +NativeRegisterContextLinux_arm64::GetReadGPROperation(void *buf, size_t buf_size) +{ + return NativeProcessLinux::OperationUP(new ReadGPROperation(m_thread.GetID(), buf, buf_size)); +} + +NativeProcessLinux::OperationUP +NativeRegisterContextLinux_arm64::GetWriteGPROperation(void *buf, size_t buf_size) +{ + return NativeProcessLinux::OperationUP(new WriteGPROperation(m_thread.GetID(), buf, buf_size)); } + +NativeProcessLinux::OperationUP +NativeRegisterContextLinux_arm64::GetReadFPROperation(void *buf, size_t buf_size) +{ + return NativeProcessLinux::OperationUP(new ReadFPROperation(m_thread.GetID(), buf, buf_size)); +} + +NativeProcessLinux::OperationUP +NativeRegisterContextLinux_arm64::GetWriteFPROperation(void *buf, size_t buf_size) +{ + return NativeProcessLinux::OperationUP(new WriteFPROperation(m_thread.GetID(), buf, buf_size)); +} + +#endif // defined (__arm64__) || defined (__aarch64__) Index: lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h =================================================================== --- lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h +++ lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h @@ -7,11 +7,12 @@ // //===----------------------------------------------------------------------===// +#if defined (__mips__) #ifndef lldb_NativeRegisterContextLinux_mips64_h #define lldb_NativeRegisterContextLinux_mips64_h -#include "lldb/Host/common/NativeRegisterContextRegisterInfo.h" +#include "Plugins/Process/Linux/NativeRegisterContextLinux.h" #include "Plugins/Process/Utility/RegisterContext_mips64.h" #include "Plugins/Process/Utility/RegisterContextLinux_mips64.h" @@ -68,11 +69,12 @@ k_num_gp_reg_mips64, }; - class NativeRegisterContextLinux_mips64 : public NativeRegisterContextRegisterInfo + class NativeRegisterContextLinux_mips64 : public NativeRegisterContextLinux { public: - NativeRegisterContextLinux_mips64 (NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx, RegisterInfoInterface *reg_info_interface_p); + NativeRegisterContextLinux_mips64 (const ArchSpec& target_arch, + NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx); uint32_t GetRegisterSetCount () const override; @@ -118,13 +120,17 @@ uint32_t NumSupportedHardwareWatchpoints () override; - private: - - lldb_private::Error - WriteRegister(const uint32_t reg, const RegisterValue &value); - - lldb_private::Error - ReadRegisterRaw (uint32_t reg_index, RegisterValue ®_value); + protected: + NativeProcessLinux::OperationUP + GetReadRegisterValueOperation(uint32_t offset, + const char* reg_name, + uint32_t size, + RegisterValue &value) override; + + NativeProcessLinux::OperationUP + GetWriteRegisterValueOperation(uint32_t offset, + const char* reg_name, + const RegisterValue &value) override; }; } // namespace process_linux @@ -132,3 +138,4 @@ #endif // #ifndef lldb_NativeRegisterContextLinux_mips64_h +#endif // defined (__mips__) Index: lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp +++ lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp @@ -7,15 +7,20 @@ // //===----------------------------------------------------------------------===// +#if defined (__mips__) + #include "NativeRegisterContextLinux_mips64.h" -#include "lldb/lldb-private-forward.h" -#include "lldb/Core/DataBufferHeap.h" +// C Includes +// C++ Includes + +// Other libraries and framework includes #include "lldb/Core/Error.h" #include "lldb/Core/RegisterValue.h" -#include "lldb/Host/common/NativeProcessProtocol.h" -#include "lldb/Host/common/NativeThreadProtocol.h" + #include "Plugins/Process/Linux/NativeProcessLinux.h" +#include "Plugins/Process/Linux/Procfs.h" +#include "Plugins/Process/Utility/RegisterContextLinux_mips64.h" using namespace lldb_private; using namespace lldb_private::process_linux; @@ -86,15 +91,90 @@ { { "General Purpose Registers", "gpr", k_num_gp_reg_mips64, g_gp_regnums_mips64 } }; + + class ReadRegOperation : public NativeProcessLinux::Operation + { + public: + ReadRegOperation(lldb::tid_t tid, uint32_t offset, RegisterValue &value) : + m_tid(tid), + m_offset(static_cast(offset)), + m_value(value) + { } + + void + Execute(NativeProcessLinux *monitor) override; + + private: + lldb::tid_t m_tid; + uintptr_t m_offset; + RegisterValue &m_value; + }; + + class WriteRegOperation : public NativeProcessLinux::Operation + { + public: + WriteRegOperation(lldb::tid_t tid, unsigned offset, const char *reg_name, const RegisterValue &value) : + m_tid(tid), + m_offset(offset), + m_reg_name(reg_name), + m_value(value) + { } + + void + Execute(NativeProcessLinux *monitor) override; + + private: + lldb::tid_t m_tid; + uintptr_t m_offset; + const char *m_reg_name; + const RegisterValue &m_value; + }; + +} // end of anonymous namespace + +void +ReadRegOperation::Execute(NativeProcessLinux *monitor) +{ + elf_gregset_t regs; + NativeProcessLinux::PtraceWrapper(PTRACE_GETREGS, m_tid, NULL, ®s, sizeof regs, m_error); + if (m_error.Success()) + { + lldb_private::ArchSpec arch; + if (monitor->GetArchitecture(arch)) + m_value.SetBytes((void *)(((unsigned char *)(regs)) + m_offset), 8, arch.GetByteOrder()); + else + m_error.SetErrorString("failed to get architecture"); + } +} + +void +WriteRegOperation::Execute(NativeProcessLinux *monitor) +{ + elf_gregset_t regs; + NativeProcessLinux::PtraceWrapper(PTRACE_GETREGS, m_tid, NULL, ®s, sizeof regs, m_error); + if (m_error.Success()) + { + ::memcpy((void *)(((unsigned char *)(®s)) + m_offset), m_value.GetBytes(), 8); + NativeProcessLinux::PtraceWrapper(PTRACE_SETREGS, m_tid, NULL, ®s, sizeof regs, m_error); + } +} + +NativeRegisterContextLinux* +NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch, + NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx) +{ + return new NativeRegisterContextLinux_mips64(target_arch, native_thread, concrete_frame_idx); } // ---------------------------------------------------------------------------- // NativeRegisterContextLinux_mips64 members. // ---------------------------------------------------------------------------- -NativeRegisterContextLinux_mips64::NativeRegisterContextLinux_mips64 (NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx, RegisterInfoInterface *reg_info_interface_p) : - NativeRegisterContextRegisterInfo (native_thread, concrete_frame_idx, reg_info_interface_p) +NativeRegisterContextLinux_mips64::NativeRegisterContextLinux_mips64 (const ArchSpec& target_arch, + NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx) : + NativeRegisterContextLinux (native_thread, concrete_frame_idx, new RegisterContextLinux_mips64 (target_arch)) { } @@ -124,33 +204,6 @@ } lldb_private::Error -NativeRegisterContextLinux_mips64::ReadRegisterRaw (uint32_t reg_index, RegisterValue ®_value) -{ - Error error; - - const RegisterInfo *const reg_info = GetRegisterInfoAtIndex (reg_index); - if (!reg_info) - { - error.SetErrorStringWithFormat ("register %" PRIu32 " not found", reg_index); - return error; - } - - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (!process_sp) - { - error.SetErrorString ("NativeProcessProtocol is NULL"); - return error; - } - - NativeProcessLinux *const process_p = reinterpret_cast (process_sp.get ()); - return process_p->ReadRegisterValue(m_thread.GetID(), - reg_info->byte_offset, - reg_info->name, - reg_info->byte_size, - reg_value); -} - -lldb_private::Error NativeRegisterContextLinux_mips64::ReadRegister (const RegisterInfo *reg_info, RegisterValue ®_value) { Error error; @@ -183,39 +236,6 @@ } lldb_private::Error -NativeRegisterContextLinux_mips64::WriteRegister(const uint32_t reg, - const RegisterValue &value) -{ - Error error; - - uint32_t reg_to_write = reg; - RegisterValue value_to_write = value; - - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (!process_sp) - { - error.SetErrorString ("NativeProcessProtocol is NULL"); - return error; - } - - 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) - { - error.SetErrorStringWithFormat ("NativeRegisterContextLinux_mips64::%s failed to get RegisterInfo for write register index %" PRIu32, __FUNCTION__, reg_to_write); - return error; - } - - NativeProcessLinux *const process_p = reinterpret_cast (process_sp.get ()); - return process_p->WriteRegisterValue(m_thread.GetID(), - register_to_write_info_p->byte_offset, - register_to_write_info_p->name, - value_to_write); -} - - - -lldb_private::Error NativeRegisterContextLinux_mips64::WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value) { assert (reg_info && "reg_info is null"); @@ -225,7 +245,7 @@ if (reg_index == LLDB_INVALID_REGNUM) return Error ("no lldb regnum for %s", reg_info && reg_info->name ? reg_info->name : ""); - return WriteRegister(reg_index, reg_value); + return WriteRegisterRaw(reg_index, reg_value); } Error @@ -299,3 +319,22 @@ { return 0; } + +NativeProcessLinux::OperationUP +NativeRegisterContextLinux_mips64::GetReadRegisterValueOperation(uint32_t offset, + const char* reg_name, + uint32_t size, + RegisterValue &value) +{ + return NativeProcessLinux::OperationUP(new ReadRegOperation(m_thread.GetID(), offset, value)); +} + +NativeProcessLinux::OperationUP +NativeRegisterContextLinux_mips64::GetWriteRegisterValueOperation(uint32_t offset, + const char* reg_name, + const RegisterValue &value) +{ + return NativeProcessLinux::OperationUP(new WriteRegOperation(m_thread.GetID(), offset, reg_name, value)); +} + +#endif // defined (__mips__) Index: lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h =================================================================== --- lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h +++ lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h @@ -7,11 +7,12 @@ // //===----------------------------------------------------------------------===// +#if defined(__i386__) || defined(__x86_64__) #ifndef lldb_NativeRegisterContextLinux_x86_64_h #define lldb_NativeRegisterContextLinux_x86_64_h -#include "lldb/Host/common/NativeRegisterContextRegisterInfo.h" +#include "Plugins/Process/Linux/NativeRegisterContextLinux.h" #include "Plugins/Process/Utility/RegisterContext_x86.h" #include "Plugins/Process/Utility/lldb-x86-register-enums.h" @@ -20,10 +21,12 @@ class NativeProcessLinux; - class NativeRegisterContextLinux_x86_64 : public NativeRegisterContextRegisterInfo + class NativeRegisterContextLinux_x86_64 : public NativeRegisterContextLinux { public: - NativeRegisterContextLinux_x86_64 (NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx, RegisterInfoInterface *reg_info_interface_p); + NativeRegisterContextLinux_x86_64 (const ArchSpec& target_arch, + NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx); uint32_t GetRegisterSetCount () const override; @@ -75,6 +78,22 @@ uint32_t NumSupportedHardwareWatchpoints() override; + protected: + void* + GetGPRBuffer() override { return &m_gpr_x86_64; } + + void* + GetFPRBuffer() override; + + size_t + GetFPRSize() override; + + Error + ReadFPR() override; + + Error + WriteFPR() override; + private: // Private member types. @@ -119,14 +138,8 @@ uint64_t m_gpr_x86_64[k_num_gpr_registers_x86_64]; // Private member methods. - Error - WriteRegister(const uint32_t reg, const RegisterValue &value); - bool IsRegisterSetAvailable (uint32_t set_index) const; - lldb::ByteOrder - GetByteOrder() const; - bool IsGPR(uint32_t reg_index) const; @@ -137,9 +150,7 @@ IsFPR(uint32_t reg_index) const; bool - WriteFPR(); - - bool IsFPR(uint32_t reg_index, FPRType fpr_type) const; + IsFPR(uint32_t reg_index, FPRType fpr_type) const; bool CopyXSTATEtoYMM (uint32_t reg_index, lldb::ByteOrder byte_order); @@ -149,18 +160,6 @@ bool IsAVX (uint32_t reg_index) const; - - bool - ReadFPR (); - - Error - ReadRegisterRaw (uint32_t reg_index, RegisterValue ®_value); - - bool - ReadGPR(); - - bool - WriteGPR(); }; } // namespace process_linux @@ -168,3 +167,4 @@ #endif // #ifndef lldb_NativeRegisterContextLinux_x86_64_h +#endif // defined(__i386__) || defined(__x86_64__) Index: lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp +++ lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp @@ -7,16 +7,18 @@ // //===----------------------------------------------------------------------===// +#if defined(__i386__) || defined(__x86_64__) + #include "NativeRegisterContextLinux_x86_64.h" #include "lldb/Core/Log.h" -#include "lldb/lldb-private-forward.h" #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/Error.h" #include "lldb/Core/RegisterValue.h" -#include "lldb/Host/common/NativeProcessProtocol.h" -#include "lldb/Host/common/NativeThreadProtocol.h" -#include "Plugins/Process/Linux/NativeProcessLinux.h" +#include "lldb/Host/HostInfo.h" + +#include "Plugins/Process/Utility/RegisterContextLinux_i386.h" +#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h" using namespace lldb_private; using namespace lldb_private::process_linux; @@ -326,12 +328,39 @@ #define NT_X86_XSTATE 0x202 #endif +NativeRegisterContextLinux* +NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch, + NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx) +{ + return new NativeRegisterContextLinux_x86_64(target_arch, native_thread, concrete_frame_idx); +} + // ---------------------------------------------------------------------------- // NativeRegisterContextLinux_x86_64 members. // ---------------------------------------------------------------------------- -NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64 (NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx, RegisterInfoInterface *reg_info_interface_p) : - NativeRegisterContextRegisterInfo (native_thread, concrete_frame_idx, reg_info_interface_p), +static RegisterInfoInterface* +CreateRegisterInfoInterface(const ArchSpec& target_arch) +{ + if (HostInfo::GetArchitecture().GetAddressByteSize() == 4) + { + // 32-bit hosts run with a RegisterContextLinux_i386 context. + return new RegisterContextLinux_i386(target_arch); + } + else + { + assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) && + "Register setting path assumes this is a 64-bit host"); + // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the x86_64 register context. + return new RegisterContextLinux_x86_64 (target_arch); + } +} + +NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64 (const ArchSpec& target_arch, + NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx) : + NativeRegisterContextLinux (native_thread, concrete_frame_idx, CreateRegisterInfoInterface(target_arch)), m_fpr_type (eFPRTypeNotValid), m_fpr (), m_iovec (), @@ -340,7 +369,7 @@ m_gpr_x86_64 () { // Set up data about ranges of valid registers. - switch (reg_info_interface_p->GetTargetArchitecture ().GetMachine ()) + switch (target_arch.GetMachine ()) { case llvm::Triple::x86: m_reg_info.num_registers = k_num_registers_i386; @@ -444,32 +473,6 @@ } Error -NativeRegisterContextLinux_x86_64::ReadRegisterRaw (uint32_t reg_index, RegisterValue ®_value) -{ - Error error; - const RegisterInfo *const reg_info = GetRegisterInfoAtIndex (reg_index); - if (!reg_info) - { - error.SetErrorStringWithFormat ("register %" PRIu32 " not found", reg_index); - return error; - } - - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (!process_sp) - { - error.SetErrorString ("NativeProcessProtocol is NULL"); - return error; - } - - NativeProcessLinux *const process_p = reinterpret_cast (process_sp.get ()); - return process_p->ReadRegisterValue(m_thread.GetID(), - reg_info->byte_offset, - reg_info->name, - reg_info->byte_size, - reg_value); -} - -Error NativeRegisterContextLinux_x86_64::ReadRegister (const RegisterInfo *reg_info, RegisterValue ®_value) { Error error; @@ -490,11 +493,9 @@ if (IsFPR(reg, GetFPRType())) { - if (!ReadFPR()) - { - error.SetErrorString ("failed to read floating point register"); + error = ReadFPR(); + if (error.Fail()) return error; - } } else { @@ -581,78 +582,6 @@ } Error -NativeRegisterContextLinux_x86_64::WriteRegister(const uint32_t reg, - const RegisterValue &value) -{ - Error error; - - uint32_t reg_to_write = reg; - RegisterValue value_to_write = value; - - // Check if this is a subregister of a full register. - const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg); - if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) - { - RegisterValue full_value; - uint32_t full_reg = reg_info->invalidate_regs[0]; - const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg); - - // Read the full register. - error = ReadRegister(full_reg_info, full_value); - if (error.Fail ()) - return error; - - lldb::ByteOrder byte_order = GetByteOrder(); - uint8_t dst[RegisterValue::kMaxRegisterByteSize]; - - // Get the bytes for the full register. - const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info, - dst, - sizeof(dst), - byte_order, - error); - if (error.Success() && dest_size) - { - uint8_t src[RegisterValue::kMaxRegisterByteSize]; - - // Get the bytes for the source data. - const uint32_t src_size = value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error); - if (error.Success() && src_size && (src_size < dest_size)) - { - // Copy the src bytes to the destination. - memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size); - // Set this full register as the value to write. - value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order); - value_to_write.SetType(full_reg_info); - reg_to_write = full_reg; - } - } - } - - - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (!process_sp) - { - error.SetErrorString ("NativeProcessProtocol is NULL"); - return error; - } - - 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) - { - error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s failed to get RegisterInfo for write register index %" PRIu32, __FUNCTION__, reg_to_write); - return error; - } - - NativeProcessLinux *const process_p = reinterpret_cast (process_sp.get ()); - return process_p->WriteRegisterValue(m_thread.GetID(), - register_to_write_info_p->byte_offset, - register_to_write_info_p->name, - value_to_write); -} - -Error NativeRegisterContextLinux_x86_64::WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value) { assert (reg_info && "reg_info is null"); @@ -662,7 +591,7 @@ return Error ("no lldb regnum for %s", reg_info && reg_info->name ? reg_info->name : ""); if (IsGPR(reg_index)) - return WriteRegister(reg_index, reg_value); + return WriteRegisterRaw(reg_index, reg_value); if (IsFPR(reg_index, GetFPRType())) { @@ -710,15 +639,16 @@ } } - if (WriteFPR()) + Error error = WriteFPR(); + if (error.Fail()) + return error; + + if (IsAVX(reg_index)) { - if (IsAVX(reg_index)) - { - if (!CopyYMMtoXSTATE(reg_index, GetByteOrder())) - return Error ("CopyYMMtoXSTATE() failed"); - } - return Error (); + if (!CopyYMMtoXSTATE(reg_index, GetByteOrder())) + return Error ("CopyYMMtoXSTATE() failed"); } + return Error (); } return Error ("failed - register wasn't recognized to be a GPR or an FPR, write strategy unknown"); } @@ -735,17 +665,13 @@ return error; } - if (!ReadGPR ()) - { - error.SetErrorString ("ReadGPR() failed"); + error = ReadGPR(); + if (error.Fail()) return error; - } - if (!ReadFPR ()) - { - error.SetErrorString ("ReadFPR() failed"); + error = ReadFPR(); + if (error.Fail()) return error; - } uint8_t *dst = data_sp->GetBytes (); if (dst == nullptr) @@ -810,11 +736,9 @@ } ::memcpy (&m_gpr_x86_64, src, GetRegisterInfoInterface ().GetGPRSize ()); - if (!WriteGPR ()) - { - error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s WriteGPR() failed", __FUNCTION__); + error = WriteGPR(); + if (error.Fail()) return error; - } src += GetRegisterInfoInterface ().GetGPRSize (); if (GetFPRType () == eFPRTypeFXSAVE) @@ -822,11 +746,9 @@ else if (GetFPRType () == eFPRTypeXSAVE) ::memcpy (&m_fpr.xstate.xsave, src, sizeof(m_fpr.xstate.xsave)); - if (!WriteFPR ()) - { - error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s WriteFPR() failed", __FUNCTION__); + error = WriteFPR(); + if (error.Fail()) return error; - } if (GetFPRType() == eFPRTypeXSAVE) { @@ -860,24 +782,6 @@ return (set_index < num_sets); } -lldb::ByteOrder -NativeRegisterContextLinux_x86_64::GetByteOrder() const -{ - // Get the target process whose privileged thread was used for the register read. - lldb::ByteOrder byte_order = lldb::eByteOrderInvalid; - - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (!process_sp) - return byte_order; - - if (!process_sp->GetByteOrder (byte_order)) - { - // FIXME log here - } - - return byte_order; -} - bool NativeRegisterContextLinux_x86_64::IsGPR(uint32_t reg_index) const { @@ -894,7 +798,7 @@ // Try and see if AVX register retrieval works. m_fpr_type = eFPRTypeXSAVE; - if (!const_cast (this)->ReadFPR ()) + if (const_cast(this)->ReadFPR().Fail()) { // Fall back to general floating point with no AVX support. m_fpr_type = eFPRTypeFXSAVE; @@ -920,20 +824,19 @@ return generic_fpr; } -bool +Error NativeRegisterContextLinux_x86_64::WriteFPR() { - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (!process_sp) - return false; - NativeProcessLinux *const process_p = reinterpret_cast (process_sp.get ()); - - if (GetFPRType() == eFPRTypeFXSAVE) - return process_p->WriteFPR (m_thread.GetID (), &m_fpr.xstate.fxsave, sizeof (m_fpr.xstate.fxsave)).Success(); - - if (GetFPRType() == eFPRTypeXSAVE) - return process_p->WriteRegisterSet (m_thread.GetID (), &m_iovec, sizeof (m_fpr.xstate.xsave), NT_X86_XSTATE).Success(); - return false; + const FPRType fpr_type = GetFPRType (); + switch (fpr_type) + { + case FPRType::eFPRTypeFXSAVE: + return NativeRegisterContextLinux::WriteFPR(); + case FPRType::eFPRTypeXSAVE: + return WriteRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE); + default: + return Error("Unrecognized FPR type"); + } } bool @@ -1003,48 +906,49 @@ return false; // unsupported or invalid byte order } -bool -NativeRegisterContextLinux_x86_64::ReadFPR () +void* +NativeRegisterContextLinux_x86_64::GetFPRBuffer() { - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (!process_sp) - return false; - NativeProcessLinux *const process_p = reinterpret_cast (process_sp.get ()); - const FPRType fpr_type = GetFPRType (); switch (fpr_type) { case FPRType::eFPRTypeFXSAVE: - return process_p->ReadFPR (m_thread.GetID (), &m_fpr.xstate.fxsave, sizeof (m_fpr.xstate.fxsave)).Success(); - + return &m_fpr.xstate.fxsave; case FPRType::eFPRTypeXSAVE: - return process_p->ReadRegisterSet (m_thread.GetID (), &m_iovec, sizeof (m_fpr.xstate.xsave), NT_X86_XSTATE).Success(); - + return &m_iovec; default: - return false; + return nullptr; } } -bool -NativeRegisterContextLinux_x86_64::ReadGPR() +size_t +NativeRegisterContextLinux_x86_64::GetFPRSize() { - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (!process_sp) - return false; - NativeProcessLinux *const process_p = reinterpret_cast (process_sp.get ()); - - return process_p->ReadGPR (m_thread.GetID (), &m_gpr_x86_64, GetRegisterInfoInterface ().GetGPRSize ()).Success(); + const FPRType fpr_type = GetFPRType (); + switch (fpr_type) + { + case FPRType::eFPRTypeFXSAVE: + return sizeof(m_fpr.xstate.fxsave); + case FPRType::eFPRTypeXSAVE: + return sizeof(m_iovec); + default: + return 0; + } } -bool -NativeRegisterContextLinux_x86_64::WriteGPR() +Error +NativeRegisterContextLinux_x86_64::ReadFPR () { - NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); - if (!process_sp) - return false; - NativeProcessLinux *const process_p = reinterpret_cast (process_sp.get ()); - - return process_p->WriteGPR (m_thread.GetID (), &m_gpr_x86_64, GetRegisterInfoInterface ().GetGPRSize ()).Success(); + const FPRType fpr_type = GetFPRType (); + switch (fpr_type) + { + case FPRType::eFPRTypeFXSAVE: + return NativeRegisterContextLinux::ReadFPR(); + case FPRType::eFPRTypeXSAVE: + return ReadRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE); + default: + return Error("Unrecognized FPR type"); + } } Error @@ -1148,10 +1052,10 @@ control_bits |= enable_bit | rw_bits | size_bits; - error = WriteRegister(m_reg_info.first_dr + wp_index, RegisterValue(addr)); + error = WriteRegisterRaw(m_reg_info.first_dr + wp_index, RegisterValue(addr)); if (error.Fail()) return error; - error = WriteRegister(m_reg_info.first_dr + 7, RegisterValue(control_bits)); + error = WriteRegisterRaw(m_reg_info.first_dr + 7, RegisterValue(control_bits)); if (error.Fail()) return error; error.Clear(); @@ -1172,7 +1076,7 @@ if (error.Fail()) return false; uint64_t bit_mask = 1 << wp_index; uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask; - error = WriteRegister(m_reg_info.first_dr + 6, RegisterValue(status_bits)); + error = WriteRegisterRaw(m_reg_info.first_dr + 6, RegisterValue(status_bits)); if (error.Fail()) return false; // for watchpoints 0, 1, 2, or 3, respectively, @@ -1182,7 +1086,7 @@ if (error.Fail()) return false; bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index)); uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask; - return WriteRegister(m_reg_info.first_dr + 7, RegisterValue(control_bits)).Success(); + return WriteRegisterRaw(m_reg_info.first_dr + 7, RegisterValue(control_bits)).Success(); } Error @@ -1195,7 +1099,7 @@ if (error.Fail()) return error; uint64_t bit_mask = 0xF; uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask; - error = WriteRegister(m_reg_info.first_dr + 6, RegisterValue(status_bits)); + error = WriteRegisterRaw(m_reg_info.first_dr + 6, RegisterValue(status_bits)); if (error.Fail()) return error; // clear bits {0-7,16-31} of the debug control register (DR7) @@ -1203,7 +1107,7 @@ if (error.Fail()) return error; bit_mask = 0xFF | (0xFFFF << 16); uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask; - return WriteRegister(m_reg_info.first_dr + 7, RegisterValue(control_bits)); + return WriteRegisterRaw(m_reg_info.first_dr + 7, RegisterValue(control_bits)); } uint32_t @@ -1248,3 +1152,5 @@ // Available debug address registers: dr0, dr1, dr2, dr3 return 4; } + +#endif // defined(__i386__) || defined(__x86_64__) Index: lldb/trunk/source/Plugins/Process/Linux/NativeThreadLinux.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/Linux/NativeThreadLinux.cpp +++ lldb/trunk/source/Plugins/Process/Linux/NativeThreadLinux.cpp @@ -20,8 +20,6 @@ #include "lldb/Core/Log.h" #include "lldb/Core/State.h" -#include "lldb/Host/Host.h" -#include "lldb/Host/HostInfo.h" #include "lldb/Host/HostNativeThread.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/lldb-enumerations.h" @@ -30,13 +28,6 @@ #include "Plugins/Process/POSIX/CrashReason.h" -#include "Plugins/Process/Utility/RegisterContextLinux_arm.h" -#include "Plugins/Process/Utility/RegisterContextLinux_arm64.h" -#include "Plugins/Process/Utility/RegisterContextLinux_i386.h" -#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h" -#include "Plugins/Process/Utility/RegisterContextLinux_mips64.h" -#include "Plugins/Process/Utility/RegisterInfoInterface.h" - #include // Try to define a macro to encapsulate the tgkill syscall #define tgkill(pid, tid, sig) \ @@ -172,8 +163,6 @@ if (m_reg_context_sp) return m_reg_context_sp; - // First select the appropriate RegisterInfoInterface. - RegisterInfoInterface *reg_interface = nullptr; NativeProcessProtocolSP m_process_sp = m_process_wp.lock (); if (!m_process_sp) return NativeRegisterContextSP (); @@ -182,93 +171,10 @@ if (!m_process_sp->GetArchitecture (target_arch)) return NativeRegisterContextSP (); - switch (target_arch.GetTriple().getOS()) - { - case llvm::Triple::Linux: - switch (target_arch.GetMachine()) - { - case llvm::Triple::aarch64: - assert((HostInfo::GetArchitecture ().GetAddressByteSize() == 8) && "Register setting path assumes this is a 64-bit host"); - reg_interface = static_cast(new RegisterContextLinux_arm64(target_arch)); - break; - case llvm::Triple::arm: - assert(HostInfo::GetArchitecture ().GetAddressByteSize() == 4); - reg_interface = static_cast(new RegisterContextLinux_arm(target_arch)); - break; - case llvm::Triple::x86: - case llvm::Triple::x86_64: - if (HostInfo::GetArchitecture().GetAddressByteSize() == 4) - { - // 32-bit hosts run with a RegisterContextLinux_i386 context. - reg_interface = static_cast(new RegisterContextLinux_i386(target_arch)); - } - else - { - assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) && - "Register setting path assumes this is a 64-bit host"); - // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the x86_64 register context. - reg_interface = static_cast (new RegisterContextLinux_x86_64 (target_arch)); - } - break; - case llvm::Triple::mips64: - case llvm::Triple::mips64el: - assert((HostInfo::GetArchitecture ().GetAddressByteSize() == 8) - && "Register setting path assumes this is a 64-bit host"); - reg_interface = static_cast(new RegisterContextLinux_mips64 (target_arch)); - break; - default: - break; - } - break; - default: - break; - } - - assert(reg_interface && "OS or CPU not supported!"); - if (!reg_interface) - return NativeRegisterContextSP (); - - // Now create the register context. - switch (target_arch.GetMachine()) - { -#if 0 - case llvm::Triple::mips64: - { - RegisterContextPOSIXProcessMonitor_mips64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_mips64(*this, 0, reg_interface); - m_posix_thread = reg_ctx; - m_reg_context_sp.reset(reg_ctx); - break; - } -#endif - case llvm::Triple::mips64: - case llvm::Triple::mips64el: - { - const uint32_t concrete_frame_idx = 0; - m_reg_context_sp.reset (new NativeRegisterContextLinux_mips64 (*this, concrete_frame_idx, reg_interface)); - break; - } - case llvm::Triple::aarch64: - { - const uint32_t concrete_frame_idx = 0; - m_reg_context_sp.reset (new NativeRegisterContextLinux_arm64(*this, concrete_frame_idx, reg_interface)); - break; - } - case llvm::Triple::arm: - { - const uint32_t concrete_frame_idx = 0; - m_reg_context_sp.reset (new NativeRegisterContextLinux_arm(*this, concrete_frame_idx, reg_interface)); - break; - } - case llvm::Triple::x86: - case llvm::Triple::x86_64: - { - const uint32_t concrete_frame_idx = 0; - m_reg_context_sp.reset (new NativeRegisterContextLinux_x86_64(*this, concrete_frame_idx, reg_interface)); - break; - } - default: - break; - } + const uint32_t concrete_frame_idx = 0; + m_reg_context_sp.reset (NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(target_arch, + *this, + concrete_frame_idx)); return m_reg_context_sp; } Index: lldb/trunk/source/Plugins/Process/Linux/Procfs.h =================================================================== --- lldb/trunk/source/Plugins/Process/Linux/Procfs.h +++ lldb/trunk/source/Plugins/Process/Linux/Procfs.h @@ -20,7 +20,14 @@ #ifndef NT_FPREGSET #define NT_FPREGSET NT_PRFPREG #endif // NT_FPREGSET -#endif // defined (__arm64__) || defined (__aarch64__) +#elif defined (__mips__) +typedef unsigned long elf_greg_t; +typedef elf_greg_t elf_gregset_t[(sizeof (struct user_regs_struct) / sizeof(elf_greg_t))]; +typedef struct user_fpsimd_state elf_fpregset_t; +#ifndef NT_FPREGSET + #define NT_FPREGSET NT_PRFPREG +#endif // NT_FPREGSET +#endif #else // __ANDROID__ #include #endif // __ANDROID__ Index: lldb/trunk/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h =================================================================== --- lldb/trunk/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h +++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +#if defined (__mips__) + #ifndef liblldb_RegisterContextLinux_mips64_H_ #define liblldb_RegisterContextLinux_mips64_H_ @@ -34,3 +36,5 @@ }; #endif + +#endif Index: lldb/trunk/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp +++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp @@ -7,6 +7,8 @@ // //===---------------------------------------------------------------------===// +#if defined (__mips__) + #include #include @@ -150,3 +152,4 @@ return m_register_info_count; } +#endif