diff options
Diffstat (limited to 'include/lldb/Host/Debug.h')
-rw-r--r-- | include/lldb/Host/Debug.h | 406 |
1 files changed, 406 insertions, 0 deletions
diff --git a/include/lldb/Host/Debug.h b/include/lldb/Host/Debug.h new file mode 100644 index 000000000000..2cb758e1b733 --- /dev/null +++ b/include/lldb/Host/Debug.h @@ -0,0 +1,406 @@ +//===-- Debug.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_Debug_h_ +#define liblldb_Debug_h_ + +#include "lldb/lldb-private.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Host/Mutex.h" +#include <vector> + +namespace lldb_private { + + //------------------------------------------------------------------ + // Tells a thread what it needs to do when the process is resumed. + //------------------------------------------------------------------ + struct ResumeAction + { + lldb::tid_t tid; // The thread ID that this action applies to, LLDB_INVALID_THREAD_ID for the default thread action + lldb::StateType state; // Valid values are eStateStopped/eStateSuspended, eStateRunning, and eStateStepping. + int signal; // When resuming this thread, resume it with this signal if this value is > 0 + }; + + //------------------------------------------------------------------ + // A class that contains instructions for all threads for + // NativeProcessProtocol::Resume(). Each thread can either run, stay + // suspended, or step when the process is resumed. We optionally + // have the ability to also send a signal to the thread when the + // action is run or step. + //------------------------------------------------------------------ + class ResumeActionList + { + public: + ResumeActionList () : + m_actions (), + m_signal_handled () + { + } + + ResumeActionList (lldb::StateType default_action, int signal) : + m_actions(), + m_signal_handled () + { + SetDefaultThreadActionIfNeeded (default_action, signal); + } + + + ResumeActionList (const ResumeAction *actions, size_t num_actions) : + m_actions (), + m_signal_handled () + { + if (actions && num_actions) + { + m_actions.assign (actions, actions + num_actions); + m_signal_handled.assign (num_actions, false); + } + } + + ~ResumeActionList() + { + } + + bool + IsEmpty() const + { + return m_actions.empty(); + } + + void + Append (const ResumeAction &action) + { + m_actions.push_back (action); + m_signal_handled.push_back (false); + } + + void + AppendAction (lldb::tid_t tid, + lldb::StateType state, + int signal = 0) + { + ResumeAction action = { tid, state, signal }; + Append (action); + } + + void + AppendResumeAll () + { + AppendAction (LLDB_INVALID_THREAD_ID, lldb::eStateRunning); + } + + void + AppendSuspendAll () + { + AppendAction (LLDB_INVALID_THREAD_ID, lldb::eStateStopped); + } + + void + AppendStepAll () + { + AppendAction (LLDB_INVALID_THREAD_ID, lldb::eStateStepping); + } + + const ResumeAction * + GetActionForThread (lldb::tid_t tid, bool default_ok) const + { + const size_t num_actions = m_actions.size(); + for (size_t i=0; i<num_actions; ++i) + { + if (m_actions[i].tid == tid) + return &m_actions[i]; + } + if (default_ok && tid != LLDB_INVALID_THREAD_ID) + return GetActionForThread (LLDB_INVALID_THREAD_ID, false); + return NULL; + } + + size_t + NumActionsWithState (lldb::StateType state) const + { + size_t count = 0; + const size_t num_actions = m_actions.size(); + for (size_t i=0; i<num_actions; ++i) + { + if (m_actions[i].state == state) + ++count; + } + return count; + } + + bool + SetDefaultThreadActionIfNeeded (lldb::StateType action, int signal) + { + if (GetActionForThread (LLDB_INVALID_THREAD_ID, true) == NULL) + { + // There isn't a default action so we do need to set it. + ResumeAction default_action = {LLDB_INVALID_THREAD_ID, action, signal }; + m_actions.push_back (default_action); + m_signal_handled.push_back (false); + return true; // Return true as we did add the default action + } + return false; + } + + void + SetSignalHandledForThread (lldb::tid_t tid) const + { + if (tid != LLDB_INVALID_THREAD_ID) + { + const size_t num_actions = m_actions.size(); + for (size_t i=0; i<num_actions; ++i) + { + if (m_actions[i].tid == tid) + m_signal_handled[i] = true; + } + } + } + + const ResumeAction * + GetFirst() const + { + return m_actions.data(); + } + + size_t + GetSize () const + { + return m_actions.size(); + } + + void + Clear() + { + m_actions.clear(); + m_signal_handled.clear(); + } + + protected: + std::vector<ResumeAction> m_actions; + mutable std::vector<bool> m_signal_handled; + }; + + struct ThreadStopInfo + { + lldb::StopReason reason; + union + { + // eStopTypeSignal + struct + { + uint32_t signo; + } signal; + + // eStopTypeException + struct + { + uint64_t type; + uint32_t data_count; + lldb::addr_t data[2]; + } exception; + } details; + }; + + //------------------------------------------------------------------ + // NativeThreadProtocol + //------------------------------------------------------------------ + class NativeThreadProtocol { + + public: + NativeThreadProtocol (NativeProcessProtocol *process, lldb::tid_t tid) : + m_process (process), + m_tid (tid) + { + } + + virtual ~NativeThreadProtocol() + { + } + virtual const char *GetName() = 0; + virtual lldb::StateType GetState () = 0; + virtual Error ReadRegister (uint32_t reg, RegisterValue ®_value) = 0; + virtual Error WriteRegister (uint32_t reg, const RegisterValue ®_value) = 0; + virtual Error SaveAllRegisters (lldb::DataBufferSP &data_sp) = 0; + virtual Error RestoreAllRegisters (lldb::DataBufferSP &data_sp) = 0; + virtual bool GetStopReason (ThreadStopInfo &stop_info) = 0; + + lldb::tid_t + GetID() const + { + return m_tid; + } + protected: + NativeProcessProtocol *m_process; + lldb::tid_t m_tid; + }; + + + //------------------------------------------------------------------ + // NativeProcessProtocol + //------------------------------------------------------------------ + class NativeProcessProtocol { + public: + + static NativeProcessProtocol * + CreateInstance (lldb::pid_t pid); + + // lldb_private::Host calls should be used to launch a process for debugging, and + // then the process should be attached to. When attaching to a process + // lldb_private::Host calls should be used to locate the process to attach to, + // and then this function should be called. + NativeProcessProtocol (lldb::pid_t pid) : + m_pid (pid), + m_threads(), + m_threads_mutex (Mutex::eMutexTypeRecursive), + m_state (lldb::eStateInvalid), + m_exit_status(0), + m_exit_description() + { + } + + public: + virtual ~NativeProcessProtocol () + { + } + + virtual Error Resume (const ResumeActionList &resume_actions) = 0; + virtual Error Halt () = 0; + virtual Error Detach () = 0; + virtual Error Signal (int signo) = 0; + virtual Error Kill () = 0; + + virtual Error ReadMemory (lldb::addr_t addr, void *buf, lldb::addr_t size, lldb::addr_t &bytes_read) = 0; + virtual Error WriteMemory (lldb::addr_t addr, const void *buf, lldb::addr_t size, lldb::addr_t &bytes_written) = 0; + virtual Error AllocateMemory (lldb::addr_t size, uint32_t permissions, lldb::addr_t &addr) = 0; + virtual Error DeallocateMemory (lldb::addr_t addr) = 0; + + virtual lldb::addr_t GetSharedLibraryInfoAddress () = 0; + + virtual bool IsAlive () = 0; + virtual size_t UpdateThreads () = 0; + virtual bool GetArchitecture (ArchSpec &arch) = 0; + + //---------------------------------------------------------------------- + // Breakpoint functions + //---------------------------------------------------------------------- + virtual Error SetBreakpoint (lldb::addr_t addr, size_t size, bool hardware) = 0; + virtual Error RemoveBreakpoint (lldb::addr_t addr, size_t size) = 0; + + //---------------------------------------------------------------------- + // Watchpoint functions + //---------------------------------------------------------------------- + virtual uint32_t GetMaxWatchpoints () = 0; + virtual Error SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware) = 0; + virtual Error RemoveWatchpoint (lldb::addr_t addr) = 0; + + + //---------------------------------------------------------------------- + // Accessors + //---------------------------------------------------------------------- + lldb::pid_t + GetID() const + { + return m_pid; + } + + lldb::StateType + GetState () const + { + return m_state; + } + + bool + IsRunning () const + { + return m_state == lldb::eStateRunning || IsStepping(); + } + + bool + IsStepping () const + { + return m_state == lldb::eStateStepping; + } + + bool + CanResume () const + { + return m_state == lldb::eStateStopped; + } + + + void + SetState (lldb::StateType state) + { + m_state = state; + } + + //---------------------------------------------------------------------- + // Exit Status + //---------------------------------------------------------------------- + virtual bool + GetExitStatus (int *status) + { + if (m_state == lldb::eStateExited) + { + *status = m_exit_status; + return true; + } + *status = 0; + return false; + } + virtual bool + SetExitStatus (int status, const char *exit_description) + { + // Exit status already set + if (m_state == lldb::eStateExited) + return false; + m_state = lldb::eStateExited; + m_exit_status = status; + if (exit_description && exit_description[0]) + m_exit_description = exit_description; + else + m_exit_description.clear(); + return true; + } + + //---------------------------------------------------------------------- + // Access to threads + //---------------------------------------------------------------------- + lldb::NativeThreadProtocolSP + GetThreadAtIndex (uint32_t idx) + { + Mutex::Locker locker(m_threads_mutex); + if (idx < m_threads.size()) + return m_threads[idx]; + return lldb::NativeThreadProtocolSP(); + } + + lldb::NativeThreadProtocolSP + GetThreadByID (lldb::tid_t tid) + { + Mutex::Locker locker(m_threads_mutex); + for (auto thread_sp : m_threads) + { + if (thread_sp->GetID() == tid) + return thread_sp; + } + return lldb::NativeThreadProtocolSP(); + } + + protected: + lldb::pid_t m_pid; + std::vector<lldb::NativeThreadProtocolSP> m_threads; + mutable Mutex m_threads_mutex; + lldb::StateType m_state; + int m_exit_status; + std::string m_exit_description; + }; + +} +#endif // #ifndef liblldb_Debug_h_ |