//===-- ProcessLinux.cpp ----------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // C Includes #include // C++ Includes // Other libraries and framework includes #include "lldb/Core/PluginManager.h" #include "lldb/Core/State.h" #include "lldb/Host/Host.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/DynamicLoader.h" #include "lldb/Target/Target.h" #include "ProcessLinux.h" #include "ProcessPOSIXLog.h" #include "Plugins/Process/Utility/InferiorCallPOSIX.h" #include "ProcessMonitor.h" #include "LinuxThread.h" using namespace lldb; using namespace lldb_private; //------------------------------------------------------------------------------ // Static functions. ProcessSP ProcessLinux::CreateInstance(Target &target, Listener &listener, const FileSpec *core_file) { return ProcessSP(new ProcessLinux(target, listener, (FileSpec *)core_file)); } void ProcessLinux::Initialize() { static bool g_initialized = false; if (!g_initialized) { g_initialized = true; PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance); Log::Callbacks log_callbacks = { ProcessPOSIXLog::DisableLog, ProcessPOSIXLog::EnableLog, ProcessPOSIXLog::ListLogCategories }; Log::RegisterLogChannel (ProcessLinux::GetPluginNameStatic(), log_callbacks); ProcessPOSIXLog::RegisterPluginName(GetPluginNameStatic()); } } //------------------------------------------------------------------------------ // Constructors and destructors. ProcessLinux::ProcessLinux(Target& target, Listener &listener, FileSpec *core_file) : ProcessPOSIX(target, listener), m_core_file(core_file), m_stopping_threads(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. ObjectFile *obj_file = GetTarget().GetExecutableModule()->GetObjectFile(); m_byte_order = obj_file->GetByteOrder(); #else // XXX: Will work only for local processes. m_byte_order = lldb::endian::InlHostByteOrder(); #endif } void ProcessLinux::Terminate() { } lldb_private::ConstString ProcessLinux::GetPluginNameStatic() { static ConstString g_name("linux"); return g_name; } const char * ProcessLinux::GetPluginDescriptionStatic() { return "Process plugin for Linux"; } bool ProcessLinux::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) { new_thread_list = old_thread_list; return new_thread_list.GetSize(false) > 0; } //------------------------------------------------------------------------------ // ProcessInterface protocol. lldb_private::ConstString ProcessLinux::GetPluginName() { return GetPluginNameStatic(); } uint32_t ProcessLinux::GetPluginVersion() { return 1; } void ProcessLinux::GetPluginCommandHelp(const char *command, Stream *strm) { } Error ProcessLinux::ExecutePluginCommand(Args &command, Stream *strm) { return Error(1, eErrorTypeGeneric); } Log * ProcessLinux::EnablePluginLogging(Stream *strm, Args &command) { return NULL; } // ProcessPOSIX override void ProcessLinux::StopAllThreads(lldb::tid_t stop_tid) { // If a breakpoint occurs while we're stopping threads, we'll get back // here, but we don't want to do it again. Only the MonitorChildProcess // thread calls this function, so we don't need to protect this flag. if (m_stopping_threads) return; m_stopping_threads = true; Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); if (log) log->Printf ("ProcessLinux::%s() stopping all threads", __FUNCTION__); // Walk the thread list and stop the other threads. The thread that caused // the stop should already be marked as stopped before we get here. Mutex::Locker thread_list_lock(m_thread_list.GetMutex()); uint32_t thread_count = m_thread_list.GetSize(false); for (uint32_t i = 0; i < thread_count; ++i) { POSIXThread *thread = static_cast( m_thread_list.GetThreadAtIndex(i, false).get()); assert(thread); lldb::tid_t tid = thread->GetID(); if (!StateIsStoppedState(thread->GetState(), false)) m_monitor->StopThread(tid); } m_stopping_threads = false; if (log) log->Printf ("ProcessLinux::%s() finished", __FUNCTION__); } // ProcessPOSIX override POSIXThread * ProcessLinux::CreateNewPOSIXThread(lldb_private::Process &process, lldb::tid_t tid) { return new LinuxThread(process, tid); } bool ProcessLinux::CanDebug(Target &target, bool plugin_specified_by_name) { if (plugin_specified_by_name) return true; /* If core file is specified then let elf-core plugin handle it */ if (m_core_file) return false; return ProcessPOSIX::CanDebug(target, plugin_specified_by_name); }