* Sends a SIGSTOP to the process. * Fixes busted SIGSTOP handling. Now builds a list of non-stopped that we wait for the PTRACE group-stop for. When the final must-stop tid gets its group stop, we propagate the process state change. Only the signal receiving the notification of the pending SIGSTOP is marked with the SIGSTOP signal. All the rest, if they weren't already stopped, are marked as stopped with signal 0. * Fixes a few broken tests. * Marks the Linux test I added earlier as expect-pass (no longer XFAIL). Implements fix for http://llvm.org/bugs/show_bug.cgi?id=20908. llvm-svn: 217647
345 lines
11 KiB
C++
345 lines
11 KiB
C++
//===-- NativeProcessProtocol.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_NativeProcessProtocol_h_
|
|
#define liblldb_NativeProcessProtocol_h_
|
|
|
|
#include <vector>
|
|
|
|
#include "lldb/lldb-private-forward.h"
|
|
#include "lldb/lldb-types.h"
|
|
#include "lldb/Core/Error.h"
|
|
#include "lldb/Host/Mutex.h"
|
|
|
|
#include "NativeBreakpointList.h"
|
|
|
|
namespace lldb_private
|
|
{
|
|
class MemoryRegionInfo;
|
|
class ResumeActionList;
|
|
|
|
//------------------------------------------------------------------
|
|
// NativeProcessProtocol
|
|
//------------------------------------------------------------------
|
|
class NativeProcessProtocol :
|
|
public std::enable_shared_from_this<NativeProcessProtocol>
|
|
{
|
|
friend class SoftwareBreakpoint;
|
|
|
|
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);
|
|
|
|
public:
|
|
virtual ~NativeProcessProtocol ()
|
|
{
|
|
}
|
|
|
|
virtual Error
|
|
Resume (const ResumeActionList &resume_actions) = 0;
|
|
|
|
virtual Error
|
|
Halt () = 0;
|
|
|
|
virtual Error
|
|
Detach () = 0;
|
|
|
|
//------------------------------------------------------------------
|
|
/// Sends a process a UNIX signal \a signal.
|
|
///
|
|
/// @return
|
|
/// Returns an error object.
|
|
//------------------------------------------------------------------
|
|
virtual Error
|
|
Signal (int signo) = 0;
|
|
|
|
//------------------------------------------------------------------
|
|
/// Tells a process to interrupt all operations as if by a Ctrl-C.
|
|
///
|
|
/// The default implementation will send a local host's equivalent of
|
|
/// a SIGSTOP to the process via the NativeProcessProtocol::Signal()
|
|
/// operation.
|
|
///
|
|
/// @return
|
|
/// Returns an error object.
|
|
//------------------------------------------------------------------
|
|
virtual Error
|
|
Interrupt ();
|
|
|
|
virtual Error
|
|
Kill () = 0;
|
|
|
|
//----------------------------------------------------------------------
|
|
// Memory and memory region functions
|
|
//----------------------------------------------------------------------
|
|
|
|
virtual Error
|
|
GetMemoryRegionInfo (lldb::addr_t load_addr, MemoryRegionInfo &range_info);
|
|
|
|
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 () const;
|
|
|
|
virtual size_t
|
|
UpdateThreads () = 0;
|
|
|
|
virtual bool
|
|
GetArchitecture (ArchSpec &arch) const = 0;
|
|
|
|
//----------------------------------------------------------------------
|
|
// Breakpoint functions
|
|
//----------------------------------------------------------------------
|
|
virtual Error
|
|
SetBreakpoint (lldb::addr_t addr, uint32_t size, bool hardware) = 0;
|
|
|
|
virtual Error
|
|
RemoveBreakpoint (lldb::addr_t addr);
|
|
|
|
virtual Error
|
|
EnableBreakpoint (lldb::addr_t addr);
|
|
|
|
virtual Error
|
|
DisableBreakpoint (lldb::addr_t addr);
|
|
|
|
//----------------------------------------------------------------------
|
|
// Watchpoint functions
|
|
//----------------------------------------------------------------------
|
|
virtual uint32_t
|
|
GetMaxWatchpoints () const;
|
|
|
|
virtual Error
|
|
SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware);
|
|
|
|
virtual Error
|
|
RemoveWatchpoint (lldb::addr_t addr);
|
|
|
|
//----------------------------------------------------------------------
|
|
// Accessors
|
|
//----------------------------------------------------------------------
|
|
lldb::pid_t
|
|
GetID() const
|
|
{
|
|
return m_pid;
|
|
}
|
|
|
|
lldb::StateType
|
|
GetState () const;
|
|
|
|
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;
|
|
}
|
|
|
|
bool
|
|
GetByteOrder (lldb::ByteOrder &byte_order) const;
|
|
|
|
//----------------------------------------------------------------------
|
|
// Exit Status
|
|
//----------------------------------------------------------------------
|
|
virtual bool
|
|
GetExitStatus (lldb_private::ExitType *exit_type, int *status, std::string &exit_description);
|
|
|
|
virtual bool
|
|
SetExitStatus (lldb_private::ExitType exit_type, int status, const char *exit_description, bool bNotifyStateChange);
|
|
|
|
//----------------------------------------------------------------------
|
|
// Access to threads
|
|
//----------------------------------------------------------------------
|
|
NativeThreadProtocolSP
|
|
GetThreadAtIndex (uint32_t idx);
|
|
|
|
NativeThreadProtocolSP
|
|
GetThreadByID (lldb::tid_t tid);
|
|
|
|
void
|
|
SetCurrentThreadID (lldb::tid_t tid)
|
|
{
|
|
m_current_thread_id = tid;
|
|
}
|
|
|
|
lldb::tid_t
|
|
GetCurrentThreadID ()
|
|
{
|
|
return m_current_thread_id;
|
|
}
|
|
|
|
NativeThreadProtocolSP
|
|
GetCurrentThread ()
|
|
{
|
|
return GetThreadByID (m_current_thread_id);
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Access to inferior stdio
|
|
//----------------------------------------------------------------------
|
|
virtual
|
|
int GetTerminalFileDescriptor ()
|
|
{
|
|
return m_terminal_fd;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Stop id interface
|
|
//----------------------------------------------------------------------
|
|
|
|
uint32_t
|
|
GetStopID () const;
|
|
|
|
// ---------------------------------------------------------------------
|
|
// Callbacks for low-level process state changes
|
|
// ---------------------------------------------------------------------
|
|
class NativeDelegate
|
|
{
|
|
public:
|
|
virtual
|
|
~NativeDelegate () {}
|
|
|
|
virtual void
|
|
InitializeDelegate (NativeProcessProtocol *process) = 0;
|
|
|
|
virtual void
|
|
ProcessStateChanged (NativeProcessProtocol *process, lldb::StateType state) = 0;
|
|
|
|
virtual void
|
|
DidExec (NativeProcessProtocol *process) = 0;
|
|
};
|
|
|
|
//------------------------------------------------------------------
|
|
/// Register a native delegate.
|
|
///
|
|
/// Clients can register nofication callbacks by passing in a
|
|
/// NativeDelegate impl and passing it into this function.
|
|
///
|
|
/// Note: it is required that the lifetime of the
|
|
/// native_delegate outlive the NativeProcessProtocol.
|
|
///
|
|
/// @param[in] native_delegate
|
|
/// A NativeDelegate impl to be called when certain events
|
|
/// happen within the NativeProcessProtocol or related threads.
|
|
///
|
|
/// @return
|
|
/// true if the delegate was registered successfully;
|
|
/// false if the delegate was already registered.
|
|
///
|
|
/// @see NativeProcessProtocol::NativeDelegate.
|
|
//------------------------------------------------------------------
|
|
bool
|
|
RegisterNativeDelegate (NativeDelegate &native_delegate);
|
|
|
|
//------------------------------------------------------------------
|
|
/// Unregister a native delegate previously registered.
|
|
///
|
|
/// @param[in] native_delegate
|
|
/// A NativeDelegate impl previously registered with this process.
|
|
///
|
|
/// @return Returns \b true if the NativeDelegate was
|
|
/// successfully removed from the process, \b false otherwise.
|
|
///
|
|
/// @see NativeProcessProtocol::NativeDelegate
|
|
//------------------------------------------------------------------
|
|
bool
|
|
UnregisterNativeDelegate (NativeDelegate &native_delegate);
|
|
|
|
protected:
|
|
lldb::pid_t m_pid;
|
|
|
|
std::vector<NativeThreadProtocolSP> m_threads;
|
|
lldb::tid_t m_current_thread_id;
|
|
mutable Mutex m_threads_mutex;
|
|
|
|
lldb::StateType m_state;
|
|
mutable Mutex m_state_mutex;
|
|
|
|
lldb_private::ExitType m_exit_type;
|
|
int m_exit_status;
|
|
std::string m_exit_description;
|
|
Mutex m_delegates_mutex;
|
|
std::vector<NativeDelegate*> m_delegates;
|
|
NativeBreakpointList m_breakpoint_list;
|
|
int m_terminal_fd;
|
|
uint32_t m_stop_id;
|
|
|
|
// -----------------------------------------------------------
|
|
// Internal interface for state handling
|
|
// -----------------------------------------------------------
|
|
void
|
|
SetState (lldb::StateType state, bool notify_delegates = true);
|
|
|
|
// Derived classes need not impelment this. It can be used as a
|
|
// hook to clear internal caches that should be invalidated when
|
|
// stop ids change.
|
|
//
|
|
// Note this function is called with the state mutex obtained
|
|
// by the caller.
|
|
virtual void
|
|
DoStopIDBumped (uint32_t newBumpId);
|
|
|
|
// -----------------------------------------------------------
|
|
// Internal interface for software breakpoints
|
|
// -----------------------------------------------------------
|
|
Error
|
|
SetSoftwareBreakpoint (lldb::addr_t addr, uint32_t size_hint);
|
|
|
|
virtual Error
|
|
GetSoftwareBreakpointTrapOpcode (size_t trap_opcode_size_hint, size_t &actual_opcode_size, const uint8_t *&trap_opcode_bytes) = 0;
|
|
|
|
// -----------------------------------------------------------
|
|
/// Notify the delegate that an exec occurred.
|
|
///
|
|
/// Provide a mechanism for a delegate to clear out any exec-
|
|
/// sensitive data.
|
|
// -----------------------------------------------------------
|
|
void
|
|
NotifyDidExec ();
|
|
|
|
NativeThreadProtocolSP
|
|
GetThreadByIDUnlocked (lldb::tid_t tid);
|
|
|
|
private:
|
|
|
|
void
|
|
SynchronouslyNotifyProcessStateChanged (lldb::StateType state);
|
|
};
|
|
}
|
|
|
|
#endif // #ifndef liblldb_NativeProcessProtocol_h_
|