diff options
29 files changed, 1297 insertions, 661 deletions
diff --git a/lldb/include/lldb/Host/Host.h b/lldb/include/lldb/Host/Host.h index cbb573df82a..392902d6a25 100644 --- a/lldb/include/lldb/Host/Host.h +++ b/lldb/include/lldb/Host/Host.h @@ -101,6 +101,15 @@ public: uint32_t &minor, uint32_t &update); + static bool + GetOSBuildString (std::string &s); + + static bool + GetOSKernelDescription (std::string &s); + + static bool + GetHostname (std::string &s); + //------------------------------------------------------------------ /// Gets the host architecture. /// diff --git a/lldb/include/lldb/Target/Platform.h b/lldb/include/lldb/Target/Platform.h index 98003e43d12..1795a3dfe0d 100644 --- a/lldb/include/lldb/Target/Platform.h +++ b/lldb/include/lldb/Target/Platform.h @@ -115,22 +115,14 @@ namespace lldb_private { uint32_t minor, uint32_t update); - const char * - GetInstanceName () - { - if (IsHost()) - return "localhost"; + bool + GetOSBuildString (std::string &s); + + bool + GetOSKernelDescription (std::string &s); - if (IsConnected()) - { - if (m_remote_instance_name.empty()) - GetRemoteInstanceName (); - - if (!m_remote_instance_name.empty()) - return m_remote_instance_name.c_str(); - } - return "remote"; - } + const char * + GetHostname (); virtual const char * GetDescription () = 0; @@ -144,7 +136,7 @@ namespace lldb_private { /// what this platform is connected to. //------------------------------------------------------------------ virtual void - GetStatus (Stream &strm) = 0; + GetStatus (Stream &strm); //------------------------------------------------------------------ // Subclasses must be able to fetch the current OS version @@ -153,13 +145,41 @@ namespace lldb_private { // subclasses don't need to override this function as it will just // call the Host::GetOSVersion(). //------------------------------------------------------------------ -protected: virtual bool - FetchRemoteOSVersion () + GetRemoteOSVersion () { return false; } + + virtual bool + GetRemoteOSBuildString (std::string &s) + { + s.clear(); + return false; + } + virtual bool + GetRemoteOSKernelDescription (std::string &s) + { + s.clear(); + return false; + } + + // Remote Platform subclasses need to override this function + virtual ArchSpec + GetRemoteSystemArchitecture () + { + return ArchSpec(); // Return an invalid architecture + } + + // Remote subclasses should override this and return a valid instance + // name if connected. + virtual const char * + GetRemoteHostname () + { + return NULL; + } + //------------------------------------------------------------------ /// Locate a file for a platform. /// @@ -179,7 +199,6 @@ protected: /// @return /// An error object. //------------------------------------------------------------------ -public: virtual Error GetFile (const FileSpec &platform_file, const UUID *uuid_ptr, @@ -191,15 +210,6 @@ public: virtual Error 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 /// they should be searched. @@ -349,10 +359,11 @@ public: return !m_is_host; } - bool + virtual bool IsConnected () const { - return m_is_connected; + // Remote subclasses should override this function + return IsHost(); } const ArchSpec & @@ -366,16 +377,8 @@ public: m_os_version_set_while_connected = m_system_arch.IsValid(); } - // Remote Platform subclasses need to override this function - virtual ArchSpec - FetchRemoteSystemArchitecture () - { - return ArchSpec(); // Return an invalid architecture - } - protected: bool m_is_host; - bool m_is_connected; // Set to true when we are able to actually set the OS version while // being connected. For remote platforms, we might set the version ahead // of time before we actually connect and this version might change when @@ -384,7 +387,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; + std::string m_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 cbe416fd904..5ab9f04012d 100644 --- a/lldb/lldb.xcodeproj/project.pbxproj +++ b/lldb/lldb.xcodeproj/project.pbxproj @@ -360,6 +360,8 @@ 2689FFFF13353DB600698AC0 /* BreakpointResolver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E1210F1B83100F91463 /* BreakpointResolver.cpp */; }; 268F9D53123AA15200B91E9B /* SBSymbolContextList.h in Headers */ = {isa = PBXBuildFile; fileRef = 268F9D52123AA15200B91E9B /* SBSymbolContextList.h */; settings = {ATTRIBUTES = (Public, ); }; }; 268F9D55123AA16600B91E9B /* SBSymbolContextList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 268F9D54123AA16600B91E9B /* SBSymbolContextList.cpp */; }; + 2697A54D133A6305004E4240 /* PlatformDarwin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2697A54B133A6305004E4240 /* PlatformDarwin.cpp */; }; + 2697A54E133A6305004E4240 /* PlatformDarwin.h in Headers */ = {isa = PBXBuildFile; fileRef = 2697A54C133A6305004E4240 /* PlatformDarwin.h */; }; 26B1FA1413380E61002886E2 /* LLDBWrapPython.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26A4EEB511682AAC007A372A /* LLDBWrapPython.cpp */; }; 26B1FCB813381071002886E2 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C39010F3FA26009D5894 /* CoreFoundation.framework */; }; 26B1FCB913381071002886E2 /* DebugSymbols.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 265ABF6210F42EE900531910 /* DebugSymbols.framework */; }; @@ -669,6 +671,8 @@ 268F9D54123AA16600B91E9B /* SBSymbolContextList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBSymbolContextList.cpp; path = source/API/SBSymbolContextList.cpp; sourceTree = "<group>"; }; 269416AD119A024800FF2715 /* CommandObjectTarget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectTarget.cpp; path = source/Commands/CommandObjectTarget.cpp; sourceTree = "<group>"; }; 269416AE119A024800FF2715 /* CommandObjectTarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectTarget.h; path = source/Commands/CommandObjectTarget.h; sourceTree = "<group>"; }; + 2697A54B133A6305004E4240 /* PlatformDarwin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformDarwin.cpp; sourceTree = "<group>"; }; + 2697A54C133A6305004E4240 /* PlatformDarwin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformDarwin.h; sourceTree = "<group>"; }; 269FF07D12494F7D00225026 /* FuncUnwinders.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FuncUnwinders.h; path = include/lldb/Symbol/FuncUnwinders.h; sourceTree = "<group>"; }; 269FF07F12494F8E00225026 /* UnwindPlan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UnwindPlan.h; path = include/lldb/Symbol/UnwindPlan.h; sourceTree = "<group>"; }; 269FF08112494FC200225026 /* UnwindTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UnwindTable.h; path = include/lldb/Symbol/UnwindTable.h; sourceTree = "<group>"; }; @@ -2246,6 +2250,8 @@ 26C5577F132575C8008FD8FE /* MacOSX */ = { isa = PBXGroup; children = ( + 2697A54B133A6305004E4240 /* PlatformDarwin.cpp */, + 2697A54C133A6305004E4240 /* PlatformDarwin.h */, 26C5577B132575AD008FD8FE /* PlatformMacOSX.cpp */, 26C5577C132575AD008FD8FE /* PlatformMacOSX.h */, 2675F6FE1332BE690067997B /* PlatformRemoteiOS.cpp */, @@ -2512,6 +2518,7 @@ 26744EF21338317700EF765A /* GDBRemoteCommunicationClient.h in Headers */, 26744EF41338317700EF765A /* GDBRemoteCommunicationServer.h in Headers */, 264A97C0133918BC0017F0BE /* PlatformRemoteGDBServer.h in Headers */, + 2697A54E133A6305004E4240 /* PlatformDarwin.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3070,6 +3077,7 @@ 26744EF11338317700EF765A /* GDBRemoteCommunicationClient.cpp in Sources */, 26744EF31338317700EF765A /* GDBRemoteCommunicationServer.cpp in Sources */, 264A97BF133918BC0017F0BE /* PlatformRemoteGDBServer.cpp in Sources */, + 2697A54D133A6305004E4240 /* PlatformDarwin.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3595,6 +3603,7 @@ GCC_INLINES_ARE_PRIVATE_EXTERN = NO; GCC_MODEL_TUNING = G5; GCC_OPTIMIZATION_LEVEL = 0; + GCC_SYMBOLS_PRIVATE_EXTERN = NO; INSTALL_PATH = /usr/local/bin; OTHER_LDFLAGS = ( "-framework", @@ -3621,6 +3630,7 @@ GCC_ENABLE_CPP_RTTI = NO; GCC_INLINES_ARE_PRIVATE_EXTERN = NO; GCC_MODEL_TUNING = G5; + GCC_SYMBOLS_PRIVATE_EXTERN = NO; INSTALL_PATH = /usr/local/bin; OTHER_LDFLAGS = ( "-framework", @@ -3646,6 +3656,7 @@ GCC_ENABLE_CPP_RTTI = NO; GCC_INLINES_ARE_PRIVATE_EXTERN = NO; GCC_MODEL_TUNING = G5; + GCC_SYMBOLS_PRIVATE_EXTERN = NO; INSTALL_PATH = /usr/local/bin; OTHER_LDFLAGS = ( "-framework", diff --git a/lldb/source/Commands/CommandObjectPlatform.cpp b/lldb/source/Commands/CommandObjectPlatform.cpp index dc6b4efb8dc..0294d678822 100644 --- a/lldb/source/Commands/CommandObjectPlatform.cpp +++ b/lldb/source/Commands/CommandObjectPlatform.cpp @@ -68,7 +68,7 @@ public: } else { - result.AppendError ("command not implemented"); + result.AppendError ("command not implemented\n"); result.SetStatus (eReturnStatusFailed); } return result.Succeeded(); @@ -203,7 +203,7 @@ public: if (idx == 0) { - result.AppendError ("no platforms are available"); + result.AppendError ("no platforms are available\n"); result.SetStatus (eReturnStatusFailed); } return result.Succeeded(); @@ -243,7 +243,7 @@ public: } else { - result.AppendError ("no platform us currently selected"); + result.AppendError ("no platform us currently selected\n"); result.SetStatus (eReturnStatusFailed); } return result.Succeeded(); @@ -274,7 +274,7 @@ public: virtual bool Execute (Args& args, CommandReturnObject &result) { - result.AppendError ("command not implemented"); + result.AppendError ("command not implemented\n"); result.SetStatus (eReturnStatusFailed); return result.Succeeded(); } @@ -306,27 +306,24 @@ public: { 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.AppendErrorWithFormat ("%s\n", error.AsCString()); result.SetStatus (eReturnStatusFailed); } } else { - result.AppendError ("no platform us currently selected"); + result.AppendError ("no platform us currently selected\n"); result.SetStatus (eReturnStatusFailed); } return result.Succeeded(); @@ -367,31 +364,31 @@ public: { // 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); + const char *hostname_cstr = selected_platform_sp->GetHostname(); + std::string hostname; + if (hostname_cstr) + hostname.assign (hostname_cstr); error = selected_platform_sp->DisconnectRemote (); if (error.Success()) { Stream &ostrm = result.GetOutputStream(); - if (instance_name.empty()) + if (hostname.empty()) ostrm.Printf ("Disconnected from \"%s\"\n", selected_platform_sp->GetShortPluginName()); else - ostrm.Printf ("Disconnected from \"%s\"\n", instance_name.c_str()); + ostrm.Printf ("Disconnected from \"%s\"\n", hostname.c_str()); result.SetStatus (eReturnStatusSuccessFinishResult); } else { - result.AppendErrorWithFormat ("disconnect failed: %s", error.AsCString()); + result.AppendErrorWithFormat ("%s", error.AsCString()); result.SetStatus (eReturnStatusFailed); } } else { // Not connected... - result.AppendError ("not connected."); + result.AppendErrorWithFormat ("not connected to '%s'", selected_platform_sp->GetShortPluginName()); result.SetStatus (eReturnStatusFailed); } } @@ -404,7 +401,7 @@ public: } else { - result.AppendError ("no platform us currently selected"); + result.AppendError ("no platform is currently selected"); result.SetStatus (eReturnStatusFailed); } return result.Succeeded(); diff --git a/lldb/source/Core/ArchSpec.cpp b/lldb/source/Core/ArchSpec.cpp index 512b5f030de..b44aa21842c 100644 --- a/lldb/source/Core/ArchSpec.cpp +++ b/lldb/source/Core/ArchSpec.cpp @@ -357,7 +357,7 @@ ArchSpec::GetMachOCPUSubType () const const ArchDefinitionEntry *arch_def = FindArchDefinitionEntry (&g_macho_arch_def, core_def->core); if (arch_def) { - return arch_def->cpu; + return arch_def->sub; } } return LLDB_INVALID_CPUTYPE; diff --git a/lldb/source/Core/Communication.cpp b/lldb/source/Core/Communication.cpp index a12927e22f1..789228a5b9a 100644 --- a/lldb/source/Core/Communication.cpp +++ b/lldb/source/Core/Communication.cpp @@ -228,6 +228,9 @@ Communication::Write (const void *src, size_t src_len, ConnectionStatus &status, bool Communication::StartReadThread (Error *error_ptr) { + if (error_ptr) + error_ptr->Clear(); + if (IS_VALID_LLDB_HOST_THREAD(m_read_thread)) return true; diff --git a/lldb/source/Core/ConnectionFileDescriptor.cpp b/lldb/source/Core/ConnectionFileDescriptor.cpp index 8c6a123bc89..e5b27bc8624 100644 --- a/lldb/source/Core/ConnectionFileDescriptor.cpp +++ b/lldb/source/Core/ConnectionFileDescriptor.cpp @@ -122,11 +122,11 @@ ConnectionFileDescriptor::Connect (const char *s, Error *error_ptr) return eConnectionStatusSuccess; } if (error_ptr) - error_ptr->SetErrorStringWithFormat ("Unsupported connection URL: '%s'.\n", s); + error_ptr->SetErrorStringWithFormat ("unsupported connection URL: '%s'", s); return eConnectionStatusError; } if (error_ptr) - error_ptr->SetErrorString("NULL connection URL."); + error_ptr->SetErrorString("invalid connect arguments"); return eConnectionStatusError; } @@ -236,7 +236,7 @@ ConnectionFileDescriptor::Write (const void *src, size_t src_len, ConnectionStat if (!IsConnected ()) { if (error_ptr) - error_ptr->SetErrorString("Not connected."); + error_ptr->SetErrorString("not connected"); status = eConnectionStatusNoConnection; return 0; } @@ -375,7 +375,7 @@ ConnectionFileDescriptor::BytesAvailable (uint32_t timeout_usec, Error *error_pt } if (error_ptr) - error_ptr->SetErrorString("Not connected."); + error_ptr->SetErrorString("not connected"); return eConnectionStatusLostConnection; } @@ -536,7 +536,7 @@ ConnectionFileDescriptor::SocketConnect (const char *host_and_port, Error *error if (regex.Execute (host_and_port, 2) == false) { if (error_ptr) - error_ptr->SetErrorStringWithFormat("Invalid host:port specification: '%s'.\n", host_and_port); + error_ptr->SetErrorStringWithFormat("invalid host:port specification: '%s'", host_and_port); return eConnectionStatusError; } std::string host_str; @@ -545,7 +545,7 @@ ConnectionFileDescriptor::SocketConnect (const char *host_and_port, Error *error regex.GetMatchAtIndex (host_and_port, 2, port_str) == false) { if (error_ptr) - error_ptr->SetErrorStringWithFormat("Invalid host:port specification '%s'.\n", host_and_port); + error_ptr->SetErrorStringWithFormat("invalid host:port specification '%s'", host_and_port); return eConnectionStatusError; } @@ -553,7 +553,7 @@ ConnectionFileDescriptor::SocketConnect (const char *host_and_port, Error *error if (port == INT32_MIN) { if (error_ptr) - error_ptr->SetErrorStringWithFormat("Invalid port '%s'.\n", port_str.c_str()); + error_ptr->SetErrorStringWithFormat("invalid port '%s'", port_str.c_str()); return eConnectionStatusError; } // Create the socket @@ -591,7 +591,7 @@ ConnectionFileDescriptor::SocketConnect (const char *host_and_port, Error *error if (inet_pton_result == -1) error_ptr->SetErrorToErrno(); else - error_ptr->SetErrorStringWithFormat("Invalid host string: '%s'.\n", host_str.c_str()); + error_ptr->SetErrorStringWithFormat("invalid host string: '%s'", host_str.c_str()); } Close (m_fd, NULL); return eConnectionStatusError; diff --git a/lldb/source/Core/PluginManager.cpp b/lldb/source/Core/PluginManager.cpp index b7ee57dc991..a853c507908 100644 --- a/lldb/source/Core/PluginManager.cpp +++ b/lldb/source/Core/PluginManager.cpp @@ -153,6 +153,7 @@ LoadPluginCallback void PluginManager::Initialize () { +#if 1 FileSpec dir_spec; const bool find_directories = true; const bool find_files = true; @@ -183,6 +184,7 @@ PluginManager::Initialize () NULL); } } +#endif } void diff --git a/lldb/source/Host/common/Host.cpp b/lldb/source/Host/common/Host.cpp index 2e4a863113d..e6c4bdeec2a 100644 --- a/lldb/source/Host/common/Host.cpp +++ b/lldb/source/Host/common/Host.cpp @@ -24,6 +24,7 @@ #include <dlfcn.h> #include <errno.h> +#include <netdb.h> #if defined (__APPLE__) @@ -974,8 +975,10 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec) { #if defined (__APPLE__) static ConstString g_lldb_system_plugin_dir; - if (!g_lldb_system_plugin_dir) + static bool g_lldb_system_plugin_dir_located = false; + if (!g_lldb_system_plugin_dir_located) { + g_lldb_system_plugin_dir_located = true; FileSpec lldb_file_spec; if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec)) { @@ -988,13 +991,18 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec) { framework_pos += strlen("LLDB.framework"); ::strncpy (framework_pos, "/Resources/PlugIns", PATH_MAX - (framework_pos - raw_path)); + FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path)); + g_lldb_system_plugin_dir.SetCString(resolved_path); } - FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path)); - g_lldb_system_plugin_dir.SetCString(resolved_path); + return false; } } - file_spec.GetDirectory() = g_lldb_system_plugin_dir; - return file_spec.GetDirectory(); + + if (g_lldb_system_plugin_dir) + { + file_spec.GetDirectory() = g_lldb_system_plugin_dir; + return true; + } #endif // TODO: where would system LLDB plug-ins be located on linux? Other systems? return false; @@ -1029,8 +1037,40 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec) return false; } + +bool +Host::GetHostname (std::string &s) +{ + char hostname[PATH_MAX]; + hostname[sizeof(hostname) - 1] = '\0'; + if (::gethostname (hostname, sizeof(hostname) - 1) == 0) + { + struct hostent* h = ::gethostbyname (hostname); + if (h) + s.assign (h->h_name); + else + s.assign (hostname); + return true; + } + return false; +} + #if !defined (__APPLE__) // see macosx/Host.mm +bool +Host::GetOSBuildString (std::string &s) +{ + s.clear(); + return false; +} + +bool +Host::GetOSKernelDescription (std::string &s) +{ + s.clear(); + return false; +} + uint32_t Host::FindProcessesByName (const char *name, NameMatchType name_match_type, ProcessInfoList &process_infos) { diff --git a/lldb/source/Host/macosx/Host.mm b/lldb/source/Host/macosx/Host.mm index 81f5c5699b3..3231be9ed8a 100644 --- a/lldb/source/Host/macosx/Host.mm +++ b/lldb/source/Host/macosx/Host.mm @@ -840,6 +840,37 @@ Host::GetEnvironment (StringList &env) bool +Host::GetOSBuildString (std::string &s) +{ + int mib[2] = { CTL_KERN, KERN_OSVERSION }; + char cstr[PATH_MAX]; + size_t cstr_len = sizeof(cstr); + if (::sysctl (mib, 2, cstr, &cstr_len, NULL, 0) == 0) + { + s.assign (cstr, cstr_len); + return true; + } + + s.clear(); + return false; +} + +bool +Host::GetOSKernelDescription (std::string &s) +{ + int mib[2] = { CTL_KERN, KERN_VERSION }; + char cstr[PATH_MAX]; + size_t cstr_len = sizeof(cstr); + if (::sysctl (mib, 2, cstr, &cstr_len, NULL, 0) == 0) + { + s.assign (cstr, cstr_len); + return true; + } + s.clear(); + return false; +} + +bool Host::GetOSVersion ( uint32_t &major, @@ -878,7 +909,6 @@ Host::GetOSVersion } return true; - } static bool diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp new file mode 100644 index 00000000000..9613558c36e --- /dev/null +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp @@ -0,0 +1,313 @@ +//===-- PlatformDarwin.cpp --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "PlatformDarwin.h" + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Breakpoint/BreakpointLocation.h" +#include "lldb/Core/Error.h" +#include "lldb/Host/Host.h" +#include "lldb/Target/Target.h" + +using namespace lldb; +using namespace lldb_private; + + +//------------------------------------------------------------------ +/// Default Constructor +//------------------------------------------------------------------ +PlatformDarwin::PlatformDarwin (bool is_host) : + Platform(is_host), // This is the local host platform + m_remote_platform_sp () +{ +} + +//------------------------------------------------------------------ +/// Destructor. +/// +/// The destructor is virtual since this class is designed to be +/// inherited from by the plug-in instance. +//------------------------------------------------------------------ +PlatformDarwin::~PlatformDarwin() +{ +} + + +Error +PlatformDarwin::ResolveExecutable (const FileSpec &exe_file, + const ArchSpec &exe_arch, + lldb::ModuleSP &exe_module_sp) +{ + Error error; + // Nothing special to do here, just use the actual file and architecture + + FileSpec resolved_exe_file (exe_file); + + // If we have "ls" as the exe_file, resolve the executable loation based on + // the current path variables + if (!resolved_exe_file.Exists()) + resolved_exe_file.ResolveExecutableLocation (); + + // Resolve any executable within a bundle on MacOSX + Host::ResolveExecutableInBundle (resolved_exe_file); + + if (resolved_exe_file.Exists()) + { + if (exe_arch.IsValid()) + { + error = ModuleList::GetSharedModule (resolved_exe_file, + exe_arch, + NULL, + NULL, + 0, + exe_module_sp, + NULL, + NULL); + + if (exe_module_sp->GetObjectFile() == NULL) + { + exe_module_sp.reset(); + error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain the architecture %s", + exe_file.GetDirectory().AsCString(""), + exe_file.GetDirectory() ? "/" : "", + exe_file.GetFilename().AsCString(""), + exe_arch.GetArchitectureName()); + } + } + else + { + // No valid architecture was specified, ask the platform for + // the architectures that we should be using (in the correct order) + // and see if we can find a match that way + StreamString arch_names; + ArchSpec platform_arch; + for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx) + { + error = ModuleList::GetSharedModule (resolved_exe_file, + platform_arch, + NULL, + NULL, + 0, + exe_module_sp, + NULL, + NULL); + // Did we find an executable using one of the + if (error.Success()) + { + if (exe_module_sp && exe_module_sp->GetObjectFile()) + break; + else + error.SetErrorToGenericError(); + } + + if (idx > 0) + arch_names.PutCString (", "); + arch_names.PutCString (platform_arch.GetArchitectureName()); + } + + if (error.Fail() || !exe_module_sp) + { + error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain any '%s' platform architectures: %s", + exe_file.GetDirectory().AsCString(""), + exe_file.GetDirectory() ? "/" : "", + exe_file.GetFilename().AsCString(""), + GetShortPluginName(), + arch_names.GetString().c_str()); + } + } + } + else + { + error.SetErrorStringWithFormat ("'%s%s%s' does not exist", + exe_file.GetDirectory().AsCString(""), + exe_file.GetDirectory() ? "/" : "", + exe_file.GetFilename().AsCString("")); + } + + return error; +} + + +size_t +PlatformDarwin::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site) +{ + const uint8_t *trap_opcode = NULL; + uint32_t trap_opcode_size = 0; + + llvm::Triple::ArchType machine = target.GetArchitecture().GetMachine(); + switch (machine) + { + case llvm::Triple::x86: + case llvm::Triple::x86_64: + { + static const uint8_t g_i386_breakpoint_opcode[] = { 0xCC }; + trap_opcode = g_i386_breakpoint_opcode; + trap_opcode_size = sizeof(g_i386_breakpoint_opcode); + } + break; + + case llvm::Triple::arm: + { + static const uint8_t g_arm_breakpoint_opcode[] = { 0xFE, 0xDE, 0xFF, 0xE7 }; + static const uint8_t g_thumb_breakpooint_opcode[] = { 0xFE, 0xDE }; + + lldb::BreakpointLocationSP bp_loc_sp (bp_site->GetOwnerAtIndex (0)); + if (bp_loc_sp) + { + const AddressClass addr_class = bp_loc_sp->GetAddress().GetAddressClass (); + if (addr_class == eAddressClassCodeAlternateISA) + { + trap_opcode = g_thumb_breakpooint_opcode; + trap_opcode_size = sizeof(g_thumb_breakpooint_opcode); + break; + } + } + trap_opcode = g_arm_breakpoint_opcode; + trap_opcode_size = sizeof(g_arm_breakpoint_opcode); + } + break; + + case llvm::Triple::ppc: + case llvm::Triple::ppc64: + { + static const uint8_t g_ppc_breakpoint_opcode[] = { 0x7F, 0xC0, 0x00, 0x08 }; + trap_opcode = g_ppc_breakpoint_opcode; + trap_opcode_size = sizeof(g_ppc_breakpoint_opcode); + } + break; + + default: + assert(!"Unhandled architecture in ProcessMacOSX::GetSoftwareBreakpointTrapOpcode()"); + break; + } + + if (trap_opcode && trap_opcode_size) + { + if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size)) + return trap_opcode_size; + } + return 0; + +} + +bool +PlatformDarwin::GetRemoteOSVersion () +{ + if (m_remote_platform_sp) + return m_remote_platform_sp->GetOSVersion (m_major_os_version, + m_minor_os_version, + m_update_os_version); + return false; +} + +bool +PlatformDarwin::GetRemoteOSBuildString (std::string &s) +{ + if (m_remote_platform_sp) + return m_remote_platform_sp->GetRemoteOSBuildString (s); + s.clear(); + return false; +} + +bool +PlatformDarwin::GetRemoteOSKernelDescription (std::string &s) +{ + if (m_remote_platform_sp) + return m_remote_platform_sp->GetRemoteOSKernelDescription (s); + s.clear(); + return false; +} + +// Remote Platform subclasses need to override this function +ArchSpec +PlatformDarwin::GetRemoteSystemArchitecture () +{ + if (m_remote_platform_sp) + return m_remote_platform_sp->GetRemoteSystemArchitecture (); + return ArchSpec(); +} + + +const char * +PlatformDarwin::GetRemoteHostname () +{ + if (m_remote_platform_sp) + return m_remote_platform_sp->GetHostname (); + return NULL; +} + +bool +PlatformDarwin::IsConnected () const +{ + if (IsHost()) + return true; + else if (m_remote_platform_sp) + return m_remote_platform_sp->IsConnected(); + return false; +} + +Error +PlatformDarwin::ConnectRemote (Args& args) +{ + Error error; + if (IsHost()) + { + error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetShortPluginName()); + } + else + { + if (!m_remote_platform_sp) + m_remote_platform_sp = Platform::Create ("remote-gdb-server", error); + + if (m_remote_platform_sp) + { + if (error.Success()) + { + if (m_remote_platform_sp) + { + error = m_remote_platform_sp->ConnectRemote (args); + } + else + { + error.SetErrorString ("\"platform connect\" takes a single argument: <connect-url>"); + } + } + } + else + error.SetErrorString ("failed to create a 'remote-gdb-server' platform"); + + if (error.Fail()) + m_remote_platform_sp.reset(); + } + + return error; +} + +Error +PlatformDarwin::DisconnectRemote () +{ + Error error; + + if (IsHost()) + { + error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetShortPluginName()); + } + else + { + if (m_remote_platform_sp) + error = m_remote_platform_sp->DisconnectRemote (); + else + error.SetErrorString ("the platform is not currently connected"); + } + return error; +} + diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h new file mode 100644 index 00000000000..ff73a555957 --- /dev/null +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h @@ -0,0 +1,76 @@ +//===-- PlatformDarwin.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_PlatformDarwin_h_ +#define liblldb_PlatformDarwin_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Target/Platform.h" + +namespace lldb_private { + + class PlatformDarwin : public Platform + { + public: + PlatformDarwin (bool is_host); + + virtual + ~PlatformDarwin(); + + //------------------------------------------------------------ + // lldb_private::Platform functions + //------------------------------------------------------------ + virtual Error + ResolveExecutable (const FileSpec &exe_file, + const ArchSpec &arch, + lldb::ModuleSP &module_sp); + + virtual size_t + GetSoftwareBreakpointTrapOpcode (Target &target, + BreakpointSite *bp_site); + + virtual bool + GetRemoteOSVersion (); + + virtual bool + GetRemoteOSBuildString (std::string &s); + + virtual bool + GetRemoteOSKernelDescription (std::string &s); + + // Remote Platform subclasses need to override this function + virtual ArchSpec + GetRemoteSystemArchitecture (); + + virtual bool + IsConnected () const; + + virtual Error + ConnectRemote (Args& args); + + virtual Error + DisconnectRemote (); + + virtual const char * + GetRemoteHostname (); + + + protected: + lldb::PlatformSP m_remote_platform_sp; // Allow multiple ways to connect to a remote darwin OS + + private: + DISALLOW_COPY_AND_ASSIGN (PlatformDarwin); + + }; +} // namespace lldb_private + +#endif // liblldb_PlatformDarwin_h_ diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp index ba7be39b1bd..24789302a69 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp @@ -19,6 +19,7 @@ #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" @@ -28,174 +29,76 @@ using namespace lldb; using namespace lldb_private; +static uint32_t g_initialize_count = 0; + void PlatformMacOSX::Initialize () { + if (g_initialize_count++ == 0) + { #if defined (__APPLE__) - PlatformSP default_platform_sp (new PlatformMacOSX()); - default_platform_sp->SetSystemArchitecture (Host::GetArchitecture()); - Platform::SetDefaultPlatform (default_platform_sp); -#endif + PlatformSP default_platform_sp (new PlatformMacOSX(true)); + default_platform_sp->SetSystemArchitecture (Host::GetArchitecture()); + Platform::SetDefaultPlatform (default_platform_sp); +#endif + PluginManager::RegisterPlugin (PlatformMacOSX::GetShortPluginNameStatic(false), + PlatformMacOSX::GetDescriptionStatic(false), + PlatformMacOSX::CreateInstance); + } + } void PlatformMacOSX::Terminate () { -} - -Error -PlatformMacOSX::ResolveExecutable (const FileSpec &exe_file, - const ArchSpec &exe_arch, - lldb::ModuleSP &exe_module_sp) -{ - Error error; - // Nothing special to do here, just use the actual file and architecture - - FileSpec resolved_exe_file (exe_file); - - // If we have "ls" as the exe_file, resolve the executable loation based on - // the current path variables - if (!resolved_exe_file.Exists()) - resolved_exe_file.ResolveExecutableLocation (); - - // Resolve any executable within a bundle on MacOSX - Host::ResolveExecutableInBundle (resolved_exe_file); - - if (resolved_exe_file.Exists()) + if (g_initialize_count > 0) { - if (exe_arch.IsValid()) + if (--g_initialize_count == 0) { - error = ModuleList::GetSharedModule (resolved_exe_file, - exe_arch, - NULL, - NULL, - 0, - exe_module_sp, - NULL, - NULL); - - if (exe_module_sp->GetObjectFile() == NULL) - { - exe_module_sp.reset(); - error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain the architecture %s", - exe_file.GetDirectory().AsCString(""), - exe_file.GetDirectory() ? "/" : "", - exe_file.GetFilename().AsCString(""), - exe_arch.GetArchitectureName()); - } + PluginManager::UnregisterPlugin (PlatformMacOSX::CreateInstance); } - else - { - // No valid architecture was specified, ask the platform for - // the architectures that we should be using (in the correct order) - // and see if we can find a match that way - StreamString arch_names; - ArchSpec platform_arch; - for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx) - { - error = ModuleList::GetSharedModule (resolved_exe_file, - platform_arch, - NULL, - NULL, - 0, - exe_module_sp, - NULL, - NULL); - // Did we find an executable using one of the - if (error.Success()) - { - if (exe_module_sp && exe_module_sp->GetObjectFile()) - break; - else - error.SetErrorToGenericError(); - } - - if (idx > 0) - arch_names.PutCString (", "); - arch_names.PutCString (platform_arch.GetArchitectureName()); - } - - if (error.Fail() || !exe_module_sp) - { - error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain any '%s' platform architectures: %s", - exe_file.GetDirectory().AsCString(""), - exe_file.GetDirectory() ? "/" : "", - exe_file.GetFilename().AsCString(""), - GetShortPluginName(), - arch_names.GetString().c_str()); - } - } - } - else - { - error.SetErrorStringWithFormat ("'%s%s%s' does not exist", - exe_file.GetDirectory().AsCString(""), - exe_file.GetDirectory() ? "/" : "", - exe_file.GetFilename().AsCString("")); } - - return error; } -Error -PlatformMacOSX::GetFile (const FileSpec &platform_file, - const UUID *uuid_ptr, - FileSpec &local_file) +Platform* +PlatformMacOSX::CreateInstance () { - // Default to the local case - local_file = platform_file; - return Error(); + // The only time we create an instance is when we are creating a remote + // macosx platform + const bool is_host = false; + return new PlatformMacOSX (is_host); } -void -PlatformMacOSX::GetStatus (Stream &strm) +const char * +PlatformMacOSX::GetPluginNameStatic () { - 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("Host platform: Mac OS X Native\n"); - 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); - } + return "PlatformMacOSX"; +} - 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); - } +const char * +PlatformMacOSX::GetShortPluginNameStatic (bool is_host) +{ + if (is_host) + return "local-macosx"; + else + return "remote-macosx"; } +const char * +PlatformMacOSX::GetDescriptionStatic (bool is_host) +{ + if (is_host) + return "Local Mac OS X user platform plug-in."; + else + return "Remote Mac OS X user platform plug-in."; +} //------------------------------------------------------------------ /// Default Constructor //------------------------------------------------------------------ -PlatformMacOSX::PlatformMacOSX () : - Platform(true) // This is the local host platform +PlatformMacOSX::PlatformMacOSX (bool is_host) : + PlatformDarwin (is_host) { } @@ -209,18 +112,55 @@ PlatformMacOSX::~PlatformMacOSX() { } +Error +PlatformMacOSX::GetFile (const FileSpec &platform_file, + const UUID *uuid_ptr, + FileSpec &local_file) +{ + if (IsRemote()) + { + if (m_remote_platform_sp) + return m_remote_platform_sp->GetFile (platform_file, uuid_ptr, local_file); + } + + // Default to the local case + local_file = platform_file; + return Error(); +} + uint32_t PlatformMacOSX::FindProcessesByName (const char *name_match, lldb::NameMatchType name_match_type, ProcessInfoList &process_infos) { - return Host::FindProcessesByName (name_match, name_match_type, process_infos); + uint32_t match_count = 0; + if (IsHost()) + { + match_count = Host::FindProcessesByName (name_match, name_match_type, process_infos); + + } + else + { + if (m_remote_platform_sp) + match_count = m_remote_platform_sp->FindProcessesByName (name_match, name_match_type, process_infos); + } + return 0; } bool PlatformMacOSX::GetProcessInfo (lldb::pid_t pid, ProcessInfo &process_info) { - return Host::GetProcessInfo (pid, process_info); + bool sucess = false; + if (IsHost()) + { + sucess = Host::GetProcessInfo (pid, process_info); + } + else + { + if (m_remote_platform_sp) + sucess = m_remote_platform_sp->GetProcessInfo (pid, process_info); + } + return sucess; } bool @@ -247,64 +187,3 @@ PlatformMacOSX::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch) return false; } -size_t -PlatformMacOSX::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site) -{ - const uint8_t *trap_opcode = NULL; - uint32_t trap_opcode_size = 0; - - llvm::Triple::ArchType machine = target.GetArchitecture().GetMachine(); - switch (machine) - { - case llvm::Triple::x86: - case llvm::Triple::x86_64: - { - static const uint8_t g_i386_breakpoint_opcode[] = { 0xCC }; - trap_opcode = g_i386_breakpoint_opcode; - trap_opcode_size = sizeof(g_i386_breakpoint_opcode); - } - break; - - case llvm::Triple::arm: - { - static const uint8_t g_arm_breakpoint_opcode[] = { 0xFE, 0xDE, 0xFF, 0xE7 }; - static const uint8_t g_thumb_breakpooint_opcode[] = { 0xFE, 0xDE }; - - lldb::BreakpointLocationSP bp_loc_sp (bp_site->GetOwnerAtIndex (0)); - if (bp_loc_sp) - { - const AddressClass addr_class = bp_loc_sp->GetAddress().GetAddressClass (); - if (addr_class == eAddressClassCodeAlternateISA) - { - trap_opcode = g_thumb_breakpooint_opcode; - trap_opcode_size = sizeof(g_thumb_breakpooint_opcode); - break; - } - } - trap_opcode = g_arm_breakpoint_opcode; - trap_opcode_size = sizeof(g_arm_breakpoint_opcode); - } - break; - - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - { - static const uint8_t g_ppc_breakpoint_opcode[] = { 0x7F, 0xC0, 0x00, 0x08 }; - trap_opcode = g_ppc_breakpoint_opcode; - trap_opcode_size = sizeof(g_ppc_breakpoint_opcode); - } - break; - - default: - assert(!"Unhandled architecture in ProcessMacOSX::GetSoftwareBreakpointTrapOpcode()"); - break; - } - - if (trap_opcode && trap_opcode_size) - { - if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size)) - return trap_opcode_size; - } - return 0; - -} diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.h b/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.h index b0e3d1ad987..851db84e4ba 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.h +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.h @@ -14,21 +14,39 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/Target/Platform.h" +#include "PlatformDarwin.h" namespace lldb_private { - class PlatformMacOSX : public Platform + class PlatformMacOSX : public PlatformDarwin { public: + //------------------------------------------------------------ + // Class functions + //------------------------------------------------------------ + static Platform* + CreateInstance (); + static void Initialize (); static void Terminate (); - PlatformMacOSX (); + static const char * + GetPluginNameStatic (); + + static const char * + GetShortPluginNameStatic(bool is_host); + + static const char * + GetDescriptionStatic(bool is_host); + + //------------------------------------------------------------ + // Class Methods + //------------------------------------------------------------ + PlatformMacOSX (bool is_host); virtual ~PlatformMacOSX(); @@ -39,13 +57,13 @@ namespace lldb_private { virtual const char * GetPluginName() { - return "PlatformMacOSX"; + return GetPluginNameStatic (); } virtual const char * GetShortPluginName() { - return "local-macosx"; + return GetShortPluginNameStatic (IsHost()); } virtual uint32_t @@ -54,24 +72,12 @@ namespace lldb_private { return 1; } - - //------------------------------------------------------------ - // lldb_private::Platform functions - //------------------------------------------------------------ - virtual Error - ResolveExecutable (const FileSpec &exe_file, - const ArchSpec &arch, - lldb::ModuleSP &module_sp); - virtual const char * GetDescription () { - return "The native host platform on MacOSX."; + return GetDescriptionStatic (IsHost()); } - virtual void - GetStatus (Stream &strm); - virtual Error GetFile (const FileSpec &platform_file, const UUID *uuid_ptr, @@ -88,10 +94,6 @@ namespace lldb_private { virtual bool GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch); - virtual size_t - GetSoftwareBreakpointTrapOpcode (Target &target, - BreakpointSite *bp_site); - private: DISALLOW_COPY_AND_ASSIGN (PlatformMacOSX); diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp index fa6fcdc3d4a..d56ed3fcec2 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp @@ -28,14 +28,19 @@ using namespace lldb; using namespace lldb_private; -static bool g_initialized = false; - +//------------------------------------------------------------------ +// Static Variables +//------------------------------------------------------------------ +static uint32_t g_initialize_count = 0; + +//------------------------------------------------------------------ +// Static Functions +//------------------------------------------------------------------ void PlatformRemoteiOS::Initialize () { - if (g_initialized == false) + if (g_initialize_count++ == 0) { - g_initialized = true; PluginManager::RegisterPlugin (PlatformRemoteiOS::GetShortPluginNameStatic(), PlatformRemoteiOS::GetDescriptionStatic(), PlatformRemoteiOS::CreateInstance); @@ -45,10 +50,12 @@ PlatformRemoteiOS::Initialize () void PlatformRemoteiOS::Terminate () { - if (g_initialized) + if (g_initialize_count > 0) { - g_initialized = false; - PluginManager::UnregisterPlugin (PlatformRemoteiOS::CreateInstance); + if (--g_initialize_count == 0) + { + PluginManager::UnregisterPlugin (PlatformRemoteiOS::CreateInstance); + } } } @@ -78,36 +85,36 @@ PlatformRemoteiOS::GetDescriptionStatic() } +//------------------------------------------------------------------ +/// Default Constructor +//------------------------------------------------------------------ +PlatformRemoteiOS::PlatformRemoteiOS () : + PlatformDarwin (false), // This is a remote platform + m_device_support_directory (), + m_device_support_directory_for_os_version () +{ +} + +//------------------------------------------------------------------ +/// Destructor. +/// +/// The destructor is virtual since this class is designed to be +/// inherited from by the plug-in instance. +//------------------------------------------------------------------ +PlatformRemoteiOS::~PlatformRemoteiOS() +{ +} + + void PlatformRemoteiOS::GetStatus (Stream &strm) { - uint32_t major = UINT32_MAX; - uint32_t minor = UINT32_MAX; - uint32_t update = UINT32_MAX; + Platform::GetStatus (strm); const char *sdk_directory = GetDeviceSupportDirectoryForOSVersion(); - strm.PutCString ("Remote platform: iOS platform\n"); - if (GetOSVersion(major, minor, update)) - { - strm.Printf("SDK version: %u", major); - if (minor != UINT32_MAX) - strm.Printf(".%u", minor); - if (update != UINT32_MAX) - strm.Printf(".%u", update); - strm.EOL(); - } - - if (!m_build_update.empty()) - strm.Printf("SDK update: %s\n", m_build_update.c_str()); - if (sdk_directory) - strm.Printf ("SDK path: \"%s\"\n", sdk_directory); + strm.Printf ("SDKROOT: \"%s\"\n", sdk_directory); else - strm.PutCString ("SDK path: error: unable to locate SDK\n"); - - if (IsConnected()) - strm.Printf("Connected to: %s\n", m_remote_url.c_str()); - else - strm.PutCString("Not connected to a remote device.\n"); + strm.PutCString ("SDKROOT: error: unable to locate SDK\n"); } @@ -411,26 +418,6 @@ PlatformRemoteiOS::GetFile (const FileSpec &platform_file, return error; } -//------------------------------------------------------------------ -/// Default Constructor -//------------------------------------------------------------------ -PlatformRemoteiOS::PlatformRemoteiOS () : - Platform(false), // This is a remote platform - m_device_support_directory (), - m_device_support_directory_for_os_version () -{ -} - -//------------------------------------------------------------------ -/// Destructor. -/// -/// The destructor is virtual since this class is designed to be -/// inherited from by the plug-in instance. -//------------------------------------------------------------------ -PlatformRemoteiOS::~PlatformRemoteiOS() -{ -} - uint32_t PlatformRemoteiOS::FindProcessesByName (const char *name_match, lldb::NameMatchType name_match_type, @@ -449,29 +436,6 @@ 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) { @@ -578,104 +542,3 @@ PlatformRemoteiOS::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch arch.Clear(); return false; } - -bool -PlatformRemoteiOS::FetchRemoteOSVersion () -{ - return false; -} - - -size_t -PlatformRemoteiOS::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site) -{ - const uint8_t *trap_opcode = NULL; - uint32_t trap_opcode_size = 0; - - llvm::Triple::ArchType machine = target.GetArchitecture().GetMachine(); - switch (machine) - { - case llvm::Triple::x86: - case llvm::Triple::x86_64: - { - static const uint8_t g_i386_breakpoint_opcode[] = { 0xCC }; - trap_opcode = g_i386_breakpoint_opcode; - trap_opcode_size = sizeof(g_i386_breakpoint_opcode); - } - break; - - case llvm::Triple::arm: - { - static const uint8_t g_arm_breakpoint_opcode[] = { 0xFE, 0xDE, 0xFF, 0xE7 }; - static const uint8_t g_thumb_breakpooint_opcode[] = { 0xFE, 0xDE }; - - lldb::BreakpointLocationSP bp_loc_sp (bp_site->GetOwnerAtIndex (0)); - if (bp_loc_sp) - { - const AddressClass addr_class = bp_loc_sp->GetAddress().GetAddressClass (); - if (addr_class == eAddressClassCodeAlternateISA) - { - trap_opcode = g_thumb_breakpooint_opcode; - trap_opcode_size = sizeof(g_thumb_breakpooint_opcode); - break; - } - } - trap_opcode = g_arm_breakpoint_opcode; - trap_opcode_size = sizeof(g_arm_breakpoint_opcode); - } - break; - - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - { - static const uint8_t g_ppc_breakpoint_opcode[] = { 0x7F, 0xC0, 0x00, 0x08 }; - trap_opcode = g_ppc_breakpoint_opcode; - trap_opcode_size = sizeof(g_ppc_breakpoint_opcode); - } - break; - - default: - assert(!"Unhandled architecture in ProcessMacOSX::GetSoftwareBreakpointTrapOpcode()"); - break; - } - - if (trap_opcode && trap_opcode_size) - { - if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size)) - return trap_opcode_size; - } - 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: <connect-url>"); -// } - - 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 36f4c004597..a6bfc44eb15 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h @@ -14,14 +14,17 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/Target/Platform.h" +#include "PlatformDarwin.h" namespace lldb_private { - class PlatformRemoteiOS : public Platform + class PlatformRemoteiOS : public PlatformDarwin { public: + //------------------------------------------------------------ + // Class Functions + //------------------------------------------------------------ static Platform* CreateInstance (); @@ -31,15 +34,6 @@ namespace lldb_private { static void Terminate (); - PlatformRemoteiOS (); - - virtual - ~PlatformRemoteiOS(); - - //------------------------------------------------------------ - // lldb_private::PluginInterface functions - //------------------------------------------------------------ - static const char * GetPluginNameStatic (); @@ -48,7 +42,18 @@ namespace lldb_private { static const char * GetDescriptionStatic(); + + //------------------------------------------------------------ + // Class Methods + //------------------------------------------------------------ + PlatformRemoteiOS (); + virtual + ~PlatformRemoteiOS(); + + //------------------------------------------------------------ + // lldb_private::PluginInterface functions + //------------------------------------------------------------ virtual const char * GetPluginName() { @@ -100,23 +105,6 @@ namespace lldb_private { 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: std::string m_device_support_directory; std::string m_device_support_directory_for_os_version; diff --git a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp index f8a73a3826d..6c955e0a18e 100644 --- a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp +++ b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp @@ -15,8 +15,9 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/Core/Error.h" #include "lldb/Breakpoint/BreakpointLocation.h" +#include "lldb/Core/ConnectionFileDescriptor.h" +#include "lldb/Core/Error.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/PluginManager.h" @@ -107,50 +108,6 @@ PlatformRemoteGDBServer::GetFile (const FileSpec &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 //------------------------------------------------------------------ @@ -198,27 +155,77 @@ PlatformRemoteGDBServer::GetSoftwareBreakpointTrapOpcode (Target &target, Breakp } bool -PlatformRemoteGDBServer::FetchRemoteOSVersion () +PlatformRemoteGDBServer::GetRemoteOSVersion () { + uint32_t major, minor, update; + if (m_gdb_client.GetOSVersion (major, minor, update)) + { + m_major_os_version = major; + m_minor_os_version = minor; + m_update_os_version = update; + return true; + } return false; } +bool +PlatformRemoteGDBServer::GetRemoteOSBuildString (std::string &s) +{ + return m_gdb_client.GetOSBuildString (s); +} + +bool +PlatformRemoteGDBServer::GetRemoteOSKernelDescription (std::string &s) +{ + return m_gdb_client.GetOSKernelDescription (s); +} + +// Remote Platform subclasses need to override this function +ArchSpec +PlatformRemoteGDBServer::GetRemoteSystemArchitecture () +{ + return m_gdb_client.GetSystemArchitecture(); +} + +bool +PlatformRemoteGDBServer::IsConnected () const +{ + return m_gdb_client.IsConnected(); +} + Error PlatformRemoteGDBServer::ConnectRemote (Args& args) { Error error; - if (args.GetArgumentCount() == 1) + if (IsConnected()) { - const char *remote_url = args.GetArgumentAtIndex(0); - ConnectionStatus status = m_gdb_client.Connect(remote_url, &error); - if (status == eConnectionStatusSuccess) - { - m_gdb_client.GetHostInfo(); - } + error.SetErrorStringWithFormat ("the platform is already connected to '%s', execute 'platform disconnect' to close the current connection", + GetHostname()); } else { - error.SetErrorString ("\"platform connect\" takes a single argument: <connect-url>"); + if (args.GetArgumentCount() == 1) + { + const char *url = args.GetArgumentAtIndex(0); + m_gdb_client.SetConnection (new ConnectionFileDescriptor()); + const ConnectionStatus status = m_gdb_client.Connect(url, &error); + if (status == eConnectionStatusSuccess) + { + if (m_gdb_client.HandshakeWithServer(&error)) + { + m_gdb_client.QueryNoAckModeSupported(); + m_gdb_client.GetHostInfo(); + } + else + { + m_gdb_client.Disconnect(); + } + } + } + else + { + error.SetErrorString ("\"platform connect\" takes a single argument: <connect-url>"); + } } return error; @@ -233,8 +240,11 @@ PlatformRemoteGDBServer::DisconnectRemote () } const char * -PlatformRemoteGDBServer::GetRemoteInstanceName () +PlatformRemoteGDBServer::GetRemoteHostname () { - return NULL; + m_gdb_client.GetHostname (m_name); + if (m_name.empty()) + return NULL; + return m_name.c_str(); } diff --git a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h index 6c322d38c9c..9551cd8a081 100644 --- a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h +++ b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h @@ -79,9 +79,6 @@ namespace lldb_private { virtual const char * GetDescription (); - virtual void - GetStatus (Stream &strm); - virtual Error GetFile (const FileSpec &platform_file, const UUID *uuid_ptr, @@ -103,7 +100,25 @@ namespace lldb_private { BreakpointSite *bp_site); virtual bool - FetchRemoteOSVersion (); + GetRemoteOSVersion (); + + virtual bool + GetRemoteOSBuildString (std::string &s); + + virtual bool + GetRemoteOSKernelDescription (std::string &s); + + // Remote Platform subclasses need to override this function + virtual ArchSpec + GetRemoteSystemArchitecture (); + + // Remote subclasses should override this and return a valid instance + // name if connected. + virtual const char * + GetRemoteHostname (); + + virtual bool + IsConnected () const; virtual Error ConnectRemote (Args& args); @@ -111,9 +126,6 @@ namespace lldb_private { 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 diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp index 707fe46c26f..15ab58975cc 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -32,7 +32,8 @@ GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name, const char m_rx_packet_listener (listener_name), m_sequence_mutex (Mutex::eMutexTypeRecursive), m_public_is_running (false), - m_private_is_running (false) + m_private_is_running (false), + m_send_acks (true) { m_rx_packet_listener.StartListeningForEvents(this, Communication::eBroadcastBitPacketAvailable | @@ -127,7 +128,10 @@ GDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_le if (GetSendAcks ()) { if (GetAck () != '+') + { + printf("get ack failed..."); return 0; + } } } else @@ -238,9 +242,10 @@ GDBRemoteCommunication::WaitForPacketNoLock (StringExtractorGDBRemote &packet, c } } } - else if (Communication::eBroadcastBitReadThreadDidExit) + else if (event_type | Communication::eBroadcastBitReadThreadDidExit) { // Our read thread exited on us so just fall through and return zero... + Disconnect(); } } return 0; diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h index 858f67c6534..e8129ce919f 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h @@ -88,15 +88,18 @@ public: return m_public_is_running.GetValue(); } + bool + GetSendAcks () + { + return m_send_acks; + } + //------------------------------------------------------------------ // Client and server must implement these pure virtual functions //------------------------------------------------------------------ virtual bool GetThreadSuffixSupported () = 0; - virtual bool - GetSendAcks () = 0; - //------------------------------------------------------------------ // Set the global packet timeout. // @@ -135,6 +138,10 @@ protected: lldb_private::Mutex m_sequence_mutex; // Restrict access to sending/receiving packets to a single thread at a time lldb_private::Predicate<bool> m_public_is_running; lldb_private::Predicate<bool> m_private_is_running; + bool m_send_acks; + + + private: //------------------------------------------------------------------ diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index 7700ab2b7f5..e158e5c6237 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -50,7 +50,10 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient() : m_async_packet (), m_async_response (), m_async_signal (-1), - m_host_arch() + m_host_arch(), + m_os_version_major (UINT32_MAX), + m_os_version_minor (UINT32_MAX), + m_os_version_update (UINT32_MAX) { m_rx_packet_listener.StartListeningForEvents(this, Communication::eBroadcastBitPacketAvailable | @@ -73,19 +76,36 @@ GDBRemoteCommunicationClient::~GDBRemoteCommunicationClient() } bool -GDBRemoteCommunicationClient::GetSendAcks () +GDBRemoteCommunicationClient::HandshakeWithServer (Error *error_ptr) +{ + // Start the read thread after we send the handshake ack since if we + // fail to send the handshake ack, there is no reason to continue... + if (SendAck()) + return StartReadThread (error_ptr); + + if (error_ptr) + error_ptr->SetErrorString("failed to send the handshake ack"); + return false; +} + +void +GDBRemoteCommunicationClient::QueryNoAckModeSupported () { if (m_supports_not_sending_acks == eLazyBoolCalculate) { - StringExtractorGDBRemote response; + m_send_acks = true; m_supports_not_sending_acks = eLazyBoolNo; + + StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse("QStartNoAckMode", response, false)) { if (response.IsOKResponse()) + { + m_send_acks = false; m_supports_not_sending_acks = eLazyBoolYes; + } } } - return m_supports_not_sending_acks != eLazyBoolYes; } void @@ -664,6 +684,79 @@ GDBRemoteCommunicationClient::SendEnvironmentPacket (char const *name_equal_valu } bool +GDBRemoteCommunicationClient::GetOSVersion (uint32_t &major, + uint32_t &minor, + uint32_t &update) +{ + if (GetHostInfo ()) + { + if (m_os_version_major != UINT32_MAX) + { + major = m_os_version_major; + minor = m_os_version_minor; + update = m_os_version_update; + return true; + } + } + return false; +} + +bool +GDBRemoteCommunicationClient::GetOSBuildString (std::string &s) +{ + if (GetHostInfo ()) + { + if (!m_os_build.empty()) + { + s = m_os_build; + return true; + } + } + s.clear(); + return false; +} + + +bool +GDBRemoteCommunicationClient::GetOSKernelDescription (std::string &s) +{ + if (GetHostInfo ()) + { + if (!m_os_kernel.empty()) + { + s = m_os_kernel; + return true; + } + } + s.clear(); + return false; +} + +bool +GDBRemoteCommunicationClient::GetHostname (std::string &s) +{ + if (GetHostInfo ()) + { + if (!m_hostname.empty()) + { + s = m_hostname; + return true; + } + } + s.clear(); + return false; +} + +ArchSpec +GDBRemoteCommunicationClient::GetSystemArchitecture () +{ + if (GetHostInfo ()) + return m_host_arch; + return ArchSpec(); +} + + +bool GDBRemoteCommunicationClient::GetHostInfo () { if (m_supports_qHostInfo == eLazyBoolCalculate) @@ -685,7 +778,9 @@ GDBRemoteCommunicationClient::GetHostInfo () std::string arch_name; std::string os_name; std::string vendor_name; + std::string triple; uint32_t pointer_byte_size = 0; + StringExtractor extractor; ByteOrder byte_order = eByteOrderInvalid; while (response.GetNameColonValue(name, value)) { @@ -703,6 +798,31 @@ GDBRemoteCommunicationClient::GetHostInfo () { arch_name.swap (value); } + else if (name.compare("triple") == 0) + { + // The triple comes as ASCII hex bytes since it contains '-' chars + extractor.GetStringRef().swap(value); + extractor.SetFilePos(0); + extractor.GetHexByteString (triple); + } + else if (name.compare("os_build") == 0) + { + extractor.GetStringRef().swap(value); + extractor.SetFilePos(0); + extractor.GetHexByteString (m_os_build); + } + else if (name.compare("hostname") == 0) + { + extractor.GetStringRef().swap(value); + extractor.SetFilePos(0); + extractor.GetHexByteString (m_hostname); + } + else if (name.compare("os_kernel") == 0) + { + extractor.GetStringRef().swap(value); + extractor.SetFilePos(0); + extractor.GetHexByteString (m_os_kernel); + } else if (name.compare("ostype") == 0) { os_name.swap (value); @@ -724,13 +844,52 @@ GDBRemoteCommunicationClient::GetHostInfo () { pointer_byte_size = Args::StringToUInt32 (value.c_str(), 0, 0); } + else if (name.compare("os_version") == 0) + { + Args::StringToVersion (value.c_str(), + m_os_version_major, + m_os_version_minor, + m_os_version_update); + } } - if (arch_name.empty()) + if (triple.empty()) { - if (cpu != LLDB_INVALID_CPUTYPE) + 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 { - m_host_arch.SetArchitecture (lldb::eArchTypeMachO, cpu, sub); + 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()); if (pointer_byte_size) { assert (pointer_byte_size == m_host_arch.GetAddressByteSize()); @@ -739,29 +898,21 @@ GDBRemoteCommunicationClient::GetHostInfo () { 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()); - } + if (pointer_byte_size) + { + assert (pointer_byte_size == m_host_arch.GetAddressByteSize()); + } + if (byte_order != eByteOrderInvalid) + { + assert (byte_order == m_host_arch.GetByteOrder()); + } + } } } return m_supports_qHostInfo == eLazyBoolYes; diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index bcf23f2c589..410d80de316 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -29,6 +29,13 @@ public: virtual ~GDBRemoteCommunicationClient(); + //------------------------------------------------------------------ + // After connecting, send the handshake to the server to make sure + // we are communicating with it. + //------------------------------------------------------------------ + bool + HandshakeWithServer (lldb_private::Error *error_ptr); + size_t SendPacketAndWaitForResponse (const char *send_payload, StringExtractorGDBRemote &response, @@ -49,8 +56,8 @@ public: virtual bool GetThreadSuffixSupported (); - virtual bool - GetSendAcks (); + void + QueryNoAckModeSupported (); bool SendAsyncSignal (int signo); @@ -186,6 +193,23 @@ public: GetHostInfo (); bool + GetOSVersion (uint32_t &major, + uint32_t &minor, + uint32_t &update); + + bool + GetOSBuildString (std::string &s); + + bool + GetOSKernelDescription (std::string &s); + + lldb_private::ArchSpec + GetSystemArchitecture (); + + bool + GetHostname (std::string &s); + + bool GetSupportsThreadSuffix (); bool @@ -232,7 +256,12 @@ protected: int m_async_signal; // We were asked to deliver a signal to the inferior process. lldb_private::ArchSpec m_host_arch; - uint32_t m_cpusubtype; + uint32_t m_os_version_major; + uint32_t m_os_version_minor; + uint32_t m_os_version_update; + std::string m_os_build; + std::string m_os_kernel; + std::string m_hostname; private: //------------------------------------------------------------------ diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp index 18d6087e8b5..faee6776a83 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp @@ -35,8 +35,7 @@ using namespace lldb_private; //---------------------------------------------------------------------- GDBRemoteCommunicationServer::GDBRemoteCommunicationServer() : GDBRemoteCommunication ("gdb-remote.server", "gdb-remote.server.rx_packet"), - m_async_thread (LLDB_INVALID_HOST_THREAD), - m_send_acks (true) + m_async_thread (LLDB_INVALID_HOST_THREAD) { } @@ -73,6 +72,7 @@ GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer() // bool GDBRemoteCommunicationServer::GetPacketAndSendResponse (const TimeValue* timeout_ptr, + Error &error, bool &interrupt, bool &quit) { @@ -87,10 +87,12 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (const TimeValue* timeout break; case StringExtractorGDBRemote::eServerPacketType_invalid: + error.SetErrorString("invalid packet"); quit = true; break; case StringExtractorGDBRemote::eServerPacketType_interrupt: + error.SetErrorString("interrupt received"); interrupt = true; break; @@ -99,9 +101,20 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (const TimeValue* timeout case StringExtractorGDBRemote::eServerPacketType_qHostInfo: return Handle_qHostInfo (); + + case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode: + return Handle_QStartNoAckMode (); } return true; } + else + { + if (!IsConnected()) + error.SetErrorString("lost connection"); + else + error.SetErrorString("timeout"); + } + return false; } @@ -111,6 +124,19 @@ GDBRemoteCommunicationServer::SendUnimplementedResponse () return SendPacket (""); } +size_t +GDBRemoteCommunicationServer::SendOKResponse () +{ + return SendPacket ("OK"); +} + +bool +GDBRemoteCommunicationServer::HandshakeWithClient(Error *error_ptr) +{ + if (StartReadThread(error_ptr)) + return GetAck(); + return false; +} bool GDBRemoteCommunicationServer::Handle_qHostInfo () @@ -120,17 +146,18 @@ GDBRemoteCommunicationServer::Handle_qHostInfo () // $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00 ArchSpec host_arch (Host::GetArchitecture ()); - const llvm::Triple &host_triple = host_arch.GetTriple(); - const llvm::StringRef arch_name (host_triple.getArchName()); - const llvm::StringRef vendor_name (host_triple.getOSName()); - const llvm::StringRef os_name (host_triple.getVendorName()); - response.Printf ("arch:%.*s;ostype:%.*s;vendor:%.*s;ptrsize:%u", - (int)arch_name.size(), arch_name.data(), - (int)os_name.size(), os_name.data(), - (int)vendor_name.size(), vendor_name.data(), - host_arch.GetAddressByteSize()); - + response.PutCString("triple:"); + response.PutCStringAsRawHex8(host_triple.getTriple().c_str()); + response.Printf (";ptrsize:%u;",host_arch.GetAddressByteSize()); + + uint32_t cpu = host_arch.GetMachOCPUType(); + uint32_t sub = host_arch.GetMachOCPUSubType(); + if (cpu != LLDB_INVALID_CPUTYPE) + response.Printf ("cputype:%u;", cpu); + if (sub != LLDB_INVALID_CPUTYPE) + response.Printf ("cpusubtype:%u;", sub); + switch (lldb::endian::InlHostByteOrder()) { case eByteOrderBig: response.PutCString ("endian:big;"); break; @@ -139,5 +166,52 @@ GDBRemoteCommunicationServer::Handle_qHostInfo () default: response.PutCString ("endian:unknown;"); break; } + uint32_t major = UINT32_MAX; + uint32_t minor = UINT32_MAX; + uint32_t update = UINT32_MAX; + if (Host::GetOSVersion (major, minor, update)) + { + if (major != UINT32_MAX) + { + response.Printf("os_version:%u", major); + if (minor != UINT32_MAX) + { + response.Printf(".%u", minor); + if (update != UINT32_MAX) + response.Printf(".%u", update); + } + response.PutChar(';'); + } + } + + std::string s; + if (Host::GetOSBuildString (s)) + { + response.PutCString ("os_build:"); + response.PutCStringAsRawHex8(s.c_str()); + response.PutChar(';'); + } + if (Host::GetOSKernelDescription (s)) + { + response.PutCString ("os_kernel:"); + response.PutCStringAsRawHex8(s.c_str()); + response.PutChar(';'); + } + if (Host::GetHostname (s)) + { + response.PutCString ("hostname:"); + response.PutCStringAsRawHex8(s.c_str()); + response.PutChar(';'); + } + return SendPacket (response.GetString().c_str(),response.GetString().size()) > 0; } + + +bool +GDBRemoteCommunicationServer::Handle_QStartNoAckMode () +{ + SendOKResponse (); + m_send_acks = false; + return true; +} diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h index 4e0b24ddea0..66ddc77bc95 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h @@ -35,6 +35,7 @@ public: bool GetPacketAndSendResponse (const lldb_private::TimeValue* timeout_ptr, + lldb_private::Error &error, bool &interrupt, bool &quit); @@ -44,23 +45,26 @@ public: return true; } - virtual bool - GetSendAcks () - { - return m_send_acks; - } + // After connecting, do a little handshake with the client to make sure + // we are at least communicating + bool + HandshakeWithClient (lldb_private::Error *error_ptr); protected: lldb::thread_t m_async_thread; - bool m_send_acks; size_t SendUnimplementedResponse (); + size_t + SendOKResponse (); bool Handle_qHostInfo (); + bool + Handle_QStartNoAckMode (); + private: //------------------------------------------------------------------ // For GDBRemoteCommunicationServer only diff --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp index a6df50d9e70..0f025147608 100644 --- a/lldb/source/Target/Platform.cpp +++ b/lldb/source/Target/Platform.cpp @@ -121,11 +121,10 @@ Platform::GetConnectedRemotePlatformAtIndex (uint32_t idx) //------------------------------------------------------------------ Platform::Platform (bool is_host) : m_is_host (is_host), - m_is_connected (is_host), // If this is the default host platform, then we are always connected m_os_version_set_while_connected (false), m_system_arch_set_while_connected (false), m_remote_url (), - m_remote_instance_name (), + m_name (), m_major_os_version (UINT32_MAX), m_minor_os_version (UINT32_MAX), m_update_os_version (UINT32_MAX) @@ -142,6 +141,52 @@ Platform::~Platform() { } +void +Platform::GetStatus (Stream &strm) +{ + uint32_t major = UINT32_MAX; + uint32_t minor = UINT32_MAX; + uint32_t update = UINT32_MAX; + std::string s; + strm.Printf ("Platform: %s\n", GetShortPluginName()); + + ArchSpec arch (GetSystemArchitecture()); + if (arch.IsValid()) + { + if (!arch.GetTriple().str().empty()) + strm.Printf("Triple: %s\n", arch.GetTriple().str().c_str()); + } + + if (GetOSVersion(major, minor, update)) + { + strm.Printf("OS: %u", major); + if (minor != UINT32_MAX) + strm.Printf(".%u", minor); + if (update != UINT32_MAX) + strm.Printf(".%u", update); + + if (GetOSBuildString (s)) + strm.Printf(" (%s)", s.c_str()); + + strm.EOL(); + } + + if (GetOSKernelDescription (s)) + strm.Printf("Kernel: %s\n", s.c_str()); + + if (IsHost()) + { + strm.Printf("Hostname: %s\n", GetHostname()); + } + else + { + if (IsConnected()) + strm.Printf("Remote hostname: %s\n", GetHostname()); + else + strm.PutCString("Not connected to a remote platform.\n"); + } +} + bool Platform::GetOSVersion (uint32_t &major, @@ -168,7 +213,7 @@ Platform::GetOSVersion (uint32_t &major, const bool is_connected = IsConnected(); - bool fetch_os_version = false; + bool fetch = false; if (success) { // We have valid OS version info, check to make sure it wasn't @@ -176,17 +221,17 @@ Platform::GetOSVersion (uint32_t &major, // to connecting, then lets fetch the actual OS version info // if we are now connected. if (is_connected && !m_os_version_set_while_connected) - fetch_os_version = true; + fetch = true; } else { // We don't have valid OS version info, fetch it if we are connected - fetch_os_version = is_connected; + fetch = is_connected; } - if (fetch_os_version) + if (fetch) { - success = FetchRemoteOSVersion (); + success = GetRemoteOSVersion (); m_os_version_set_while_connected = success; } } @@ -199,7 +244,56 @@ Platform::GetOSVersion (uint32_t &major, } return success; } - + +bool +Platform::GetOSBuildString (std::string &s) +{ + if (IsHost()) + return Host::GetOSBuildString (s); + else + return GetRemoteOSBuildString (s); +} + +bool +Platform::GetOSKernelDescription (std::string &s) +{ + if (IsHost()) + return Host::GetOSKernelDescription (s); + else + return GetRemoteOSKernelDescription (s); +} + +const char * +Platform::GetHostname () +{ + if (m_name.empty()) + { + if (IsHost()) + { + if (!Host::GetHostname(m_name)) + return "localhost"; + } + else + { + if (IsConnected()) + { + const char *instance_name = GetRemoteHostname (); + if (instance_name) + m_name.assign (instance_name); + } + else + { + return "remote"; + } + } + } + if (!m_name.empty()) + return m_name.c_str(); + return NULL; +} + + + bool Platform::SetOSVersion (uint32_t major, uint32_t minor, @@ -324,7 +418,7 @@ Platform::GetSystemArchitecture() if (fetch) { - m_system_arch = FetchRemoteSystemArchitecture (); + m_system_arch = GetRemoteSystemArchitecture (); m_system_arch_set_while_connected = m_system_arch.IsValid(); } } diff --git a/lldb/source/Utility/StringExtractorGDBRemote.cpp b/lldb/source/Utility/StringExtractorGDBRemote.cpp index e78aff73e58..4ac07b5cf85 100644 --- a/lldb/source/Utility/StringExtractorGDBRemote.cpp +++ b/lldb/source/Utility/StringExtractorGDBRemote.cpp @@ -75,6 +75,11 @@ StringExtractorGDBRemote::GetServerPacketType () const return eServerPacketType_ack; break; + case 'Q': + if (strcmp (packet_cstr, "QStartNoAckMode") == 0) + return eServerPacketType_QStartNoAckMode; + break; + case 'q': if (strcmp (packet_cstr, "qHostInfo") == 0) return eServerPacketType_qHostInfo; diff --git a/lldb/source/Utility/StringExtractorGDBRemote.h b/lldb/source/Utility/StringExtractorGDBRemote.h index 5b2ea374288..d2b94d1302a 100644 --- a/lldb/source/Utility/StringExtractorGDBRemote.h +++ b/lldb/source/Utility/StringExtractorGDBRemote.h @@ -46,7 +46,8 @@ public: eServerPacketType_invalid, eServerPacketType_unimplemented, eServerPacketType_interrupt, // CTRL+c packet or "\x03" - eServerPacketType_qHostInfo + eServerPacketType_qHostInfo, + eServerPacketType_QStartNoAckMode }; ServerPacketType diff --git a/lldb/source/lldb.cpp b/lldb/source/lldb.cpp index 6f219d446ff..f6a30ed7052 100644 --- a/lldb/source/lldb.cpp +++ b/lldb/source/lldb.cpp @@ -54,6 +54,7 @@ #include "Plugins/Process/Linux/ProcessLinux.h" #endif +#include "Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h" #include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h" using namespace lldb; @@ -86,6 +87,9 @@ lldb_private::Initialize () ArchVolatileRegs_x86::Initialize(); #if defined (__APPLE__) + //---------------------------------------------------------------------- + // Apple/Darwin hosted plugins + //---------------------------------------------------------------------- ABIMacOSX_i386::Initialize(); ABISysV_x86_64::Initialize(); DynamicLoaderMacOSXDYLD::Initialize(); @@ -102,11 +106,19 @@ lldb_private::Initialize () PlatformRemoteiOS::Initialize(); #endif #if defined (__linux__) + //---------------------------------------------------------------------- + // Linux hosted plugins + //---------------------------------------------------------------------- PlatformLinux::Initialize(); ProcessLinux::Initialize(); DynamicLoaderLinuxDYLD::Initialize(); #endif + //---------------------------------------------------------------------- + // Platform agnostic plugins + //---------------------------------------------------------------------- + PlatformRemoteGDBServer::Initialize (); DynamicLoaderStatic::Initialize(); + // Scan for any system or user LLDB plug-ins PluginManager::Initialize(); diff --git a/lldb/tools/lldb-platform/lldb-platform.cpp b/lldb/tools/lldb-platform/lldb-platform.cpp index 736daeb4d20..8e4174ec4e4 100644 --- a/lldb/tools/lldb-platform/lldb-platform.cpp +++ b/lldb/tools/lldb-platform/lldb-platform.cpp @@ -21,8 +21,10 @@ // Other libraries and framework includes #include "lldb/Core/Error.h" #include "lldb/Core/ConnectionFileDescriptor.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/StreamFile.h" #include "GDBRemoteCommunicationServer.h" - +#include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h" using namespace lldb; using namespace lldb_private; @@ -66,12 +68,14 @@ main (int argc, char *argv[]) { signal (SIGPIPE, signal_handler); int long_option_index = 0; - FILE* log_file = NULL; - uint32_t log_flags = 0; - std::string connect_url; + StreamSP log_stream_sp; + Args log_args; + std::string listen_host_post; char ch; + Debugger::Initialize(); + - while ((ch = getopt_long(argc, argv, "l:f:", g_long_options, &long_option_index)) != -1) + while ((ch = getopt_long(argc, argv, "l:f:L:", g_long_options, &long_option_index)) != -1) { // DNBLogDebug("option: ch == %c (0x%2.2x) --%s%c%s\n", // ch, (uint8_t)ch, @@ -86,37 +90,51 @@ main (int argc, char *argv[]) case 'l': // Set Log File if (optarg && optarg[0]) { - if (strcasecmp(optarg, "stdout") == 0) - log_file = stdout; - else if (strcasecmp(optarg, "stderr") == 0) - log_file = stderr; + if ((strcasecmp(optarg, "stdout") == 0) || (strcmp(optarg, "/dev/stdout") == 0)) + { + log_stream_sp.reset (new StreamFile (stdout, false)); + } + else if ((strcasecmp(optarg, "stderr") == 0) || (strcmp(optarg, "/dev/stderr") == 0)) + { + log_stream_sp.reset (new StreamFile (stderr, false)); + } else { - log_file = fopen(optarg, "w"); - if (log_file != NULL) + FILE *log_file = fopen(optarg, "w"); + if (log_file) + { setlinebuf(log_file); + log_stream_sp.reset (new StreamFile (log_file, true)); + } + else + { + const char *errno_str = strerror(errno); + fprintf (stderr, "Failed to open log file '%s' for writing: errno = %i (%s)", optarg, errno, errno_str ? errno_str : "unknown error"); + } + } - if (log_file == NULL) - { - const char *errno_str = strerror(errno); - fprintf (stderr, "Failed to open log file '%s' for writing: errno = %i (%s)", optarg, errno, errno_str ? errno_str : "unknown error"); - } } break; case 'f': // Log Flags if (optarg && optarg[0]) - log_flags = strtoul(optarg, NULL, 0); + log_args.AppendArgument(optarg); break; case 'L': - connect_url.assign ("connect://"); - connect_url.append (optarg); + listen_host_post.append (optarg); break; } } + if (log_stream_sp) + { + if (log_args.GetArgumentCount() == 0) + log_args.AppendArgument("default"); + ProcessGDBRemoteLog::EnableLog (log_stream_sp, 0,log_args, log_stream_sp.get()); + } + // Skip any options we consumed with getopt_long argc -= optind; argv += optind; @@ -124,26 +142,19 @@ main (int argc, char *argv[]) GDBRemoteCommunicationServer gdb_server; Error error; - if (!connect_url.empty()) + if (!listen_host_post.empty()) { std::auto_ptr<ConnectionFileDescriptor> 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++; + std::string connect_url ("listen://"); + connect_url.append(listen_host_post.c_str()); - if (retry_count >= max_retry_count) - break; - - usleep (100000); + printf ("Listening for a connection on %s...\n", listen_host_post.c_str()); + if (conn_ap->Connect(connect_url.c_str(), &error) == eConnectionStatusSuccess) + { + printf ("Connection established.\n"); + gdb_server.SetConnection (conn_ap.release()); } } } @@ -151,19 +162,24 @@ main (int argc, char *argv[]) if (gdb_server.IsConnected()) { - if (gdb_server.StartReadThread(&error)) + // After we connected, we need to get an initial ack from... + if (gdb_server.HandshakeWithClient(&error)) { bool interrupt = false; bool done = false; while (!interrupt && !done) { - gdb_server.GetPacketAndSendResponse(NULL, interrupt, done); + if (!gdb_server.GetPacketAndSendResponse(NULL, error, interrupt, done)) + break; } } else { + fprintf(stderr, "error: handshake with client failed\n"); } } + Debugger::Terminate(); + return 0; } |