Added new platform commands:

platform connect <args>
platform disconnect

Each platform can decide the args they want to use for "platform connect". I 
will need to add a function that gets the connect options for the current
platform as each one can have different options and argument counts.

Hooked up more functionality in the PlatformMacOSX and PlatformRemoteiOS.
Also started an platform agnostic PlatformRemoteGDBServer.cpp which can end
up being used by one or more actual platforms. It can also be specialized and
allow for platform specific commands.

llvm-svn: 128123
This commit is contained in:
Greg Clayton 2011-03-23 00:09:55 +00:00
parent 7ca3ddc233
commit d314e810a7
19 changed files with 847 additions and 134 deletions

View File

@ -115,6 +115,23 @@ namespace lldb_private {
uint32_t minor,
uint32_t update);
const char *
GetInstanceName ()
{
if (IsHost())
return "localhost";
if (IsConnected())
{
if (m_remote_instance_name.empty())
GetRemoteInstanceName ();
if (!m_remote_instance_name.empty())
return m_remote_instance_name.c_str();
}
return "remote";
}
virtual const char *
GetDescription () = 0;
@ -164,13 +181,24 @@ protected:
//------------------------------------------------------------------
public:
virtual Error
GetFile (const FileSpec &platform_file, FileSpec &local_file);
GetFile (const FileSpec &platform_file,
const UUID *uuid_ptr,
FileSpec &local_file);
virtual Error
ConnectRemote (const char *remote_url);
ConnectRemote (Args& args);
virtual Error
DisconnectRemote (const lldb::PlatformSP &platform_sp);
DisconnectRemote ();
// Remote subclasses should override this and return a valid instance
// name if connected.
virtual const char *
GetRemoteInstanceName ()
{
return NULL;
}
//------------------------------------------------------------------
/// Get the platform's supported architectures in the order in which
@ -356,6 +384,7 @@ public:
bool m_os_version_set_while_connected;
bool m_system_arch_set_while_connected;
std::string m_remote_url;
std::string m_remote_instance_name;
uint32_t m_major_os_version;
uint32_t m_minor_os_version;
uint32_t m_update_os_version;

View File

@ -13,6 +13,8 @@
262CFC7711A4510000946C6C /* debugserver in Resources */ = {isa = PBXBuildFile; fileRef = 26CE05A0115C31E50022F371 /* debugserver */; };
26368A3C126B697600E8659F /* darwin-debug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26368A3B126B697600E8659F /* darwin-debug.cpp */; };
26368AF7126B960500E8659F /* darwin-debug in Resources */ = {isa = PBXBuildFile; fileRef = 26579F68126A25920007C5CB /* darwin-debug */; };
264A97BF133918BC0017F0BE /* PlatformRemoteGDBServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 264A97BD133918BC0017F0BE /* PlatformRemoteGDBServer.cpp */; };
264A97C0133918BC0017F0BE /* PlatformRemoteGDBServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 264A97BE133918BC0017F0BE /* PlatformRemoteGDBServer.h */; };
265ABF6310F42EE900531910 /* DebugSymbols.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 265ABF6210F42EE900531910 /* DebugSymbols.framework */; };
2668020E115FD12C008E1FE4 /* lldb-defines.h in Headers */ = {isa = PBXBuildFile; fileRef = 26BC7C2510F1B3BC00F91463 /* lldb-defines.h */; settings = {ATTRIBUTES = (Public, ); }; };
2668020F115FD12C008E1FE4 /* lldb-enumerations.h in Headers */ = {isa = PBXBuildFile; fileRef = 26BC7C2610F1B3BC00F91463 /* lldb-enumerations.h */; settings = {ATTRIBUTES = (Public, ); }; };
@ -615,6 +617,8 @@
264723A511FA076E00DE380C /* CleanUp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CleanUp.h; path = include/lldb/Utility/CleanUp.h; sourceTree = "<group>"; };
264A43BB1320B3B4005B4096 /* Platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Platform.h; path = include/lldb/Target/Platform.h; sourceTree = "<group>"; };
264A43BD1320BCEB005B4096 /* Platform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Platform.cpp; path = source/Target/Platform.cpp; sourceTree = "<group>"; };
264A97BD133918BC0017F0BE /* PlatformRemoteGDBServer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PlatformRemoteGDBServer.cpp; path = "gdb-server/PlatformRemoteGDBServer.cpp"; sourceTree = "<group>"; };
264A97BE133918BC0017F0BE /* PlatformRemoteGDBServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PlatformRemoteGDBServer.h; path = "gdb-server/PlatformRemoteGDBServer.h"; sourceTree = "<group>"; };
264AD83711095BA600E0B039 /* CommandObjectLog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectLog.cpp; path = source/Commands/CommandObjectLog.cpp; sourceTree = "<group>"; };
264AD83911095BBD00E0B039 /* CommandObjectLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectLog.h; path = source/Commands/CommandObjectLog.h; sourceTree = "<group>"; };
26579F68126A25920007C5CB /* darwin-debug */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "darwin-debug"; sourceTree = BUILT_PRODUCTS_DIR; };
@ -1630,6 +1634,15 @@
name = API;
sourceTree = "<group>";
};
264A97BC133918A30017F0BE /* GDB Server */ = {
isa = PBXGroup;
children = (
264A97BD133918BC0017F0BE /* PlatformRemoteGDBServer.cpp */,
264A97BE133918BC0017F0BE /* PlatformRemoteGDBServer.h */,
);
name = "GDB Server";
sourceTree = "<group>";
};
26579F55126A255E0007C5CB /* darwin-debug */ = {
isa = PBXGroup;
children = (
@ -2224,6 +2237,7 @@
26C5577E132575B6008FD8FE /* Platform */ = {
isa = PBXGroup;
children = (
264A97BC133918A30017F0BE /* GDB Server */,
26C5577F132575C8008FD8FE /* MacOSX */,
);
path = Platform;
@ -2497,6 +2511,7 @@
2689001013353DB600698AC0 /* WatchpointLocation.h in Headers */,
26744EF21338317700EF765A /* GDBRemoteCommunicationClient.h in Headers */,
26744EF41338317700EF765A /* GDBRemoteCommunicationServer.h in Headers */,
264A97C0133918BC0017F0BE /* PlatformRemoteGDBServer.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -3054,6 +3069,7 @@
26B1FCC21338115F002886E2 /* Host.mm in Sources */,
26744EF11338317700EF765A /* GDBRemoteCommunicationClient.cpp in Sources */,
26744EF31338317700EF765A /* GDBRemoteCommunicationServer.cpp in Sources */,
264A97BF133918BC0017F0BE /* PlatformRemoteGDBServer.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -3569,12 +3585,14 @@
isa = XCBuildConfiguration;
buildSettings = {
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"",
);
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_CPP_RTTI = NO;
GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
GCC_MODEL_TUNING = G5;
GCC_OPTIMIZATION_LEVEL = 0;
INSTALL_PATH = /usr/local/bin;
@ -3594,12 +3612,14 @@
isa = XCBuildConfiguration;
buildSettings = {
COPY_PHASE_STRIP = YES;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"",
);
GCC_ENABLE_CPP_RTTI = NO;
GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
GCC_MODEL_TUNING = G5;
INSTALL_PATH = /usr/local/bin;
OTHER_LDFLAGS = (
@ -3618,11 +3638,13 @@
26DC6A141337FE6A00FF7998 /* BuildAndIntegration */ = {
isa = XCBuildConfiguration;
buildSettings = {
DEAD_CODE_STRIPPING = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"",
);
GCC_ENABLE_CPP_RTTI = NO;
GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
GCC_MODEL_TUNING = G5;
INSTALL_PATH = /usr/local/bin;
OTHER_LDFLAGS = (

View File

@ -281,6 +281,137 @@ public:
};
//----------------------------------------------------------------------
// "platform connect <connect-url>"
//----------------------------------------------------------------------
class CommandObjectPlatformConnect : public CommandObject
{
public:
CommandObjectPlatformConnect (CommandInterpreter &interpreter) :
CommandObject (interpreter,
"platform connect",
"Connect a platform by name to be the currently selected platform.",
"platform connect <connect-url>",
0)
{
}
virtual
~CommandObjectPlatformConnect ()
{
}
virtual bool
Execute (Args& args, CommandReturnObject &result)
{
Stream &ostrm = result.GetOutputStream();
// Get rid of the "connect" from the args and leave the rest to the platform
args.Shift();
PlatformSP selected_platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
if (selected_platform_sp)
{
Error error (selected_platform_sp->ConnectRemote (args));
if (error.Success())
{
ostrm.Printf ("Connected to \"%s\"\n", selected_platform_sp->GetInstanceName());
selected_platform_sp->GetStatus (ostrm);
result.SetStatus (eReturnStatusSuccessFinishResult);
}
else
{
result.AppendErrorWithFormat ("connection failed: %s", error.AsCString());
result.SetStatus (eReturnStatusFailed);
}
}
else
{
result.AppendError ("no platform us currently selected");
result.SetStatus (eReturnStatusFailed);
}
return result.Succeeded();
}
};
//----------------------------------------------------------------------
// "platform disconnect"
//----------------------------------------------------------------------
class CommandObjectPlatformDisconnect : public CommandObject
{
public:
CommandObjectPlatformDisconnect (CommandInterpreter &interpreter) :
CommandObject (interpreter,
"platform disconnect",
"Disconnect a platform by name to be the currently selected platform.",
"platform disconnect",
0)
{
}
virtual
~CommandObjectPlatformDisconnect ()
{
}
virtual bool
Execute (Args& args, CommandReturnObject &result)
{
PlatformSP selected_platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
if (selected_platform_sp)
{
if (args.GetArgumentCount() == 0)
{
Error error;
if (selected_platform_sp->IsConnected())
{
// Cache the instance name if there is one since we are
// about to disconnect and the name might go with it.
const char *instance_name_cstr = selected_platform_sp->GetInstanceName();
std::string instance_name;
if (instance_name_cstr)
instance_name.assign (instance_name_cstr);
error = selected_platform_sp->DisconnectRemote ();
if (error.Success())
{
Stream &ostrm = result.GetOutputStream();
if (instance_name.empty())
ostrm.Printf ("Disconnected from \"%s\"\n", selected_platform_sp->GetShortPluginName());
else
ostrm.Printf ("Disconnected from \"%s\"\n", instance_name.c_str());
result.SetStatus (eReturnStatusSuccessFinishResult);
}
else
{
result.AppendErrorWithFormat ("disconnect failed: %s", error.AsCString());
result.SetStatus (eReturnStatusFailed);
}
}
else
{
// Not connected...
result.AppendError ("not connected.");
result.SetStatus (eReturnStatusFailed);
}
}
else
{
// Bad args
result.AppendError ("\"platform disconnect\" doesn't take any arguments");
result.SetStatus (eReturnStatusFailed);
}
}
else
{
result.AppendError ("no platform us currently selected");
result.SetStatus (eReturnStatusFailed);
}
return result.Succeeded();
}
};
//----------------------------------------------------------------------
// CommandObjectPlatform constructor
@ -289,12 +420,14 @@ CommandObjectPlatform::CommandObjectPlatform(CommandInterpreter &interpreter) :
CommandObjectMultiword (interpreter,
"platform",
"A set of commands to manage and create platforms.",
"platform [create|list|status|select] ...")
"platform [connect|create|disconnect|list|status|select] ...")
{
LoadSubCommand ("create", CommandObjectSP (new CommandObjectPlatformCreate (interpreter)));
LoadSubCommand ("list" , CommandObjectSP (new CommandObjectPlatformList (interpreter)));
LoadSubCommand ("select", CommandObjectSP (new CommandObjectPlatformSelect (interpreter)));
LoadSubCommand ("status", CommandObjectSP (new CommandObjectPlatformStatus (interpreter)));
LoadSubCommand ("connect", CommandObjectSP (new CommandObjectPlatformConnect (interpreter)));
LoadSubCommand ("disconnect", CommandObjectSP (new CommandObjectPlatformDisconnect (interpreter)));
}

View File

@ -1,4 +1,4 @@
//===-- Platform.cpp --------------------------------------------*- C++ -*-===//
//===-- PlatformMacOSX.cpp --------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -138,7 +138,9 @@ PlatformMacOSX::ResolveExecutable (const FileSpec &exe_file,
}
Error
PlatformMacOSX::GetFile (const FileSpec &platform_file, FileSpec &local_file)
PlatformMacOSX::GetFile (const FileSpec &platform_file,
const UUID *uuid_ptr,
FileSpec &local_file)
{
// Default to the local case
local_file = platform_file;
@ -193,11 +195,7 @@ PlatformMacOSX::GetStatus (Stream &strm)
/// Default Constructor
//------------------------------------------------------------------
PlatformMacOSX::PlatformMacOSX () :
#if defined (__APPLE__)
Platform(true) // This is the local host platform
#else
Platform(false) // This is a remote platform
#endif
{
}

View File

@ -73,7 +73,9 @@ namespace lldb_private {
GetStatus (Stream &strm);
virtual Error
GetFile (const FileSpec &platform_file, FileSpec &local_file);
GetFile (const FileSpec &platform_file,
const UUID *uuid_ptr,
FileSpec &local_file);
virtual uint32_t
FindProcessesByName (const char *name_match,
@ -96,4 +98,4 @@ namespace lldb_private {
};
} // namespace lldb_private
#endif // liblldb_Platform_h_
#endif // liblldb_PlatformMacOSX_h_

View File

@ -1,4 +1,4 @@
//===-- Platform.cpp --------------------------------------------*- C++ -*-===//
//===-- PlatformRemoteiOS.cpp -----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -27,18 +27,28 @@
using namespace lldb;
using namespace lldb_private;
static bool g_initialized = false;
void
PlatformRemoteiOS::Initialize ()
{
static bool g_initialized = false;
if (g_initialized == false)
{
g_initialized = true;
PluginManager::RegisterPlugin (GetShortPluginNameStatic(),
GetDescriptionStatic(),
CreateInstance);
PluginManager::RegisterPlugin (PlatformRemoteiOS::GetShortPluginNameStatic(),
PlatformRemoteiOS::GetDescriptionStatic(),
PlatformRemoteiOS::CreateInstance);
}
}
void
PlatformRemoteiOS::Terminate ()
{
if (g_initialized)
{
g_initialized = false;
PluginManager::UnregisterPlugin (PlatformRemoteiOS::CreateInstance);
}
}
@ -48,10 +58,6 @@ PlatformRemoteiOS::CreateInstance ()
return new PlatformRemoteiOS ();
}
void
PlatformRemoteiOS::Terminate ()
{
}
const char *
PlatformRemoteiOS::GetPluginNameStatic ()
@ -358,6 +364,7 @@ PlatformRemoteiOS::GetDeviceSupportDirectoryForOSVersion()
Error
PlatformRemoteiOS::GetFile (const FileSpec &platform_file,
const UUID *uuid_ptr,
FileSpec &local_file)
{
Error error;
@ -442,6 +449,29 @@ PlatformRemoteiOS::GetProcessInfo (lldb::pid_t pid, ProcessInfo &process_info)
return false;
}
const char *
PlatformRemoteiOS::GetRemoteInstanceName ()
{
if (m_remote_instance_name.empty())
{
const char *device_support_dir = GetDeviceSupportDirectory();
if (device_support_dir)
{
std::string latest_device_support_dir;
latest_device_support_dir.assign (device_support_dir);
latest_device_support_dir.append ("/Platforms/iPhoneOS.platform/DeviceSupport/Latest");
const bool resolve_path = true;
FileSpec file_spec (m_device_support_directory_for_os_version.c_str(), resolve_path);
// We are using the resolved basename of the "Latest" symlink (which
// is usually the latest and greatest SDK version and the update
// which is something like: "4.0 (8A123)"
if (file_spec.Exists())
m_remote_instance_name.assign (file_spec.GetFilename().GetCString());
}
}
return m_remote_instance_name.c_str();
}
bool
PlatformRemoteiOS::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
{
@ -549,6 +579,13 @@ PlatformRemoteiOS::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch
return false;
}
bool
PlatformRemoteiOS::FetchRemoteOSVersion ()
{
return false;
}
size_t
PlatformRemoteiOS::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site)
{
@ -610,3 +647,35 @@ PlatformRemoteiOS::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSi
return 0;
}
Error
PlatformRemoteiOS::ConnectRemote (Args& args)
{
Error error;
error.SetErrorStringWithFormat ("'platform connect' is not implemented yet for platform '%s'", GetShortPluginNameStatic());
// if (args.GetArgumentCount() == 1)
// {
// const char *remote_url = args.GetArgumentAtIndex(0);
// ConnectionStatus status = m_gdb_client.Connect(remote_url, &error);
// if (status == eConnectionStatusSuccess)
// {
// m_gdb_client.GetHostInfo();
// }
// }
// else
// {
// error.SetErrorString ("\"platform connect\" takes a single argument: <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;
}

View File

@ -85,7 +85,9 @@ namespace lldb_private {
GetStatus (Stream &strm);
virtual Error
GetFile (const FileSpec &platform_file, FileSpec &local_file);
GetFile (const FileSpec &platform_file,
const UUID *uuid_ptr,
FileSpec &local_file);
virtual uint32_t
FindProcessesByName (const char *name_match,
@ -102,6 +104,19 @@ namespace lldb_private {
GetSoftwareBreakpointTrapOpcode (Target &target,
BreakpointSite *bp_site);
virtual bool
FetchRemoteOSVersion ();
virtual Error
ConnectRemote (Args& args);
virtual Error
DisconnectRemote ();
virtual const char *
GetRemoteInstanceName ();
protected:
std::string m_device_support_directory;
std::string m_device_support_directory_for_os_version;
@ -120,4 +135,4 @@ namespace lldb_private {
};
} // namespace lldb_private
#endif // liblldb_Platform_h_
#endif // liblldb_PlatformRemoteiOS_h_

View File

@ -0,0 +1,240 @@
//===-- PlatformRemoteGDBServer.cpp -----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "PlatformRemoteGDBServer.h"
// C Includes
#include <sys/sysctl.h>
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Error.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/Host.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
using namespace lldb;
using namespace lldb_private;
static bool g_initialized = false;
void
PlatformRemoteGDBServer::Initialize ()
{
if (g_initialized == false)
{
g_initialized = true;
PluginManager::RegisterPlugin (PlatformRemoteGDBServer::GetShortPluginNameStatic(),
PlatformRemoteGDBServer::GetDescriptionStatic(),
PlatformRemoteGDBServer::CreateInstance);
}
}
void
PlatformRemoteGDBServer::Terminate ()
{
if (g_initialized)
{
g_initialized = false;
PluginManager::UnregisterPlugin (PlatformRemoteGDBServer::CreateInstance);
}
}
Platform*
PlatformRemoteGDBServer::CreateInstance ()
{
return new PlatformRemoteGDBServer ();
}
const char *
PlatformRemoteGDBServer::GetShortPluginNameStatic()
{
return "remote-gdb-server";
}
const char *
PlatformRemoteGDBServer::GetDescriptionStatic()
{
return "A platform that uses the GDB remote protocol as the communication transport.";
}
const char *
PlatformRemoteGDBServer::GetDescription ()
{
if (m_platform_description.empty())
{
if (IsConnected())
{
// Send the get description packet
}
}
if (!m_platform_description.empty())
return m_platform_description.c_str();
return GetDescriptionStatic();
}
Error
PlatformRemoteGDBServer::ResolveExecutable (const FileSpec &exe_file,
const ArchSpec &exe_arch,
lldb::ModuleSP &exe_module_sp)
{
Error error;
error.SetErrorString ("PlatformRemoteGDBServer::ResolveExecutable() is unimplemented");
return error;
}
Error
PlatformRemoteGDBServer::GetFile (const FileSpec &platform_file,
const UUID *uuid_ptr,
FileSpec &local_file)
{
// Default to the local case
local_file = platform_file;
return Error();
}
void
PlatformRemoteGDBServer::GetStatus (Stream &strm)
{
char sysctlstring[1024];
size_t datalen;
int mib[CTL_MAXNAME];
uint32_t major = UINT32_MAX;
uint32_t minor = UINT32_MAX;
uint32_t update = UINT32_MAX;
strm.PutCString("Remote GDB server platform");
if (GetOSVersion(major, minor, update))
{
strm.Printf("OS version: %u", major);
if (minor != UINT32_MAX)
strm.Printf(".%u", minor);
if (update != UINT32_MAX)
strm.Printf(".%u", update);
mib[0] = CTL_KERN;
mib[1] = KERN_OSVERSION;
datalen = sizeof(sysctlstring);
if (::sysctl (mib, 2, sysctlstring, &datalen, NULL, 0) == 0)
{
sysctlstring[datalen] = '\0';
strm.Printf(" (%s)", sysctlstring);
}
strm.EOL();
}
mib[0] = CTL_KERN;
mib[1] = KERN_VERSION;
datalen = sizeof(sysctlstring);
if (::sysctl (mib, 2, sysctlstring, &datalen, NULL, 0) == 0)
{
sysctlstring[datalen] = '\0';
strm.Printf("Kernel version: %s\n", sysctlstring);
}
}
//------------------------------------------------------------------
/// Default Constructor
//------------------------------------------------------------------
PlatformRemoteGDBServer::PlatformRemoteGDBServer () :
Platform(false) // This is a remote platform
{
}
//------------------------------------------------------------------
/// Destructor.
///
/// The destructor is virtual since this class is designed to be
/// inherited from by the plug-in instance.
//------------------------------------------------------------------
PlatformRemoteGDBServer::~PlatformRemoteGDBServer()
{
}
uint32_t
PlatformRemoteGDBServer::FindProcessesByName (const char *name_match,
lldb::NameMatchType name_match_type,
ProcessInfoList &process_infos)
{
return 0;
}
bool
PlatformRemoteGDBServer::GetProcessInfo (lldb::pid_t pid, ProcessInfo &process_info)
{
return false;
}
bool
PlatformRemoteGDBServer::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
{
return false;
}
size_t
PlatformRemoteGDBServer::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site)
{
// This isn't needed if the z/Z packets are supported in the GDB remote
// server. But we might need a packet to detect this.
return 0;
}
bool
PlatformRemoteGDBServer::FetchRemoteOSVersion ()
{
return false;
}
Error
PlatformRemoteGDBServer::ConnectRemote (Args& args)
{
Error error;
if (args.GetArgumentCount() == 1)
{
const char *remote_url = args.GetArgumentAtIndex(0);
ConnectionStatus status = m_gdb_client.Connect(remote_url, &error);
if (status == eConnectionStatusSuccess)
{
m_gdb_client.GetHostInfo();
}
}
else
{
error.SetErrorString ("\"platform connect\" takes a single argument: <connect-url>");
}
return error;
}
Error
PlatformRemoteGDBServer::DisconnectRemote ()
{
Error error;
m_gdb_client.Disconnect(&error);
return error;
}
const char *
PlatformRemoteGDBServer::GetRemoteInstanceName ()
{
return NULL;
}

View File

@ -0,0 +1,127 @@
//===-- PlatformRemoteGDBServer.h ----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_PlatformRemoteGDBServer_h_
#define liblldb_PlatformRemoteGDBServer_h_
// C Includes
// C++ Includes
#include <string>
// Other libraries and framework includes
// Project includes
#include "lldb/Target/Platform.h"
#include "../../Process/gdb-remote/GDBRemoteCommunicationClient.h"
namespace lldb_private {
class PlatformRemoteGDBServer : public Platform
{
public:
static void
Initialize ();
static void
Terminate ();
static Platform*
CreateInstance ();
static const char *
GetShortPluginNameStatic();
static const char *
GetDescriptionStatic();
PlatformRemoteGDBServer ();
virtual
~PlatformRemoteGDBServer();
//------------------------------------------------------------
// lldb_private::PluginInterface functions
//------------------------------------------------------------
virtual const char *
GetPluginName()
{
return "PlatformRemoteGDBServer";
}
virtual const char *
GetShortPluginName()
{
return GetShortPluginNameStatic();
}
virtual uint32_t
GetPluginVersion()
{
return 1;
}
//------------------------------------------------------------
// lldb_private::Platform functions
//------------------------------------------------------------
virtual Error
ResolveExecutable (const FileSpec &exe_file,
const ArchSpec &arch,
lldb::ModuleSP &module_sp);
virtual const char *
GetDescription ();
virtual void
GetStatus (Stream &strm);
virtual Error
GetFile (const FileSpec &platform_file,
const UUID *uuid_ptr,
FileSpec &local_file);
virtual uint32_t
FindProcessesByName (const char *name_match,
lldb::NameMatchType name_match_type,
ProcessInfoList &process_infos);
virtual bool
GetProcessInfo (lldb::pid_t pid, ProcessInfo &proc_info);
virtual bool
GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch);
virtual size_t
GetSoftwareBreakpointTrapOpcode (Target &target,
BreakpointSite *bp_site);
virtual bool
FetchRemoteOSVersion ();
virtual Error
ConnectRemote (Args& args);
virtual Error
DisconnectRemote ();
virtual const char *
GetRemoteInstanceName ();
protected:
GDBRemoteCommunicationClient m_gdb_client;
std::string m_platform_description; // After we connect we can get a more complete description of what we are connected to
private:
DISALLOW_COPY_AND_ASSIGN (PlatformRemoteGDBServer);
};
} // namespace lldb_private
#endif // liblldb_PlatformRemoteGDBServer_h_

View File

@ -50,11 +50,7 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient() :
m_async_packet (),
m_async_response (),
m_async_signal (-1),
m_arch(),
m_os(),
m_vendor(),
m_byte_order(lldb::endian::InlHostByteOrder()),
m_pointer_byte_size(0)
m_host_arch()
{
m_rx_packet_listener.StartListeningForEvents(this,
Communication::eBroadcastBitPacketAvailable |
@ -102,11 +98,7 @@ GDBRemoteCommunicationClient::ResetDiscoverableSettings()
m_supports_vCont_C = eLazyBoolCalculate;
m_supports_vCont_s = eLazyBoolCalculate;
m_supports_vCont_S = eLazyBoolCalculate;
m_arch.Clear();
m_os.Clear();
m_vendor.Clear();
m_byte_order = lldb::endian::InlHostByteOrder();
m_pointer_byte_size = 0;
m_host_arch.Clear();
}
@ -690,7 +682,11 @@ GDBRemoteCommunicationClient::GetHostInfo ()
std::string value;
uint32_t cpu = LLDB_INVALID_CPUTYPE;
uint32_t sub = 0;
std::string arch_name;
std::string os_name;
std::string vendor_name;
uint32_t pointer_byte_size = 0;
ByteOrder byte_order = eByteOrderInvalid;
while (response.GetNameColonValue(name, value))
{
if (name.compare("cputype") == 0)
@ -703,32 +699,69 @@ GDBRemoteCommunicationClient::GetHostInfo ()
// exception count in big endian hex
sub = Args::StringToUInt32 (value.c_str(), 0, 0);
}
else if (name.compare("arch") == 0)
{
arch_name.swap (value);
}
else if (name.compare("ostype") == 0)
{
// exception data in big endian hex
m_os.SetCString(value.c_str());
os_name.swap (value);
}
else if (name.compare("vendor") == 0)
{
m_vendor.SetCString(value.c_str());
vendor_name.swap(value);
}
else if (name.compare("endian") == 0)
{
if (value.compare("little") == 0)
m_byte_order = eByteOrderLittle;
byte_order = eByteOrderLittle;
else if (value.compare("big") == 0)
m_byte_order = eByteOrderBig;
byte_order = eByteOrderBig;
else if (value.compare("pdp") == 0)
m_byte_order = eByteOrderPDP;
byte_order = eByteOrderPDP;
}
else if (name.compare("ptrsize") == 0)
{
m_pointer_byte_size = Args::StringToUInt32 (value.c_str(), 0, 0);
pointer_byte_size = Args::StringToUInt32 (value.c_str(), 0, 0);
}
}
if (cpu != LLDB_INVALID_CPUTYPE)
m_arch.SetArchitecture (lldb::eArchTypeMachO, cpu, sub);
if (arch_name.empty())
{
if (cpu != LLDB_INVALID_CPUTYPE)
{
m_host_arch.SetArchitecture (lldb::eArchTypeMachO, cpu, sub);
if (pointer_byte_size)
{
assert (pointer_byte_size == m_host_arch.GetAddressByteSize());
}
if (byte_order != eByteOrderInvalid)
{
assert (byte_order == m_host_arch.GetByteOrder());
}
if (!vendor_name.empty())
m_host_arch.GetTriple().setVendorName (llvm::StringRef (vendor_name));
if (!os_name.empty())
m_host_arch.GetTriple().setVendorName (llvm::StringRef (os_name));
}
}
else
{
std::string triple;
triple += arch_name;
triple += '-';
if (vendor_name.empty())
triple += "unknown";
else
triple += vendor_name;
triple += '-';
if (os_name.empty())
triple += "unknown";
else
triple += os_name;
m_host_arch.SetTriple (triple.c_str());
}
}
}
return m_supports_qHostInfo == eLazyBoolYes;
@ -759,41 +792,9 @@ GDBRemoteCommunicationClient::SendAttach
const lldb_private::ArchSpec &
GDBRemoteCommunicationClient::GetHostArchitecture ()
{
if (!HostInfoIsValid ())
if (m_supports_qHostInfo == lldb::eLazyBoolCalculate)
GetHostInfo ();
return m_arch;
}
const lldb_private::ConstString &
GDBRemoteCommunicationClient::GetOSString ()
{
if (!HostInfoIsValid ())
GetHostInfo ();
return m_os;
}
const lldb_private::ConstString &
GDBRemoteCommunicationClient::GetVendorString()
{
if (!HostInfoIsValid ())
GetHostInfo ();
return m_vendor;
}
lldb::ByteOrder
GDBRemoteCommunicationClient::GetByteOrder ()
{
if (!HostInfoIsValid ())
GetHostInfo ();
return m_byte_order;
}
uint32_t
GDBRemoteCommunicationClient::GetAddressByteSize ()
{
if (!HostInfoIsValid ())
GetHostInfo ();
return m_pointer_byte_size;
return m_host_arch;
}
addr_t

View File

@ -176,18 +176,6 @@ public:
const lldb_private::ArchSpec &
GetHostArchitecture ();
const lldb_private::ConstString &
GetOSString ();
const lldb_private::ConstString &
GetVendorString();
lldb::ByteOrder
GetByteOrder ();
uint32_t
GetAddressByteSize ();
bool
GetVContSupported (char flavor);
@ -222,12 +210,6 @@ public:
protected:
bool
HostInfoIsValid () const
{
return m_supports_qHostInfo != lldb::eLazyBoolCalculate;
}
//------------------------------------------------------------------
// Classes that inherit from GDBRemoteCommunicationClient can see and modify these
//------------------------------------------------------------------
@ -249,14 +231,8 @@ protected:
StringExtractorGDBRemote m_async_response;
int m_async_signal; // We were asked to deliver a signal to the inferior process.
lldb_private::ArchSpec m_arch;
lldb_private::ArchSpec m_host_arch;
uint32_t m_cpusubtype;
lldb_private::ConstString m_os;
lldb_private::ConstString m_vendor;
lldb::ByteOrder m_byte_order;
uint32_t m_pointer_byte_size;
private:
//------------------------------------------------------------------

View File

@ -72,10 +72,12 @@ GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer()
//}
//
bool
GDBRemoteCommunicationServer::GetPacketAndSendResponse (const TimeValue* timeout_time_ptr)
GDBRemoteCommunicationServer::GetPacketAndSendResponse (const TimeValue* timeout_ptr,
bool &interrupt,
bool &quit)
{
StringExtractorGDBRemote packet;
if (WaitForPacketNoLock (packet, timeout_time_ptr))
if (WaitForPacketNoLock (packet, timeout_ptr))
{
const StringExtractorGDBRemote::ServerPacketType packet_type = packet.GetServerPacketType ();
switch (packet_type)
@ -85,6 +87,13 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (const TimeValue* timeout
break;
case StringExtractorGDBRemote::eServerPacketType_invalid:
quit = true;
break;
case StringExtractorGDBRemote::eServerPacketType_interrupt:
interrupt = true;
break;
case StringExtractorGDBRemote::eServerPacketType_unimplemented:
return SendUnimplementedResponse () > 0;

View File

@ -34,7 +34,9 @@ public:
~GDBRemoteCommunicationServer();
bool
GetPacketAndSendResponse (const lldb_private::TimeValue* timeout_time_ptr);
GetPacketAndSendResponse (const lldb_private::TimeValue* timeout_ptr,
bool &interrupt,
bool &quit);
virtual bool
GetThreadSuffixSupported ()

View File

@ -622,34 +622,52 @@ ProcessGDBRemote::DidLaunchOrAttach ()
BuildDynamicRegisterInfo (false);
m_target.GetArchitecture().SetByteOrder (m_gdb_comm.GetByteOrder());
StreamString strm;
// See if the GDB server supports the qHostInfo information
const char *vendor = m_gdb_comm.GetVendorString().AsCString();
const char *os_type = m_gdb_comm.GetOSString().AsCString();
ArchSpec target_arch (GetTarget().GetArchitecture());
ArchSpec gdb_remote_arch (m_gdb_comm.GetHostArchitecture());
// If the remote host is ARM and we have apple as the vendor, then
// ARM executables and shared libraries can have mixed ARM architectures.
// You can have an armv6 executable, and if the host is armv7, then the
// system will load the best possible architecture for all shared libraries
// it has, so we really need to take the remote host architecture as our
// defacto architecture in this case.
if (gdb_remote_arch.GetMachine() == llvm::Triple::arm &&
gdb_remote_arch.GetTriple().getVendor() == llvm::Triple::Apple)
const ArchSpec &gdb_remote_arch = m_gdb_comm.GetHostArchitecture();
if (gdb_remote_arch.IsValid())
{
GetTarget().SetArchitecture (gdb_remote_arch);
target_arch = gdb_remote_arch;
ArchSpec &target_arch = GetTarget().GetArchitecture();
if (target_arch.IsValid())
{
// If the remote host is ARM and we have apple as the vendor, then
// ARM executables and shared libraries can have mixed ARM architectures.
// You can have an armv6 executable, and if the host is armv7, then the
// system will load the best possible architecture for all shared libraries
// it has, so we really need to take the remote host architecture as our
// defacto architecture in this case.
if (gdb_remote_arch.GetMachine() == llvm::Triple::arm &&
gdb_remote_arch.GetTriple().getVendor() == llvm::Triple::Apple)
{
target_arch = gdb_remote_arch;
}
else
{
// Fill in what is missing in the triple
const llvm::Triple &remote_triple = gdb_remote_arch.GetTriple();
llvm::Triple &target_triple = target_arch.GetTriple();
if (target_triple.getVendor() == llvm::Triple::UnknownVendor)
target_triple.setVendor (remote_triple.getVendor());
if (target_triple.getOS() == llvm::Triple::UnknownOS)
target_triple.setOS (remote_triple.getOS());
if (target_triple.getEnvironment() == llvm::Triple::UnknownEnvironment)
target_triple.setEnvironment (remote_triple.getEnvironment());
}
}
else
{
// The target doesn't have a valid architecture yet, set it from
// the architecture we got from the remote GDB server
target_arch = gdb_remote_arch;
}
}
if (vendor)
m_target.GetArchitecture().GetTriple().setVendorName(vendor);
if (os_type)
m_target.GetArchitecture().GetTriple().setOSName(os_type);
}
}

View File

@ -69,7 +69,9 @@ Platform::SetDefaultPlatform (const lldb::PlatformSP &platform_sp)
}
Error
Platform::GetFile (const FileSpec &platform_file, FileSpec &local_file)
Platform::GetFile (const FileSpec &platform_file,
const UUID *uuid_ptr,
FileSpec &local_file)
{
// Default to the local case
local_file = platform_file;
@ -123,6 +125,7 @@ Platform::Platform (bool is_host) :
m_os_version_set_while_connected (false),
m_system_arch_set_while_connected (false),
m_remote_url (),
m_remote_instance_name (),
m_major_os_version (UINT32_MAX),
m_minor_os_version (UINT32_MAX),
m_update_os_version (UINT32_MAX)
@ -330,17 +333,23 @@ Platform::GetSystemArchitecture()
Error
Platform::ConnectRemote (const char *remote_url)
Platform::ConnectRemote (Args& args)
{
Error error;
error.SetErrorStringWithFormat ("Platform::ConnectRemote() is not supported by %s", GetShortPluginName());
if (IsHost())
error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetShortPluginName());
else
error.SetErrorStringWithFormat ("Platform::ConnectRemote() is not supported by %s", GetShortPluginName());
return error;
}
Error
Platform::DisconnectRemote (const lldb::PlatformSP &platform_sp)
Platform::DisconnectRemote ()
{
Error error;
error.SetErrorStringWithFormat ("Platform::DisconnectRemote() is not supported by %s", GetShortPluginName());
if (IsHost())
error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetShortPluginName());
else
error.SetErrorStringWithFormat ("Platform::DisconnectRemote() is not supported by %s", GetShortPluginName());
return error;
}

View File

@ -428,7 +428,7 @@ Target::SetExecutableModule (ModuleSP& executable_sp, bool get_dependent_files)
FileSpec dependent_file_spec (dependent_files.GetFileSpecPointerAtIndex(i));
FileSpec platform_dependent_file_spec;
if (m_platform_sp)
m_platform_sp->GetFile (dependent_file_spec, platform_dependent_file_spec);
m_platform_sp->GetFile (dependent_file_spec, NULL, platform_dependent_file_spec);
else
platform_dependent_file_spec = dependent_file_spec;

View File

@ -59,6 +59,11 @@ StringExtractorGDBRemote::GetServerPacketType () const
const char *packet_cstr = m_packet.c_str();
switch (m_packet[0])
{
case '\x03':
if (m_packet.size() == 1)
return eServerPacketType_interrupt;
break;
case '-':
if (m_packet.size() == 1)
return eServerPacketType_nack;

View File

@ -45,6 +45,7 @@ public:
eServerPacketType_ack,
eServerPacketType_invalid,
eServerPacketType_unimplemented,
eServerPacketType_interrupt, // CTRL+c packet or "\x03"
eServerPacketType_qHostInfo
};

View File

@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
// C Includes
#include <errno.h>
#include <getopt.h>
#include <signal.h>
@ -15,8 +16,16 @@
#include <stdlib.h>
#include <string.h>
// C++ Includes
// Other libraries and framework includes
#include "lldb/Core/Error.h"
#include "lldb/Core/ConnectionFileDescriptor.h"
#include "GDBRemoteCommunicationServer.h"
using namespace lldb;
using namespace lldb_private;
//----------------------------------------------------------------------
// option descriptors for getopt_long()
//----------------------------------------------------------------------
@ -30,6 +39,7 @@ static struct option g_long_options[] =
{ "verbose", no_argument, &g_verbose, 1 },
{ "log-file", required_argument, NULL, 'l' },
{ "log-flags", required_argument, NULL, 'f' },
{ "listen", required_argument, NULL, 'L' },
{ NULL, 0, NULL, 0 }
};
@ -58,6 +68,7 @@ main (int argc, char *argv[])
int long_option_index = 0;
FILE* log_file = NULL;
uint32_t log_flags = 0;
std::string connect_url;
char ch;
while ((ch = getopt_long(argc, argv, "l:f:", g_long_options, &long_option_index)) != -1)
@ -98,6 +109,11 @@ main (int argc, char *argv[])
if (optarg && optarg[0])
log_flags = strtoul(optarg, NULL, 0);
break;
case 'L':
connect_url.assign ("connect://");
connect_url.append (optarg);
break;
}
}
@ -106,7 +122,48 @@ main (int argc, char *argv[])
argv += optind;
GDBRemoteCommunicationServer gdb_comm;
GDBRemoteCommunicationServer gdb_server;
Error error;
if (!connect_url.empty())
{
std::auto_ptr<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++;
if (retry_count >= max_retry_count)
break;
usleep (100000);
}
}
}
if (gdb_server.IsConnected())
{
if (gdb_server.StartReadThread(&error))
{
bool interrupt = false;
bool done = false;
while (!interrupt && !done)
{
gdb_server.GetPacketAndSendResponse(NULL, interrupt, done);
}
}
else
{
}
}
return 0;
}