Separate monolithic GDBRemoteCommunicationServer class into 4 part

GDBRemoteCommunicationServer: Basic packet handling, handler registration
LLDBCommonPacketHandler: Common packet handling for lldb-platform and lldb-gdbserver
LLDBPlatformPacketHandler: lldb-platform specific packet handling
LLGSPacketHandler: lldb-gdbserver specific packet handling

Differential Revision: http://reviews.llvm.org/D7538

llvm-svn: 228823
This commit is contained in:
Tamas Berghammer 2015-02-11 10:29:30 +00:00
parent c4d5ed06cd
commit e13c2731ba
25 changed files with 5006 additions and 4976 deletions

View File

@ -737,6 +737,9 @@
4CF3D80C15AF4DC800845BF3 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDB919B414F6F10D008FF64B /* Security.framework */; };
4CF52AF51428291E0051E832 /* SBFileSpecList.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF52AF41428291E0051E832 /* SBFileSpecList.h */; settings = {ATTRIBUTES = (Public, ); }; };
4CF52AF8142829390051E832 /* SBFileSpecList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF52AF7142829390051E832 /* SBFileSpecList.cpp */; };
6D55B2901A8A806200A70529 /* GDBRemoteCommunicationServerCommon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D55B28D1A8A806200A70529 /* GDBRemoteCommunicationServerCommon.cpp */; };
6D55B2911A8A806200A70529 /* GDBRemoteCommunicationServerLLGS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D55B28E1A8A806200A70529 /* GDBRemoteCommunicationServerLLGS.cpp */; };
6D55B2921A8A806200A70529 /* GDBRemoteCommunicationServerPlatform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D55B28F1A8A806200A70529 /* GDBRemoteCommunicationServerPlatform.cpp */; };
8C2D6A53197A1EAF006989C9 /* MemoryHistory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C2D6A52197A1EAF006989C9 /* MemoryHistory.cpp */; };
8C2D6A5E197A250F006989C9 /* MemoryHistoryASan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C2D6A5A197A1FDC006989C9 /* MemoryHistoryASan.cpp */; };
8CCB017E19BA28A80009FD44 /* ThreadCollection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CCB017A19BA283D0009FD44 /* ThreadCollection.cpp */; };
@ -2348,6 +2351,12 @@
69A01E1E1236C5D400C660B5 /* Mutex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Mutex.cpp; sourceTree = "<group>"; };
69A01E1F1236C5D400C660B5 /* Symbols.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Symbols.cpp; sourceTree = "<group>"; };
69A01E201236C5D400C660B5 /* TimeValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TimeValue.cpp; sourceTree = "<group>"; };
6D55B28D1A8A806200A70529 /* GDBRemoteCommunicationServerCommon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GDBRemoteCommunicationServerCommon.cpp; sourceTree = "<group>"; };
6D55B28E1A8A806200A70529 /* GDBRemoteCommunicationServerLLGS.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GDBRemoteCommunicationServerLLGS.cpp; sourceTree = "<group>"; };
6D55B28F1A8A806200A70529 /* GDBRemoteCommunicationServerPlatform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GDBRemoteCommunicationServerPlatform.cpp; sourceTree = "<group>"; };
6D55B2931A8A808400A70529 /* GDBRemoteCommunicationServerCommon.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GDBRemoteCommunicationServerCommon.h; sourceTree = "<group>"; };
6D55B2941A8A808400A70529 /* GDBRemoteCommunicationServerLLGS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GDBRemoteCommunicationServerLLGS.h; sourceTree = "<group>"; };
6D55B2951A8A808400A70529 /* GDBRemoteCommunicationServerPlatform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GDBRemoteCommunicationServerPlatform.h; sourceTree = "<group>"; };
8C2D6A52197A1EAF006989C9 /* MemoryHistory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MemoryHistory.cpp; path = source/Target/MemoryHistory.cpp; sourceTree = "<group>"; };
8C2D6A54197A1EBE006989C9 /* MemoryHistory.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MemoryHistory.h; path = include/lldb/Target/MemoryHistory.h; sourceTree = "<group>"; };
8C2D6A5A197A1FDC006989C9 /* MemoryHistoryASan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MemoryHistoryASan.cpp; sourceTree = "<group>"; };
@ -4868,6 +4877,12 @@
4CEE62F71145F1C70064CF93 /* GDB Remote */ = {
isa = PBXGroup;
children = (
6D55B2931A8A808400A70529 /* GDBRemoteCommunicationServerCommon.h */,
6D55B2941A8A808400A70529 /* GDBRemoteCommunicationServerLLGS.h */,
6D55B2951A8A808400A70529 /* GDBRemoteCommunicationServerPlatform.h */,
6D55B28D1A8A806200A70529 /* GDBRemoteCommunicationServerCommon.cpp */,
6D55B28E1A8A806200A70529 /* GDBRemoteCommunicationServerLLGS.cpp */,
6D55B28F1A8A806200A70529 /* GDBRemoteCommunicationServerPlatform.cpp */,
2618EE5B1315B29C001D6D71 /* GDBRemoteCommunication.cpp */,
2618EE5C1315B29C001D6D71 /* GDBRemoteCommunication.h */,
26744EED1338317700EF765A /* GDBRemoteCommunicationClient.cpp */,
@ -5496,7 +5511,7 @@
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0600;
LastUpgradeCheck = 0610;
TargetAttributes = {
2690CD161A6DC0D000E717C8 = {
CreatedOnToolsVersion = 6.3;
@ -5820,6 +5835,7 @@
2689001513353DDE00698AC0 /* CommandObjectBreakpointCommand.cpp in Sources */,
2689001613353DDE00698AC0 /* CommandObjectCommands.cpp in Sources */,
AFEC3362194A8ABA00FF05C6 /* StructuredData.cpp in Sources */,
6D55B2901A8A806200A70529 /* GDBRemoteCommunicationServerCommon.cpp in Sources */,
26474CAC18D0CB070073DEBA /* RegisterContextFreeBSD_x86_64.cpp in Sources */,
2689001713353DDE00698AC0 /* CommandObjectDisassemble.cpp in Sources */,
2689001813353DDE00698AC0 /* CommandObjectExpression.cpp in Sources */,
@ -6241,6 +6257,7 @@
260CC65015D0440D002BF2E0 /* OptionValueFormat.cpp in Sources */,
260CC65115D0440D002BF2E0 /* OptionValueSInt64.cpp in Sources */,
260CC65215D0440D002BF2E0 /* OptionValueString.cpp in Sources */,
6D55B2911A8A806200A70529 /* GDBRemoteCommunicationServerLLGS.cpp in Sources */,
260CC65315D0440D002BF2E0 /* OptionValueUInt64.cpp in Sources */,
260CC65415D0440D002BF2E0 /* OptionValueUUID.cpp in Sources */,
94BA8B6D176F8C9B005A91B5 /* Range.cpp in Sources */,
@ -6251,6 +6268,7 @@
2640E19F15DC78FD00F23B50 /* Property.cpp in Sources */,
26491E3E15E1DB9F00CBFFC2 /* OptionValueRegex.cpp in Sources */,
2697A39315E404B1003E682C /* OptionValueArch.cpp in Sources */,
6D55B2921A8A806200A70529 /* GDBRemoteCommunicationServerPlatform.cpp in Sources */,
94EA1D5C15E6C9B400D4171A /* PythonDataObjects.cpp in Sources */,
94D6A0AC16CEB55F00833B6E /* NSSet.cpp in Sources */,
94CD704E16F8DDEA00CF1E42 /* Cocoa.cpp in Sources */,

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0600"
LastUpgradeVersion = "0610"
version = "1.8">
<BuildAction
parallelizeBuildables = "NO"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0600"
LastUpgradeVersion = "0610"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0600"
LastUpgradeVersion = "0610"
version = "1.8">
<BuildAction
parallelizeBuildables = "NO"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0600"
LastUpgradeVersion = "0610"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0600"
LastUpgradeVersion = "0610"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0600"
version = "1.3">
LastUpgradeVersion = "0610"
version = "1.8">
<BuildAction
parallelizeBuildables = "NO"
buildImplicitDependencies = "YES">

View File

@ -194,8 +194,8 @@ PlatformRemoteGDBServer::GetFileWithUUID (const FileSpec &platform_file,
/// Default Constructor
//------------------------------------------------------------------
PlatformRemoteGDBServer::PlatformRemoteGDBServer () :
Platform(false), // This is a remote platform
m_gdb_client(true)
Platform (false), // This is a remote platform
m_gdb_client ()
{
}

View File

@ -4,6 +4,9 @@ add_lldb_library(lldbPluginProcessGDBRemote
GDBRemoteCommunication.cpp
GDBRemoteCommunicationClient.cpp
GDBRemoteCommunicationServer.cpp
GDBRemoteCommunicationServerCommon.cpp
GDBRemoteCommunicationServerLLGS.cpp
GDBRemoteCommunicationServerPlatform.cpp
GDBRemoteRegisterContext.cpp
ProcessGDBRemote.cpp
ProcessGDBRemoteLog.cpp

View File

@ -142,8 +142,7 @@ GDBRemoteCommunication::History::Dump (lldb_private::Log *log) const
// GDBRemoteCommunication constructor
//----------------------------------------------------------------------
GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name,
const char *listener_name,
bool is_platform) :
const char *listener_name) :
Communication(comm_name),
#ifdef LLDB_CONFIGURATION_DEBUG
m_packet_timeout (1000),
@ -155,7 +154,6 @@ GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name,
m_private_is_running (false),
m_history (512),
m_send_acks (true),
m_is_platform (is_platform),
m_listen_url ()
{
}

View File

@ -63,8 +63,7 @@ public:
// Constructors and Destructors
//------------------------------------------------------------------
GDBRemoteCommunication(const char *comm_name,
const char *listener_name,
bool is_platform);
const char *listener_name);
virtual
~GDBRemoteCommunication();

View File

@ -48,8 +48,8 @@ using namespace lldb_private;
//----------------------------------------------------------------------
// GDBRemoteCommunicationClient constructor
//----------------------------------------------------------------------
GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) :
GDBRemoteCommunication("gdb-remote.client", "gdb-remote.client.rx_packet", is_platform),
GDBRemoteCommunicationClient::GDBRemoteCommunicationClient() :
GDBRemoteCommunication("gdb-remote.client", "gdb-remote.client.rx_packet"),
m_supports_not_sending_acks (eLazyBoolCalculate),
m_supports_thread_suffix (eLazyBoolCalculate),
m_supports_threads_in_stop_reply (eLazyBoolCalculate),

View File

@ -27,7 +27,7 @@ public:
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
GDBRemoteCommunicationClient(bool is_platform);
GDBRemoteCommunicationClient();
~GDBRemoteCommunicationClient();

View File

@ -12,236 +12,47 @@
// C Includes
// C++ Includes
#include <vector>
#include <set>
#include <unordered_map>
// Other libraries and framework includes
// Project includes
#include "lldb/lldb-private-forward.h"
#include "lldb/Core/Communication.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Target/Process.h"
#include "GDBRemoteCommunication.h"
#include "lldb/Host/common/NativeProcessProtocol.h"
class ProcessGDBRemote;
class StringExtractorGDBRemote;
class GDBRemoteCommunicationServer :
public GDBRemoteCommunication,
public lldb_private::NativeProcessProtocol::NativeDelegate
public GDBRemoteCommunication
{
public:
typedef std::map<uint16_t, lldb::pid_t> PortMap;
using PortMap = std::map<uint16_t, lldb::pid_t>;
using PacketHandler = std::function<PacketResult(StringExtractorGDBRemote &packet,
lldb_private::Error &error,
bool &interrupt,
bool &quit)>;
enum
{
eBroadcastBitRunPacketSent = kLoUserBroadcastBit
};
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
GDBRemoteCommunicationServer(bool is_platform);
GDBRemoteCommunicationServer(bool is_platform,
const lldb::PlatformSP& platform_sp,
lldb::DebuggerSP& debugger_sp);
GDBRemoteCommunicationServer(const char *comm_name,
const char *listener_name);
virtual
~GDBRemoteCommunicationServer();
void RegisterPacketHandler(StringExtractorGDBRemote::ServerPacketType packet_type,
PacketHandler handler);
PacketResult
GetPacketAndSendResponse (uint32_t timeout_usec,
lldb_private::Error &error,
bool &interrupt,
bool &quit);
virtual bool
GetThreadSuffixSupported () override
{
return true;
}
// After connecting, do a little handshake with the client to make sure
// we are at least communicating
bool
HandshakeWithClient (lldb_private::Error *error_ptr);
// Set both ports to zero to let the platform automatically bind to
// a port chosen by the OS.
void
SetPortMap (PortMap &&port_map)
{
m_port_map = port_map;
}
//----------------------------------------------------------------------
// If we are using a port map where we can only use certain ports,
// get the next available port.
//
// If we are using a port map and we are out of ports, return UINT16_MAX
//
// If we aren't using a port map, return 0 to indicate we should bind to
// port 0 and then figure out which port we used.
//----------------------------------------------------------------------
uint16_t
GetNextAvailablePort ()
{
if (m_port_map.empty())
return 0; // Bind to port zero and get a port, we didn't have any limitations
for (auto &pair : m_port_map)
{
if (pair.second == LLDB_INVALID_PROCESS_ID)
{
pair.second = ~(lldb::pid_t)LLDB_INVALID_PROCESS_ID;
return pair.first;
}
}
return UINT16_MAX;
}
bool
AssociatePortWithProcess (uint16_t port, lldb::pid_t pid)
{
PortMap::iterator pos = m_port_map.find(port);
if (pos != m_port_map.end())
{
pos->second = pid;
return true;
}
return false;
}
bool
FreePort (uint16_t port)
{
PortMap::iterator pos = m_port_map.find(port);
if (pos != m_port_map.end())
{
pos->second = LLDB_INVALID_PROCESS_ID;
return true;
}
return false;
}
bool
FreePortForProcess (lldb::pid_t pid)
{
if (!m_port_map.empty())
{
for (auto &pair : m_port_map)
{
if (pair.second == pid)
{
pair.second = LLDB_INVALID_PROCESS_ID;
return true;
}
}
}
return false;
}
void
SetPortOffset (uint16_t port_offset)
{
m_port_offset = port_offset;
}
//------------------------------------------------------------------
/// Specify the program to launch and its arguments.
///
/// @param[in] args
/// The command line to launch.
///
/// @param[in] argc
/// The number of elements in the args array of cstring pointers.
///
/// @return
/// An Error object indicating the success or failure of making
/// the setting.
//------------------------------------------------------------------
lldb_private::Error
SetLaunchArguments (const char *const args[], int argc);
//------------------------------------------------------------------
/// Specify the launch flags for the process.
///
/// @param[in] launch_flags
/// The launch flags to use when launching this process.
///
/// @return
/// An Error object indicating the success or failure of making
/// the setting.
//------------------------------------------------------------------
lldb_private::Error
SetLaunchFlags (unsigned int launch_flags);
//------------------------------------------------------------------
/// Launch a process with the current launch settings.
///
/// This method supports running an lldb-gdbserver or similar
/// server in a situation where the startup code has been provided
/// with all the information for a child process to be launched.
///
/// @return
/// An Error object indicating the success or failure of the
/// launch.
//------------------------------------------------------------------
lldb_private::Error
LaunchProcess ();
//------------------------------------------------------------------
/// Attach to a process.
///
/// This method supports attaching llgs to a process accessible via the
/// configured Platform.
///
/// @return
/// An Error object indicating the success or failure of the
/// attach operation.
//------------------------------------------------------------------
lldb_private::Error
AttachToProcess (lldb::pid_t pid);
//------------------------------------------------------------------
// NativeProcessProtocol::NativeDelegate overrides
//------------------------------------------------------------------
void
InitializeDelegate (lldb_private::NativeProcessProtocol *process) override;
void
ProcessStateChanged (lldb_private::NativeProcessProtocol *process, lldb::StateType state) override;
void
DidExec (lldb_private::NativeProcessProtocol *process) override;
protected:
lldb::PlatformSP m_platform_sp;
lldb::thread_t m_async_thread;
lldb_private::ProcessLaunchInfo m_process_launch_info;
lldb_private::Error m_process_launch_error;
std::set<lldb::pid_t> m_spawned_pids;
lldb_private::Mutex m_spawned_pids_mutex;
lldb_private::ProcessInstanceInfoList m_proc_infos;
uint32_t m_proc_infos_index;
PortMap m_port_map;
uint16_t m_port_offset;
lldb::tid_t m_current_tid;
lldb::tid_t m_continue_tid;
lldb_private::Mutex m_debugged_process_mutex;
lldb_private::NativeProcessProtocolSP m_debugged_process_sp;
lldb::DebuggerSP m_debugger_sp;
Communication m_stdio_communication;
std::map<StringExtractorGDBRemote::ServerPacketType, PacketHandler> m_packet_handlers;
bool m_exit_now; // use in asynchronous handling to indicate process should exit.
lldb::StateType m_inferior_prev_state;
bool m_thread_suffix_supported;
bool m_list_threads_in_stop_reply;
lldb::DataBufferSP m_active_auxv_buffer_sp;
lldb_private::Mutex m_saved_registers_mutex;
std::unordered_map<uint32_t, lldb::DataBufferSP> m_saved_registers_map;
uint32_t m_next_saved_registers_id;
PacketResult
SendUnimplementedResponse (const char *packet);
@ -255,302 +66,7 @@ protected:
PacketResult
SendOKResponse ();
PacketResult
SendONotification (const char *buffer, uint32_t len);
PacketResult
SendWResponse (lldb_private::NativeProcessProtocol *process);
PacketResult
SendStopReplyPacketForThread (lldb::tid_t tid);
PacketResult
SendStopReasonForState (lldb::StateType process_state, bool flush_on_exit);
PacketResult
Handle_A (StringExtractorGDBRemote &packet);
PacketResult
Handle_qLaunchSuccess (StringExtractorGDBRemote &packet);
PacketResult
Handle_qHostInfo (StringExtractorGDBRemote &packet);
PacketResult
Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet);
PacketResult
Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet);
PacketResult
Handle_k (StringExtractorGDBRemote &packet);
PacketResult
Handle_qPlatform_mkdir (StringExtractorGDBRemote &packet);
PacketResult
Handle_qPlatform_chmod (StringExtractorGDBRemote &packet);
PacketResult
Handle_qProcessInfo (StringExtractorGDBRemote &packet);
PacketResult
Handle_qProcessInfoPID (StringExtractorGDBRemote &packet);
PacketResult
Handle_qfProcessInfo (StringExtractorGDBRemote &packet);
PacketResult
Handle_qsProcessInfo (StringExtractorGDBRemote &packet);
PacketResult
Handle_qC (StringExtractorGDBRemote &packet);
PacketResult
Handle_qUserName (StringExtractorGDBRemote &packet);
PacketResult
Handle_qGroupName (StringExtractorGDBRemote &packet);
PacketResult
Handle_qSpeedTest (StringExtractorGDBRemote &packet);
PacketResult
Handle_QEnvironment (StringExtractorGDBRemote &packet);
PacketResult
Handle_QLaunchArch (StringExtractorGDBRemote &packet);
PacketResult
Handle_QSetDisableASLR (StringExtractorGDBRemote &packet);
PacketResult
Handle_QSetDetachOnError (StringExtractorGDBRemote &packet);
PacketResult
Handle_QSetWorkingDir (StringExtractorGDBRemote &packet);
PacketResult
Handle_qGetWorkingDir (StringExtractorGDBRemote &packet);
PacketResult
Handle_QStartNoAckMode (StringExtractorGDBRemote &packet);
PacketResult
Handle_QSetSTDIN (StringExtractorGDBRemote &packet);
PacketResult
Handle_QSetSTDOUT (StringExtractorGDBRemote &packet);
PacketResult
Handle_QSetSTDERR (StringExtractorGDBRemote &packet);
PacketResult
Handle_C (StringExtractorGDBRemote &packet);
PacketResult
Handle_c (StringExtractorGDBRemote &packet, bool skip_file_pos_adjustment = false);
PacketResult
Handle_vCont (StringExtractorGDBRemote &packet);
PacketResult
Handle_vCont_actions (StringExtractorGDBRemote &packet);
PacketResult
Handle_stop_reason (StringExtractorGDBRemote &packet);
PacketResult
Handle_vFile_Open (StringExtractorGDBRemote &packet);
PacketResult
Handle_vFile_Close (StringExtractorGDBRemote &packet);
PacketResult
Handle_vFile_pRead (StringExtractorGDBRemote &packet);
PacketResult
Handle_vFile_pWrite (StringExtractorGDBRemote &packet);
PacketResult
Handle_vFile_Size (StringExtractorGDBRemote &packet);
PacketResult
Handle_vFile_Mode (StringExtractorGDBRemote &packet);
PacketResult
Handle_vFile_Exists (StringExtractorGDBRemote &packet);
PacketResult
Handle_vFile_symlink (StringExtractorGDBRemote &packet);
PacketResult
Handle_vFile_unlink (StringExtractorGDBRemote &packet);
PacketResult
Handle_vFile_Stat (StringExtractorGDBRemote &packet);
PacketResult
Handle_vFile_MD5 (StringExtractorGDBRemote &packet);
PacketResult
Handle_qPlatform_shell (StringExtractorGDBRemote &packet);
PacketResult
Handle_qRegisterInfo (StringExtractorGDBRemote &packet);
PacketResult
Handle_qfThreadInfo (StringExtractorGDBRemote &packet);
PacketResult
Handle_qsThreadInfo (StringExtractorGDBRemote &packet);
PacketResult
Handle_p (StringExtractorGDBRemote &packet);
PacketResult
Handle_P (StringExtractorGDBRemote &packet);
PacketResult
Handle_H (StringExtractorGDBRemote &packet);
PacketResult
Handle_I (StringExtractorGDBRemote &packet);
PacketResult
Handle_interrupt (StringExtractorGDBRemote &packet);
PacketResult
Handle_m (StringExtractorGDBRemote &packet);
PacketResult
Handle_M (StringExtractorGDBRemote &packet);
PacketResult
Handle_qMemoryRegionInfoSupported (StringExtractorGDBRemote &packet);
PacketResult
Handle_qMemoryRegionInfo (StringExtractorGDBRemote &packet);
PacketResult
Handle_Z (StringExtractorGDBRemote &packet);
PacketResult
Handle_z (StringExtractorGDBRemote &packet);
PacketResult
Handle_s (StringExtractorGDBRemote &packet);
PacketResult
Handle_qSupported (StringExtractorGDBRemote &packet);
PacketResult
Handle_QThreadSuffixSupported (StringExtractorGDBRemote &packet);
PacketResult
Handle_QListThreadsInStopReply (StringExtractorGDBRemote &packet);
PacketResult
Handle_qXfer_auxv_read (StringExtractorGDBRemote &packet);
PacketResult
Handle_QSaveRegisterState (StringExtractorGDBRemote &packet);
PacketResult
Handle_QRestoreRegisterState (StringExtractorGDBRemote &packet);
PacketResult
Handle_vAttach (StringExtractorGDBRemote &packet);
PacketResult
Handle_D (StringExtractorGDBRemote &packet);
PacketResult
Handle_qThreadStopInfo (StringExtractorGDBRemote &packet);
PacketResult
Handle_qWatchpointSupportInfo (StringExtractorGDBRemote &packet);
void
SetCurrentThreadID (lldb::tid_t tid);
lldb::tid_t
GetCurrentThreadID () const;
void
SetContinueThreadID (lldb::tid_t tid);
lldb::tid_t
GetContinueThreadID () const { return m_continue_tid; }
lldb_private::Error
SetSTDIOFileDescriptor (int fd);
static void
STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_len);
private:
bool
DebugserverProcessReaped (lldb::pid_t pid);
static bool
ReapDebugserverProcess (void *callback_baton,
lldb::pid_t pid,
bool exited,
int signal,
int status);
bool
DebuggedProcessReaped (lldb::pid_t pid);
static bool
ReapDebuggedProcess (void *callback_baton,
lldb::pid_t pid,
bool exited,
int signal,
int status);
bool
KillSpawnedProcess (lldb::pid_t pid);
bool
IsGdbServer ()
{
return !m_is_platform;
}
/// Launch an inferior process from lldb-gdbserver
lldb_private::Error
LaunchProcessForDebugging ();
/// Launch a process from lldb-platform
lldb_private::Error
LaunchPlatformProcess ();
void
HandleInferiorState_Exited (lldb_private::NativeProcessProtocol *process);
void
HandleInferiorState_Stopped (lldb_private::NativeProcessProtocol *process);
void
FlushInferiorOutput ();
lldb_private::NativeThreadProtocolSP
GetThreadFromSuffix (StringExtractorGDBRemote &packet);
uint32_t
GetNextSavedRegistersID ();
void
MaybeCloseInferiorTerminalConnection ();
void
ClearProcessSpecificData ();
bool
ShouldRedirectInferiorOutputOverGdbRemote (const lldb_private::ProcessLaunchInfo &launch_info) const;
//------------------------------------------------------------------
// For GDBRemoteCommunicationServer only
//------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,200 @@
//===-- GDBRemoteCommunicationServerCommon.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_GDBRemoteCommunicationServerCommon_h_
#define liblldb_GDBRemoteCommunicationServerCommon_h_
// C Includes
// C++ Includes
#include <set>
// Other libraries and framework includes
#include "lldb/lldb-private-forward.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Target/Process.h"
// Project includes
#include "GDBRemoteCommunicationServer.h"
#include "GDBRemoteCommunicationServerCommon.h"
class ProcessGDBRemote;
class StringExtractorGDBRemote;
class GDBRemoteCommunicationServerCommon :
public GDBRemoteCommunicationServer
{
public:
GDBRemoteCommunicationServerCommon(const char *comm_name, const char *listener_name);
virtual
~GDBRemoteCommunicationServerCommon();
virtual bool
GetThreadSuffixSupported () override
{
return true;
}
//------------------------------------------------------------------
/// Launch a process with the current launch settings.
///
/// This method supports running an lldb-gdbserver or similar
/// server in a situation where the startup code has been provided
/// with all the information for a child process to be launched.
///
/// @return
/// An Error object indicating the success or failure of the
/// launch.
//------------------------------------------------------------------
virtual lldb_private::Error
LaunchProcess () = 0;
protected:
std::set<lldb::pid_t> m_spawned_pids;
lldb_private::Mutex m_spawned_pids_mutex;
lldb_private::ProcessLaunchInfo m_process_launch_info;
lldb_private::Error m_process_launch_error;
lldb_private::ProcessInstanceInfoList m_proc_infos;
uint32_t m_proc_infos_index;
bool m_thread_suffix_supported;
bool m_list_threads_in_stop_reply;
PacketResult
Handle_A (StringExtractorGDBRemote &packet);
PacketResult
Handle_qHostInfo (StringExtractorGDBRemote &packet);
PacketResult
Handle_qProcessInfoPID (StringExtractorGDBRemote &packet);
PacketResult
Handle_qfProcessInfo (StringExtractorGDBRemote &packet);
PacketResult
Handle_qsProcessInfo (StringExtractorGDBRemote &packet);
PacketResult
Handle_qUserName (StringExtractorGDBRemote &packet);
PacketResult
Handle_qGroupName (StringExtractorGDBRemote &packet);
PacketResult
Handle_qSpeedTest (StringExtractorGDBRemote &packet);
PacketResult
Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet);
PacketResult
Handle_vFile_Open (StringExtractorGDBRemote &packet);
PacketResult
Handle_vFile_Close (StringExtractorGDBRemote &packet);
PacketResult
Handle_vFile_pRead (StringExtractorGDBRemote &packet);
PacketResult
Handle_vFile_pWrite (StringExtractorGDBRemote &packet);
PacketResult
Handle_vFile_Size (StringExtractorGDBRemote &packet);
PacketResult
Handle_vFile_Mode (StringExtractorGDBRemote &packet);
PacketResult
Handle_vFile_Exists (StringExtractorGDBRemote &packet);
PacketResult
Handle_vFile_symlink (StringExtractorGDBRemote &packet);
PacketResult
Handle_vFile_unlink (StringExtractorGDBRemote &packet);
PacketResult
Handle_vFile_Stat (StringExtractorGDBRemote &packet);
PacketResult
Handle_vFile_MD5 (StringExtractorGDBRemote &packet);
PacketResult
Handle_qPlatform_shell (StringExtractorGDBRemote &packet);
PacketResult
Handle_qPlatform_mkdir (StringExtractorGDBRemote &packet);
PacketResult
Handle_qPlatform_chmod (StringExtractorGDBRemote &packet);
PacketResult
Handle_qSupported (StringExtractorGDBRemote &packet);
PacketResult
Handle_QThreadSuffixSupported (StringExtractorGDBRemote &packet);
PacketResult
Handle_QListThreadsInStopReply (StringExtractorGDBRemote &packet);
PacketResult
Handle_QSetDetachOnError (StringExtractorGDBRemote &packet);
PacketResult
Handle_QStartNoAckMode (StringExtractorGDBRemote &packet);
PacketResult
Handle_QSetSTDIN (StringExtractorGDBRemote &packet);
PacketResult
Handle_QSetSTDOUT (StringExtractorGDBRemote &packet);
PacketResult
Handle_QSetSTDERR (StringExtractorGDBRemote &packet);
PacketResult
Handle_qLaunchSuccess (StringExtractorGDBRemote &packet);
PacketResult
Handle_QEnvironment (StringExtractorGDBRemote &packet);
PacketResult
Handle_QLaunchArch (StringExtractorGDBRemote &packet);
bool
KillSpawnedProcess (lldb::pid_t pid);
static void
CreateProcessInfoResponse (const lldb_private::ProcessInstanceInfo &proc_info,
lldb_private::StreamString &response);
static void
CreateProcessInfoResponse_DebugServerStyle (const lldb_private::ProcessInstanceInfo &proc_info,
lldb_private::StreamString &response);
template <typename T>
using MemberFunctionPacketHandler = PacketResult (T::*) (StringExtractorGDBRemote& packet);
template <typename T>
void
RegisterMemberFunctionHandler(StringExtractorGDBRemote::ServerPacketType packet_type,
MemberFunctionPacketHandler<T> handler)
{
RegisterPacketHandler(packet_type,
[this, handler] (StringExtractorGDBRemote packet,
lldb_private::Error &error,
bool &interrupt,
bool &quit)
{
return (static_cast<T*>(this)->*handler) (packet);
});
}
};
#endif // liblldb_GDBRemoteCommunicationServerCommon_h_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,299 @@
//===-- GDBRemoteCommunicationServerLLGS.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_GDBRemoteCommunicationServerLLGS_h_
#define liblldb_GDBRemoteCommunicationServerLLGS_h_
// C Includes
// C++ Includes
#include <unordered_map>
// Other libraries and framework includes
#include "lldb/lldb-private-forward.h"
#include "lldb/Core/Communication.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Host/common/NativeProcessProtocol.h"
// Project includes
#include "GDBRemoteCommunicationServerCommon.h"
class ProcessGDBRemote;
class StringExtractorGDBRemote;
class GDBRemoteCommunicationServerLLGS :
public GDBRemoteCommunicationServerCommon,
public lldb_private::NativeProcessProtocol::NativeDelegate
{
public:
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
GDBRemoteCommunicationServerLLGS(const lldb::PlatformSP& platform_sp,
lldb::DebuggerSP& debugger_sp);
virtual
~GDBRemoteCommunicationServerLLGS();
//------------------------------------------------------------------
/// Specify the program to launch and its arguments.
///
/// @param[in] args
/// The command line to launch.
///
/// @param[in] argc
/// The number of elements in the args array of cstring pointers.
///
/// @return
/// An Error object indicating the success or failure of making
/// the setting.
//------------------------------------------------------------------
lldb_private::Error
SetLaunchArguments (const char *const args[], int argc);
//------------------------------------------------------------------
/// Specify the launch flags for the process.
///
/// @param[in] launch_flags
/// The launch flags to use when launching this process.
///
/// @return
/// An Error object indicating the success or failure of making
/// the setting.
//------------------------------------------------------------------
lldb_private::Error
SetLaunchFlags (unsigned int launch_flags);
//------------------------------------------------------------------
/// Launch a process with the current launch settings.
///
/// This method supports running an lldb-gdbserver or similar
/// server in a situation where the startup code has been provided
/// with all the information for a child process to be launched.
///
/// @return
/// An Error object indicating the success or failure of the
/// launch.
//------------------------------------------------------------------
lldb_private::Error
LaunchProcess () override;
//------------------------------------------------------------------
/// Attach to a process.
///
/// This method supports attaching llgs to a process accessible via the
/// configured Platform.
///
/// @return
/// An Error object indicating the success or failure of the
/// attach operation.
//------------------------------------------------------------------
lldb_private::Error
AttachToProcess (lldb::pid_t pid);
//------------------------------------------------------------------
// NativeProcessProtocol::NativeDelegate overrides
//------------------------------------------------------------------
void
InitializeDelegate (lldb_private::NativeProcessProtocol *process) override;
void
ProcessStateChanged (lldb_private::NativeProcessProtocol *process, lldb::StateType state) override;
void
DidExec (lldb_private::NativeProcessProtocol *process) override;
protected:
lldb::PlatformSP m_platform_sp;
lldb::thread_t m_async_thread;
lldb::tid_t m_current_tid;
lldb::tid_t m_continue_tid;
lldb_private::Mutex m_debugged_process_mutex;
lldb_private::NativeProcessProtocolSP m_debugged_process_sp;
lldb::DebuggerSP m_debugger_sp;
Communication m_stdio_communication;
lldb::StateType m_inferior_prev_state;
lldb::DataBufferSP m_active_auxv_buffer_sp;
lldb_private::Mutex m_saved_registers_mutex;
std::unordered_map<uint32_t, lldb::DataBufferSP> m_saved_registers_map;
uint32_t m_next_saved_registers_id;
PacketResult
SendONotification (const char *buffer, uint32_t len);
PacketResult
SendWResponse (lldb_private::NativeProcessProtocol *process);
PacketResult
SendStopReplyPacketForThread (lldb::tid_t tid);
PacketResult
SendStopReasonForState (lldb::StateType process_state, bool flush_on_exit);
PacketResult
Handle_k (StringExtractorGDBRemote &packet);
PacketResult
Handle_qProcessInfo (StringExtractorGDBRemote &packet);
PacketResult
Handle_qC (StringExtractorGDBRemote &packet);
PacketResult
Handle_QSetDisableASLR (StringExtractorGDBRemote &packet);
PacketResult
Handle_QSetWorkingDir (StringExtractorGDBRemote &packet);
PacketResult
Handle_qGetWorkingDir (StringExtractorGDBRemote &packet);
PacketResult
Handle_C (StringExtractorGDBRemote &packet);
PacketResult
Handle_c (StringExtractorGDBRemote &packet);
PacketResult
Handle_vCont (StringExtractorGDBRemote &packet);
PacketResult
Handle_vCont_actions (StringExtractorGDBRemote &packet);
PacketResult
Handle_stop_reason (StringExtractorGDBRemote &packet);
PacketResult
Handle_qRegisterInfo (StringExtractorGDBRemote &packet);
PacketResult
Handle_qfThreadInfo (StringExtractorGDBRemote &packet);
PacketResult
Handle_qsThreadInfo (StringExtractorGDBRemote &packet);
PacketResult
Handle_p (StringExtractorGDBRemote &packet);
PacketResult
Handle_P (StringExtractorGDBRemote &packet);
PacketResult
Handle_H (StringExtractorGDBRemote &packet);
PacketResult
Handle_I (StringExtractorGDBRemote &packet);
PacketResult
Handle_interrupt (StringExtractorGDBRemote &packet);
PacketResult
Handle_m (StringExtractorGDBRemote &packet);
PacketResult
Handle_M (StringExtractorGDBRemote &packet);
PacketResult
Handle_qMemoryRegionInfoSupported (StringExtractorGDBRemote &packet);
PacketResult
Handle_qMemoryRegionInfo (StringExtractorGDBRemote &packet);
PacketResult
Handle_Z (StringExtractorGDBRemote &packet);
PacketResult
Handle_z (StringExtractorGDBRemote &packet);
PacketResult
Handle_s (StringExtractorGDBRemote &packet);
PacketResult
Handle_qXfer_auxv_read (StringExtractorGDBRemote &packet);
PacketResult
Handle_QSaveRegisterState (StringExtractorGDBRemote &packet);
PacketResult
Handle_QRestoreRegisterState (StringExtractorGDBRemote &packet);
PacketResult
Handle_vAttach (StringExtractorGDBRemote &packet);
PacketResult
Handle_D (StringExtractorGDBRemote &packet);
PacketResult
Handle_qThreadStopInfo (StringExtractorGDBRemote &packet);
PacketResult
Handle_qWatchpointSupportInfo (StringExtractorGDBRemote &packet);
void
SetCurrentThreadID (lldb::tid_t tid);
lldb::tid_t
GetCurrentThreadID () const;
void
SetContinueThreadID (lldb::tid_t tid);
lldb::tid_t
GetContinueThreadID () const { return m_continue_tid; }
lldb_private::Error
SetSTDIOFileDescriptor (int fd);
static void
STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_len);
private:
bool
DebuggedProcessReaped (lldb::pid_t pid);
static bool
ReapDebuggedProcess (void *callback_baton,
lldb::pid_t pid,
bool exited,
int signal,
int status);
void
HandleInferiorState_Exited (lldb_private::NativeProcessProtocol *process);
void
HandleInferiorState_Stopped (lldb_private::NativeProcessProtocol *process);
void
FlushInferiorOutput ();
lldb_private::NativeThreadProtocolSP
GetThreadFromSuffix (StringExtractorGDBRemote &packet);
uint32_t
GetNextSavedRegistersID ();
void
MaybeCloseInferiorTerminalConnection ();
void
ClearProcessSpecificData ();
bool
ShouldRedirectInferiorOutputOverGdbRemote (const lldb_private::ProcessLaunchInfo &launch_info) const;
void
RegisterPacketHandlers ();
//------------------------------------------------------------------
// For GDBRemoteCommunicationServerLLGS only
//------------------------------------------------------------------
DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunicationServerLLGS);
};
#endif // liblldb_GDBRemoteCommunicationServerLLGS_h_

View File

@ -0,0 +1,380 @@
//===-- GDBRemoteCommunicationServerPlatform.cpp ----------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "GDBRemoteCommunicationServerPlatform.h"
#include <errno.h>
// C Includes
// C++ Includes
#include <cstring>
#include <chrono>
// Other libraries and framework includes
#include "lldb/Core/Log.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Host/Config.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Target/FileAction.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
// Project includes
#include "Utility/StringExtractorGDBRemote.h"
#include "Utility/UriParser.h"
using namespace lldb;
using namespace lldb_private;
//----------------------------------------------------------------------
// GDBRemoteCommunicationServerPlatform constructor
//----------------------------------------------------------------------
GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform() :
GDBRemoteCommunicationServerCommon ("gdb-remote.server", "gdb-remote.server.rx_packet"),
m_platform_sp (Platform::GetHostPlatform ()),
m_port_map (),
m_port_offset(0)
{
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qC,
&GDBRemoteCommunicationServerPlatform::Handle_qC);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir,
&GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer,
&GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qProcessInfo,
&GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir,
&GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir);
RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_interrupt,
[this](StringExtractorGDBRemote packet,
Error &error,
bool &interrupt,
bool &quit)
{
error.SetErrorString("interrupt received");
interrupt = true;
return PacketResult::Success;
});
}
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform()
{
}
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet)
{
#ifdef _WIN32
return SendErrorResponse(9);
#else
// Spawn a local debugserver as a platform so we can then attach or launch
// a process...
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
if (log)
log->Printf ("LLGSPacketHandler::%s() called", __FUNCTION__);
// Sleep and wait a bit for debugserver to start to listen...
ConnectionFileDescriptor file_conn;
std::string hostname;
// TODO: /tmp/ should not be hardcoded. User might want to override /tmp
// with the TMPDIR environment variable
packet.SetFilePos(::strlen ("qLaunchLLGSPacketHandler;"));
std::string name;
std::string value;
uint16_t port = UINT16_MAX;
while (packet.GetNameColonValue(name, value))
{
if (name.compare ("host") == 0)
hostname.swap(value);
else if (name.compare ("port") == 0)
port = StringConvert::ToUInt32(value.c_str(), 0, 0);
}
if (port == UINT16_MAX)
port = GetNextAvailablePort();
// Spawn a new thread to accept the port that gets bound after
// binding to port 0 (zero).
// ignore the hostname send from the remote end, just use the ip address
// that we're currently communicating with as the hostname
// Spawn a debugserver and try to get the port it listens to.
ProcessLaunchInfo debugserver_launch_info;
if (hostname.empty())
hostname = "127.0.0.1";
if (log)
log->Printf("Launching debugserver with: %s:%u...\n", hostname.c_str(), port);
// Do not run in a new session so that it can not linger after the
// platform closes.
debugserver_launch_info.SetLaunchInSeparateProcessGroup(false);
debugserver_launch_info.SetMonitorProcessCallback(ReapDebugserverProcess, this, false);
std::string platform_scheme;
std::string platform_ip;
int platform_port;
std::string platform_path;
bool ok = UriParser::Parse(GetConnection()->GetURI().c_str(), platform_scheme, platform_ip, platform_port, platform_path);
assert(ok);
Error error = StartDebugserverProcess (
platform_ip.c_str(),
port,
debugserver_launch_info,
port);
lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID();
if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
{
Mutex::Locker locker (m_spawned_pids_mutex);
m_spawned_pids.insert(debugserver_pid);
if (port > 0)
AssociatePortWithProcess(port, debugserver_pid);
}
else
{
if (port > 0)
FreePort (port);
}
if (error.Success())
{
if (log)
log->Printf ("LLGSPacketHandler::%s() debugserver launched successfully as pid %" PRIu64, __FUNCTION__, debugserver_pid);
char response[256];
const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset);
assert (response_len < (int)sizeof(response));
PacketResult packet_result = SendPacketNoLock (response, response_len);
if (packet_result != PacketResult::Success)
{
if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
::kill (debugserver_pid, SIGINT);
}
return packet_result;
}
else
{
if (log)
log->Printf ("LLGSPacketHandler::%s() debugserver launch failed: %s", __FUNCTION__, error.AsCString ());
}
return SendErrorResponse (9);
#endif
}
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo (StringExtractorGDBRemote &packet)
{
lldb::pid_t pid = m_process_launch_info.GetProcessID ();
m_process_launch_info.Clear ();
if (pid == LLDB_INVALID_PROCESS_ID)
return SendErrorResponse (1);
ProcessInstanceInfo proc_info;
if (!Host::GetProcessInfo (pid, proc_info))
return SendErrorResponse (1);
StreamString response;
CreateProcessInfoResponse_DebugServerStyle(proc_info, response);
return SendPacketNoLock (response.GetData (), response.GetSize ());
}
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir (StringExtractorGDBRemote &packet)
{
// If this packet is sent to a platform, then change the current working directory
char cwd[PATH_MAX];
if (getcwd(cwd, sizeof(cwd)) == NULL)
return SendErrorResponse(errno);
StreamString response;
response.PutBytesAsRawHex8(cwd, strlen(cwd));
return SendPacketNoLock(response.GetData(), response.GetSize());
}
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir (StringExtractorGDBRemote &packet)
{
packet.SetFilePos (::strlen ("QSetWorkingDir:"));
std::string path;
packet.GetHexByteString (path);
#ifdef _WIN32
// Not implemented on Windows
return SendUnimplementedResponse ("LLGSPacketHandler::Handle_QSetWorkingDir unimplemented");
#else
// If this packet is sent to a platform, then change the current working directory
if (::chdir(path.c_str()) != 0)
return SendErrorResponse (errno);
return SendOKResponse ();
#endif
}
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerPlatform::Handle_qC (StringExtractorGDBRemote &packet)
{
// NOTE: lldb should now be using qProcessInfo for process IDs. This path here
// should not be used. It is reporting process id instead of thread id. The
// correct answer doesn't seem to make much sense for lldb-platform.
// CONSIDER: flip to "unsupported".
lldb::pid_t pid = m_process_launch_info.GetProcessID();
StreamString response;
response.Printf("QC%" PRIx64, pid);
// If we launch a process and this GDB server is acting as a platform,
// then we need to clear the process launch state so we can start
// launching another process. In order to launch a process a bunch or
// packets need to be sent: environment packets, working directory,
// disable ASLR, and many more settings. When we launch a process we
// then need to know when to clear this information. Currently we are
// selecting the 'qC' packet as that packet which seems to make the most
// sense.
if (pid != LLDB_INVALID_PROCESS_ID)
{
m_process_launch_info.Clear();
}
return SendPacketNoLock (response.GetData(), response.GetSize());
}
bool
GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped (lldb::pid_t pid)
{
Mutex::Locker locker (m_spawned_pids_mutex);
FreePortForProcess(pid);
return m_spawned_pids.erase(pid) > 0;
}
bool
GDBRemoteCommunicationServerPlatform::ReapDebugserverProcess (void *callback_baton,
lldb::pid_t pid,
bool exited,
int signal, // Zero for no signal
int status) // Exit value of process if signal is zero
{
GDBRemoteCommunicationServerPlatform *server = (GDBRemoteCommunicationServerPlatform *)callback_baton;
server->DebugserverProcessReaped (pid);
return true;
}
lldb_private::Error
GDBRemoteCommunicationServerPlatform::LaunchProcess ()
{
if (!m_process_launch_info.GetArguments ().GetArgumentCount ())
return lldb_private::Error ("%s: no process command line specified to launch", __FUNCTION__);
// specify the process monitor if not already set. This should
// generally be what happens since we need to reap started
// processes.
if (!m_process_launch_info.GetMonitorProcessCallback ())
m_process_launch_info.SetMonitorProcessCallback(ReapDebugserverProcess, this, false);
lldb_private::Error error = m_platform_sp->LaunchProcess (m_process_launch_info);
if (!error.Success ())
{
fprintf (stderr, "%s: failed to launch executable %s", __FUNCTION__, m_process_launch_info.GetArguments ().GetArgumentAtIndex (0));
return error;
}
printf ("Launched '%s' as process %" PRIu64 "...\n", m_process_launch_info.GetArguments ().GetArgumentAtIndex (0), m_process_launch_info.GetProcessID());
// add to list of spawned processes. On an lldb-gdbserver, we
// would expect there to be only one.
const auto pid = m_process_launch_info.GetProcessID();
if (pid != LLDB_INVALID_PROCESS_ID)
{
// add to spawned pids
Mutex::Locker locker (m_spawned_pids_mutex);
m_spawned_pids.insert(pid);
}
return error;
}
void
GDBRemoteCommunicationServerPlatform::SetPortMap (PortMap &&port_map)
{
m_port_map = port_map;
}
uint16_t
GDBRemoteCommunicationServerPlatform::GetNextAvailablePort ()
{
if (m_port_map.empty())
return 0; // Bind to port zero and get a port, we didn't have any limitations
for (auto &pair : m_port_map)
{
if (pair.second == LLDB_INVALID_PROCESS_ID)
{
pair.second = ~(lldb::pid_t)LLDB_INVALID_PROCESS_ID;
return pair.first;
}
}
return UINT16_MAX;
}
bool
GDBRemoteCommunicationServerPlatform::AssociatePortWithProcess (uint16_t port, lldb::pid_t pid)
{
PortMap::iterator pos = m_port_map.find(port);
if (pos != m_port_map.end())
{
pos->second = pid;
return true;
}
return false;
}
bool
GDBRemoteCommunicationServerPlatform::FreePort (uint16_t port)
{
PortMap::iterator pos = m_port_map.find(port);
if (pos != m_port_map.end())
{
pos->second = LLDB_INVALID_PROCESS_ID;
return true;
}
return false;
}
bool
GDBRemoteCommunicationServerPlatform::FreePortForProcess (lldb::pid_t pid)
{
if (!m_port_map.empty())
{
for (auto &pair : m_port_map)
{
if (pair.second == pid)
{
pair.second = LLDB_INVALID_PROCESS_ID;
return true;
}
}
}
return false;
}
void
GDBRemoteCommunicationServerPlatform::SetPortOffset (uint16_t port_offset)
{
m_port_offset = port_offset;
}

View File

@ -0,0 +1,96 @@
//===-- GDBRemoteCommunicationServerPlatform.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_GDBRemoteCommunicationServerPlatform_h_
#define liblldb_GDBRemoteCommunicationServerPlatform_h_
#include "GDBRemoteCommunicationServerCommon.h"
class GDBRemoteCommunicationServerPlatform :
public GDBRemoteCommunicationServerCommon
{
public:
typedef std::map<uint16_t, lldb::pid_t> PortMap;
GDBRemoteCommunicationServerPlatform();
virtual
~GDBRemoteCommunicationServerPlatform();
lldb_private::Error
LaunchProcess () override;
// Set both ports to zero to let the platform automatically bind to
// a port chosen by the OS.
void
SetPortMap (PortMap &&port_map);
//----------------------------------------------------------------------
// If we are using a port map where we can only use certain ports,
// get the next available port.
//
// If we are using a port map and we are out of ports, return UINT16_MAX
//
// If we aren't using a port map, return 0 to indicate we should bind to
// port 0 and then figure out which port we used.
//----------------------------------------------------------------------
uint16_t
GetNextAvailablePort ();
bool
AssociatePortWithProcess (uint16_t port, lldb::pid_t pid);
bool
FreePort (uint16_t port);
bool
FreePortForProcess (lldb::pid_t pid);
void
SetPortOffset (uint16_t port_offset);
protected:
lldb::PlatformSP m_platform_sp;
PortMap m_port_map;
uint16_t m_port_offset;
PacketResult
Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet);
PacketResult
Handle_qProcessInfo (StringExtractorGDBRemote &packet);
PacketResult
Handle_qGetWorkingDir (StringExtractorGDBRemote &packet);
PacketResult
Handle_QSetWorkingDir (StringExtractorGDBRemote &packet);
PacketResult
Handle_qC (StringExtractorGDBRemote &packet);
private:
bool
DebugserverProcessReaped (lldb::pid_t pid);
static bool
ReapDebugserverProcess (void *callback_baton,
lldb::pid_t pid,
bool exited,
int signal,
int status);
//------------------------------------------------------------------
// For GDBRemoteCommunicationServerPlatform only
//------------------------------------------------------------------
DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunicationServerPlatform);
};
#endif // liblldb_GDBRemoteCommunicationServerPlatform_h_

View File

@ -268,7 +268,7 @@ ProcessGDBRemote::CanDebug (Target &target, bool plugin_specified_by_name)
ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) :
Process (target, listener),
m_flags (0),
m_gdb_comm(false),
m_gdb_comm (),
m_debugserver_pid (LLDB_INVALID_PROCESS_ID),
m_last_stop_packet (),
m_last_stop_packet_mutex (Mutex::eMutexTypeNormal),

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0600"
LastUpgradeVersion = "0610"
version = "1.8">
<BuildAction
parallelizeBuildables = "NO"

View File

@ -38,7 +38,7 @@
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h"
#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h"
#include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h"
#ifndef LLGS_PROGRAM_NAME
@ -203,7 +203,7 @@ setup_platform (const std::string &platform_name)
}
void
handle_attach_to_pid (GDBRemoteCommunicationServer &gdb_server, lldb::pid_t pid)
handle_attach_to_pid (GDBRemoteCommunicationServerLLGS &gdb_server, lldb::pid_t pid)
{
Error error = gdb_server.AttachToProcess (pid);
if (error.Fail ())
@ -214,13 +214,13 @@ handle_attach_to_pid (GDBRemoteCommunicationServer &gdb_server, lldb::pid_t pid)
}
void
handle_attach_to_process_name (GDBRemoteCommunicationServer &gdb_server, const std::string &process_name)
handle_attach_to_process_name (GDBRemoteCommunicationServerLLGS &gdb_server, const std::string &process_name)
{
// FIXME implement.
}
void
handle_attach (GDBRemoteCommunicationServer &gdb_server, const std::string &attach_target)
handle_attach (GDBRemoteCommunicationServerLLGS &gdb_server, const std::string &attach_target)
{
assert (!attach_target.empty () && "attach_target cannot be empty");
@ -236,7 +236,7 @@ handle_attach (GDBRemoteCommunicationServer &gdb_server, const std::string &atta
}
void
handle_launch (GDBRemoteCommunicationServer &gdb_server, int argc, const char *const argv[])
handle_launch (GDBRemoteCommunicationServerLLGS &gdb_server, int argc, const char *const argv[])
{
Error error;
error = gdb_server.SetLaunchArguments (argv, argc);
@ -326,7 +326,7 @@ writePortToPipe (const char *const named_pipe_path, const uint16_t port)
}
void
ConnectToRemote (GDBRemoteCommunicationServer &gdb_server, bool reverse_connect, const char *const host_and_port, const char *const progname, const char *const named_pipe_path)
ConnectToRemote (GDBRemoteCommunicationServerLLGS &gdb_server, bool reverse_connect, const char *const host_and_port, const char *const progname, const char *const named_pipe_path)
{
Error error;
@ -663,11 +663,10 @@ main (int argc, char *argv[])
// Run any commands requested.
run_lldb_commands (debugger_sp, lldb_commands);
// Setup the platform that GDBRemoteCommunicationServer will use.
// Setup the platform that GDBRemoteCommunicationServerLLGS will use.
lldb::PlatformSP platform_sp = setup_platform (platform_name);
const bool is_platform = false;
GDBRemoteCommunicationServer gdb_server (is_platform, platform_sp, debugger_sp);
GDBRemoteCommunicationServerLLGS gdb_server (platform_sp, debugger_sp);
const char *const host_and_port = argv[0];
argc -= 1;

View File

@ -33,8 +33,9 @@
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h"
#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h"
#include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h"
using namespace lldb;
using namespace lldb_private;
@ -115,7 +116,7 @@ main (int argc, char *argv[])
debugger_sp->SetOutputFileHandle(stdout, false);
debugger_sp->SetErrorFileHandle(stderr, false);
GDBRemoteCommunicationServer::PortMap gdbserver_portmap;
GDBRemoteCommunicationServerPlatform::PortMap gdbserver_portmap;
int min_gdbserver_port = 0;
int max_gdbserver_port = 0;
uint16_t port_offset = 0;
@ -246,14 +247,14 @@ main (int argc, char *argv[])
do {
GDBRemoteCommunicationServer gdb_server (true);
GDBRemoteCommunicationServerPlatform platform;
if (port_offset > 0)
gdb_server.SetPortOffset(port_offset);
platform.SetPortOffset(port_offset);
if (!gdbserver_portmap.empty())
{
gdb_server.SetPortMap(std::move(gdbserver_portmap));
platform.SetPortMap(std::move(gdbserver_portmap));
}
if (!listen_host_port.empty())
@ -268,7 +269,7 @@ main (int argc, char *argv[])
if (conn_ap->Connect(connect_url.c_str(), &error) == eConnectionStatusSuccess)
{
printf ("Connection established.\n");
gdb_server.SetConnection (conn_ap.release());
platform.SetConnection (conn_ap.release());
}
else
{
@ -276,16 +277,16 @@ main (int argc, char *argv[])
}
}
if (gdb_server.IsConnected())
if (platform.IsConnected())
{
// After we connected, we need to get an initial ack from...
if (gdb_server.HandshakeWithClient(&error))
if (platform.HandshakeWithClient(&error))
{
bool interrupt = false;
bool done = false;
while (!interrupt && !done)
{
if (gdb_server.GetPacketAndSendResponse (UINT32_MAX, error, interrupt, done) != GDBRemoteCommunication::PacketResult::Success)
if (platform.GetPacketAndSendResponse (UINT32_MAX, error, interrupt, done) != GDBRemoteCommunication::PacketResult::Success)
break;
}