llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h

358 lines
11 KiB
C
Raw Normal View History

//===-- ProcessGDBRemote.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_ProcessGDBRemote_h_
#define liblldb_ProcessGDBRemote_h_
// C Includes
// C++ Includes
#include <list>
#include <vector>
// Other libraries and framework includes
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/Broadcaster.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/InputReader.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/StringList.h"
#include "lldb/Core/ThreadSafeValue.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Thread.h"
#include "GDBRemoteCommunicationClient.h"
#include "Utility/StringExtractor.h"
#include "GDBRemoteRegisterContext.h"
class ThreadGDBRemote;
class ProcessGDBRemote : public lldb_private::Process
{
public:
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
static Process*
CreateInstance (lldb_private::Target& target, lldb_private::Listener &listener);
static void
Initialize();
static void
Terminate();
static const char *
GetPluginNameStatic();
static const char *
GetPluginDescriptionStatic();
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
ProcessGDBRemote(lldb_private::Target& target, lldb_private::Listener &listener);
virtual
~ProcessGDBRemote();
//------------------------------------------------------------------
// Check if a given Process
//------------------------------------------------------------------
virtual bool
CanDebug (lldb_private::Target &target,
bool plugin_specified_by_name);
LLDB now has "Platform" plug-ins. Platform plug-ins are plug-ins that provide an interface to a local or remote debugging platform. By default each host OS that supports LLDB should be registering a "default" platform that will be used unless a new platform is selected. Platforms are responsible for things such as: - getting process information by name or by processs ID - finding platform files. This is useful for remote debugging where there is an SDK with files that might already or need to be cached for debug access. - getting a list of platform supported architectures in the exact order they should be selected. This helps the native x86 platform on MacOSX select the correct x86_64/i386 slice from universal binaries. - Connect to remote platforms for remote debugging - Resolving an executable including finding an executable inside platform specific bundles (macosx uses .app bundles that contain files) and also selecting the appropriate slice of universal files for a given platform. So by default there is always a local platform, but remote platforms can be connected to. I will soon be adding a new "platform" command that will support the following commands: (lldb) platform connect --name machine1 macosx connect://host:port Connected to "machine1" platform. (lldb) platform disconnect macosx This allows LLDB to be well setup to do remote debugging and also once connected process listing and finding for things like: (lldb) process attach --name x<TAB> The currently selected platform plug-in can now auto complete any available processes that start with "x". The responsibilities for the platform plug-in will soon grow and expand. llvm-svn: 127286
2011-03-09 06:40:15 +08:00
// virtual uint32_t
// ListProcessesMatchingName (const char *name, lldb_private::StringList &matches, std::vector<lldb::pid_t> &pids);
//------------------------------------------------------------------
// Creating a new process, or attaching to an existing one
//------------------------------------------------------------------
virtual lldb_private::Error
WillLaunch (lldb_private::Module* module);
virtual lldb_private::Error
DoLaunch (lldb_private::Module *exe_module,
const lldb_private::ProcessLaunchInfo &launch_info);
virtual void
DidLaunch ();
virtual lldb_private::Error
2010-11-18 13:57:03 +08:00
WillAttachToProcessWithID (lldb::pid_t pid);
virtual lldb_private::Error
2010-11-18 13:57:03 +08:00
WillAttachToProcessWithName (const char *process_name, bool wait_for_launch);
Added support for attaching to a remote debug server with the new command: (lldb) process connect <remote-url> Currently when you specify a file with the file command it helps us to find a process plug-in that is suitable for debugging. If you specify a file you can rely upon this to find the correct debugger plug-in: % lldb a.out Current executable set to 'a.out' (x86_64). (lldb) process connect connect://localhost:2345 ... If you don't specify a file, you will need to specify the plug-in name that you wish to use: % lldb (lldb) process connect --plugin process.gdb-remote connect://localhost:2345 Other connection URL examples: (lldb) process connect connect://localhost:2345 (lldb) process connect tcp://127.0.0.1 (lldb) process connect file:///dev/ttyS1 We are currently treating the "connect://host:port" as a way to do raw socket connections. If there is a URL for this already, please let me know and we will adopt it. So now you can connect to a remote debug server with the ProcessGDBRemote plug-in. After connection, it will ask for the pid info using the "qC" packet and if it responds with a valid process ID, it will be equivalent to attaching. If it response with an error or invalid process ID, the LLDB process will be in a new state: eStateConnected. This allows us to then download a program or specify the program to run (using the 'A' packet), or specify a process to attach to (using the "vAttach" packets), or query info about the processes that might be available. llvm-svn: 124846
2011-02-04 09:58:07 +08:00
virtual lldb_private::Error
DoConnectRemote (const char *remote_url);
lldb_private::Error
WillLaunchOrAttach ();
virtual lldb_private::Error
DoAttachToProcessWithID (lldb::pid_t pid);
virtual lldb_private::Error
DoAttachToProcessWithName (const char *process_name, bool wait_for_launch);
virtual void
DidAttach ();
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
virtual const char *
GetPluginName();
virtual const char *
GetShortPluginName();
virtual uint32_t
GetPluginVersion();
//------------------------------------------------------------------
// Process Control
//------------------------------------------------------------------
virtual lldb_private::Error
WillResume ();
virtual lldb_private::Error
DoResume ();
virtual lldb_private::Error
DoHalt (bool &caused_stop);
virtual lldb_private::Error
WillDetach ();
virtual lldb_private::Error
DoDetach ();
virtual lldb_private::Error
DoSignal (int signal);
virtual lldb_private::Error
DoDestroy ();
virtual void
RefreshStateAfterStop();
//------------------------------------------------------------------
// Process Queries
//------------------------------------------------------------------
virtual bool
IsAlive ();
virtual lldb::addr_t
GetImageInfoAddress();
//------------------------------------------------------------------
// Process Memory
//------------------------------------------------------------------
virtual size_t
DoReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error);
virtual size_t
DoWriteMemory (lldb::addr_t addr, const void *buf, size_t size, lldb_private::Error &error);
virtual lldb::addr_t
DoAllocateMemory (size_t size, uint32_t permissions, lldb_private::Error &error);
virtual lldb_private::Error
GetMemoryRegionInfo (lldb::addr_t load_addr,
lldb_private::MemoryRegionInfo &region_info);
virtual lldb_private::Error
DoDeallocateMemory (lldb::addr_t ptr);
//------------------------------------------------------------------
// Process STDIO
//------------------------------------------------------------------
virtual size_t
PutSTDIN (const char *buf, size_t buf_size, lldb_private::Error &error);
//----------------------------------------------------------------------
// Process Breakpoints
//----------------------------------------------------------------------
virtual lldb_private::Error
EnableBreakpoint (lldb_private::BreakpointSite *bp_site);
virtual lldb_private::Error
DisableBreakpoint (lldb_private::BreakpointSite *bp_site);
//----------------------------------------------------------------------
// Process Watchpoints
//----------------------------------------------------------------------
virtual lldb_private::Error
EnableWatchpoint (lldb_private::Watchpoint *wp);
virtual lldb_private::Error
DisableWatchpoint (lldb_private::Watchpoint *wp);
virtual bool
StartNoticingNewThreads();
virtual bool
StopNoticingNewThreads();
protected:
friend class ThreadGDBRemote;
friend class GDBRemoteCommunicationClient;
friend class GDBRemoteRegisterContext;
//----------------------------------------------------------------------
// Accessors
//----------------------------------------------------------------------
bool
IsRunning ( lldb::StateType state )
{
return state == lldb::eStateRunning || IsStepping(state);
}
bool
IsStepping ( lldb::StateType state)
{
return state == lldb::eStateStepping;
}
bool
CanResume ( lldb::StateType state)
{
return state == lldb::eStateStopped;
}
bool
HasExited (lldb::StateType state)
{
return state == lldb::eStateExited;
}
bool
ProcessIDIsValid ( ) const;
void
Clear ( );
lldb_private::Flags &
GetFlags ()
{
return m_flags;
}
const lldb_private::Flags &
GetFlags () const
{
return m_flags;
}
uint32_t
UpdateThreadList (lldb_private::ThreadList &old_thread_list,
lldb_private::ThreadList &new_thread_list);
lldb_private::Error
Moved the execution context that was in the Debugger into the CommandInterpreter where it was always being used. Make sure that Modules can track their object file offsets correctly to allow opening of sub object files (like the "__commpage" on darwin). Modified the Platforms to be able to launch processes. The first part of this move is the platform soon will become the entity that launches your program and when it does, it uses a new ProcessLaunchInfo class which encapsulates all process launching settings. This simplifies the internal APIs needed for launching. I want to slowly phase out process launching from the process classes, so for now we can still launch just as we used to, but eventually the platform is the object that should do the launching. Modified the Host::LaunchProcess in the MacOSX Host.mm to correctly be able to launch processes with all of the new eLaunchFlag settings. Modified any code that was manually launching processes to use the Host::LaunchProcess functions. Fixed an issue where lldb_private::Args had implicitly defined copy constructors that could do the wrong thing. This has now been fixed by adding an appropriate copy constructor and assignment operator. Make sure we don't add empty ModuleSP entries to a module list. Fixed the commpage module creation on MacOSX, but we still need to train the MacOSX dynamic loader to not get rid of it when it doesn't have an entry in the all image infos. Abstracted many more calls from in ProcessGDBRemote down into the GDBRemoteCommunicationClient subclass to make the classes cleaner and more efficient. Fixed the default iOS ARM register context to be correct and also added support for targets that don't support the qThreadStopInfo packet by selecting the current thread (only if needed) and then sending a stop reply packet. Debugserver can now start up with a --unix-socket (-u for short) and can then bind to port zero and send the port it bound to to a listening process on the other end. This allows the GDB remote platform to spawn new GDB server instances (debugserver) to allow platform debugging. llvm-svn: 129351
2011-04-12 13:54:46 +08:00
StartDebugserverProcess (const char *debugserver_url);
void
KillDebugserverProcess ();
void
BuildDynamicRegisterInfo (bool force);
GDBRemoteCommunicationClient &
GetGDBRemote()
{
return m_gdb_comm;
}
//------------------------------------------------------------------
/// Broadcaster event bits definitions.
//------------------------------------------------------------------
enum
{
eBroadcastBitAsyncContinue = (1 << 0),
eBroadcastBitAsyncThreadShouldExit = (1 << 1)
};
lldb_private::Flags m_flags; // Process specific flags (see eFlags enums)
GDBRemoteCommunicationClient m_gdb_comm;
lldb::pid_t m_debugserver_pid;
StringExtractorGDBRemote m_last_stop_packet;
GDBRemoteDynamicRegisterInfo m_register_info;
lldb_private::Broadcaster m_async_broadcaster;
lldb::thread_t m_async_thread;
typedef std::vector<lldb::tid_t> tid_collection;
typedef std::vector< std::pair<lldb::tid_t,int> > tid_sig_collection;
Added the ability to get the return value from a ThreadPlanCallFunction thread plan. In order to get the return value, you can call: void ThreadPlanCallFunction::RequestReturnValue (lldb::ValueSP &return_value_sp); This registers a shared pointer to a return value that will get filled in if everything goes well. After the thread plan is run the return value will be extracted for you. Added an ifdef to be able to switch between the LLVM MCJIT and the standand JIT. We currently have the standard JIT selected because we have some work to do to get the MCJIT fuctioning properly. Added the ability to call functions with 6 argument in the x86_64 ABI. Added the ability for GDBRemoteCommunicationClient to detect if the allocate and deallocate memory packets are supported and to not call allocate memory ("_M") or deallocate ("_m") if we find they aren't supported. Modified the ProcessGDBRemote::DoAllocateMemory(...) and ProcessGDBRemote::DoDeallocateMemory(...) to be able to deal with the allocate and deallocate memory packets not being supported. If they are not supported, ProcessGDBRemote will switch to calling "mmap" and "munmap" to allocate and deallocate memory instead using our trivial function call support. Modified the "void ProcessGDBRemote::DidLaunchOrAttach()" to correctly ignore the qHostInfo triple information if any was specified in the target. Currently if the target only specifies an architecture when creating the target: (lldb) target create --arch i386 a.out Then the vendor, os and environemnt will be adopted by the target. If the target was created with any triple that specifies more than the arch: (lldb) target create --arch i386-unknown-unknown a.out Then the target will maintain its triple and not adopt any new values. This can be used to help force bare board debugging where the dynamic loader for static files will get used and users can then use "target modules load ..." to set addressses for any files that are desired. Added back some convenience functions to the lldb_private::RegisterContext class for writing registers with unsigned values. Also made all RegisterContext constructors explicit to make sure we know when an integer is being converted to a RegisterValue. llvm-svn: 131370
2011-05-15 09:25:55 +08:00
typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap;
tid_collection m_continue_c_tids; // 'c' for continue
tid_sig_collection m_continue_C_tids; // 'C' for continue with signal
tid_collection m_continue_s_tids; // 's' for step
tid_sig_collection m_continue_S_tids; // 'S' for step with signal
lldb::addr_t m_dispatch_queue_offsets_addr;
size_t m_max_memory_size; // The maximum number of bytes to read/write when reading and writing memory
bool m_waiting_for_attach;
std::vector<lldb::user_id_t> m_thread_observation_bps;
Added the ability to get the return value from a ThreadPlanCallFunction thread plan. In order to get the return value, you can call: void ThreadPlanCallFunction::RequestReturnValue (lldb::ValueSP &return_value_sp); This registers a shared pointer to a return value that will get filled in if everything goes well. After the thread plan is run the return value will be extracted for you. Added an ifdef to be able to switch between the LLVM MCJIT and the standand JIT. We currently have the standard JIT selected because we have some work to do to get the MCJIT fuctioning properly. Added the ability to call functions with 6 argument in the x86_64 ABI. Added the ability for GDBRemoteCommunicationClient to detect if the allocate and deallocate memory packets are supported and to not call allocate memory ("_M") or deallocate ("_m") if we find they aren't supported. Modified the ProcessGDBRemote::DoAllocateMemory(...) and ProcessGDBRemote::DoDeallocateMemory(...) to be able to deal with the allocate and deallocate memory packets not being supported. If they are not supported, ProcessGDBRemote will switch to calling "mmap" and "munmap" to allocate and deallocate memory instead using our trivial function call support. Modified the "void ProcessGDBRemote::DidLaunchOrAttach()" to correctly ignore the qHostInfo triple information if any was specified in the target. Currently if the target only specifies an architecture when creating the target: (lldb) target create --arch i386 a.out Then the vendor, os and environemnt will be adopted by the target. If the target was created with any triple that specifies more than the arch: (lldb) target create --arch i386-unknown-unknown a.out Then the target will maintain its triple and not adopt any new values. This can be used to help force bare board debugging where the dynamic loader for static files will get used and users can then use "target modules load ..." to set addressses for any files that are desired. Added back some convenience functions to the lldb_private::RegisterContext class for writing registers with unsigned values. Also made all RegisterContext constructors explicit to make sure we know when an integer is being converted to a RegisterValue. llvm-svn: 131370
2011-05-15 09:25:55 +08:00
MMapMap m_addr_to_mmap_size;
bool
StartAsyncThread ();
void
StopAsyncThread ();
static void *
AsyncThread (void *arg);
static bool
MonitorDebugserverProcess (void *callback_baton,
lldb::pid_t pid,
bool exited,
int signo,
int exit_status);
lldb::StateType
SetThreadStopInfo (StringExtractor& stop_packet);
void
DidLaunchOrAttach ();
lldb_private::Error
ConnectToDebugserver (const char *host_port);
const char *
GetDispatchQueueNameForThread (lldb::addr_t thread_dispatch_qaddr,
std::string &dispatch_queue_name);
static size_t
AttachInputReaderCallback (void *baton,
lldb_private::InputReader *reader,
lldb::InputReaderAction notification,
const char *bytes,
size_t bytes_len);
lldb_private::Error
InterruptIfRunning (bool discard_thread_plans,
bool catch_stop_event,
lldb::EventSP &stop_event_sp);
private:
//------------------------------------------------------------------
// For ProcessGDBRemote only
//------------------------------------------------------------------
static bool
NewThreadNotifyBreakpointHit (void *baton,
lldb_private::StoppointCallbackContext *context,
lldb::user_id_t break_id,
lldb::user_id_t break_loc_id);
DISALLOW_COPY_AND_ASSIGN (ProcessGDBRemote);
};
#endif // liblldb_ProcessGDBRemote_h_