diff options
Diffstat (limited to 'lldb/source/Plugins')
14 files changed, 956 insertions, 543 deletions
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 |