| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,379 @@ | ||
| //===-- NativeProcessLinux.h ---------------------------------- -*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef liblldb_NativeProcessLinux_H_ | ||
| #define liblldb_NativeProcessLinux_H_ | ||
|
|
||
| // C Includes | ||
| #include <semaphore.h> | ||
| #include <signal.h> | ||
|
|
||
| // C++ Includes | ||
| #include <unordered_set> | ||
|
|
||
| // Other libraries and framework includes | ||
| #include "lldb/Core/ArchSpec.h" | ||
| #include "lldb/lldb-types.h" | ||
| #include "lldb/Host/Debug.h" | ||
| #include "lldb/Host/Mutex.h" | ||
| #include "lldb/Target/MemoryRegionInfo.h" | ||
|
|
||
| #include "Host/common/NativeProcessProtocol.h" | ||
|
|
||
| namespace lldb_private | ||
| { | ||
| class Error; | ||
| class Module; | ||
| class Scalar; | ||
|
|
||
| /// @class NativeProcessLinux | ||
| /// @brief Manages communication with the inferior (debugee) process. | ||
| /// | ||
| /// Upon construction, this class prepares and launches an inferior process for | ||
| /// debugging. | ||
| /// | ||
| /// Changes in the inferior process state are broadcasted. | ||
| class NativeProcessLinux: public NativeProcessProtocol | ||
| { | ||
| public: | ||
|
|
||
| // --------------------------------------------------------------------- | ||
| // Public Static Methods | ||
| // --------------------------------------------------------------------- | ||
| static lldb_private::Error | ||
| LaunchProcess ( | ||
| Module *exe_module, | ||
| ProcessLaunchInfo &launch_info, | ||
| lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate, | ||
| NativeProcessProtocolSP &native_process_sp); | ||
|
|
||
| static lldb_private::Error | ||
| AttachToProcess ( | ||
| lldb::pid_t pid, | ||
| lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate, | ||
| NativeProcessProtocolSP &native_process_sp); | ||
|
|
||
| // --------------------------------------------------------------------- | ||
| // Public Instance Methods | ||
| // --------------------------------------------------------------------- | ||
|
|
||
| ~NativeProcessLinux() override; | ||
|
|
||
| // --------------------------------------------------------------------- | ||
| // NativeProcessProtocol Interface | ||
| // --------------------------------------------------------------------- | ||
| Error | ||
| Resume (const ResumeActionList &resume_actions) override; | ||
|
|
||
| Error | ||
| Halt () override; | ||
|
|
||
| Error | ||
| Detach () override; | ||
|
|
||
| Error | ||
| Signal (int signo) override; | ||
|
|
||
| Error | ||
| Kill () override; | ||
|
|
||
| Error | ||
| GetMemoryRegionInfo (lldb::addr_t load_addr, MemoryRegionInfo &range_info) override; | ||
|
|
||
| Error | ||
| ReadMemory (lldb::addr_t addr, void *buf, lldb::addr_t size, lldb::addr_t &bytes_read) override; | ||
|
|
||
| Error | ||
| WriteMemory (lldb::addr_t addr, const void *buf, lldb::addr_t size, lldb::addr_t &bytes_written) override; | ||
|
|
||
| Error | ||
| AllocateMemory (lldb::addr_t size, uint32_t permissions, lldb::addr_t &addr) override; | ||
|
|
||
| Error | ||
| DeallocateMemory (lldb::addr_t addr) override; | ||
|
|
||
| lldb::addr_t | ||
| GetSharedLibraryInfoAddress () override; | ||
|
|
||
| size_t | ||
| UpdateThreads () override; | ||
|
|
||
| bool | ||
| GetArchitecture (ArchSpec &arch) const override; | ||
|
|
||
| Error | ||
| SetBreakpoint (lldb::addr_t addr, uint32_t size, bool hardware) override; | ||
|
|
||
| void | ||
| DoStopIDBumped (uint32_t newBumpId) 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. | ||
| bool | ||
| ReadRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name, | ||
| unsigned size, lldb_private::RegisterValue &value); | ||
|
|
||
| /// Writes the given value to the register identified by the given | ||
| /// (architecture dependent) offset. | ||
| /// | ||
| /// This method is provided for use by RegisterContextLinux derivatives. | ||
| bool | ||
| WriteRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name, | ||
| const lldb_private::RegisterValue &value); | ||
|
|
||
| /// Reads all general purpose registers into the specified buffer. | ||
| bool | ||
| ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size); | ||
|
|
||
| /// Reads generic floating point registers into the specified buffer. | ||
| bool | ||
| ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size); | ||
|
|
||
| /// Reads the specified register set into the specified buffer. | ||
| /// For instance, the extended floating-point register set. | ||
| bool | ||
| ReadRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset); | ||
|
|
||
| /// Writes all general purpose registers into the specified buffer. | ||
| bool | ||
| WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size); | ||
|
|
||
| /// Writes generic floating point registers into the specified buffer. | ||
| bool | ||
| WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size); | ||
|
|
||
| /// Writes the specified register set into the specified buffer. | ||
| /// For instance, the extended floating-point register set. | ||
| bool | ||
| WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset); | ||
|
|
||
| protected: | ||
| // --------------------------------------------------------------------- | ||
| // NativeProcessProtocol protected interface | ||
| // --------------------------------------------------------------------- | ||
| Error | ||
| GetSoftwareBreakpointTrapOpcode (size_t trap_opcode_size_hint, size_t &actual_opcode_size, const uint8_t *&trap_opcode_bytes) override; | ||
|
|
||
| private: | ||
|
|
||
| lldb_private::ArchSpec m_arch; | ||
|
|
||
| lldb::thread_t m_operation_thread; | ||
| lldb::thread_t m_monitor_thread; | ||
|
|
||
| // current operation which must be executed on the priviliged thread | ||
| void *m_operation; | ||
| lldb_private::Mutex m_operation_mutex; | ||
|
|
||
| // semaphores notified when Operation is ready to be processed and when | ||
| // the operation is complete. | ||
| sem_t m_operation_pending; | ||
| sem_t m_operation_done; | ||
|
|
||
| // Set of tids we're waiting to stop before we notify the delegate of | ||
| // the stopped state. We only notify the delegate after all threads | ||
| // ordered to stop have signaled their stop. | ||
| std::unordered_set<lldb::tid_t> m_wait_for_stop_tids; | ||
| lldb_private::Mutex m_wait_for_stop_tids_mutex; | ||
|
|
||
| lldb_private::LazyBool m_supports_mem_region; | ||
| std::vector<MemoryRegionInfo> m_mem_region_cache; | ||
| lldb_private::Mutex m_mem_region_cache_mutex; | ||
|
|
||
|
|
||
| struct OperationArgs | ||
| { | ||
| OperationArgs(NativeProcessLinux *monitor); | ||
|
|
||
| ~OperationArgs(); | ||
|
|
||
| NativeProcessLinux *m_monitor; // The monitor performing the attach. | ||
| sem_t m_semaphore; // Posted to once operation complete. | ||
| lldb_private::Error m_error; // Set if process operation failed. | ||
| }; | ||
|
|
||
| /// @class LauchArgs | ||
| /// | ||
| /// @brief Simple structure to pass data to the thread responsible for | ||
| /// launching a child process. | ||
| struct LaunchArgs : OperationArgs | ||
| { | ||
| LaunchArgs(NativeProcessLinux *monitor, | ||
| lldb_private::Module *module, | ||
| char const **argv, | ||
| char const **envp, | ||
| const char *stdin_path, | ||
| const char *stdout_path, | ||
| const char *stderr_path, | ||
| const char *working_dir); | ||
|
|
||
| ~LaunchArgs(); | ||
|
|
||
| lldb_private::Module *m_module; // The executable image to launch. | ||
| char const **m_argv; // Process arguments. | ||
| char const **m_envp; // Process environment. | ||
| const char *m_stdin_path; // Redirect stdin or NULL. | ||
| const char *m_stdout_path; // Redirect stdout or NULL. | ||
| const char *m_stderr_path; // Redirect stderr or NULL. | ||
| const char *m_working_dir; // Working directory or NULL. | ||
| }; | ||
|
|
||
| struct AttachArgs : OperationArgs | ||
| { | ||
| AttachArgs(NativeProcessLinux *monitor, | ||
| lldb::pid_t pid); | ||
|
|
||
| ~AttachArgs(); | ||
|
|
||
| lldb::pid_t m_pid; // pid of the process to be attached. | ||
| }; | ||
|
|
||
| // --------------------------------------------------------------------- | ||
| // Private Instance Methods | ||
| // --------------------------------------------------------------------- | ||
| NativeProcessLinux (); | ||
|
|
||
| /// Launches an inferior process ready for debugging. Forms the | ||
| /// implementation of Process::DoLaunch. | ||
| void | ||
| LaunchInferior ( | ||
| Module *module, | ||
| char const *argv[], | ||
| char const *envp[], | ||
| const char *stdin_path, | ||
| const char *stdout_path, | ||
| const char *stderr_path, | ||
| const char *working_dir, | ||
| Error &error); | ||
|
|
||
| /// Attaches to an existing process. Forms the | ||
| /// implementation of Process::DoLaunch. | ||
| void | ||
| AttachToInferior (lldb::pid_t pid, Error &error); | ||
|
|
||
| void | ||
| StartLaunchOpThread(LaunchArgs *args, lldb_private::Error &error); | ||
|
|
||
| static void * | ||
| LaunchOpThread(void *arg); | ||
|
|
||
| static bool | ||
| Launch(LaunchArgs *args); | ||
|
|
||
| void | ||
| StartAttachOpThread(AttachArgs *args, lldb_private::Error &error); | ||
|
|
||
| static void * | ||
| AttachOpThread(void *args); | ||
|
|
||
| static bool | ||
| Attach(AttachArgs *args); | ||
|
|
||
| static bool | ||
| SetDefaultPtraceOpts(const lldb::pid_t); | ||
|
|
||
| static void | ||
| ServeOperation(OperationArgs *args); | ||
|
|
||
| static bool | ||
| DupDescriptor(const char *path, int fd, int flags); | ||
|
|
||
| static bool | ||
| MonitorCallback(void *callback_baton, | ||
| lldb::pid_t pid, bool exited, int signal, int status); | ||
|
|
||
| void | ||
| MonitorSIGTRAP(const siginfo_t *info, lldb::pid_t pid); | ||
|
|
||
| void | ||
| MonitorSignal(const siginfo_t *info, lldb::pid_t pid, bool exited); | ||
|
|
||
| #if 0 | ||
| static ::ProcessMessage::CrashReason | ||
| GetCrashReasonForSIGSEGV(const siginfo_t *info); | ||
|
|
||
| static ::ProcessMessage::CrashReason | ||
| GetCrashReasonForSIGILL(const siginfo_t *info); | ||
|
|
||
| static ::ProcessMessage::CrashReason | ||
| GetCrashReasonForSIGFPE(const siginfo_t *info); | ||
|
|
||
| static ::ProcessMessage::CrashReason | ||
| GetCrashReasonForSIGBUS(const siginfo_t *info); | ||
| #endif | ||
|
|
||
| void | ||
| DoOperation(void *op); | ||
|
|
||
| /// Stops the child monitor thread. | ||
| void | ||
| StopMonitoringChildProcess(); | ||
|
|
||
| /// Stops the operation thread used to attach/launch a process. | ||
| void | ||
| StopOpThread(); | ||
|
|
||
| /// Stops monitoring the child process thread. | ||
| void | ||
| StopMonitor(); | ||
|
|
||
| bool | ||
| HasThreadNoLock (lldb::tid_t thread_id); | ||
|
|
||
| NativeThreadProtocolSP | ||
| MaybeGetThreadNoLock (lldb::tid_t thread_id); | ||
|
|
||
| bool | ||
| StopTrackingThread (lldb::tid_t thread_id); | ||
|
|
||
| NativeThreadProtocolSP | ||
| AddThread (lldb::tid_t thread_id); | ||
|
|
||
| NativeThreadProtocolSP | ||
| GetOrCreateThread (lldb::tid_t thread_id, bool &created); | ||
|
|
||
| Error | ||
| GetSoftwareBreakpointSize (NativeRegisterContextSP context_sp, uint32_t &actual_opcode_size); | ||
|
|
||
| Error | ||
| FixupBreakpointPCAsNeeded (NativeThreadProtocolSP &thread_sp); | ||
|
|
||
| /// Writes a siginfo_t structure corresponding to the given thread ID to the | ||
| /// memory region pointed to by @p siginfo. | ||
| bool | ||
| GetSignalInfo(lldb::tid_t tid, void *siginfo, int &ptrace_err); | ||
|
|
||
| /// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG) | ||
| /// corresponding to the given thread ID to the memory pointed to by @p | ||
| /// message. | ||
| bool | ||
| GetEventMessage(lldb::tid_t tid, unsigned long *message); | ||
|
|
||
| /// Resumes the given thread. If @p signo is anything but | ||
| /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread. | ||
| bool | ||
| Resume(lldb::tid_t tid, uint32_t signo); | ||
|
|
||
| /// Single steps the given thread. If @p signo is anything but | ||
| /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread. | ||
| bool | ||
| SingleStep(lldb::tid_t tid, uint32_t signo); | ||
|
|
||
| lldb_private::Error | ||
| Detach(lldb::tid_t tid); | ||
| }; | ||
| } // End lldb_private namespace. | ||
|
|
||
| #endif // #ifndef liblldb_NativeProcessLinux_H_ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,363 @@ | ||
| //===-- NativeThreadLinux.cpp --------------------------------- -*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "NativeThreadLinux.h" | ||
|
|
||
| #include <signal.h> | ||
|
|
||
| #include "NativeProcessLinux.h" | ||
| #include "lldb/Core/Log.h" | ||
| #include "lldb/Core/State.h" | ||
| #include "lldb/Host/Host.h" | ||
| #include "lldb/lldb-enumerations.h" | ||
| #include "lldb/lldb-private-log.h" | ||
| #include "Plugins/Process/Utility/NativeRegisterContextLinux_x86_64.h" | ||
| #include "Plugins/Process/Utility/RegisterContextLinux_i386.h" | ||
| #include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h" | ||
| #include "Plugins/Process/Utility/RegisterInfoInterface.h" | ||
|
|
||
| using namespace lldb; | ||
| using namespace lldb_private; | ||
|
|
||
| namespace | ||
| { | ||
| void LogThreadStopInfo (Log &log, const ThreadStopInfo &stop_info, const char *const header) | ||
| { | ||
| switch (stop_info.reason) | ||
| { | ||
| case eStopReasonSignal: | ||
| log.Printf ("%s: %s: signal 0x%" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo); | ||
| return; | ||
| case eStopReasonException: | ||
| log.Printf ("%s: %s: exception type 0x%" PRIx64, __FUNCTION__, header, stop_info.details.exception.type); | ||
| return; | ||
| default: | ||
| log.Printf ("%s: %s: invalid stop reason %" PRIu32, __FUNCTION__, header, static_cast<uint32_t> (stop_info.reason)); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| NativeThreadLinux::NativeThreadLinux (NativeProcessLinux *process, lldb::tid_t tid) : | ||
| NativeThreadProtocol (process, tid), | ||
| m_state (StateType::eStateInvalid), | ||
| m_stop_info (), | ||
| m_reg_context_sp () | ||
| { | ||
| } | ||
|
|
||
| const char * | ||
| NativeThreadLinux::GetName() | ||
| { | ||
| NativeProcessProtocolSP process_sp = m_process_wp.lock (); | ||
| if (!process_sp) | ||
| return "<unknown: no process>"; | ||
|
|
||
| // const NativeProcessLinux *const process = reinterpret_cast<NativeProcessLinux*> (process_sp->get ()); | ||
| return Host::GetThreadName (process_sp->GetID (), GetID ()).c_str (); | ||
| } | ||
|
|
||
| lldb::StateType | ||
| NativeThreadLinux::GetState () | ||
| { | ||
| return m_state; | ||
| } | ||
|
|
||
|
|
||
| bool | ||
| NativeThreadLinux::GetStopReason (ThreadStopInfo &stop_info) | ||
| { | ||
| Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); | ||
| switch (m_state) | ||
| { | ||
| case eStateStopped: | ||
| case eStateCrashed: | ||
| case eStateExited: | ||
| case eStateSuspended: | ||
| case eStateUnloaded: | ||
| if (log) | ||
| LogThreadStopInfo (*log, m_stop_info, "m_stop_info in thread: "); | ||
| stop_info = m_stop_info; | ||
| if (log) | ||
| LogThreadStopInfo (*log, stop_info, "returned stop_info: "); | ||
| return true; | ||
|
|
||
| case eStateInvalid: | ||
| case eStateConnected: | ||
| case eStateAttaching: | ||
| case eStateLaunching: | ||
| case eStateRunning: | ||
| case eStateStepping: | ||
| case eStateDetached: | ||
| default: | ||
| if (log) | ||
| { | ||
| log->Printf ("NativeThreadLinux::%s tid %" PRIu64 " in state %s cannot answer stop reason", | ||
| __FUNCTION__, GetID (), StateAsCString (m_state)); | ||
| } | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| lldb_private::NativeRegisterContextSP | ||
| NativeThreadLinux::GetRegisterContext () | ||
| { | ||
| // Return the register context if we already created it. | ||
| 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 (); | ||
|
|
||
| ArchSpec target_arch; | ||
| 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::x86: | ||
| case llvm::Triple::x86_64: | ||
| if (Host::GetArchitecture().GetAddressByteSize() == 4) | ||
| { | ||
| // 32-bit hosts run with a RegisterContextLinux_i386 context. | ||
| reg_interface = static_cast<RegisterInfoInterface*>(new RegisterContextLinux_i386(target_arch)); | ||
| } | ||
| else | ||
| { | ||
| assert((Host::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<RegisterInfoInterface*> (new RegisterContextLinux_x86_64 (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 | ||
| #if 0 | ||
| case llvm::Triple::x86: | ||
| #endif | ||
| 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; | ||
| } | ||
|
|
||
| return m_reg_context_sp; | ||
| } | ||
|
|
||
| Error | ||
| NativeThreadLinux::SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware) | ||
| { | ||
| // TODO implement | ||
| return Error ("not implemented"); | ||
| } | ||
|
|
||
| Error | ||
| NativeThreadLinux::RemoveWatchpoint (lldb::addr_t addr) | ||
| { | ||
| // TODO implement | ||
| return Error ("not implemented"); | ||
| } | ||
|
|
||
| void | ||
| NativeThreadLinux::SetLaunching () | ||
| { | ||
| const StateType new_state = StateType::eStateLaunching; | ||
| MaybeLogStateChange (new_state); | ||
| m_state = new_state; | ||
|
|
||
| // Also mark it as stopped since launching temporarily stops the newly created thread | ||
| // in the ptrace machinery. | ||
| m_stop_info.reason = StopReason::eStopReasonSignal; | ||
| m_stop_info.details.signal.signo = SIGSTOP; | ||
| } | ||
|
|
||
|
|
||
| void | ||
| NativeThreadLinux::SetRunning () | ||
| { | ||
| const StateType new_state = StateType::eStateRunning; | ||
| MaybeLogStateChange (new_state); | ||
| m_state = new_state; | ||
|
|
||
| m_stop_info.reason = StopReason::eStopReasonNone; | ||
| } | ||
|
|
||
| void | ||
| NativeThreadLinux::SetStepping () | ||
| { | ||
| const StateType new_state = StateType::eStateStepping; | ||
| MaybeLogStateChange (new_state); | ||
| m_state = new_state; | ||
|
|
||
| m_stop_info.reason = StopReason::eStopReasonNone; | ||
| } | ||
|
|
||
| void | ||
| NativeThreadLinux::SetStoppedBySignal (uint32_t signo) | ||
| { | ||
| Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); | ||
| if (log) | ||
| log->Printf ("NativeThreadLinux::%s called with signal 0x%" PRIx32, __FUNCTION__, signo); | ||
|
|
||
| const StateType new_state = StateType::eStateStopped; | ||
| MaybeLogStateChange (new_state); | ||
| m_state = new_state; | ||
|
|
||
| m_stop_info.reason = StopReason::eStopReasonSignal; | ||
| m_stop_info.details.signal.signo = signo; | ||
| } | ||
|
|
||
| void | ||
| NativeThreadLinux::SetStoppedByBreakpoint () | ||
| { | ||
| const StateType new_state = StateType::eStateStopped; | ||
| MaybeLogStateChange (new_state); | ||
| m_state = new_state; | ||
|
|
||
| m_stop_info.reason = StopReason::eStopReasonSignal; | ||
| m_stop_info.details.signal.signo = SIGTRAP; | ||
| } | ||
|
|
||
| bool | ||
| NativeThreadLinux::IsStoppedAtBreakpoint () | ||
| { | ||
| // Are we stopped? If not, this can't be a breakpoint. | ||
| if (GetState () != StateType::eStateStopped) | ||
| return false; | ||
|
|
||
| // Was the stop reason a signal with signal number SIGTRAP? If not, not a breakpoint. | ||
| return (m_stop_info.reason == StopReason::eStopReasonSignal) && | ||
| (m_stop_info.details.signal.signo == SIGTRAP); | ||
| } | ||
|
|
||
| void | ||
| NativeThreadLinux::SetCrashedWithException (uint64_t exception_type, lldb::addr_t exception_addr) | ||
| { | ||
| const StateType new_state = StateType::eStateCrashed; | ||
| MaybeLogStateChange (new_state); | ||
| m_state = new_state; | ||
|
|
||
| m_stop_info.reason = StopReason::eStopReasonException; | ||
| m_stop_info.details.exception.type = exception_type; | ||
| m_stop_info.details.exception.data_count = 1; | ||
| m_stop_info.details.exception.data[0] = exception_addr; | ||
| } | ||
|
|
||
|
|
||
| void | ||
| NativeThreadLinux::SetSuspended () | ||
| { | ||
| const StateType new_state = StateType::eStateSuspended; | ||
| MaybeLogStateChange (new_state); | ||
| m_state = new_state; | ||
|
|
||
| // FIXME what makes sense here? Do we need a suspended StopReason? | ||
| m_stop_info.reason = StopReason::eStopReasonNone; | ||
| } | ||
|
|
||
| void | ||
| NativeThreadLinux::SetExited () | ||
| { | ||
| const StateType new_state = StateType::eStateExited; | ||
| MaybeLogStateChange (new_state); | ||
| m_state = new_state; | ||
|
|
||
| m_stop_info.reason = StopReason::eStopReasonThreadExiting; | ||
| } | ||
|
|
||
| void | ||
| NativeThreadLinux::MaybeLogStateChange (lldb::StateType new_state) | ||
| { | ||
| Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); | ||
| // If we're not logging, we're done. | ||
| if (!log) | ||
| return; | ||
|
|
||
| // If this is a state change to the same state, we're done. | ||
| lldb::StateType old_state = m_state; | ||
| if (new_state == old_state) | ||
| return; | ||
|
|
||
| NativeProcessProtocolSP m_process_sp = m_process_wp.lock (); | ||
| lldb::pid_t pid = m_process_sp ? m_process_sp->GetID () : LLDB_INVALID_PROCESS_ID; | ||
|
|
||
| // Log it. | ||
| log->Printf ("NativeThreadLinux: thread (pid=%" PRIu64 ", tid=%" PRIu64 ") changing from state %s to %s", pid, GetID (), StateAsCString (old_state), StateAsCString (new_state)); | ||
| } | ||
|
|
||
| static | ||
| uint32_t MaybeTranslateHostSignoToGdbSigno (uint32_t host_signo) | ||
| { | ||
| switch (host_signo) | ||
| { | ||
| case SIGSEGV: return eGdbSignalBadAccess; | ||
| case SIGILL: return eGdbSignalBadInstruction; | ||
| case SIGFPE: return eGdbSignalArithmetic; | ||
| // NOTE: debugserver sends SIGTRAP through unmodified. Do the same here. | ||
| // case SIGTRAP: return eGdbSignalBreakpoint; | ||
|
|
||
| // Nothing for eGdbSignalSoftware (0x95). | ||
| // Nothing for eGdbSignalEmulation (0x94). | ||
|
|
||
| default: | ||
| // No translations. | ||
| return host_signo; | ||
| } | ||
| } | ||
|
|
||
| uint32_t | ||
| NativeThreadLinux::TranslateStopInfoToGdbSignal (const ThreadStopInfo &stop_info) const | ||
| { | ||
| switch (stop_info.reason) | ||
| { | ||
| case eStopReasonSignal: | ||
| return MaybeTranslateHostSignoToGdbSigno (stop_info.details.signal.signo); | ||
| break; | ||
|
|
||
| case eStopReasonException: | ||
| // FIXME verify how we handle exception type. | ||
| return MaybeTranslateHostSignoToGdbSigno (static_cast<uint32_t> (stop_info.details.exception.type)); | ||
| break; | ||
|
|
||
| default: | ||
| assert (0 && "unexpected stop_info.reason found"); | ||
| return 0; | ||
| } | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| //===-- NativeThreadLinux.h ----------------------------------- -*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef liblldb_NativeThreadLinux_H_ | ||
| #define liblldb_NativeThreadLinux_H_ | ||
|
|
||
| #include "lldb/lldb-private-forward.h" | ||
| #include "../../../Host/common/NativeThreadProtocol.h" | ||
|
|
||
| namespace lldb_private | ||
| { | ||
| class NativeProcessLinux; | ||
|
|
||
| class NativeThreadLinux : public NativeThreadProtocol | ||
| { | ||
| friend class NativeProcessLinux; | ||
|
|
||
| public: | ||
| NativeThreadLinux (NativeProcessLinux *process, lldb::tid_t tid); | ||
|
|
||
| // --------------------------------------------------------------------- | ||
| // NativeThreadProtocol Interface | ||
| // --------------------------------------------------------------------- | ||
| const char * | ||
| GetName() override; | ||
|
|
||
| lldb::StateType | ||
| GetState () override; | ||
|
|
||
| bool | ||
| GetStopReason (ThreadStopInfo &stop_info) override; | ||
|
|
||
| NativeRegisterContextSP | ||
| GetRegisterContext () override; | ||
|
|
||
| Error | ||
| SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware) override; | ||
|
|
||
| Error | ||
| RemoveWatchpoint (lldb::addr_t addr) override; | ||
|
|
||
| uint32_t | ||
| TranslateStopInfoToGdbSignal (const ThreadStopInfo &stop_info) const override; | ||
|
|
||
| private: | ||
| // --------------------------------------------------------------------- | ||
| // Interface for friend classes | ||
| // --------------------------------------------------------------------- | ||
| void | ||
| SetLaunching (); | ||
|
|
||
| void | ||
| SetRunning (); | ||
|
|
||
| void | ||
| SetStepping (); | ||
|
|
||
| void | ||
| SetStoppedBySignal (uint32_t signo); | ||
|
|
||
| void | ||
| SetStoppedByBreakpoint (); | ||
|
|
||
| bool | ||
| IsStoppedAtBreakpoint (); | ||
|
|
||
| void | ||
| SetCrashedWithException (uint64_t exception_type, lldb::addr_t exception_addr); | ||
|
|
||
| void | ||
| SetSuspended (); | ||
|
|
||
| void | ||
| SetExited (); | ||
|
|
||
| // --------------------------------------------------------------------- | ||
| // Private interface | ||
| // --------------------------------------------------------------------- | ||
| void | ||
| MaybeLogStateChange (lldb::StateType new_state); | ||
|
|
||
| // --------------------------------------------------------------------- | ||
| // Member Variables | ||
| // --------------------------------------------------------------------- | ||
| lldb::StateType m_state; | ||
| ThreadStopInfo m_stop_info; | ||
| NativeRegisterContextSP m_reg_context_sp; | ||
| }; | ||
| } | ||
|
|
||
| #endif // #ifndef liblldb_NativeThreadLinux_H_ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,135 @@ | ||
| //===-- NativeRegisterContextLinux_x86_64.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_x86_64_h | ||
| #define lldb_NativeRegisterContextLinux_x86_64_h | ||
|
|
||
| #include "lldb/Target/NativeRegisterContextRegisterInfo.h" | ||
| #include "RegisterContext_x86.h" | ||
| #include "lldb-x86-register-enums.h" | ||
|
|
||
| namespace lldb_private | ||
| { | ||
| class NativeProcessLinux; | ||
|
|
||
| class NativeRegisterContextLinux_x86_64 : public NativeRegisterContextRegisterInfo | ||
| { | ||
| public: | ||
| NativeRegisterContextLinux_x86_64 (NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx, RegisterInfoInterface *reg_info_interface_p); | ||
|
|
||
| uint32_t | ||
| GetRegisterSetCount () const override; | ||
|
|
||
| const RegisterSet * | ||
| GetRegisterSet (uint32_t set_index) const override; | ||
|
|
||
| Error | ||
| ReadRegister (const RegisterInfo *reg_info, RegisterValue ®_value) override; | ||
|
|
||
| Error | ||
| WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value) override; | ||
|
|
||
| Error | ||
| ReadAllRegisterValues (lldb::DataBufferSP &data_sp) override; | ||
|
|
||
| Error | ||
| WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) override; | ||
|
|
||
| private: | ||
|
|
||
| // Private member types. | ||
| enum FPRType | ||
| { | ||
| eFPRTypeNotValid = 0, | ||
| eFPRTypeFXSAVE, | ||
| eFPRTypeXSAVE | ||
| }; | ||
|
|
||
| // Info about register ranges. | ||
| struct RegInfo | ||
| { | ||
| uint32_t num_registers; | ||
| uint32_t num_gpr_registers; | ||
| uint32_t num_fpr_registers; | ||
| uint32_t num_avx_registers; | ||
|
|
||
| uint32_t last_gpr; | ||
| uint32_t first_fpr; | ||
| uint32_t last_fpr; | ||
|
|
||
| uint32_t first_st; | ||
| uint32_t last_st; | ||
| uint32_t first_mm; | ||
| uint32_t last_mm; | ||
| uint32_t first_xmm; | ||
| uint32_t last_xmm; | ||
| uint32_t first_ymm; | ||
| uint32_t last_ymm; | ||
|
|
||
| uint32_t first_dr; | ||
| uint32_t gpr_flags; | ||
| }; | ||
|
|
||
| // Private member variables. | ||
| mutable FPRType m_fpr_type; | ||
| FPR m_fpr; | ||
| IOVEC m_iovec; | ||
| YMM m_ymm_set; | ||
| RegInfo m_reg_info; | ||
| uint64_t m_gpr_x86_64[k_num_gpr_registers_x86_64]; | ||
|
|
||
| // Private member methods. | ||
| lldb_private::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; | ||
|
|
||
| FPRType | ||
| GetFPRType () const; | ||
|
|
||
| bool | ||
| IsFPR(uint32_t reg_index) const; | ||
|
|
||
| bool | ||
| WriteFPR(); | ||
|
|
||
| bool IsFPR(uint32_t reg_index, FPRType fpr_type) const; | ||
|
|
||
| bool | ||
| CopyXSTATEtoYMM (uint32_t reg_index, lldb::ByteOrder byte_order); | ||
|
|
||
| bool | ||
| CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order); | ||
|
|
||
| bool | ||
| IsAVX (uint32_t reg_index) const; | ||
|
|
||
| bool | ||
| ReadFPR (); | ||
|
|
||
| lldb_private::Error | ||
| ReadRegisterRaw (uint32_t reg_index, RegisterValue ®_value); | ||
|
|
||
| bool | ||
| ReadGPR(); | ||
|
|
||
| bool | ||
| WriteGPR(); | ||
| }; | ||
| } | ||
|
|
||
| #endif // #ifndef lldb_NativeRegisterContextLinux_x86_64_h | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,292 @@ | ||
| //===-- lldb-x86-register-enums.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_x86_register_enums_h | ||
| #define lldb_x86_register_enums_h | ||
|
|
||
| namespace lldb_private | ||
| { | ||
|
|
||
| //--------------------------------------------------------------------------- | ||
| // Internal codes for all i386 registers. | ||
| //--------------------------------------------------------------------------- | ||
| enum | ||
| { | ||
| k_first_gpr_i386, | ||
| gpr_eax_i386 = k_first_gpr_i386, | ||
| gpr_ebx_i386, | ||
| gpr_ecx_i386, | ||
| gpr_edx_i386, | ||
| gpr_edi_i386, | ||
| gpr_esi_i386, | ||
| gpr_ebp_i386, | ||
| gpr_esp_i386, | ||
| gpr_eip_i386, | ||
| gpr_eflags_i386, | ||
| gpr_cs_i386, | ||
| gpr_fs_i386, | ||
| gpr_gs_i386, | ||
| gpr_ss_i386, | ||
| gpr_ds_i386, | ||
| gpr_es_i386, | ||
|
|
||
| k_first_alias_i386, | ||
| gpr_ax_i386 = k_first_alias_i386, | ||
| gpr_bx_i386, | ||
| gpr_cx_i386, | ||
| gpr_dx_i386, | ||
| gpr_di_i386, | ||
| gpr_si_i386, | ||
| gpr_bp_i386, | ||
| gpr_sp_i386, | ||
| gpr_ah_i386, | ||
| gpr_bh_i386, | ||
| gpr_ch_i386, | ||
| gpr_dh_i386, | ||
| gpr_al_i386, | ||
| gpr_bl_i386, | ||
| gpr_cl_i386, | ||
| gpr_dl_i386, | ||
| k_last_alias_i386 = gpr_dl_i386, | ||
|
|
||
| k_last_gpr_i386 = k_last_alias_i386, | ||
|
|
||
| k_first_fpr_i386, | ||
| fpu_fctrl_i386 = k_first_fpr_i386, | ||
| fpu_fstat_i386, | ||
| fpu_ftag_i386, | ||
| fpu_fop_i386, | ||
| fpu_fiseg_i386, | ||
| fpu_fioff_i386, | ||
| fpu_foseg_i386, | ||
| fpu_fooff_i386, | ||
| fpu_mxcsr_i386, | ||
| fpu_mxcsrmask_i386, | ||
| fpu_st0_i386, | ||
| fpu_st1_i386, | ||
| fpu_st2_i386, | ||
| fpu_st3_i386, | ||
| fpu_st4_i386, | ||
| fpu_st5_i386, | ||
| fpu_st6_i386, | ||
| fpu_st7_i386, | ||
| fpu_mm0_i386, | ||
| fpu_mm1_i386, | ||
| fpu_mm2_i386, | ||
| fpu_mm3_i386, | ||
| fpu_mm4_i386, | ||
| fpu_mm5_i386, | ||
| fpu_mm6_i386, | ||
| fpu_mm7_i386, | ||
| fpu_xmm0_i386, | ||
| fpu_xmm1_i386, | ||
| fpu_xmm2_i386, | ||
| fpu_xmm3_i386, | ||
| fpu_xmm4_i386, | ||
| fpu_xmm5_i386, | ||
| fpu_xmm6_i386, | ||
| fpu_xmm7_i386, | ||
| k_last_fpr_i386 = fpu_xmm7_i386, | ||
|
|
||
| k_first_avx_i386, | ||
| fpu_ymm0_i386 = k_first_avx_i386, | ||
| fpu_ymm1_i386, | ||
| fpu_ymm2_i386, | ||
| fpu_ymm3_i386, | ||
| fpu_ymm4_i386, | ||
| fpu_ymm5_i386, | ||
| fpu_ymm6_i386, | ||
| fpu_ymm7_i386, | ||
| k_last_avx_i386 = fpu_ymm7_i386, | ||
|
|
||
| dr0_i386, | ||
| dr1_i386, | ||
| dr2_i386, | ||
| dr3_i386, | ||
| dr4_i386, | ||
| dr5_i386, | ||
| dr6_i386, | ||
| dr7_i386, | ||
|
|
||
| k_num_registers_i386, | ||
| k_num_gpr_registers_i386 = k_last_gpr_i386 - k_first_gpr_i386 + 1, | ||
| k_num_fpr_registers_i386 = k_last_fpr_i386 - k_first_fpr_i386 + 1, | ||
| k_num_avx_registers_i386 = k_last_avx_i386 - k_first_avx_i386 + 1 | ||
| }; | ||
|
|
||
| //--------------------------------------------------------------------------- | ||
| // Internal codes for all x86_64 registers. | ||
| //--------------------------------------------------------------------------- | ||
| enum | ||
| { | ||
| k_first_gpr_x86_64, | ||
| gpr_rax_x86_64 = k_first_gpr_x86_64, | ||
| gpr_rbx_x86_64, | ||
| gpr_rcx_x86_64, | ||
| gpr_rdx_x86_64, | ||
| gpr_rdi_x86_64, | ||
| gpr_rsi_x86_64, | ||
| gpr_rbp_x86_64, | ||
| gpr_rsp_x86_64, | ||
| gpr_r8_x86_64, | ||
| gpr_r9_x86_64, | ||
| gpr_r10_x86_64, | ||
| gpr_r11_x86_64, | ||
| gpr_r12_x86_64, | ||
| gpr_r13_x86_64, | ||
| gpr_r14_x86_64, | ||
| gpr_r15_x86_64, | ||
| gpr_rip_x86_64, | ||
| gpr_rflags_x86_64, | ||
| gpr_cs_x86_64, | ||
| gpr_fs_x86_64, | ||
| gpr_gs_x86_64, | ||
| gpr_ss_x86_64, | ||
| gpr_ds_x86_64, | ||
| gpr_es_x86_64, | ||
|
|
||
| k_first_alias_x86_64, | ||
| gpr_eax_x86_64 = k_first_alias_x86_64, | ||
| gpr_ebx_x86_64, | ||
| gpr_ecx_x86_64, | ||
| gpr_edx_x86_64, | ||
| gpr_edi_x86_64, | ||
| gpr_esi_x86_64, | ||
| gpr_ebp_x86_64, | ||
| gpr_esp_x86_64, | ||
| gpr_r8d_x86_64, // Low 32 bits of r8 | ||
| gpr_r9d_x86_64, // Low 32 bits of r9 | ||
| gpr_r10d_x86_64, // Low 32 bits of r10 | ||
| gpr_r11d_x86_64, // Low 32 bits of r11 | ||
| gpr_r12d_x86_64, // Low 32 bits of r12 | ||
| gpr_r13d_x86_64, // Low 32 bits of r13 | ||
| gpr_r14d_x86_64, // Low 32 bits of r14 | ||
| gpr_r15d_x86_64, // Low 32 bits of r15 | ||
| gpr_ax_x86_64, | ||
| gpr_bx_x86_64, | ||
| gpr_cx_x86_64, | ||
| gpr_dx_x86_64, | ||
| gpr_di_x86_64, | ||
| gpr_si_x86_64, | ||
| gpr_bp_x86_64, | ||
| gpr_sp_x86_64, | ||
| gpr_r8w_x86_64, // Low 16 bits of r8 | ||
| gpr_r9w_x86_64, // Low 16 bits of r9 | ||
| gpr_r10w_x86_64, // Low 16 bits of r10 | ||
| gpr_r11w_x86_64, // Low 16 bits of r11 | ||
| gpr_r12w_x86_64, // Low 16 bits of r12 | ||
| gpr_r13w_x86_64, // Low 16 bits of r13 | ||
| gpr_r14w_x86_64, // Low 16 bits of r14 | ||
| gpr_r15w_x86_64, // Low 16 bits of r15 | ||
| gpr_ah_x86_64, | ||
| gpr_bh_x86_64, | ||
| gpr_ch_x86_64, | ||
| gpr_dh_x86_64, | ||
| gpr_al_x86_64, | ||
| gpr_bl_x86_64, | ||
| gpr_cl_x86_64, | ||
| gpr_dl_x86_64, | ||
| gpr_dil_x86_64, | ||
| gpr_sil_x86_64, | ||
| gpr_bpl_x86_64, | ||
| gpr_spl_x86_64, | ||
| gpr_r8l_x86_64, // Low 8 bits of r8 | ||
| gpr_r9l_x86_64, // Low 8 bits of r9 | ||
| gpr_r10l_x86_64, // Low 8 bits of r10 | ||
| gpr_r11l_x86_64, // Low 8 bits of r11 | ||
| gpr_r12l_x86_64, // Low 8 bits of r12 | ||
| gpr_r13l_x86_64, // Low 8 bits of r13 | ||
| gpr_r14l_x86_64, // Low 8 bits of r14 | ||
| gpr_r15l_x86_64, // Low 8 bits of r15 | ||
| k_last_alias_x86_64 = gpr_r15l_x86_64, | ||
|
|
||
| k_last_gpr_x86_64 = k_last_alias_x86_64, | ||
|
|
||
| k_first_fpr_x86_64, | ||
| fpu_fctrl_x86_64 = k_first_fpr_x86_64, | ||
| fpu_fstat_x86_64, | ||
| fpu_ftag_x86_64, | ||
| fpu_fop_x86_64, | ||
| fpu_fiseg_x86_64, | ||
| fpu_fioff_x86_64, | ||
| fpu_foseg_x86_64, | ||
| fpu_fooff_x86_64, | ||
| fpu_mxcsr_x86_64, | ||
| fpu_mxcsrmask_x86_64, | ||
| fpu_st0_x86_64, | ||
| fpu_st1_x86_64, | ||
| fpu_st2_x86_64, | ||
| fpu_st3_x86_64, | ||
| fpu_st4_x86_64, | ||
| fpu_st5_x86_64, | ||
| fpu_st6_x86_64, | ||
| fpu_st7_x86_64, | ||
| fpu_mm0_x86_64, | ||
| fpu_mm1_x86_64, | ||
| fpu_mm2_x86_64, | ||
| fpu_mm3_x86_64, | ||
| fpu_mm4_x86_64, | ||
| fpu_mm5_x86_64, | ||
| fpu_mm6_x86_64, | ||
| fpu_mm7_x86_64, | ||
| fpu_xmm0_x86_64, | ||
| fpu_xmm1_x86_64, | ||
| fpu_xmm2_x86_64, | ||
| fpu_xmm3_x86_64, | ||
| fpu_xmm4_x86_64, | ||
| fpu_xmm5_x86_64, | ||
| fpu_xmm6_x86_64, | ||
| fpu_xmm7_x86_64, | ||
| fpu_xmm8_x86_64, | ||
| fpu_xmm9_x86_64, | ||
| fpu_xmm10_x86_64, | ||
| fpu_xmm11_x86_64, | ||
| fpu_xmm12_x86_64, | ||
| fpu_xmm13_x86_64, | ||
| fpu_xmm14_x86_64, | ||
| fpu_xmm15_x86_64, | ||
| k_last_fpr_x86_64 = fpu_xmm15_x86_64, | ||
|
|
||
| k_first_avx_x86_64, | ||
| fpu_ymm0_x86_64 = k_first_avx_x86_64, | ||
| fpu_ymm1_x86_64, | ||
| fpu_ymm2_x86_64, | ||
| fpu_ymm3_x86_64, | ||
| fpu_ymm4_x86_64, | ||
| fpu_ymm5_x86_64, | ||
| fpu_ymm6_x86_64, | ||
| fpu_ymm7_x86_64, | ||
| fpu_ymm8_x86_64, | ||
| fpu_ymm9_x86_64, | ||
| fpu_ymm10_x86_64, | ||
| fpu_ymm11_x86_64, | ||
| fpu_ymm12_x86_64, | ||
| fpu_ymm13_x86_64, | ||
| fpu_ymm14_x86_64, | ||
| fpu_ymm15_x86_64, | ||
| k_last_avx_x86_64 = fpu_ymm15_x86_64, | ||
|
|
||
| dr0_x86_64, | ||
| dr1_x86_64, | ||
| dr2_x86_64, | ||
| dr3_x86_64, | ||
| dr4_x86_64, | ||
| dr5_x86_64, | ||
| dr6_x86_64, | ||
| dr7_x86_64, | ||
|
|
||
| k_num_registers_x86_64, | ||
| k_num_gpr_registers_x86_64 = k_last_gpr_x86_64 - k_first_gpr_x86_64 + 1, | ||
| k_num_fpr_registers_x86_64 = k_last_fpr_x86_64 - k_first_fpr_x86_64 + 1, | ||
| k_num_avx_registers_x86_64 = k_last_avx_x86_64 - k_first_avx_x86_64 + 1 | ||
| }; | ||
|
|
||
| } | ||
|
|
||
| #endif // #ifndef lldb_x86_register_enums_h |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| //===-- NativeRegisterContex.cpp --------------------------------*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "lldb/lldb-types.h" | ||
| #include "lldb/lldb-private-forward.h" | ||
| #include "lldb/Target/NativeRegisterContextRegisterInfo.h" | ||
|
|
||
| using namespace lldb_private; | ||
|
|
||
| NativeRegisterContextRegisterInfo::NativeRegisterContextRegisterInfo (NativeThreadProtocol &thread, | ||
| uint32_t concrete_frame_idx, | ||
| RegisterInfoInterface *register_info_interface) : | ||
| NativeRegisterContext (thread, concrete_frame_idx), | ||
| m_register_info_interface_up (register_info_interface) | ||
| { | ||
| assert (register_info_interface && "null register_info_interface"); | ||
| } | ||
|
|
||
| uint32_t | ||
| NativeRegisterContextRegisterInfo::GetRegisterCount () const | ||
| { | ||
| return m_register_info_interface_up->GetRegisterCount (); | ||
| } | ||
|
|
||
| const RegisterInfo * | ||
| NativeRegisterContextRegisterInfo::GetRegisterInfoAtIndex (uint32_t reg_index) const | ||
| { | ||
| if (reg_index <= GetRegisterCount ()) | ||
| return m_register_info_interface_up->GetRegisterInfo () + reg_index; | ||
| else | ||
| return nullptr; | ||
| } | ||
|
|
||
| const RegisterInfoInterface& | ||
| NativeRegisterContextRegisterInfo::GetRegisterInfoInterface () const | ||
| { | ||
| return *m_register_info_interface_up; | ||
| } |