Files
clang-p2996/lldb/source/Plugins/Platform/Kalimba/PlatformKalimba.cpp
Pavel Labath d5b310f2a3 Avoid going through Platform when creating a NativeProcessProtocol instance
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
2015-07-09 11:51:11 +00:00

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.
}