mirror of
https://github.com/intel/llvm.git
synced 2026-01-16 21:55:39 +08:00
Patch from Dawn that fixes up linux debugging and a first passs at an
implementation of the linux platform. llvm-svn: 145433
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
// 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/PluginManager.h"
|
||||
@@ -29,10 +30,12 @@
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
static uint32_t g_initialize_count = 0;
|
||||
|
||||
Platform *
|
||||
PlatformLinux::CreateInstance ()
|
||||
{
|
||||
return new PlatformLinux();
|
||||
return new PlatformLinux(true);
|
||||
}
|
||||
|
||||
const char *
|
||||
@@ -42,33 +45,51 @@ PlatformLinux::GetPluginNameStatic()
|
||||
}
|
||||
|
||||
const char *
|
||||
PlatformLinux::GetPluginDescriptionStatic()
|
||||
PlatformLinux::GetShortPluginNameStatic (bool is_host)
|
||||
{
|
||||
return "Default platform plugin for Linux";
|
||||
if (is_host)
|
||||
return Platform::GetHostPlatformName ();
|
||||
else
|
||||
return "remote-linux";
|
||||
}
|
||||
|
||||
const char *
|
||||
PlatformLinux::GetPluginDescriptionStatic (bool is_host)
|
||||
{
|
||||
if (is_host)
|
||||
return "Local Linux user platform plug-in.";
|
||||
else
|
||||
return "Remote Linux user platform plug-in.";
|
||||
}
|
||||
|
||||
void
|
||||
PlatformLinux::Initialize ()
|
||||
{
|
||||
static bool g_initialized = false;
|
||||
|
||||
if (!g_initialized)
|
||||
if (g_initialize_count++ == 0)
|
||||
{
|
||||
PlatformSP default_platform_sp (CreateInstance());
|
||||
#if defined(__linux__)
|
||||
PlatformSP default_platform_sp (new PlatformLinux(true));
|
||||
default_platform_sp->SetSystemArchitecture (Host::GetArchitecture());
|
||||
Platform::SetDefaultPlatform (default_platform_sp);
|
||||
PluginManager::RegisterPlugin(GetPluginNameStatic(),
|
||||
GetPluginDescriptionStatic(),
|
||||
CreateInstance);
|
||||
g_initialized = true;
|
||||
#endif
|
||||
PluginManager::RegisterPlugin(PlatformLinux::GetShortPluginNameStatic(false),
|
||||
PlatformLinux::GetPluginDescriptionStatic(false),
|
||||
PlatformLinux::CreateInstance);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PlatformLinux::Terminate ()
|
||||
{
|
||||
if (g_initialize_count > 0)
|
||||
{
|
||||
if (--g_initialize_count == 0)
|
||||
{
|
||||
PluginManager::UnregisterPlugin (PlatformLinux::CreateInstance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Error
|
||||
PlatformLinux::ResolveExecutable (const FileSpec &exe_file,
|
||||
const ArchSpec &exe_arch,
|
||||
@@ -77,17 +98,50 @@ PlatformLinux::ResolveExecutable (const FileSpec &exe_file,
|
||||
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 ();
|
||||
if (IsHost())
|
||||
{
|
||||
// If we have "ls" as the exe_file, resolve the executable location 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);
|
||||
}
|
||||
|
||||
// Resolve any executable within a bundle on MacOSX
|
||||
Host::ResolveExecutableInBundle (resolved_exe_file);
|
||||
if (!resolved_exe_file.Exists())
|
||||
resolved_exe_file.ResolveExecutableLocation ();
|
||||
|
||||
if (resolved_exe_file.Exists())
|
||||
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).
|
||||
|
||||
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.", exe_path);
|
||||
}
|
||||
}
|
||||
|
||||
if (error.Success())
|
||||
{
|
||||
if (exe_arch.IsValid())
|
||||
{
|
||||
@@ -152,21 +206,20 @@ PlatformLinux::ResolveExecutable (const FileSpec &exe_file,
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
error.SetErrorStringWithFormat ("'%s%s%s' does not exist",
|
||||
exe_file.GetDirectory().AsCString(""),
|
||||
exe_file.GetDirectory() ? "/" : "",
|
||||
exe_file.GetFilename().AsCString(""));
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
Error
|
||||
PlatformLinux::GetFile (const FileSpec &platform_file,
|
||||
const UUID *uuid, FileSpec &local_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();
|
||||
@@ -176,8 +229,9 @@ PlatformLinux::GetFile (const FileSpec &platform_file,
|
||||
//------------------------------------------------------------------
|
||||
/// Default Constructor
|
||||
//------------------------------------------------------------------
|
||||
PlatformLinux::PlatformLinux () :
|
||||
Platform(true)
|
||||
PlatformLinux::PlatformLinux (bool is_host) :
|
||||
Platform(is_host), // This is the local host platform
|
||||
m_remote_platform_sp ()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -194,7 +248,17 @@ PlatformLinux::~PlatformLinux()
|
||||
bool
|
||||
PlatformLinux::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
|
||||
{
|
||||
return Host::GetProcessInfo (pid, process_info);
|
||||
bool success = false;
|
||||
if (IsHost())
|
||||
{
|
||||
success = Platform::GetProcessInfo (pid, process_info);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_remote_platform_sp)
|
||||
success = m_remote_platform_sp->GetProcessInfo (pid, process_info);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -225,11 +289,9 @@ size_t
|
||||
PlatformLinux::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;
|
||||
const uint8_t *trap_opcode = NULL;
|
||||
size_t trap_opcode_size = 0;
|
||||
|
||||
switch (arch.GetCore())
|
||||
{
|
||||
@@ -239,13 +301,39 @@ PlatformLinux::GetSoftwareBreakpointTrapOpcode (Target &target,
|
||||
|
||||
case ArchSpec::eCore_x86_32_i386:
|
||||
case ArchSpec::eCore_x86_64_x86_64:
|
||||
opcode = g_i386_opcode;
|
||||
opcode_size = sizeof(g_i386_opcode);
|
||||
{
|
||||
static const uint8_t g_i386_breakpoint_opcode[] = { 0xCC };
|
||||
trap_opcode = g_i386_breakpoint_opcode;
|
||||
trap_opcode_size = sizeof(g_i386_breakpoint_opcode);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
bp_site->SetTrapOpcode(opcode, opcode_size);
|
||||
return opcode_size;
|
||||
if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
|
||||
return trap_opcode_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Error
|
||||
PlatformLinux::LaunchProcess (ProcessLaunchInfo &launch_info)
|
||||
{
|
||||
Error error;
|
||||
|
||||
if (IsHost())
|
||||
{
|
||||
if (launch_info.GetFlags().Test (eLaunchFlagLaunchInShell))
|
||||
{
|
||||
const bool is_localhost = true;
|
||||
if (!launch_info.ConvertArgumentsForLaunchingInShell (error, is_localhost))
|
||||
return error;
|
||||
}
|
||||
error = Platform::LaunchProcess (launch_info);
|
||||
}
|
||||
else
|
||||
{
|
||||
error.SetErrorString ("the platform is not currently connected");
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
lldb::ProcessSP
|
||||
@@ -255,7 +343,42 @@ PlatformLinux::Attach(ProcessAttachInfo &attach_info,
|
||||
Listener &listener,
|
||||
Error &error)
|
||||
{
|
||||
ProcessSP processSP;
|
||||
assert(!"Not implemented yet!");
|
||||
return processSP;
|
||||
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,
|
||||
m_remote_platform_sp,
|
||||
new_target_sp);
|
||||
target = new_target_sp.get();
|
||||
}
|
||||
else
|
||||
error.Clear();
|
||||
|
||||
if (target && error.Success())
|
||||
{
|
||||
debugger.GetTargetList().SetSelectedTarget(target);
|
||||
|
||||
process_sp = target->CreateProcess (listener, attach_info.GetProcessPluginName());
|
||||
|
||||
if (process_sp)
|
||||
error = process_sp->Attach (attach_info);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_remote_platform_sp)
|
||||
process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, listener, error);
|
||||
else
|
||||
error.SetErrorString ("the platform is not currently connected");
|
||||
}
|
||||
return process_sp;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace lldb_private {
|
||||
static void
|
||||
Terminate ();
|
||||
|
||||
PlatformLinux ();
|
||||
PlatformLinux (bool is_host);
|
||||
|
||||
virtual
|
||||
~PlatformLinux();
|
||||
@@ -43,7 +43,10 @@ namespace lldb_private {
|
||||
GetPluginNameStatic();
|
||||
|
||||
static const char *
|
||||
GetPluginDescriptionStatic();
|
||||
GetShortPluginNameStatic(bool is_host);
|
||||
|
||||
static const char *
|
||||
GetPluginDescriptionStatic(bool is_host);
|
||||
|
||||
virtual const char *
|
||||
GetPluginName()
|
||||
@@ -74,7 +77,7 @@ namespace lldb_private {
|
||||
virtual const char *
|
||||
GetDescription ()
|
||||
{
|
||||
return GetPluginDescriptionStatic();
|
||||
return GetPluginDescriptionStatic(IsHost());
|
||||
}
|
||||
|
||||
virtual void
|
||||
@@ -94,6 +97,9 @@ namespace lldb_private {
|
||||
GetSoftwareBreakpointTrapOpcode (Target &target,
|
||||
BreakpointSite *bp_site);
|
||||
|
||||
virtual lldb_private::Error
|
||||
LaunchProcess (lldb_private::ProcessLaunchInfo &launch_info);
|
||||
|
||||
virtual lldb::ProcessSP
|
||||
Attach(ProcessAttachInfo &attach_info, Debugger &debugger,
|
||||
Target *target, Listener &listener, Error &error);
|
||||
@@ -105,7 +111,7 @@ namespace lldb_private {
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
lldb::PlatformSP m_remote_platform_sp; // Allow multiple ways to connect to a remote darwin OS
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN (PlatformLinux);
|
||||
|
||||
@@ -87,7 +87,6 @@ ProcessLinux::ProcessLinux(Target& target, Listener &listener)
|
||||
m_in_limbo(false),
|
||||
m_exit_now(false)
|
||||
{
|
||||
|
||||
#if 0
|
||||
// FIXME: Putting this code in the ctor and saving the byte order in a
|
||||
// member variable is a hack to avoid const qual issues in GetByteOrder.
|
||||
@@ -152,7 +151,6 @@ ProcessLinux::DoLaunch (Module *module,
|
||||
|
||||
SetPrivateState(eStateLaunching);
|
||||
|
||||
uint32_t launch_flags = launch_info.GetFlags().Get();
|
||||
const char *stdin_path = NULL;
|
||||
const char *stdout_path = NULL;
|
||||
const char *stderr_path = NULL;
|
||||
@@ -270,7 +268,13 @@ ProcessLinux::DoHalt(bool &caused_stop)
|
||||
Error
|
||||
ProcessLinux::DoDetach()
|
||||
{
|
||||
return Error(1, eErrorTypeGeneric);
|
||||
Error error;
|
||||
|
||||
error = m_monitor->Detach();
|
||||
if (error.Success())
|
||||
SetPrivateState(eStateDetached);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
Error
|
||||
@@ -388,7 +392,7 @@ bool
|
||||
ProcessLinux::IsAlive()
|
||||
{
|
||||
StateType state = GetPrivateState();
|
||||
return state != eStateExited && state != eStateInvalid;
|
||||
return state != eStateDetached && state != eStateExited && state != eStateInvalid;
|
||||
}
|
||||
|
||||
size_t
|
||||
|
||||
@@ -722,6 +722,30 @@ KillOperation::Execute(ProcessMonitor *monitor)
|
||||
m_result = true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// @class KillOperation
|
||||
/// @brief Implements ProcessMonitor::BringProcessIntoLimbo.
|
||||
class DetachOperation : public Operation
|
||||
{
|
||||
public:
|
||||
DetachOperation(Error &result) : m_error(result) { }
|
||||
|
||||
void Execute(ProcessMonitor *monitor);
|
||||
|
||||
private:
|
||||
Error &m_error;
|
||||
};
|
||||
|
||||
void
|
||||
DetachOperation::Execute(ProcessMonitor *monitor)
|
||||
{
|
||||
lldb::pid_t pid = monitor->GetPID();
|
||||
|
||||
if (ptrace(PT_DETACH, pid, NULL, 0) < 0)
|
||||
m_error.SetErrorToErrno();
|
||||
|
||||
}
|
||||
|
||||
ProcessMonitor::OperationArgs::OperationArgs(ProcessMonitor *monitor)
|
||||
: m_monitor(monitor)
|
||||
{
|
||||
@@ -1220,7 +1244,7 @@ ProcessMonitor::MonitorCallback(void *callback_baton,
|
||||
|
||||
ProcessMessage
|
||||
ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor,
|
||||
const struct siginfo *info, lldb::pid_t pid)
|
||||
const siginfo_t *info, lldb::pid_t pid)
|
||||
{
|
||||
ProcessMessage message;
|
||||
|
||||
@@ -1261,7 +1285,7 @@ ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor,
|
||||
|
||||
ProcessMessage
|
||||
ProcessMonitor::MonitorSignal(ProcessMonitor *monitor,
|
||||
const struct siginfo *info, lldb::pid_t pid)
|
||||
const siginfo_t *info, lldb::pid_t pid)
|
||||
{
|
||||
ProcessMessage message;
|
||||
int signo = info->si_signo;
|
||||
@@ -1312,7 +1336,7 @@ ProcessMonitor::MonitorSignal(ProcessMonitor *monitor,
|
||||
}
|
||||
|
||||
ProcessMessage::CrashReason
|
||||
ProcessMonitor::GetCrashReasonForSIGSEGV(const struct siginfo *info)
|
||||
ProcessMonitor::GetCrashReasonForSIGSEGV(const siginfo_t *info)
|
||||
{
|
||||
ProcessMessage::CrashReason reason;
|
||||
assert(info->si_signo == SIGSEGV);
|
||||
@@ -1336,7 +1360,7 @@ ProcessMonitor::GetCrashReasonForSIGSEGV(const struct siginfo *info)
|
||||
}
|
||||
|
||||
ProcessMessage::CrashReason
|
||||
ProcessMonitor::GetCrashReasonForSIGILL(const struct siginfo *info)
|
||||
ProcessMonitor::GetCrashReasonForSIGILL(const siginfo_t *info)
|
||||
{
|
||||
ProcessMessage::CrashReason reason;
|
||||
assert(info->si_signo == SIGILL);
|
||||
@@ -1378,7 +1402,7 @@ ProcessMonitor::GetCrashReasonForSIGILL(const struct siginfo *info)
|
||||
}
|
||||
|
||||
ProcessMessage::CrashReason
|
||||
ProcessMonitor::GetCrashReasonForSIGFPE(const struct siginfo *info)
|
||||
ProcessMonitor::GetCrashReasonForSIGFPE(const siginfo_t *info)
|
||||
{
|
||||
ProcessMessage::CrashReason reason;
|
||||
assert(info->si_signo == SIGFPE);
|
||||
@@ -1420,7 +1444,7 @@ ProcessMonitor::GetCrashReasonForSIGFPE(const struct siginfo *info)
|
||||
}
|
||||
|
||||
ProcessMessage::CrashReason
|
||||
ProcessMonitor::GetCrashReasonForSIGBUS(const struct siginfo *info)
|
||||
ProcessMonitor::GetCrashReasonForSIGBUS(const siginfo_t *info)
|
||||
{
|
||||
ProcessMessage::CrashReason reason;
|
||||
assert(info->si_signo == SIGBUS);
|
||||
@@ -1646,7 +1670,9 @@ bool
|
||||
ProcessMonitor::Detach()
|
||||
{
|
||||
bool result;
|
||||
KillOperation op(result);
|
||||
lldb_private::Error error;
|
||||
DetachOperation op(error);
|
||||
result = error.Success();
|
||||
DoOperation(&op);
|
||||
StopMonitor();
|
||||
return result;
|
||||
|
||||
@@ -257,23 +257,23 @@ private:
|
||||
|
||||
static ProcessMessage
|
||||
MonitorSIGTRAP(ProcessMonitor *monitor,
|
||||
const struct siginfo *info, lldb::pid_t pid);
|
||||
const siginfo_t *info, lldb::pid_t pid);
|
||||
|
||||
static ProcessMessage
|
||||
MonitorSignal(ProcessMonitor *monitor,
|
||||
const struct siginfo *info, lldb::pid_t pid);
|
||||
const siginfo_t *info, lldb::pid_t pid);
|
||||
|
||||
static ProcessMessage::CrashReason
|
||||
GetCrashReasonForSIGSEGV(const struct siginfo *info);
|
||||
GetCrashReasonForSIGSEGV(const siginfo_t *info);
|
||||
|
||||
static ProcessMessage::CrashReason
|
||||
GetCrashReasonForSIGILL(const struct siginfo *info);
|
||||
GetCrashReasonForSIGILL(const siginfo_t *info);
|
||||
|
||||
static ProcessMessage::CrashReason
|
||||
GetCrashReasonForSIGFPE(const struct siginfo *info);
|
||||
GetCrashReasonForSIGFPE(const siginfo_t *info);
|
||||
|
||||
static ProcessMessage::CrashReason
|
||||
GetCrashReasonForSIGBUS(const struct siginfo *info);
|
||||
GetCrashReasonForSIGBUS(const siginfo_t *info);
|
||||
|
||||
void
|
||||
DoOperation(Operation *op);
|
||||
|
||||
Reference in New Issue
Block a user