FreeBSD platform patch from Filipe!

llvm-svn: 139338
This commit is contained in:
Johnny Chen 2011-09-09 00:10:04 +00:00
parent 13f1d56170
commit 13f8dda9bc
2 changed files with 556 additions and 164 deletions

View File

@ -17,14 +17,9 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Error.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/Host.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Process.h"
using namespace lldb;
using namespace lldb_private;
@ -87,38 +82,99 @@ PlatformFreeBSD::Terminate ()
PluginManager::UnregisterPlugin (PlatformFreeBSD::CreateInstance);
}
//------------------------------------------------------------------
/// Default Constructor
//------------------------------------------------------------------
PlatformFreeBSD::PlatformFreeBSD (bool is_host) :
Platform(is_host)
{
}
//------------------------------------------------------------------
/// Destructor.
///
/// The destructor is virtual since this class is designed to be
/// inherited from by the plug-in instance.
//------------------------------------------------------------------
PlatformFreeBSD::~PlatformFreeBSD()
{
}
Error
PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file,
const ArchSpec &exe_arch,
lldb::ModuleSP &exe_module_sp)
const ArchSpec &exe_arch,
lldb::ModuleSP &exe_module_sp)
{
Error error;
// Nothing special to do here, just use the actual file and architecture
char exe_path[PATH_MAX];
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 (IsHost())
{
// If we have "ls" as the exe_file, resolve the executable loation based on
// the current path variables
if (!resolved_exe_file.Exists())
{
exe_file.GetPath(exe_path, sizeof(exe_path));
resolved_exe_file.SetFile(exe_path, true);
}
if (resolved_exe_file.Exists())
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())
error.Clear();
else
{
exe_file.GetPath(exe_path, sizeof(exe_path));
error.SetErrorStringWithFormat("unable to find executable for '%s'", exe_path);
}
}
else
{
if (m_remote_platform_sp)
{
error = m_remote_platform_sp->ResolveExecutable (exe_file,
exe_arch,
exe_module_sp);
}
else
{
// We may connect to a process and use the provided executable (Don't use local $PATH).
// Resolve any executable within a bundle on MacOSX
Host::ResolveExecutableInBundle (resolved_exe_file);
if (resolved_exe_file.Exists()) {
error.Clear();
}
else
{
error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.");
}
}
}
if (error.Success())
{
if (exe_arch.IsValid())
{
error = ModuleList::GetSharedModule (resolved_exe_file,
exe_arch,
error = ModuleList::GetSharedModule (resolved_exe_file,
exe_arch,
NULL,
NULL,
0,
exe_module_sp,
NULL,
NULL,
0,
exe_module_sp,
NULL,
NULL);
if (exe_module_sp->GetObjectFile() == NULL)
{
exe_module_sp.reset();
@ -138,15 +194,15 @@ PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file,
ArchSpec platform_arch;
for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx)
{
error = ModuleList::GetSharedModule (resolved_exe_file,
platform_arch,
error = ModuleList::GetSharedModule (resolved_exe_file,
platform_arch,
NULL,
NULL,
0,
exe_module_sp,
NULL,
NULL,
0,
exe_module_sp,
NULL,
NULL);
// Did we find an executable using one of the
// Did we find an executable using one of the
if (error.Success())
{
if (exe_module_sp && exe_module_sp->GetObjectFile())
@ -154,12 +210,12 @@ PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file,
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",
@ -182,48 +238,366 @@ PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file,
return error;
}
size_t
PlatformFreeBSD::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site)
{
ArchSpec arch = target.GetArchitecture();
const uint8_t *trap_opcode = NULL;
size_t trap_opcode_size = 0;
switch (arch.GetCore())
{
default:
assert(false && "Unhandled architecture in PlatformFreeBSD::GetSoftwareBreakpointTrapOpcode()");
break;
case ArchSpec::eCore_x86_32_i386:
case ArchSpec::eCore_x86_64_x86_64:
{
static const uint8_t g_i386_opcode[] = { 0xCC };
trap_opcode = g_i386_opcode;
trap_opcode_size = sizeof(g_i386_opcode);
}
break;
}
if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
return trap_opcode_size;
return 0;
}
bool
PlatformFreeBSD::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
PlatformFreeBSD::GetRemoteOSBuildString (std::string &s)
{
if (m_remote_platform_sp)
return m_remote_platform_sp->GetRemoteOSBuildString (s);
s.clear();
return false;
}
bool
PlatformFreeBSD::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
PlatformFreeBSD::GetRemoteSystemArchitecture ()
{
if (m_remote_platform_sp)
return m_remote_platform_sp->GetRemoteSystemArchitecture ();
return ArchSpec();
}
const char *
PlatformFreeBSD::GetHostname ()
{
if (IsHost())
return Platform::GetHostname();
if (m_remote_platform_sp)
return m_remote_platform_sp->GetHostname ();
return NULL;
}
bool
PlatformFreeBSD::IsConnected () const
{
if (IsHost())
return true;
else if (m_remote_platform_sp)
return m_remote_platform_sp->IsConnected();
return false;
}
Error
PlatformFreeBSD::GetFile (const FileSpec &platform_file,
const UUID *uuid, FileSpec &local_file)
PlatformFreeBSD::ConnectRemote (Args& args)
{
// Default to the local case
local_file = platform_file;
return Error();
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;
}
//------------------------------------------------------------------
/// Default Constructor
//------------------------------------------------------------------
PlatformFreeBSD::PlatformFreeBSD (bool is_host) :
Platform(is_host)
Error
PlatformFreeBSD::DisconnectRemote ()
{
}
Error error;
//------------------------------------------------------------------
/// Destructor.
///
/// The destructor is virtual since this class is designed to be
/// inherited from by the plug-in instance.
//------------------------------------------------------------------
PlatformFreeBSD::~PlatformFreeBSD()
{
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;
}
bool
PlatformFreeBSD::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
{
return Host::GetProcessInfo (pid, process_info);
bool sucess = false;
if (IsHost())
{
sucess = Platform::GetProcessInfo (pid, process_info);
}
else
{
if (m_remote_platform_sp)
sucess = m_remote_platform_sp->GetProcessInfo (pid, process_info);
}
return sucess;
}
uint32_t
PlatformFreeBSD::FindProcesses (const ProcessInstanceInfoMatch &match_info,
ProcessInstanceInfoList &process_infos)
{
uint32_t match_count = 0;
if (IsHost())
{
// Let the base class figure out the host details
match_count = Platform::FindProcesses (match_info, process_infos);
}
else
{
// If we are remote, we can only return results if we are connected
if (m_remote_platform_sp)
match_count = m_remote_platform_sp->FindProcesses (match_info, process_infos);
}
return match_count;
}
Error
PlatformFreeBSD::LaunchProcess (ProcessLaunchInfo &launch_info)
{
Error error;
if (IsHost())
{
error = Platform::LaunchProcess (launch_info);
}
else
{
if (m_remote_platform_sp)
error = m_remote_platform_sp->LaunchProcess (launch_info);
else
error.SetErrorString ("the platform is not currently connected");
}
return error;
}
lldb::ProcessSP
PlatformFreeBSD::Attach(lldb::pid_t pid,
Debugger &debugger,
Target *target,
Listener &listener,
Error &error)
{
lldb::ProcessSP process_sp;
if (IsHost())
{
if (target == NULL)
{
TargetSP new_target_sp;
FileSpec emptyFileSpec;
ArchSpec emptyArchSpec;
error = debugger.GetTargetList().CreateTarget (debugger,
emptyFileSpec,
emptyArchSpec,
false,
new_target_sp);
target = new_target_sp.get();
}
else
error.Clear();
if (target && error.Success())
{
debugger.GetTargetList().SetSelectedTarget(target);
// The freebsd always currently uses the GDB remote debugger plug-in
// so even when debugging locally we are debugging remotely!
// Just like the darwin plugin.
process_sp = target->CreateProcess (listener, "gdb-remote");
if (process_sp)
error = process_sp->Attach (pid);
}
}
else
{
if (m_remote_platform_sp)
process_sp = m_remote_platform_sp->Attach (pid, debugger, target, listener, error);
else
error.SetErrorString ("the platform is not currently connected");
}
return process_sp;
}
const char *
PlatformFreeBSD::GetUserName (uint32_t uid)
{
// Check the cache in Platform in case we have already looked this uid up
const char *user_name = Platform::GetUserName(uid);
if (user_name)
return user_name;
if (IsRemote() && m_remote_platform_sp)
return m_remote_platform_sp->GetUserName(uid);
return NULL;
}
const char *
PlatformFreeBSD::GetGroupName (uint32_t gid)
{
const char *group_name = Platform::GetGroupName(gid);
if (group_name)
return group_name;
if (IsRemote() && m_remote_platform_sp)
return m_remote_platform_sp->GetGroupName(gid);
return NULL;
}
// From PlatformMacOSX only
Error
PlatformFreeBSD::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();
}
Error
PlatformFreeBSD::GetSharedModule (const FileSpec &platform_file,
const ArchSpec &arch,
const UUID *uuid_ptr,
const ConstString *object_name_ptr,
off_t object_offset,
ModuleSP &module_sp,
ModuleSP *old_module_sp_ptr,
bool *did_create_ptr)
{
Error error;
module_sp.reset();
if (IsRemote())
{
// If we have a remote platform always, let it try and locate
// the shared module first.
if (m_remote_platform_sp)
{
error = m_remote_platform_sp->GetSharedModule (platform_file,
arch,
uuid_ptr,
object_name_ptr,
object_offset,
module_sp,
old_module_sp_ptr,
did_create_ptr);
}
}
if (!module_sp)
{
// Fall back to the local platform and find the file locally
error = Platform::GetSharedModule (platform_file,
arch,
uuid_ptr,
object_name_ptr,
object_offset,
module_sp,
old_module_sp_ptr,
did_create_ptr);
}
if (module_sp)
module_sp->SetPlatformFileSpec(platform_file);
return error;
}
bool
PlatformFreeBSD::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
{
// From macosx;s plugin code. For FreeBSD we may want to support more archs.
if (idx == 0)
{
arch = Host::GetArchitecture (Host::eSystemDefaultArchitecture);
return arch.IsValid();
}
else if (idx == 1)
{
ArchSpec platform_arch (Host::GetArchitecture (Host::eSystemDefaultArchitecture));
ArchSpec platform_arch64 (Host::GetArchitecture (Host::eSystemDefaultArchitecture64));
if (platform_arch == platform_arch64)
{
// This freebsd platform supports both 32 and 64 bit. Since we already
// returned the 64 bit arch for idx == 0, return the 32 bit arch
// for idx == 1
arch = Host::GetArchitecture (Host::eSystemDefaultArchitecture32);
return arch.IsValid();
}
}
return false;
}
@ -240,42 +614,3 @@ PlatformFreeBSD::GetStatus (Stream &strm)
strm << "Host: " << un.sysname << ' ' << un.release << ' ' << un.version << '\n';
Platform::GetStatus(strm);
}
size_t
PlatformFreeBSD::GetSoftwareBreakpointTrapOpcode (Target &target,
BreakpointSite *bp_site)
{
static const uint8_t g_i386_opcode[] = { 0xCC };
ArchSpec arch = target.GetArchitecture();
const uint8_t *opcode = NULL;
size_t opcode_size = 0;
switch (arch.GetCore())
{
default:
assert(false && "CPU type not supported!");
break;
case ArchSpec::eCore_x86_32_i386:
case ArchSpec::eCore_x86_64_x86_64:
opcode = g_i386_opcode;
opcode_size = sizeof(g_i386_opcode);
break;
}
bp_site->SetTrapOpcode(opcode, opcode_size);
return opcode_size;
}
lldb::ProcessSP
PlatformFreeBSD::Attach(lldb::pid_t pid,
Debugger &debugger,
Target *target,
Listener &listener,
Error &error)
{
ProcessSP processSP;
assert(!"Not implemented yet!");
return processSP;
}

View File

@ -16,97 +16,154 @@
// Project includes
#include "lldb/Target/Platform.h"
namespace lldb_private {
class PlatformFreeBSD : public lldb_private::Platform
{
public:
// Mostly taken from PlatformDarwin and PlatformMacOSX
class PlatformFreeBSD : public Platform
//------------------------------------------------------------
// Class functions
//------------------------------------------------------------
static lldb_private::Platform*
CreateInstance ();
static void
Initialize ();
static void
Terminate ();
static const char *
GetPluginNameStatic();
static const char *
GetShortPluginNameStatic(bool is_host);
static const char *
GetDescriptionStatic(bool is_host);
//------------------------------------------------------------
// Class Methods
//------------------------------------------------------------
PlatformFreeBSD (bool is_host);
virtual
~PlatformFreeBSD();
//------------------------------------------------------------
// lldb_private::PluginInterface functions
//------------------------------------------------------------
virtual const char *
GetPluginName()
{
public:
return GetPluginNameStatic();
}
static void
Initialize ();
virtual const char *
GetShortPluginName()
{
return GetShortPluginNameStatic (IsHost());
}
static void
Terminate ();
PlatformFreeBSD (bool is_host);
virtual uint32_t
GetPluginVersion()
{
return 1;
}
virtual
~PlatformFreeBSD();
virtual const char *
GetDescription ()
{
return GetDescriptionStatic(IsHost());
}
//------------------------------------------------------------
// lldb_private::PluginInterface functions
//------------------------------------------------------------
static Platform *
CreateInstance ();
//------------------------------------------------------------
// lldb_private::Platform functions
//------------------------------------------------------------
virtual lldb_private::Error
ResolveExecutable (const lldb_private::FileSpec &exe_file,
const lldb_private::ArchSpec &arch,
lldb::ModuleSP &module_sp);
static const char *
GetPluginNameStatic();
virtual size_t
GetSoftwareBreakpointTrapOpcode (lldb_private::Target &target,
lldb_private::BreakpointSite *bp_site);
static const char *
GetShortPluginNameStatic(bool is_host);
virtual bool
GetRemoteOSVersion ();
static const char *
GetDescriptionStatic(bool is_host);
virtual bool
GetRemoteOSBuildString (std::string &s);
virtual const char *
GetPluginName()
{
return GetPluginNameStatic();
}
virtual const char *
GetShortPluginName()
{
return GetShortPluginNameStatic (IsHost());
}
virtual bool
GetRemoteOSKernelDescription (std::string &s);
virtual uint32_t
GetPluginVersion()
{
return 1;
}
// Remote Platform subclasses need to override this function
virtual lldb_private::ArchSpec
GetRemoteSystemArchitecture ();
//------------------------------------------------------------
// lldb_private::Platform functions
//------------------------------------------------------------
virtual Error
ResolveExecutable (const FileSpec &exe_file,
const ArchSpec &arch,
lldb::ModuleSP &module_sp);
virtual bool
IsConnected () const;
virtual const char *
GetDescription ()
{
return GetDescriptionStatic(IsHost());
}
virtual lldb_private::Error
ConnectRemote (lldb_private::Args& args);
virtual void
GetStatus (Stream &strm);
virtual lldb_private::Error
DisconnectRemote ();
virtual Error
GetFile (const FileSpec &platform_file,
const UUID* uuid, FileSpec &local_file);
virtual const char *
GetHostname ();
virtual bool
GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &proc_info);
virtual const char *
GetUserName (uint32_t uid);
virtual bool
GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch);
virtual const char *
GetGroupName (uint32_t gid);
virtual size_t
GetSoftwareBreakpointTrapOpcode (Target &target,
BreakpointSite *bp_site);
virtual bool
GetProcessInfo (lldb::pid_t pid,
lldb_private::ProcessInstanceInfo &proc_info);
virtual lldb::ProcessSP
Attach(lldb::pid_t pid, Debugger &debugger, Target *target,
Listener &listener, Error &error);
virtual uint32_t
FindProcesses (const lldb_private::ProcessInstanceInfoMatch &match_info,
lldb_private::ProcessInstanceInfoList &process_infos);
protected:
private:
DISALLOW_COPY_AND_ASSIGN (PlatformFreeBSD);
};
} // namespace lldb_private
virtual lldb_private::Error
LaunchProcess (lldb_private::ProcessLaunchInfo &launch_info);
virtual lldb::ProcessSP
Attach(lldb::pid_t pid,
lldb_private::Debugger &debugger,
lldb_private::Target *target,
lldb_private::Listener &listener,
lldb_private::Error &error);
// Only on PlatformMacOSX:
virtual lldb_private::Error
GetFile (const lldb_private::FileSpec &platform_file,
const lldb_private::UUID* uuid, lldb_private::FileSpec &local_file);
lldb_private::Error
GetSharedModule (const lldb_private::FileSpec &platform_file,
const lldb_private::ArchSpec &arch,
const lldb_private::UUID *uuid_ptr,
const lldb_private::ConstString *object_name_ptr,
off_t object_offset,
lldb::ModuleSP &module_sp,
lldb::ModuleSP *old_module_sp_ptr,
bool *did_create_ptr);
virtual bool
GetSupportedArchitectureAtIndex (uint32_t idx, lldb_private::ArchSpec &arch);
virtual void
GetStatus (lldb_private::Stream &strm);
protected:
lldb::PlatformSP m_remote_platform_sp; // Allow multiple ways to connect to a remote freebsd OS
private:
DISALLOW_COPY_AND_ASSIGN (PlatformFreeBSD);
};
#endif // liblldb_PlatformFreeBSD_h_