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:
Greg Clayton
2011-11-29 20:50:10 +00:00
parent 31798ef3c0
commit 28041352cb
5 changed files with 221 additions and 62 deletions

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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

View File

@@ -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;

View File

@@ -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);