Summary: This commit avoids the Platform instance when spawning or attaching to a process in lldb-server. Instead, I have the server call a (static) method of NativeProcessProtocol directly. The reason for this is that I believe that NativeProcessProtocol should be decoupled from the Platform (after all, it always knows which platform it is running on, unlike the rest of lldb). Additionally, the kind of platform actions a NativeProcessProtocol instance is likely to differ greatly from the platform actions of the lldb client, so I think the separation makes sense. After this, the only dependency NativeProcessLinux has on PlatformLinux is the ResolveExecutable method, which needs additional refactoring. This is a resubmit of r241672, after it was reverted due to build failueres on non-linux platforms. Reviewers: ovyalov, clayborg Subscribers: lldb-commits Differential Revision: http://reviews.llvm.org/D10996 llvm-svn: 241796
325 lines
10 KiB
C++
325 lines
10 KiB
C++
//===-- PlatformKalimba.cpp ---------------------------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "PlatformKalimba.h"
|
|
#include "lldb/Host/Config.h"
|
|
|
|
// C++ Includes
|
|
// Other libraries and framework includes
|
|
// Project includes
|
|
#include "lldb/Core/Error.h"
|
|
#include "lldb/Core/Debugger.h"
|
|
#include "lldb/Core/Module.h"
|
|
#include "lldb/Core/ModuleList.h"
|
|
#include "lldb/Core/ModuleSpec.h"
|
|
#include "lldb/Core/PluginManager.h"
|
|
#include "lldb/Core/StreamString.h"
|
|
#include "lldb/Host/FileSpec.h"
|
|
#include "lldb/Host/HostInfo.h"
|
|
#include "lldb/Target/Target.h"
|
|
#include "lldb/Target/Process.h"
|
|
|
|
using namespace lldb;
|
|
using namespace lldb_private;
|
|
|
|
static uint32_t g_initialize_count = 0;
|
|
|
|
PlatformSP
|
|
PlatformKalimba::CreateInstance (bool force, const ArchSpec *arch)
|
|
{
|
|
bool create = force;
|
|
if (create == false && arch && arch->IsValid())
|
|
{
|
|
const llvm::Triple &triple = arch->GetTriple();
|
|
switch (triple.getVendor())
|
|
{
|
|
case llvm::Triple::CSR:
|
|
create = true;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
if (create)
|
|
return PlatformSP(new PlatformKalimba(false));
|
|
return PlatformSP();
|
|
}
|
|
|
|
lldb_private::ConstString
|
|
PlatformKalimba::GetPluginNameStatic (bool /*is_host*/)
|
|
{
|
|
static ConstString g_remote_name("kalimba");
|
|
return g_remote_name;
|
|
}
|
|
|
|
const char *
|
|
PlatformKalimba::GetPluginDescriptionStatic (bool /*is_host*/)
|
|
{
|
|
return "Kalimba user platform plug-in.";
|
|
}
|
|
|
|
lldb_private::ConstString
|
|
PlatformKalimba::GetPluginName()
|
|
{
|
|
return GetPluginNameStatic(false);
|
|
}
|
|
|
|
void
|
|
PlatformKalimba::Initialize ()
|
|
{
|
|
Platform::Initialize ();
|
|
|
|
if (g_initialize_count++ == 0)
|
|
{
|
|
PluginManager::RegisterPlugin(PlatformKalimba::GetPluginNameStatic(false),
|
|
PlatformKalimba::GetPluginDescriptionStatic(false),
|
|
PlatformKalimba::CreateInstance);
|
|
}
|
|
}
|
|
|
|
void
|
|
PlatformKalimba::Terminate ()
|
|
{
|
|
if (g_initialize_count > 0)
|
|
{
|
|
if (--g_initialize_count == 0)
|
|
{
|
|
PluginManager::UnregisterPlugin (PlatformKalimba::CreateInstance);
|
|
}
|
|
}
|
|
|
|
Platform::Terminate ();
|
|
}
|
|
|
|
Error
|
|
PlatformKalimba::ResolveExecutable (const ModuleSpec &ms,
|
|
lldb::ModuleSP &exe_module_sp,
|
|
const FileSpecList *module_search_paths_ptr)
|
|
{
|
|
Error error;
|
|
char exe_path[PATH_MAX];
|
|
ModuleSpec resolved_module_spec(ms);
|
|
|
|
if (!resolved_module_spec.GetFileSpec().Exists())
|
|
{
|
|
resolved_module_spec.GetFileSpec().GetPath(exe_path, sizeof(exe_path));
|
|
error.SetErrorStringWithFormat("unable to find executable for '%s'", exe_path);
|
|
}
|
|
|
|
if (error.Success())
|
|
{
|
|
if (resolved_module_spec.GetArchitecture().IsValid())
|
|
{
|
|
error = ModuleList::GetSharedModule (resolved_module_spec,
|
|
exe_module_sp,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
if (error.Fail())
|
|
{
|
|
// If we failed, it may be because the vendor and os aren't known. If that is the
|
|
// case, try setting them to the host architecture and give it another try.
|
|
llvm::Triple &module_triple = resolved_module_spec.GetArchitecture().GetTriple();
|
|
bool is_vendor_specified = (module_triple.getVendor() != llvm::Triple::UnknownVendor);
|
|
bool is_os_specified = (module_triple.getOS() != llvm::Triple::UnknownOS);
|
|
if (!is_vendor_specified || !is_os_specified)
|
|
{
|
|
const llvm::Triple &host_triple = HostInfo::GetArchitecture(HostInfo::eArchKindDefault).GetTriple();
|
|
|
|
if (!is_vendor_specified)
|
|
module_triple.setVendorName (host_triple.getVendorName());
|
|
if (!is_os_specified)
|
|
module_triple.setOSName (host_triple.getOSName());
|
|
|
|
error = ModuleList::GetSharedModule (resolved_module_spec,
|
|
exe_module_sp,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
}
|
|
}
|
|
|
|
// TODO find out why exe_module_sp might be NULL
|
|
if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL)
|
|
{
|
|
exe_module_sp.reset();
|
|
error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s",
|
|
resolved_module_spec.GetFileSpec().GetPath().c_str(),
|
|
resolved_module_spec.GetArchitecture().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;
|
|
for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, resolved_module_spec.GetArchitecture()); ++idx)
|
|
{
|
|
error = ModuleList::GetSharedModule (resolved_module_spec,
|
|
exe_module_sp,
|
|
NULL,
|
|
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 (resolved_module_spec.GetArchitecture().GetArchitectureName());
|
|
}
|
|
|
|
if (error.Fail() || !exe_module_sp)
|
|
{
|
|
if (resolved_module_spec.GetFileSpec().Readable())
|
|
{
|
|
error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
|
|
resolved_module_spec.GetFileSpec().GetPath().c_str(),
|
|
GetPluginName().GetCString(),
|
|
arch_names.GetString().c_str());
|
|
}
|
|
else
|
|
{
|
|
error.SetErrorStringWithFormat("'%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return error;
|
|
}
|
|
|
|
Error
|
|
PlatformKalimba::GetFileWithUUID (const FileSpec & /*platform_file*/,
|
|
const UUID * /*uuid_ptr*/, FileSpec & /*local_file*/)
|
|
{
|
|
return Error();
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------
|
|
/// Default Constructor
|
|
//------------------------------------------------------------------
|
|
PlatformKalimba::PlatformKalimba (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.
|
|
//------------------------------------------------------------------
|
|
PlatformKalimba::~PlatformKalimba()
|
|
{
|
|
}
|
|
|
|
bool
|
|
PlatformKalimba::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
|
|
{
|
|
bool success = false;
|
|
if (IsHost())
|
|
{
|
|
success = false;
|
|
}
|
|
else
|
|
{
|
|
if (m_remote_platform_sp)
|
|
success = m_remote_platform_sp->GetProcessInfo (pid, process_info);
|
|
}
|
|
return success;
|
|
}
|
|
|
|
bool
|
|
PlatformKalimba::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
|
|
{
|
|
if (idx == 0)
|
|
{
|
|
arch = ArchSpec("kalimba3-csr-unknown");
|
|
return true;
|
|
}
|
|
if (idx == 1)
|
|
{
|
|
arch = ArchSpec("kalimba4-csr-unknown");
|
|
return true;
|
|
}
|
|
if (idx == 2)
|
|
{
|
|
arch = ArchSpec("kalimba5-csr-unknown");
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void
|
|
PlatformKalimba::GetStatus (Stream &strm)
|
|
{
|
|
Platform::GetStatus(strm);
|
|
}
|
|
|
|
size_t
|
|
PlatformKalimba::GetSoftwareBreakpointTrapOpcode (Target & /*target*/,
|
|
BreakpointSite * /*bp_site*/)
|
|
{
|
|
// the target hardware does not support software breakpoints
|
|
return 0;
|
|
}
|
|
|
|
Error
|
|
PlatformKalimba::LaunchProcess (ProcessLaunchInfo &launch_info)
|
|
{
|
|
Error error;
|
|
|
|
if (IsHost())
|
|
{
|
|
error.SetErrorString ("native execution is not possible");
|
|
}
|
|
else
|
|
{
|
|
error.SetErrorString ("the platform is not currently connected");
|
|
}
|
|
return error;
|
|
}
|
|
|
|
lldb::ProcessSP
|
|
PlatformKalimba::Attach(ProcessAttachInfo &attach_info,
|
|
Debugger &debugger,
|
|
Target *target,
|
|
Error &error)
|
|
{
|
|
lldb::ProcessSP process_sp;
|
|
if (IsHost())
|
|
{
|
|
error.SetErrorString ("native execution is not possible");
|
|
}
|
|
else
|
|
{
|
|
if (m_remote_platform_sp)
|
|
process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, error);
|
|
else
|
|
error.SetErrorString ("the platform is not currently connected");
|
|
}
|
|
return process_sp;
|
|
}
|
|
|
|
void
|
|
PlatformKalimba::CalculateTrapHandlerSymbolNames ()
|
|
{
|
|
// TODO Research this sometime.
|
|
}
|