This patch combines common code from Linux and FreeBSD into
a new POSIX platform. It also contains fixes for 64bit FreeBSD.
The patch is based on changes by Mark Peek <mp@FreeBSD.org> and
"K. Macy" <kmacy@freebsd.org> in their github repo located at
https://github.com/fbsd/lldb.
git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@147609 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Plugins/Process/Linux/ProcessLinux.cpp b/source/Plugins/Process/Linux/ProcessLinux.cpp
index 2171a6d..a8c33bc 100644
--- a/source/Plugins/Process/Linux/ProcessLinux.cpp
+++ b/source/Plugins/Process/Linux/ProcessLinux.cpp
@@ -20,10 +20,10 @@
#include "lldb/Target/Target.h"
#include "ProcessLinux.h"
-#include "ProcessLinuxLog.h"
+#include "ProcessPOSIXLog.h"
#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
#include "ProcessMonitor.h"
-#include "LinuxThread.h"
+#include "POSIXThread.h"
using namespace lldb;
using namespace lldb_private;
@@ -50,42 +50,21 @@
CreateInstance);
Log::Callbacks log_callbacks = {
- ProcessLinuxLog::DisableLog,
- ProcessLinuxLog::EnableLog,
- ProcessLinuxLog::ListLogCategories
+ ProcessPOSIXLog::DisableLog,
+ ProcessPOSIXLog::EnableLog,
+ ProcessPOSIXLog::ListLogCategories
};
Log::RegisterLogChannel (ProcessLinux::GetPluginNameStatic(), log_callbacks);
+ ProcessPOSIXLog::RegisterPluginName(GetPluginNameStatic());
}
}
-void
-ProcessLinux::Terminate()
-{
-}
-
-const char *
-ProcessLinux::GetPluginNameStatic()
-{
- return "plugin.process.linux";
-}
-
-const char *
-ProcessLinux::GetPluginDescriptionStatic()
-{
- return "Process plugin for Linux";
-}
-
-
//------------------------------------------------------------------------------
// Constructors and destructors.
ProcessLinux::ProcessLinux(Target& target, Listener &listener)
- : Process(target, listener),
- m_monitor(NULL),
- m_module(NULL),
- m_in_limbo(false),
- m_exit_now(false)
+ : ProcessPOSIX(target, listener)
{
#if 0
// FIXME: Putting this code in the ctor and saving the byte order in a
@@ -98,409 +77,28 @@
#endif
}
-ProcessLinux::~ProcessLinux()
-{
- delete m_monitor;
-}
-
-//------------------------------------------------------------------------------
-// Process protocol.
-
-bool
-ProcessLinux::CanDebug(Target &target, bool plugin_specified_by_name)
-{
- // For now we are just making sure the file exists for a given module
- ModuleSP exe_module_sp(target.GetExecutableModule());
- if (exe_module_sp.get())
- return exe_module_sp->GetFileSpec().Exists();
- return false;
-}
-
-Error
-ProcessLinux::DoAttachToProcessWithID(lldb::pid_t pid)
-{
- Error error;
- assert(m_monitor == NULL);
-
- LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PROCESS));
- if (log && log->GetMask().Test(LINUX_LOG_VERBOSE))
- log->Printf ("ProcessLinux::%s(pid = %i)", __FUNCTION__, GetID());
-
- m_monitor = new ProcessMonitor(this, pid, error);
-
- if (!error.Success())
- return error;
-
- SetID(pid);
- return error;
-}
-
-Error
-ProcessLinux::WillLaunch(Module* module)
-{
- Error error;
- return error;
-}
-
-Error
-ProcessLinux::DoLaunch (Module *module,
- const ProcessLaunchInfo &launch_info)
-{
- Error error;
- assert(m_monitor == NULL);
-
- SetPrivateState(eStateLaunching);
-
- const char *stdin_path = NULL;
- const char *stdout_path = NULL;
- const char *stderr_path = NULL;
- const char *working_dir = launch_info.GetWorkingDirectory();
-
- const ProcessLaunchInfo::FileAction *file_action;
- file_action = launch_info.GetFileActionForFD (STDIN_FILENO);
- if (file_action)
- {
- if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen)
- stdin_path = file_action->GetPath();
- }
- file_action = launch_info.GetFileActionForFD (STDOUT_FILENO);
- if (file_action)
- {
- if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen)
- stdout_path = file_action->GetPath();
- }
- file_action = launch_info.GetFileActionForFD (STDERR_FILENO);
- if (file_action)
- {
- if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen)
- stderr_path = file_action->GetPath();
- }
-
- m_monitor = new ProcessMonitor (this,
- module,
- launch_info.GetArguments().GetConstArgumentVector(),
- launch_info.GetEnvironmentEntries().GetConstArgumentVector(),
- stdin_path,
- stdout_path,
- stderr_path,
- error);
-
- m_module = module;
-
- if (!error.Success())
- return error;
-
- SetID(m_monitor->GetPID());
- return error;
-}
-
void
-ProcessLinux::DidLaunch()
+ProcessLinux::Terminate()
{
}
-
-Error
-ProcessLinux::DoResume()
+const char *
+ProcessLinux::GetPluginNameStatic()
{
- StateType state = GetPrivateState();
-
- assert(state == eStateStopped || state == eStateCrashed);
-
- // We are about to resume a thread that will cause the process to exit so
- // set our exit status now. Do not change our state if the inferior
- // crashed.
- if (state == eStateStopped)
- {
- if (m_in_limbo)
- SetExitStatus(m_exit_status, NULL);
- else
- SetPrivateState(eStateRunning);
- }
-
- bool did_resume = false;
- uint32_t thread_count = m_thread_list.GetSize(false);
- for (uint32_t i = 0; i < thread_count; ++i)
- {
- LinuxThread *thread = static_cast<LinuxThread*>(
- m_thread_list.GetThreadAtIndex(i, false).get());
- did_resume = thread->Resume() || did_resume;
- }
- assert(did_resume && "Process resume failed!");
-
- return Error();
+ return "linux";
}
-addr_t
-ProcessLinux::GetImageInfoAddress()
+const char *
+ProcessLinux::GetPluginDescriptionStatic()
{
- Target *target = &GetTarget();
- ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
- Address addr = obj_file->GetImageInfoAddress();
-
- if (addr.IsValid())
- return addr.GetLoadAddress(target);
- else
- return LLDB_INVALID_ADDRESS;
+ return "Process plugin for Linux";
}
-Error
-ProcessLinux::DoHalt(bool &caused_stop)
-{
- Error error;
-
- if (IsStopped())
- {
- caused_stop = false;
- }
- else if (kill(GetID(), SIGSTOP))
- {
- caused_stop = false;
- error.SetErrorToErrno();
- }
- else
- {
- caused_stop = true;
- }
-
- return error;
-}
-
-Error
-ProcessLinux::DoDetach()
-{
- Error error;
-
- error = m_monitor->Detach();
- if (error.Success())
- SetPrivateState(eStateDetached);
-
- return error;
-}
-
-Error
-ProcessLinux::DoSignal(int signal)
-{
- Error error;
-
- if (kill(GetID(), signal))
- error.SetErrorToErrno();
-
- return error;
-}
-
-Error
-ProcessLinux::DoDestroy()
-{
- Error error;
-
- if (!HasExited())
- {
- // Drive the exit event to completion (do not keep the inferior in
- // limbo).
- m_exit_now = true;
-
- if (kill(m_monitor->GetPID(), SIGKILL) && error.Success())
- {
- error.SetErrorToErrno();
- return error;
- }
-
- SetPrivateState(eStateExited);
- }
-
- return error;
-}
-
-void
-ProcessLinux::SendMessage(const ProcessMessage &message)
-{
- Mutex::Locker lock(m_message_mutex);
-
- switch (message.GetKind())
- {
- default:
- assert(false && "Unexpected process message!");
- break;
-
- case ProcessMessage::eInvalidMessage:
- return;
-
- case ProcessMessage::eLimboMessage:
- m_in_limbo = true;
- m_exit_status = message.GetExitStatus();
- if (m_exit_now)
- {
- SetPrivateState(eStateExited);
- m_monitor->Detach();
- }
- else
- SetPrivateState(eStateStopped);
- break;
-
- case ProcessMessage::eExitMessage:
- m_exit_status = message.GetExitStatus();
- SetExitStatus(m_exit_status, NULL);
- break;
-
- case ProcessMessage::eTraceMessage:
- case ProcessMessage::eBreakpointMessage:
- SetPrivateState(eStateStopped);
- break;
-
- case ProcessMessage::eSignalMessage:
- case ProcessMessage::eSignalDeliveredMessage:
- SetPrivateState(eStateStopped);
- break;
-
- case ProcessMessage::eCrashMessage:
- SetPrivateState(eStateCrashed);
- break;
- }
-
- m_message_queue.push(message);
-}
-
-void
-ProcessLinux::RefreshStateAfterStop()
-{
- LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PROCESS));
- if (log && log->GetMask().Test(LINUX_LOG_VERBOSE))
- log->Printf ("ProcessLinux::%s()", __FUNCTION__);
-
- Mutex::Locker lock(m_message_mutex);
- if (m_message_queue.empty())
- return;
-
- ProcessMessage &message = m_message_queue.front();
-
- // Resolve the thread this message corresponds to and pass it along.
- // FIXME: we're really dealing with the pid here. This should get
- // fixed when this code is fixed to handle multiple threads.
- lldb::tid_t tid = message.GetTID();
- if (log)
- log->Printf ("ProcessLinux::%s() pid = %i", __FUNCTION__, tid);
- LinuxThread *thread = static_cast<LinuxThread*>(
- GetThreadList().FindThreadByID(tid, false).get());
-
- assert(thread);
- thread->Notify(message);
-
- m_message_queue.pop();
-}
-
-bool
-ProcessLinux::IsAlive()
-{
- StateType state = GetPrivateState();
- return state != eStateDetached && state != eStateExited && state != eStateInvalid;
-}
-
-size_t
-ProcessLinux::DoReadMemory(addr_t vm_addr,
- void *buf, size_t size, Error &error)
-{
- assert(m_monitor);
- return m_monitor->ReadMemory(vm_addr, buf, size, error);
-}
-
-size_t
-ProcessLinux::DoWriteMemory(addr_t vm_addr, const void *buf, size_t size,
- Error &error)
-{
- assert(m_monitor);
- return m_monitor->WriteMemory(vm_addr, buf, size, error);
-}
-
-addr_t
-ProcessLinux::DoAllocateMemory(size_t size, uint32_t permissions,
- Error &error)
-{
- addr_t allocated_addr = LLDB_INVALID_ADDRESS;
-
- unsigned prot = 0;
- if (permissions & lldb::ePermissionsReadable)
- prot |= eMmapProtRead;
- if (permissions & lldb::ePermissionsWritable)
- prot |= eMmapProtWrite;
- if (permissions & lldb::ePermissionsExecutable)
- prot |= eMmapProtExec;
-
- if (InferiorCallMmap(this, allocated_addr, 0, size, prot,
- eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) {
- m_addr_to_mmap_size[allocated_addr] = size;
- error.Clear();
- } else {
- allocated_addr = LLDB_INVALID_ADDRESS;
- error.SetErrorStringWithFormat("unable to allocate %zu bytes of memory with permissions %s", size, GetPermissionsAsCString (permissions));
- }
-
- return allocated_addr;
-}
-
-Error
-ProcessLinux::DoDeallocateMemory(lldb::addr_t addr)
-{
- Error error;
- MMapMap::iterator pos = m_addr_to_mmap_size.find(addr);
- if (pos != m_addr_to_mmap_size.end() &&
- InferiorCallMunmap(this, addr, pos->second))
- m_addr_to_mmap_size.erase (pos);
- else
- error.SetErrorStringWithFormat("unable to deallocate memory at 0x%llx", addr);
-
- return error;
-}
-
-size_t
-ProcessLinux::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site)
-{
- static const uint8_t g_i386_opcode[] = { 0xCC };
-
- ArchSpec arch = GetTarget().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;
-}
-
-Error
-ProcessLinux::EnableBreakpoint(BreakpointSite *bp_site)
-{
- return EnableSoftwareBreakpoint(bp_site);
-}
-
-Error
-ProcessLinux::DisableBreakpoint(BreakpointSite *bp_site)
-{
- return DisableSoftwareBreakpoint(bp_site);
-}
-
-uint32_t
-ProcessLinux::UpdateThreadListIfNeeded()
-{
- // Do not allow recursive updates.
- return m_thread_list.GetSize(false);
-}
uint32_t
ProcessLinux::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list)
{
- LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD));
- if (log && log->GetMask().Test(LINUX_LOG_VERBOSE))
+ LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
log->Printf ("ProcessLinux::%s() (pid = %i)", __FUNCTION__, GetID());
// Update the process thread list with this new thread.
@@ -508,61 +106,15 @@
assert(m_monitor);
ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false));
if (!thread_sp)
- thread_sp.reset(new LinuxThread(*this, GetID()));
+ thread_sp.reset(new POSIXThread(*this, GetID()));
- if (log && log->GetMask().Test(LINUX_LOG_VERBOSE))
+ if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
log->Printf ("ProcessLinux::%s() updated pid = %i", __FUNCTION__, GetID());
new_thread_list.AddThread(thread_sp);
return new_thread_list.GetSize(false);
}
-ByteOrder
-ProcessLinux::GetByteOrder() const
-{
- // FIXME: We should be able to extract this value directly. See comment in
- // ProcessLinux().
- return m_byte_order;
-}
-
-size_t
-ProcessLinux::PutSTDIN(const char *buf, size_t len, Error &error)
-{
- ssize_t status;
- if ((status = write(m_monitor->GetTerminalFD(), buf, len)) < 0)
- {
- error.SetErrorToErrno();
- return 0;
- }
- return status;
-}
-
-size_t
-ProcessLinux::GetSTDOUT(char *buf, size_t len, Error &error)
-{
- ssize_t bytes_read;
-
- // The terminal file descriptor is always in non-block mode.
- if ((bytes_read = read(m_monitor->GetTerminalFD(), buf, len)) < 0)
- {
- if (errno != EAGAIN)
- error.SetErrorToErrno();
- return 0;
- }
- return bytes_read;
-}
-
-size_t
-ProcessLinux::GetSTDERR(char *buf, size_t len, Error &error)
-{
- return GetSTDOUT(buf, len, error);
-}
-
-UnixSignals &
-ProcessLinux::GetUnixSignals()
-{
- return m_linux_signals;
-}
//------------------------------------------------------------------------------
// ProcessInterface protocol.
@@ -601,39 +153,3 @@
{
return NULL;
}
-
-//------------------------------------------------------------------------------
-// Utility functions.
-
-bool
-ProcessLinux::HasExited()
-{
- switch (GetPrivateState())
- {
- default:
- break;
-
- case eStateDetached:
- case eStateExited:
- return true;
- }
-
- return false;
-}
-
-bool
-ProcessLinux::IsStopped()
-{
- switch (GetPrivateState())
- {
- default:
- break;
-
- case eStateStopped:
- case eStateCrashed:
- case eStateSuspended:
- return true;
- }
-
- return false;
-}