diff --git a/lldb/include/lldb/Target/Platform.h b/lldb/include/lldb/Target/Platform.h index 5ac7b3d519a4..98003e43d124 100644 --- a/lldb/include/lldb/Target/Platform.h +++ b/lldb/include/lldb/Target/Platform.h @@ -115,6 +115,23 @@ namespace lldb_private { uint32_t minor, uint32_t update); + const char * + GetInstanceName () + { + if (IsHost()) + return "localhost"; + + if (IsConnected()) + { + if (m_remote_instance_name.empty()) + GetRemoteInstanceName (); + + if (!m_remote_instance_name.empty()) + return m_remote_instance_name.c_str(); + } + return "remote"; + } + virtual const char * GetDescription () = 0; @@ -164,13 +181,24 @@ protected: //------------------------------------------------------------------ public: virtual Error - GetFile (const FileSpec &platform_file, FileSpec &local_file); + GetFile (const FileSpec &platform_file, + const UUID *uuid_ptr, + FileSpec &local_file); virtual Error - ConnectRemote (const char *remote_url); + ConnectRemote (Args& args); virtual Error - DisconnectRemote (const lldb::PlatformSP &platform_sp); + DisconnectRemote (); + + // Remote subclasses should override this and return a valid instance + // name if connected. + virtual const char * + GetRemoteInstanceName () + { + return NULL; + } + //------------------------------------------------------------------ /// Get the platform's supported architectures in the order in which @@ -356,6 +384,7 @@ public: bool m_os_version_set_while_connected; bool m_system_arch_set_while_connected; std::string m_remote_url; + std::string m_remote_instance_name; uint32_t m_major_os_version; uint32_t m_minor_os_version; uint32_t m_update_os_version; diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj index 3b9366435908..cbe416fd904a 100644 --- a/lldb/lldb.xcodeproj/project.pbxproj +++ b/lldb/lldb.xcodeproj/project.pbxproj @@ -13,6 +13,8 @@ 262CFC7711A4510000946C6C /* debugserver in Resources */ = {isa = PBXBuildFile; fileRef = 26CE05A0115C31E50022F371 /* debugserver */; }; 26368A3C126B697600E8659F /* darwin-debug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26368A3B126B697600E8659F /* darwin-debug.cpp */; }; 26368AF7126B960500E8659F /* darwin-debug in Resources */ = {isa = PBXBuildFile; fileRef = 26579F68126A25920007C5CB /* darwin-debug */; }; + 264A97BF133918BC0017F0BE /* PlatformRemoteGDBServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 264A97BD133918BC0017F0BE /* PlatformRemoteGDBServer.cpp */; }; + 264A97C0133918BC0017F0BE /* PlatformRemoteGDBServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 264A97BE133918BC0017F0BE /* PlatformRemoteGDBServer.h */; }; 265ABF6310F42EE900531910 /* DebugSymbols.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 265ABF6210F42EE900531910 /* DebugSymbols.framework */; }; 2668020E115FD12C008E1FE4 /* lldb-defines.h in Headers */ = {isa = PBXBuildFile; fileRef = 26BC7C2510F1B3BC00F91463 /* lldb-defines.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2668020F115FD12C008E1FE4 /* lldb-enumerations.h in Headers */ = {isa = PBXBuildFile; fileRef = 26BC7C2610F1B3BC00F91463 /* lldb-enumerations.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -615,6 +617,8 @@ 264723A511FA076E00DE380C /* CleanUp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CleanUp.h; path = include/lldb/Utility/CleanUp.h; sourceTree = ""; }; 264A43BB1320B3B4005B4096 /* Platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Platform.h; path = include/lldb/Target/Platform.h; sourceTree = ""; }; 264A43BD1320BCEB005B4096 /* Platform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Platform.cpp; path = source/Target/Platform.cpp; sourceTree = ""; }; + 264A97BD133918BC0017F0BE /* PlatformRemoteGDBServer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PlatformRemoteGDBServer.cpp; path = "gdb-server/PlatformRemoteGDBServer.cpp"; sourceTree = ""; }; + 264A97BE133918BC0017F0BE /* PlatformRemoteGDBServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PlatformRemoteGDBServer.h; path = "gdb-server/PlatformRemoteGDBServer.h"; sourceTree = ""; }; 264AD83711095BA600E0B039 /* CommandObjectLog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectLog.cpp; path = source/Commands/CommandObjectLog.cpp; sourceTree = ""; }; 264AD83911095BBD00E0B039 /* CommandObjectLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectLog.h; path = source/Commands/CommandObjectLog.h; sourceTree = ""; }; 26579F68126A25920007C5CB /* darwin-debug */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "darwin-debug"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -1630,6 +1634,15 @@ name = API; sourceTree = ""; }; + 264A97BC133918A30017F0BE /* GDB Server */ = { + isa = PBXGroup; + children = ( + 264A97BD133918BC0017F0BE /* PlatformRemoteGDBServer.cpp */, + 264A97BE133918BC0017F0BE /* PlatformRemoteGDBServer.h */, + ); + name = "GDB Server"; + sourceTree = ""; + }; 26579F55126A255E0007C5CB /* darwin-debug */ = { isa = PBXGroup; children = ( @@ -2224,6 +2237,7 @@ 26C5577E132575B6008FD8FE /* Platform */ = { isa = PBXGroup; children = ( + 264A97BC133918A30017F0BE /* GDB Server */, 26C5577F132575C8008FD8FE /* MacOSX */, ); path = Platform; @@ -2497,6 +2511,7 @@ 2689001013353DB600698AC0 /* WatchpointLocation.h in Headers */, 26744EF21338317700EF765A /* GDBRemoteCommunicationClient.h in Headers */, 26744EF41338317700EF765A /* GDBRemoteCommunicationServer.h in Headers */, + 264A97C0133918BC0017F0BE /* PlatformRemoteGDBServer.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3054,6 +3069,7 @@ 26B1FCC21338115F002886E2 /* Host.mm in Sources */, 26744EF11338317700EF765A /* GDBRemoteCommunicationClient.cpp in Sources */, 26744EF31338317700EF765A /* GDBRemoteCommunicationServer.cpp in Sources */, + 264A97BF133918BC0017F0BE /* PlatformRemoteGDBServer.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3569,12 +3585,14 @@ isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"", ); GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_CPP_RTTI = NO; + GCC_INLINES_ARE_PRIVATE_EXTERN = NO; GCC_MODEL_TUNING = G5; GCC_OPTIMIZATION_LEVEL = 0; INSTALL_PATH = /usr/local/bin; @@ -3594,12 +3612,14 @@ isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = YES; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"", ); GCC_ENABLE_CPP_RTTI = NO; + GCC_INLINES_ARE_PRIVATE_EXTERN = NO; GCC_MODEL_TUNING = G5; INSTALL_PATH = /usr/local/bin; OTHER_LDFLAGS = ( @@ -3618,11 +3638,13 @@ 26DC6A141337FE6A00FF7998 /* BuildAndIntegration */ = { isa = XCBuildConfiguration; buildSettings = { + DEAD_CODE_STRIPPING = YES; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"", ); GCC_ENABLE_CPP_RTTI = NO; + GCC_INLINES_ARE_PRIVATE_EXTERN = NO; GCC_MODEL_TUNING = G5; INSTALL_PATH = /usr/local/bin; OTHER_LDFLAGS = ( diff --git a/lldb/source/Commands/CommandObjectPlatform.cpp b/lldb/source/Commands/CommandObjectPlatform.cpp index 97eb0a4e5fcf..dc6b4efb8dcf 100644 --- a/lldb/source/Commands/CommandObjectPlatform.cpp +++ b/lldb/source/Commands/CommandObjectPlatform.cpp @@ -281,6 +281,137 @@ public: }; +//---------------------------------------------------------------------- +// "platform connect " +//---------------------------------------------------------------------- +class CommandObjectPlatformConnect : public CommandObject +{ +public: + CommandObjectPlatformConnect (CommandInterpreter &interpreter) : + CommandObject (interpreter, + "platform connect", + "Connect a platform by name to be the currently selected platform.", + "platform connect ", + 0) + { + } + + virtual + ~CommandObjectPlatformConnect () + { + } + + virtual bool + Execute (Args& args, CommandReturnObject &result) + { + Stream &ostrm = result.GetOutputStream(); + + // Get rid of the "connect" from the args and leave the rest to the platform + args.Shift(); + PlatformSP selected_platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); + if (selected_platform_sp) + { + Error error (selected_platform_sp->ConnectRemote (args)); + if (error.Success()) + { + ostrm.Printf ("Connected to \"%s\"\n", selected_platform_sp->GetInstanceName()); + selected_platform_sp->GetStatus (ostrm); + result.SetStatus (eReturnStatusSuccessFinishResult); + } + else + { + result.AppendErrorWithFormat ("connection failed: %s", error.AsCString()); + result.SetStatus (eReturnStatusFailed); + } + } + else + { + result.AppendError ("no platform us currently selected"); + result.SetStatus (eReturnStatusFailed); + } + return result.Succeeded(); + } +}; + +//---------------------------------------------------------------------- +// "platform disconnect" +//---------------------------------------------------------------------- +class CommandObjectPlatformDisconnect : public CommandObject +{ +public: + CommandObjectPlatformDisconnect (CommandInterpreter &interpreter) : + CommandObject (interpreter, + "platform disconnect", + "Disconnect a platform by name to be the currently selected platform.", + "platform disconnect", + 0) + { + } + + virtual + ~CommandObjectPlatformDisconnect () + { + } + + virtual bool + Execute (Args& args, CommandReturnObject &result) + { + PlatformSP selected_platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); + if (selected_platform_sp) + { + if (args.GetArgumentCount() == 0) + { + Error error; + + if (selected_platform_sp->IsConnected()) + { + // Cache the instance name if there is one since we are + // about to disconnect and the name might go with it. + const char *instance_name_cstr = selected_platform_sp->GetInstanceName(); + std::string instance_name; + if (instance_name_cstr) + instance_name.assign (instance_name_cstr); + + error = selected_platform_sp->DisconnectRemote (); + if (error.Success()) + { + Stream &ostrm = result.GetOutputStream(); + if (instance_name.empty()) + ostrm.Printf ("Disconnected from \"%s\"\n", selected_platform_sp->GetShortPluginName()); + else + ostrm.Printf ("Disconnected from \"%s\"\n", instance_name.c_str()); + result.SetStatus (eReturnStatusSuccessFinishResult); + } + else + { + result.AppendErrorWithFormat ("disconnect failed: %s", error.AsCString()); + result.SetStatus (eReturnStatusFailed); + } + } + else + { + // Not connected... + result.AppendError ("not connected."); + result.SetStatus (eReturnStatusFailed); + } + } + else + { + // Bad args + result.AppendError ("\"platform disconnect\" doesn't take any arguments"); + result.SetStatus (eReturnStatusFailed); + } + } + else + { + result.AppendError ("no platform us currently selected"); + result.SetStatus (eReturnStatusFailed); + } + return result.Succeeded(); + } +}; + + //---------------------------------------------------------------------- // CommandObjectPlatform constructor @@ -289,12 +420,14 @@ CommandObjectPlatform::CommandObjectPlatform(CommandInterpreter &interpreter) : CommandObjectMultiword (interpreter, "platform", "A set of commands to manage and create platforms.", - "platform [create|list|status|select] ...") + "platform [connect|create|disconnect|list|status|select] ...") { LoadSubCommand ("create", CommandObjectSP (new CommandObjectPlatformCreate (interpreter))); LoadSubCommand ("list" , CommandObjectSP (new CommandObjectPlatformList (interpreter))); LoadSubCommand ("select", CommandObjectSP (new CommandObjectPlatformSelect (interpreter))); LoadSubCommand ("status", CommandObjectSP (new CommandObjectPlatformStatus (interpreter))); + LoadSubCommand ("connect", CommandObjectSP (new CommandObjectPlatformConnect (interpreter))); + LoadSubCommand ("disconnect", CommandObjectSP (new CommandObjectPlatformDisconnect (interpreter))); } diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp index 8c1ef1d5c9d3..ba7be39b1bdd 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp @@ -1,4 +1,4 @@ -//===-- Platform.cpp --------------------------------------------*- C++ -*-===// +//===-- PlatformMacOSX.cpp --------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -138,7 +138,9 @@ PlatformMacOSX::ResolveExecutable (const FileSpec &exe_file, } Error -PlatformMacOSX::GetFile (const FileSpec &platform_file, FileSpec &local_file) +PlatformMacOSX::GetFile (const FileSpec &platform_file, + const UUID *uuid_ptr, + FileSpec &local_file) { // Default to the local case local_file = platform_file; @@ -193,11 +195,7 @@ PlatformMacOSX::GetStatus (Stream &strm) /// Default Constructor //------------------------------------------------------------------ PlatformMacOSX::PlatformMacOSX () : -#if defined (__APPLE__) Platform(true) // This is the local host platform -#else - Platform(false) // This is a remote platform -#endif { } diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.h b/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.h index 4b0db1584a42..b0e3d1ad9874 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.h +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.h @@ -73,7 +73,9 @@ namespace lldb_private { GetStatus (Stream &strm); virtual Error - GetFile (const FileSpec &platform_file, FileSpec &local_file); + GetFile (const FileSpec &platform_file, + const UUID *uuid_ptr, + FileSpec &local_file); virtual uint32_t FindProcessesByName (const char *name_match, @@ -96,4 +98,4 @@ namespace lldb_private { }; } // namespace lldb_private -#endif // liblldb_Platform_h_ +#endif // liblldb_PlatformMacOSX_h_ diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp index c0bece1f207c..fa6fcdc3d4aa 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp @@ -1,4 +1,4 @@ -//===-- Platform.cpp --------------------------------------------*- C++ -*-===// +//===-- PlatformRemoteiOS.cpp -----------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -27,18 +27,28 @@ using namespace lldb; using namespace lldb_private; + +static bool g_initialized = false; void PlatformRemoteiOS::Initialize () { - static bool g_initialized = false; - if (g_initialized == false) { g_initialized = true; - PluginManager::RegisterPlugin (GetShortPluginNameStatic(), - GetDescriptionStatic(), - CreateInstance); + PluginManager::RegisterPlugin (PlatformRemoteiOS::GetShortPluginNameStatic(), + PlatformRemoteiOS::GetDescriptionStatic(), + PlatformRemoteiOS::CreateInstance); + } +} + +void +PlatformRemoteiOS::Terminate () +{ + if (g_initialized) + { + g_initialized = false; + PluginManager::UnregisterPlugin (PlatformRemoteiOS::CreateInstance); } } @@ -48,10 +58,6 @@ PlatformRemoteiOS::CreateInstance () return new PlatformRemoteiOS (); } -void -PlatformRemoteiOS::Terminate () -{ -} const char * PlatformRemoteiOS::GetPluginNameStatic () @@ -358,6 +364,7 @@ PlatformRemoteiOS::GetDeviceSupportDirectoryForOSVersion() Error PlatformRemoteiOS::GetFile (const FileSpec &platform_file, + const UUID *uuid_ptr, FileSpec &local_file) { Error error; @@ -442,6 +449,29 @@ PlatformRemoteiOS::GetProcessInfo (lldb::pid_t pid, ProcessInfo &process_info) return false; } +const char * +PlatformRemoteiOS::GetRemoteInstanceName () +{ + if (m_remote_instance_name.empty()) + { + const char *device_support_dir = GetDeviceSupportDirectory(); + if (device_support_dir) + { + std::string latest_device_support_dir; + latest_device_support_dir.assign (device_support_dir); + latest_device_support_dir.append ("/Platforms/iPhoneOS.platform/DeviceSupport/Latest"); + const bool resolve_path = true; + FileSpec file_spec (m_device_support_directory_for_os_version.c_str(), resolve_path); + // We are using the resolved basename of the "Latest" symlink (which + // is usually the latest and greatest SDK version and the update + // which is something like: "4.0 (8A123)" + if (file_spec.Exists()) + m_remote_instance_name.assign (file_spec.GetFilename().GetCString()); + } + } + return m_remote_instance_name.c_str(); +} + bool PlatformRemoteiOS::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch) { @@ -549,6 +579,13 @@ PlatformRemoteiOS::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch return false; } +bool +PlatformRemoteiOS::FetchRemoteOSVersion () +{ + return false; +} + + size_t PlatformRemoteiOS::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site) { @@ -610,3 +647,35 @@ PlatformRemoteiOS::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSi return 0; } + +Error +PlatformRemoteiOS::ConnectRemote (Args& args) +{ + Error error; + error.SetErrorStringWithFormat ("'platform connect' is not implemented yet for platform '%s'", GetShortPluginNameStatic()); + +// if (args.GetArgumentCount() == 1) +// { +// const char *remote_url = args.GetArgumentAtIndex(0); +// ConnectionStatus status = m_gdb_client.Connect(remote_url, &error); +// if (status == eConnectionStatusSuccess) +// { +// m_gdb_client.GetHostInfo(); +// } +// } +// else +// { +// error.SetErrorString ("\"platform connect\" takes a single argument: "); +// } + + return error; +} + +Error +PlatformRemoteiOS::DisconnectRemote () +{ + Error error; + error.SetErrorStringWithFormat ("'platform disconnect' is not implemented yet for platform '%s'", GetShortPluginNameStatic()); +// m_gdb_client.Disconnect(&error); + return error; +} diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h b/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h index 5c0f075b41c8..36f4c004597c 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h @@ -85,7 +85,9 @@ namespace lldb_private { GetStatus (Stream &strm); virtual Error - GetFile (const FileSpec &platform_file, FileSpec &local_file); + GetFile (const FileSpec &platform_file, + const UUID *uuid_ptr, + FileSpec &local_file); virtual uint32_t FindProcessesByName (const char *name_match, @@ -102,6 +104,19 @@ namespace lldb_private { GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site); + virtual bool + FetchRemoteOSVersion (); + + virtual Error + ConnectRemote (Args& args); + + virtual Error + DisconnectRemote (); + + virtual const char * + GetRemoteInstanceName (); + + protected: std::string m_device_support_directory; std::string m_device_support_directory_for_os_version; @@ -120,4 +135,4 @@ namespace lldb_private { }; } // namespace lldb_private -#endif // liblldb_Platform_h_ +#endif // liblldb_PlatformRemoteiOS_h_ diff --git a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp new file mode 100644 index 000000000000..f8a73a3826de --- /dev/null +++ b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp @@ -0,0 +1,240 @@ +//===-- PlatformRemoteGDBServer.cpp -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "PlatformRemoteGDBServer.h" + +// C Includes +#include + +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/Error.h" +#include "lldb/Breakpoint/BreakpointLocation.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleList.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Host/FileSpec.h" +#include "lldb/Host/Host.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" + +using namespace lldb; +using namespace lldb_private; + +static bool g_initialized = false; + +void +PlatformRemoteGDBServer::Initialize () +{ + if (g_initialized == false) + { + g_initialized = true; + PluginManager::RegisterPlugin (PlatformRemoteGDBServer::GetShortPluginNameStatic(), + PlatformRemoteGDBServer::GetDescriptionStatic(), + PlatformRemoteGDBServer::CreateInstance); + } +} + +void +PlatformRemoteGDBServer::Terminate () +{ + if (g_initialized) + { + g_initialized = false; + PluginManager::UnregisterPlugin (PlatformRemoteGDBServer::CreateInstance); + } +} + +Platform* +PlatformRemoteGDBServer::CreateInstance () +{ + return new PlatformRemoteGDBServer (); +} + +const char * +PlatformRemoteGDBServer::GetShortPluginNameStatic() +{ + return "remote-gdb-server"; +} + +const char * +PlatformRemoteGDBServer::GetDescriptionStatic() +{ + return "A platform that uses the GDB remote protocol as the communication transport."; +} + +const char * +PlatformRemoteGDBServer::GetDescription () +{ + if (m_platform_description.empty()) + { + if (IsConnected()) + { + // Send the get description packet + } + } + + if (!m_platform_description.empty()) + return m_platform_description.c_str(); + return GetDescriptionStatic(); +} + +Error +PlatformRemoteGDBServer::ResolveExecutable (const FileSpec &exe_file, + const ArchSpec &exe_arch, + lldb::ModuleSP &exe_module_sp) +{ + Error error; + error.SetErrorString ("PlatformRemoteGDBServer::ResolveExecutable() is unimplemented"); + return error; +} + +Error +PlatformRemoteGDBServer::GetFile (const FileSpec &platform_file, + const UUID *uuid_ptr, + FileSpec &local_file) +{ + // Default to the local case + local_file = platform_file; + return Error(); +} + + +void +PlatformRemoteGDBServer::GetStatus (Stream &strm) +{ + char sysctlstring[1024]; + size_t datalen; + int mib[CTL_MAXNAME]; + + uint32_t major = UINT32_MAX; + uint32_t minor = UINT32_MAX; + uint32_t update = UINT32_MAX; + strm.PutCString("Remote GDB server platform"); + if (GetOSVersion(major, minor, update)) + { + strm.Printf("OS version: %u", major); + if (minor != UINT32_MAX) + strm.Printf(".%u", minor); + if (update != UINT32_MAX) + strm.Printf(".%u", update); + + + mib[0] = CTL_KERN; + mib[1] = KERN_OSVERSION; + datalen = sizeof(sysctlstring); + if (::sysctl (mib, 2, sysctlstring, &datalen, NULL, 0) == 0) + { + sysctlstring[datalen] = '\0'; + strm.Printf(" (%s)", sysctlstring); + } + + strm.EOL(); + } + + mib[0] = CTL_KERN; + mib[1] = KERN_VERSION; + datalen = sizeof(sysctlstring); + if (::sysctl (mib, 2, sysctlstring, &datalen, NULL, 0) == 0) + { + sysctlstring[datalen] = '\0'; + strm.Printf("Kernel version: %s\n", sysctlstring); + } +} + + +//------------------------------------------------------------------ +/// Default Constructor +//------------------------------------------------------------------ +PlatformRemoteGDBServer::PlatformRemoteGDBServer () : + Platform(false) // This is a remote platform +{ +} + +//------------------------------------------------------------------ +/// Destructor. +/// +/// The destructor is virtual since this class is designed to be +/// inherited from by the plug-in instance. +//------------------------------------------------------------------ +PlatformRemoteGDBServer::~PlatformRemoteGDBServer() +{ +} + +uint32_t +PlatformRemoteGDBServer::FindProcessesByName (const char *name_match, + lldb::NameMatchType name_match_type, + ProcessInfoList &process_infos) +{ + return 0; +} + +bool +PlatformRemoteGDBServer::GetProcessInfo (lldb::pid_t pid, ProcessInfo &process_info) +{ + return false; +} + +bool +PlatformRemoteGDBServer::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch) +{ + return false; +} + +size_t +PlatformRemoteGDBServer::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site) +{ + // This isn't needed if the z/Z packets are supported in the GDB remote + // server. But we might need a packet to detect this. + return 0; +} + +bool +PlatformRemoteGDBServer::FetchRemoteOSVersion () +{ + return false; +} + +Error +PlatformRemoteGDBServer::ConnectRemote (Args& args) +{ + Error error; + if (args.GetArgumentCount() == 1) + { + const char *remote_url = args.GetArgumentAtIndex(0); + ConnectionStatus status = m_gdb_client.Connect(remote_url, &error); + if (status == eConnectionStatusSuccess) + { + m_gdb_client.GetHostInfo(); + } + } + else + { + error.SetErrorString ("\"platform connect\" takes a single argument: "); + } + + return error; +} + +Error +PlatformRemoteGDBServer::DisconnectRemote () +{ + Error error; + m_gdb_client.Disconnect(&error); + return error; +} + +const char * +PlatformRemoteGDBServer::GetRemoteInstanceName () +{ + return NULL; +} + diff --git a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h new file mode 100644 index 000000000000..6c322d38c9c3 --- /dev/null +++ b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h @@ -0,0 +1,127 @@ +//===-- PlatformRemoteGDBServer.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_PlatformRemoteGDBServer_h_ +#define liblldb_PlatformRemoteGDBServer_h_ + +// C Includes +// C++ Includes +#include + +// Other libraries and framework includes +// Project includes +#include "lldb/Target/Platform.h" +#include "../../Process/gdb-remote/GDBRemoteCommunicationClient.h" + +namespace lldb_private { + + class PlatformRemoteGDBServer : public Platform + { + public: + + static void + Initialize (); + + static void + Terminate (); + + static Platform* + CreateInstance (); + + static const char * + GetShortPluginNameStatic(); + + static const char * + GetDescriptionStatic(); + + + PlatformRemoteGDBServer (); + + virtual + ~PlatformRemoteGDBServer(); + + //------------------------------------------------------------ + // lldb_private::PluginInterface functions + //------------------------------------------------------------ + virtual const char * + GetPluginName() + { + return "PlatformRemoteGDBServer"; + } + + virtual const char * + GetShortPluginName() + { + return GetShortPluginNameStatic(); + } + + virtual uint32_t + GetPluginVersion() + { + return 1; + } + + + //------------------------------------------------------------ + // lldb_private::Platform functions + //------------------------------------------------------------ + virtual Error + ResolveExecutable (const FileSpec &exe_file, + const ArchSpec &arch, + lldb::ModuleSP &module_sp); + + virtual const char * + GetDescription (); + + virtual void + GetStatus (Stream &strm); + + virtual Error + GetFile (const FileSpec &platform_file, + const UUID *uuid_ptr, + FileSpec &local_file); + + virtual uint32_t + FindProcessesByName (const char *name_match, + lldb::NameMatchType name_match_type, + ProcessInfoList &process_infos); + + virtual bool + GetProcessInfo (lldb::pid_t pid, ProcessInfo &proc_info); + + virtual bool + GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch); + + virtual size_t + GetSoftwareBreakpointTrapOpcode (Target &target, + BreakpointSite *bp_site); + + virtual bool + FetchRemoteOSVersion (); + + virtual Error + ConnectRemote (Args& args); + + virtual Error + DisconnectRemote (); + + virtual const char * + GetRemoteInstanceName (); + + protected: + GDBRemoteCommunicationClient m_gdb_client; + std::string m_platform_description; // After we connect we can get a more complete description of what we are connected to + + private: + DISALLOW_COPY_AND_ASSIGN (PlatformRemoteGDBServer); + + }; +} // namespace lldb_private + +#endif // liblldb_PlatformRemoteGDBServer_h_ diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index b4fb6f2ddfe3..7700ab2b7f5e 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -50,11 +50,7 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient() : m_async_packet (), m_async_response (), m_async_signal (-1), - m_arch(), - m_os(), - m_vendor(), - m_byte_order(lldb::endian::InlHostByteOrder()), - m_pointer_byte_size(0) + m_host_arch() { m_rx_packet_listener.StartListeningForEvents(this, Communication::eBroadcastBitPacketAvailable | @@ -102,11 +98,7 @@ GDBRemoteCommunicationClient::ResetDiscoverableSettings() m_supports_vCont_C = eLazyBoolCalculate; m_supports_vCont_s = eLazyBoolCalculate; m_supports_vCont_S = eLazyBoolCalculate; - m_arch.Clear(); - m_os.Clear(); - m_vendor.Clear(); - m_byte_order = lldb::endian::InlHostByteOrder(); - m_pointer_byte_size = 0; + m_host_arch.Clear(); } @@ -690,7 +682,11 @@ GDBRemoteCommunicationClient::GetHostInfo () std::string value; uint32_t cpu = LLDB_INVALID_CPUTYPE; uint32_t sub = 0; - + std::string arch_name; + std::string os_name; + std::string vendor_name; + uint32_t pointer_byte_size = 0; + ByteOrder byte_order = eByteOrderInvalid; while (response.GetNameColonValue(name, value)) { if (name.compare("cputype") == 0) @@ -703,32 +699,69 @@ GDBRemoteCommunicationClient::GetHostInfo () // exception count in big endian hex sub = Args::StringToUInt32 (value.c_str(), 0, 0); } + else if (name.compare("arch") == 0) + { + arch_name.swap (value); + } else if (name.compare("ostype") == 0) { - // exception data in big endian hex - m_os.SetCString(value.c_str()); + os_name.swap (value); } else if (name.compare("vendor") == 0) { - m_vendor.SetCString(value.c_str()); + vendor_name.swap(value); } else if (name.compare("endian") == 0) { if (value.compare("little") == 0) - m_byte_order = eByteOrderLittle; + byte_order = eByteOrderLittle; else if (value.compare("big") == 0) - m_byte_order = eByteOrderBig; + byte_order = eByteOrderBig; else if (value.compare("pdp") == 0) - m_byte_order = eByteOrderPDP; + byte_order = eByteOrderPDP; } else if (name.compare("ptrsize") == 0) { - m_pointer_byte_size = Args::StringToUInt32 (value.c_str(), 0, 0); + pointer_byte_size = Args::StringToUInt32 (value.c_str(), 0, 0); } } - if (cpu != LLDB_INVALID_CPUTYPE) - m_arch.SetArchitecture (lldb::eArchTypeMachO, cpu, sub); + if (arch_name.empty()) + { + if (cpu != LLDB_INVALID_CPUTYPE) + { + m_host_arch.SetArchitecture (lldb::eArchTypeMachO, cpu, sub); + if (pointer_byte_size) + { + assert (pointer_byte_size == m_host_arch.GetAddressByteSize()); + } + if (byte_order != eByteOrderInvalid) + { + assert (byte_order == m_host_arch.GetByteOrder()); + } + if (!vendor_name.empty()) + m_host_arch.GetTriple().setVendorName (llvm::StringRef (vendor_name)); + if (!os_name.empty()) + m_host_arch.GetTriple().setVendorName (llvm::StringRef (os_name)); + + } + } + else + { + std::string triple; + triple += arch_name; + triple += '-'; + if (vendor_name.empty()) + triple += "unknown"; + else + triple += vendor_name; + triple += '-'; + if (os_name.empty()) + triple += "unknown"; + else + triple += os_name; + m_host_arch.SetTriple (triple.c_str()); + } } } return m_supports_qHostInfo == eLazyBoolYes; @@ -759,41 +792,9 @@ GDBRemoteCommunicationClient::SendAttach const lldb_private::ArchSpec & GDBRemoteCommunicationClient::GetHostArchitecture () { - if (!HostInfoIsValid ()) + if (m_supports_qHostInfo == lldb::eLazyBoolCalculate) GetHostInfo (); - return m_arch; -} - -const lldb_private::ConstString & -GDBRemoteCommunicationClient::GetOSString () -{ - if (!HostInfoIsValid ()) - GetHostInfo (); - return m_os; -} - -const lldb_private::ConstString & -GDBRemoteCommunicationClient::GetVendorString() -{ - if (!HostInfoIsValid ()) - GetHostInfo (); - return m_vendor; -} - -lldb::ByteOrder -GDBRemoteCommunicationClient::GetByteOrder () -{ - if (!HostInfoIsValid ()) - GetHostInfo (); - return m_byte_order; -} - -uint32_t -GDBRemoteCommunicationClient::GetAddressByteSize () -{ - if (!HostInfoIsValid ()) - GetHostInfo (); - return m_pointer_byte_size; + return m_host_arch; } addr_t diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index 604e09a9491a..bcf23f2c5891 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -176,18 +176,6 @@ public: const lldb_private::ArchSpec & GetHostArchitecture (); - const lldb_private::ConstString & - GetOSString (); - - const lldb_private::ConstString & - GetVendorString(); - - lldb::ByteOrder - GetByteOrder (); - - uint32_t - GetAddressByteSize (); - bool GetVContSupported (char flavor); @@ -222,12 +210,6 @@ public: protected: - bool - HostInfoIsValid () const - { - return m_supports_qHostInfo != lldb::eLazyBoolCalculate; - } - //------------------------------------------------------------------ // Classes that inherit from GDBRemoteCommunicationClient can see and modify these //------------------------------------------------------------------ @@ -249,14 +231,8 @@ protected: StringExtractorGDBRemote m_async_response; int m_async_signal; // We were asked to deliver a signal to the inferior process. - lldb_private::ArchSpec m_arch; + lldb_private::ArchSpec m_host_arch; uint32_t m_cpusubtype; - lldb_private::ConstString m_os; - lldb_private::ConstString m_vendor; - lldb::ByteOrder m_byte_order; - uint32_t m_pointer_byte_size; - - private: //------------------------------------------------------------------ diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp index 2e4ff70cf2d9..18d6087e8b58 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp @@ -72,10 +72,12 @@ GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer() //} // bool -GDBRemoteCommunicationServer::GetPacketAndSendResponse (const TimeValue* timeout_time_ptr) +GDBRemoteCommunicationServer::GetPacketAndSendResponse (const TimeValue* timeout_ptr, + bool &interrupt, + bool &quit) { StringExtractorGDBRemote packet; - if (WaitForPacketNoLock (packet, timeout_time_ptr)) + if (WaitForPacketNoLock (packet, timeout_ptr)) { const StringExtractorGDBRemote::ServerPacketType packet_type = packet.GetServerPacketType (); switch (packet_type) @@ -85,6 +87,13 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (const TimeValue* timeout break; case StringExtractorGDBRemote::eServerPacketType_invalid: + quit = true; + break; + + case StringExtractorGDBRemote::eServerPacketType_interrupt: + interrupt = true; + break; + case StringExtractorGDBRemote::eServerPacketType_unimplemented: return SendUnimplementedResponse () > 0; diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h index 8ccfca2ee1de..4e0b24ddea08 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h @@ -34,7 +34,9 @@ public: ~GDBRemoteCommunicationServer(); bool - GetPacketAndSendResponse (const lldb_private::TimeValue* timeout_time_ptr); + GetPacketAndSendResponse (const lldb_private::TimeValue* timeout_ptr, + bool &interrupt, + bool &quit); virtual bool GetThreadSuffixSupported () diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 79949669e77c..e5a1d7c0606b 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -622,34 +622,52 @@ ProcessGDBRemote::DidLaunchOrAttach () BuildDynamicRegisterInfo (false); - m_target.GetArchitecture().SetByteOrder (m_gdb_comm.GetByteOrder()); StreamString strm; // See if the GDB server supports the qHostInfo information - const char *vendor = m_gdb_comm.GetVendorString().AsCString(); - const char *os_type = m_gdb_comm.GetOSString().AsCString(); - ArchSpec target_arch (GetTarget().GetArchitecture()); - ArchSpec gdb_remote_arch (m_gdb_comm.GetHostArchitecture()); - // If the remote host is ARM and we have apple as the vendor, then - // ARM executables and shared libraries can have mixed ARM architectures. - // You can have an armv6 executable, and if the host is armv7, then the - // system will load the best possible architecture for all shared libraries - // it has, so we really need to take the remote host architecture as our - // defacto architecture in this case. - - if (gdb_remote_arch.GetMachine() == llvm::Triple::arm && - gdb_remote_arch.GetTriple().getVendor() == llvm::Triple::Apple) + const ArchSpec &gdb_remote_arch = m_gdb_comm.GetHostArchitecture(); + if (gdb_remote_arch.IsValid()) { - GetTarget().SetArchitecture (gdb_remote_arch); - target_arch = gdb_remote_arch; + ArchSpec &target_arch = GetTarget().GetArchitecture(); + + if (target_arch.IsValid()) + { + // If the remote host is ARM and we have apple as the vendor, then + // ARM executables and shared libraries can have mixed ARM architectures. + // You can have an armv6 executable, and if the host is armv7, then the + // system will load the best possible architecture for all shared libraries + // it has, so we really need to take the remote host architecture as our + // defacto architecture in this case. + + if (gdb_remote_arch.GetMachine() == llvm::Triple::arm && + gdb_remote_arch.GetTriple().getVendor() == llvm::Triple::Apple) + { + target_arch = gdb_remote_arch; + } + else + { + // Fill in what is missing in the triple + const llvm::Triple &remote_triple = gdb_remote_arch.GetTriple(); + llvm::Triple &target_triple = target_arch.GetTriple(); + if (target_triple.getVendor() == llvm::Triple::UnknownVendor) + target_triple.setVendor (remote_triple.getVendor()); + + if (target_triple.getOS() == llvm::Triple::UnknownOS) + target_triple.setOS (remote_triple.getOS()); + + if (target_triple.getEnvironment() == llvm::Triple::UnknownEnvironment) + target_triple.setEnvironment (remote_triple.getEnvironment()); + } + } + else + { + // The target doesn't have a valid architecture yet, set it from + // the architecture we got from the remote GDB server + target_arch = gdb_remote_arch; + } } - - if (vendor) - m_target.GetArchitecture().GetTriple().setVendorName(vendor); - if (os_type) - m_target.GetArchitecture().GetTriple().setOSName(os_type); } } diff --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp index 32ac194b66cb..a6df50d9e708 100644 --- a/lldb/source/Target/Platform.cpp +++ b/lldb/source/Target/Platform.cpp @@ -69,7 +69,9 @@ Platform::SetDefaultPlatform (const lldb::PlatformSP &platform_sp) } Error -Platform::GetFile (const FileSpec &platform_file, FileSpec &local_file) +Platform::GetFile (const FileSpec &platform_file, + const UUID *uuid_ptr, + FileSpec &local_file) { // Default to the local case local_file = platform_file; @@ -123,6 +125,7 @@ Platform::Platform (bool is_host) : m_os_version_set_while_connected (false), m_system_arch_set_while_connected (false), m_remote_url (), + m_remote_instance_name (), m_major_os_version (UINT32_MAX), m_minor_os_version (UINT32_MAX), m_update_os_version (UINT32_MAX) @@ -330,17 +333,23 @@ Platform::GetSystemArchitecture() Error -Platform::ConnectRemote (const char *remote_url) +Platform::ConnectRemote (Args& args) { Error error; - error.SetErrorStringWithFormat ("Platform::ConnectRemote() is not supported by %s", GetShortPluginName()); + if (IsHost()) + error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetShortPluginName()); + else + error.SetErrorStringWithFormat ("Platform::ConnectRemote() is not supported by %s", GetShortPluginName()); return error; } Error -Platform::DisconnectRemote (const lldb::PlatformSP &platform_sp) +Platform::DisconnectRemote () { Error error; - error.SetErrorStringWithFormat ("Platform::DisconnectRemote() is not supported by %s", GetShortPluginName()); + if (IsHost()) + error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetShortPluginName()); + else + error.SetErrorStringWithFormat ("Platform::DisconnectRemote() is not supported by %s", GetShortPluginName()); return error; } diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index 46aa45042e49..8cc0a725125a 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -428,7 +428,7 @@ Target::SetExecutableModule (ModuleSP& executable_sp, bool get_dependent_files) FileSpec dependent_file_spec (dependent_files.GetFileSpecPointerAtIndex(i)); FileSpec platform_dependent_file_spec; if (m_platform_sp) - m_platform_sp->GetFile (dependent_file_spec, platform_dependent_file_spec); + m_platform_sp->GetFile (dependent_file_spec, NULL, platform_dependent_file_spec); else platform_dependent_file_spec = dependent_file_spec; diff --git a/lldb/source/Utility/StringExtractorGDBRemote.cpp b/lldb/source/Utility/StringExtractorGDBRemote.cpp index fc64b275e55c..372eaee501cc 100644 --- a/lldb/source/Utility/StringExtractorGDBRemote.cpp +++ b/lldb/source/Utility/StringExtractorGDBRemote.cpp @@ -59,6 +59,11 @@ StringExtractorGDBRemote::GetServerPacketType () const const char *packet_cstr = m_packet.c_str(); switch (m_packet[0]) { + case '\x03': + if (m_packet.size() == 1) + return eServerPacketType_interrupt; + break; + case '-': if (m_packet.size() == 1) return eServerPacketType_nack; diff --git a/lldb/source/Utility/StringExtractorGDBRemote.h b/lldb/source/Utility/StringExtractorGDBRemote.h index e8c41778ec08..8c65e0c7a398 100644 --- a/lldb/source/Utility/StringExtractorGDBRemote.h +++ b/lldb/source/Utility/StringExtractorGDBRemote.h @@ -45,6 +45,7 @@ public: eServerPacketType_ack, eServerPacketType_invalid, eServerPacketType_unimplemented, + eServerPacketType_interrupt, // CTRL+c packet or "\x03" eServerPacketType_qHostInfo }; diff --git a/lldb/tools/lldb-platform/lldb-platform.cpp b/lldb/tools/lldb-platform/lldb-platform.cpp index 3ca0f3346119..736daeb4d205 100644 --- a/lldb/tools/lldb-platform/lldb-platform.cpp +++ b/lldb/tools/lldb-platform/lldb-platform.cpp @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// +// C Includes #include #include #include @@ -15,8 +16,16 @@ #include #include +// C++ Includes + +// Other libraries and framework includes +#include "lldb/Core/Error.h" +#include "lldb/Core/ConnectionFileDescriptor.h" #include "GDBRemoteCommunicationServer.h" +using namespace lldb; +using namespace lldb_private; + //---------------------------------------------------------------------- // option descriptors for getopt_long() //---------------------------------------------------------------------- @@ -30,6 +39,7 @@ static struct option g_long_options[] = { "verbose", no_argument, &g_verbose, 1 }, { "log-file", required_argument, NULL, 'l' }, { "log-flags", required_argument, NULL, 'f' }, + { "listen", required_argument, NULL, 'L' }, { NULL, 0, NULL, 0 } }; @@ -58,6 +68,7 @@ main (int argc, char *argv[]) int long_option_index = 0; FILE* log_file = NULL; uint32_t log_flags = 0; + std::string connect_url; char ch; while ((ch = getopt_long(argc, argv, "l:f:", g_long_options, &long_option_index)) != -1) @@ -98,6 +109,11 @@ main (int argc, char *argv[]) if (optarg && optarg[0]) log_flags = strtoul(optarg, NULL, 0); break; + + case 'L': + connect_url.assign ("connect://"); + connect_url.append (optarg); + break; } } @@ -106,7 +122,48 @@ main (int argc, char *argv[]) argv += optind; - GDBRemoteCommunicationServer gdb_comm; + GDBRemoteCommunicationServer gdb_server; + Error error; + if (!connect_url.empty()) + { + std::auto_ptr conn_ap(new ConnectionFileDescriptor()); + if (conn_ap.get()) + { + const uint32_t max_retry_count = 50; + uint32_t retry_count = 0; + while (!gdb_server.IsConnected()) + { + if (conn_ap->Connect(connect_url.c_str(), &error) == eConnectionStatusSuccess) + { + gdb_server.SetConnection (conn_ap.release()); + break; + } + retry_count++; + + if (retry_count >= max_retry_count) + break; + + usleep (100000); + } + } + } + + + if (gdb_server.IsConnected()) + { + if (gdb_server.StartReadThread(&error)) + { + bool interrupt = false; + bool done = false; + while (!interrupt && !done) + { + gdb_server.GetPacketAndSendResponse(NULL, interrupt, done); + } + } + else + { + } + } return 0; }