Index: source/API/SystemInitializerFull.cpp =================================================================== --- source/API/SystemInitializerFull.cpp +++ source/API/SystemInitializerFull.cpp @@ -55,10 +55,6 @@ #include "Plugins/Process/FreeBSD/ProcessFreeBSD.h" #endif -#if defined(__linux__) -#include "Plugins/Process/Linux/ProcessLinux.h" -#endif - #if defined(_MSC_VER) #include "lldb/Host/windows/windows.h" #include "Plugins/Process/Windows/DynamicLoaderWindows.h" @@ -265,12 +261,6 @@ SystemRuntimeMacOSX::Initialize(); RenderScriptRuntime::Initialize(); -#if defined(__linux__) - //---------------------------------------------------------------------- - // Linux hosted plugins - //---------------------------------------------------------------------- - process_linux::ProcessLinux::Initialize(); -#endif #if defined(_MSC_VER) DynamicLoaderWindows::Initialize(); ProcessWindows::Initialize(); @@ -380,10 +370,6 @@ DynamicLoaderWindows::Terminate(); #endif -#if defined(__linux__) - process_linux::ProcessLinux::Terminate(); -#endif - #if defined(__FreeBSD__) ProcessFreeBSD::Terminate(); #endif Index: source/Initialization/SystemInitializerCommon.cpp =================================================================== --- source/Initialization/SystemInitializerCommon.cpp +++ source/Initialization/SystemInitializerCommon.cpp @@ -42,7 +42,6 @@ #endif #if defined(__linux__) -#include "Plugins/Process/Linux/ProcessLinux.h" #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" #endif Index: source/Plugins/Platform/Linux/PlatformLinux.h =================================================================== --- source/Plugins/Platform/Linux/PlatformLinux.h +++ source/Plugins/Platform/Linux/PlatformLinux.h @@ -122,9 +122,6 @@ uint64_t ConvertMmapFlagsToPlatform(unsigned flags) override; - static bool - UseLlgsForLocalDebugging (); - private: DISALLOW_COPY_AND_ASSIGN (PlatformLinux); }; Index: source/Plugins/Platform/Linux/PlatformLinux.cpp =================================================================== --- source/Plugins/Platform/Linux/PlatformLinux.cpp +++ source/Plugins/Platform/Linux/PlatformLinux.cpp @@ -57,11 +57,6 @@ namespace { - enum - { - ePropertyUseLlgsForLocal = 0, - }; - class PlatformLinuxProperties : public Properties { public: @@ -73,9 +68,6 @@ virtual ~PlatformLinuxProperties() = default; - bool - GetUseLlgsForLocal() const; - private: static const PropertyDefinition* GetStaticPropertyDefinitions(); @@ -99,27 +91,15 @@ return g_setting_name; } -bool -PlatformLinuxProperties::GetUseLlgsForLocal() const -{ - const uint32_t idx = ePropertyUseLlgsForLocal; - return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, GetStaticPropertyDefinitions()[idx].default_uint_value != 0); -} - const PropertyDefinition* PlatformLinuxProperties::GetStaticPropertyDefinitions() { static PropertyDefinition g_properties[] = { - { "use-llgs-for-local" , OptionValue::eTypeBoolean, true, true, NULL, NULL, "Control whether the platform uses llgs for local debug sessions." }, { NULL , OptionValue::eTypeInvalid, false, 0 , NULL, NULL, NULL } }; - // Allow environment variable to disable llgs-local. - if (getenv("PLATFORM_LINUX_DISABLE_LLGS_LOCAL")) - g_properties[ePropertyUseLlgsForLocal].default_uint_value = false; - return g_properties; } @@ -678,21 +658,11 @@ } bool -PlatformLinux::UseLlgsForLocalDebugging () -{ - PlatformLinuxPropertiesSP properties_sp = GetGlobalProperties (); - assert (properties_sp && "global properties shared pointer is null"); - return properties_sp ? properties_sp->GetUseLlgsForLocal () : false; -} - -bool PlatformLinux::CanDebugProcess () { if (IsHost ()) { - // The platform only does local debugging (i.e. uses llgs) when the setting indicates we do that. - // Otherwise, we'll use ProcessLinux/ProcessPOSIX to handle with ProcessMonitor. - return UseLlgsForLocalDebugging (); + return true; } else { @@ -724,14 +694,6 @@ ProcessSP process_sp; - // Ensure we're using llgs for local debugging. - if (!UseLlgsForLocalDebugging ()) - { - assert (false && "we're trying to debug a local process but platform.plugin.linux.use-llgs-for-local is false, should never get here"); - error.SetErrorString ("attempted to start gdb-remote-based debugging for local process but platform.plugin.linux.use-llgs-for-local is false"); - return process_sp; - } - // Make sure we stop at the entry point launch_info.GetFlags ().Set (eLaunchFlagDebug); Index: source/Plugins/Process/FreeBSD/CMakeLists.txt =================================================================== --- source/Plugins/Process/FreeBSD/CMakeLists.txt +++ source/Plugins/Process/FreeBSD/CMakeLists.txt @@ -8,4 +8,13 @@ ProcessFreeBSD.cpp FreeBSDThread.cpp ProcessMonitor.cpp + + ProcessPOSIX.cpp + POSIXThread.cpp + POSIXStopInfo.cpp + RegisterContextPOSIXProcessMonitor_arm.cpp + RegisterContextPOSIXProcessMonitor_arm64.cpp + RegisterContextPOSIXProcessMonitor_powerpc.cpp + RegisterContextPOSIXProcessMonitor_x86.cpp + RegisterContextPOSIXProcessMonitor_mips64.cpp ) Index: source/Plugins/Process/FreeBSD/POSIXThread.h =================================================================== --- source/Plugins/Process/FreeBSD/POSIXThread.h +++ source/Plugins/Process/FreeBSD/POSIXThread.h @@ -37,9 +37,6 @@ void RefreshStateAfterStop() override; - void - WillResume(lldb::StateType resume_state) override; - // This notifies the thread when a private stop occurs. void DidStop () override; Index: source/Plugins/Process/FreeBSD/POSIXThread.cpp =================================================================== --- source/Plugins/Process/FreeBSD/POSIXThread.cpp +++ source/Plugins/Process/FreeBSD/POSIXThread.cpp @@ -29,16 +29,12 @@ #include "POSIXThread.h" #include "ProcessPOSIX.h" #include "ProcessPOSIXLog.h" -#include "Plugins/Process/Linux/ProcessMonitor.h" +#include "ProcessMonitor.h" #include "RegisterContextPOSIXProcessMonitor_arm.h" #include "RegisterContextPOSIXProcessMonitor_arm64.h" #include "RegisterContextPOSIXProcessMonitor_mips64.h" #include "RegisterContextPOSIXProcessMonitor_powerpc.h" #include "RegisterContextPOSIXProcessMonitor_x86.h" -#include "Plugins/Process/Utility/RegisterContextLinux_arm.h" -#include "Plugins/Process/Utility/RegisterContextLinux_arm64.h" -#include "Plugins/Process/Utility/RegisterContextLinux_i386.h" -#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h" #include "Plugins/Process/Utility/RegisterContextFreeBSD_arm.h" #include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h" #include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h" @@ -195,36 +191,6 @@ } break; - case llvm::Triple::Linux: - switch (target_arch.GetMachine()) - { - case llvm::Triple::aarch64: - assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) && "Register setting path assumes this is a 64-bit host"); - reg_interface = static_cast(new RegisterContextLinux_arm64(target_arch)); - break; - case llvm::Triple::arm: - assert(HostInfo::GetArchitecture().GetAddressByteSize() == 4); - reg_interface = static_cast(new RegisterContextLinux_arm(target_arch)); - break; - case llvm::Triple::x86: - case llvm::Triple::x86_64: - if (HostInfo::GetArchitecture().GetAddressByteSize() == 4) - { - // 32-bit hosts run with a RegisterContextLinux_i386 context. - reg_interface = static_cast(new RegisterContextLinux_i386(target_arch)); - } - else - { - assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) && - "Register setting path assumes this is a 64-bit host"); - // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the x86_64 register context. - reg_interface = static_cast(new RegisterContextLinux_x86_64(target_arch)); - } - break; - default: - break; - } - default: break; } @@ -328,18 +294,6 @@ return m_unwinder_ap.get(); } -// Overridden by FreeBSDThread; this is used only on Linux. -void -POSIXThread::WillResume(lldb::StateType resume_state) -{ - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); - if (log) - log->Printf ("POSIXThread::%s (tid = %" PRIi64 ") setting thread resume state to %s", __FUNCTION__, GetID(), StateAsCString(resume_state)); - // TODO: the line below shouldn't really be done, but - // the POSIXThread might rely on this so I will leave this in for now - SetResumeState(resume_state); -} - void POSIXThread::DidStop() { Index: source/Plugins/Process/FreeBSD/ProcessPOSIX.cpp =================================================================== --- source/Plugins/Process/FreeBSD/ProcessPOSIX.cpp +++ source/Plugins/Process/FreeBSD/ProcessPOSIX.cpp @@ -28,8 +28,8 @@ #include "ProcessPOSIX.h" #include "ProcessPOSIXLog.h" #include "Plugins/Process/Utility/InferiorCallPOSIX.h" -#include "Plugins/Process/Linux/ProcessMonitor.h" #include "POSIXThread.h" +#include "ProcessMonitor.h" #include "lldb/Host/posix/Fcntl.h" Index: source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp =================================================================== --- source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp +++ source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp @@ -13,8 +13,8 @@ #include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h" #include "ProcessPOSIX.h" +#include "ProcessMonitor.h" #include "RegisterContextPOSIXProcessMonitor_arm64.h" -#include "Plugins/Process/Linux/ProcessMonitor.h" #define REG_CONTEXT_SIZE (GetGPRSize()) Index: source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp =================================================================== --- source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp +++ source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp @@ -13,8 +13,8 @@ #include "Plugins/Process/Utility/RegisterContextPOSIX_mips64.h" #include "ProcessPOSIX.h" +#include "ProcessMonitor.h" #include "RegisterContextPOSIXProcessMonitor_mips64.h" -#include "Plugins/Process/Linux/ProcessMonitor.h" using namespace lldb_private; using namespace lldb; Index: source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp =================================================================== --- source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp +++ source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp @@ -11,13 +11,9 @@ #include "lldb/Core/RegisterValue.h" #include "lldb/Target/Thread.h" -#include "Plugins/Process/POSIX/ProcessPOSIX.h" +#include "Plugins/Process/FreeBSD/ProcessPOSIX.h" #include "RegisterContextPOSIXProcessMonitor_x86.h" -#if defined(__FreeBSD__) #include "Plugins/Process/FreeBSD/ProcessMonitor.h" -#else -#include "Plugins/Process/Linux/ProcessMonitor.h" -#endif using namespace lldb_private; using namespace lldb; Index: source/Plugins/Process/Linux/CMakeLists.txt =================================================================== --- source/Plugins/Process/Linux/CMakeLists.txt +++ source/Plugins/Process/Linux/CMakeLists.txt @@ -5,7 +5,6 @@ include_directories(../Utility) add_lldb_library(lldbPluginProcessLinux - LinuxThread.cpp NativeProcessLinux.cpp NativeRegisterContextLinux.cpp NativeRegisterContextLinux_arm.cpp @@ -13,7 +12,5 @@ NativeRegisterContextLinux_x86_64.cpp NativeRegisterContextLinux_mips64.cpp NativeThreadLinux.cpp - ProcessLinux.cpp - ProcessMonitor.cpp ProcFileReader.cpp ) Index: source/Plugins/Process/Linux/LinuxThread.h =================================================================== --- source/Plugins/Process/Linux/LinuxThread.h +++ /dev/null @@ -1,44 +0,0 @@ -//===-- LinuxThread.h -------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_LinuxThread_H_ -#define liblldb_LinuxThread_H_ - -// Other libraries and framework includes -#include "Plugins/Process/POSIX/POSIXThread.h" - -namespace lldb_private { -namespace process_linux { - -//------------------------------------------------------------------------------ -// @class LinuxThread -// @brief Abstraction of a Linux thread. -class LinuxThread : public POSIXThread -{ -public: - - //------------------------------------------------------------------ - // Constructors and destructors - //------------------------------------------------------------------ - LinuxThread(Process &process, lldb::tid_t tid); - - virtual ~LinuxThread(); - - //-------------------------------------------------------------------------- - // LinuxThread internal API. - - // POSIXThread override - void - RefreshStateAfterStop() override; -}; - -} // namespace process_linux -} // namespace lldb_private - -#endif // #ifndef liblldb_LinuxThread_H_ Index: source/Plugins/Process/Linux/LinuxThread.cpp =================================================================== --- source/Plugins/Process/Linux/LinuxThread.cpp +++ /dev/null @@ -1,43 +0,0 @@ -//===-- LinuxThread.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 -// C++ Includes -// Other libraries and framework includes -// Project includes -#include "LinuxThread.h" - -using namespace lldb; -using namespace lldb_private; -using namespace lldb_private::process_linux; - -//------------------------------------------------------------------------------ -// Constructors and destructors. - -LinuxThread::LinuxThread(Process &process, lldb::tid_t tid) - : POSIXThread(process, tid) -{ -} - -LinuxThread::~LinuxThread() -{ -} - -//------------------------------------------------------------------------------ -// ProcessInterface protocol. - -void -LinuxThread::RefreshStateAfterStop() -{ - // Invalidate the thread names every time we get a stop event on Linux so we - // will re-read the procfs comm virtual file when folks ask for the thread name. - m_thread_name_valid = false; - - POSIXThread::RefreshStateAfterStop(); -} Index: source/Plugins/Process/Linux/ProcessLinux.h =================================================================== --- source/Plugins/Process/Linux/ProcessLinux.h +++ /dev/null @@ -1,110 +0,0 @@ -//===-- ProcessLinux.h ------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_ProcessLinux_H_ -#define liblldb_ProcessLinux_H_ - -// C Includes - -// C++ Includes -#include - -// Other libraries and framework includes -#include "lldb/Target/Process.h" -#include "Plugins/Process/POSIX/ProcessMessage.h" -#include "Plugins/Process/POSIX/ProcessPOSIX.h" - -class ProcessMonitor; - -namespace lldb_private { -namespace process_linux { - -class ProcessLinux : public ProcessPOSIX -{ -public: - //------------------------------------------------------------------ - // Static functions. - //------------------------------------------------------------------ - static lldb::ProcessSP - CreateInstance(Target& target, - Listener &listener, - const FileSpec *); - - static void - Initialize(); - - static void - Terminate(); - - static ConstString - GetPluginNameStatic(); - - static const char * - GetPluginDescriptionStatic(); - - //------------------------------------------------------------------ - // Constructors and destructors - //------------------------------------------------------------------ - ProcessLinux(Target& target, - Listener &listener, - const FileSpec *core_file); - - Error - DoDetach(bool keep_stopped) override; - - bool - DetachRequiresHalt() override { return true; } - - bool - UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) override; - - //------------------------------------------------------------------ - // PluginInterface protocol - //------------------------------------------------------------------ - ConstString - GetPluginName() override; - - uint32_t - GetPluginVersion() override; - - virtual void - GetPluginCommandHelp(const char *command, Stream *strm); - - virtual Error - ExecutePluginCommand(Args &command, - Stream *strm); - - virtual Log * - EnablePluginLogging(Stream *strm, - Args &command); - - bool - CanDebug(Target &target, bool plugin_specified_by_name) override; - - //------------------------------------------------------------------ - // ProcessPOSIX overrides - //------------------------------------------------------------------ - void - StopAllThreads(lldb::tid_t stop_tid) override; - - POSIXThread * - CreateNewPOSIXThread(Process &process, lldb::tid_t tid) override; - -private: - - const FileSpec *m_core_file; - - // Flag to avoid recursion when stopping all threads. - bool m_stopping_threads; -}; - -} // namespace process_linux -} // namespace lldb_private - -#endif // liblldb_ProcessLinux_H_ Index: source/Plugins/Process/Linux/ProcessLinux.cpp =================================================================== --- source/Plugins/Process/Linux/ProcessLinux.cpp +++ /dev/null @@ -1,233 +0,0 @@ -//===-- 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 -#include - -// 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 "Plugins/Platform/Linux/PlatformLinux.h" -#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" -#include "Plugins/Process/Utility/InferiorCallPOSIX.h" -#include "Plugins/Process/Utility/LinuxSignals.h" -#include "ProcessMonitor.h" -#include "LinuxThread.h" - -using namespace lldb; -using namespace lldb_private; -using namespace lldb_private::process_linux; - -namespace -{ - UnixSignalsSP& - GetStaticLinuxSignalsSP () - { - static UnixSignalsSP s_unix_signals_sp (new process_linux::LinuxSignals ()); - return s_unix_signals_sp; - } -} - -//------------------------------------------------------------------------------ -// Static functions. - -ProcessSP -ProcessLinux::CreateInstance(Target &target, Listener &listener, const FileSpec *core_file) -{ - return ProcessSP(new ProcessLinux(target, listener, core_file)); -} - -void -ProcessLinux::Initialize() -{ - static std::once_flag g_once_flag; - - std::call_once(g_once_flag, []() { - PluginManager::RegisterPlugin(GetPluginNameStatic(), - GetPluginDescriptionStatic(), - CreateInstance); - ProcessPOSIXLog::Initialize(GetPluginNameStatic()); - }); -} - -//------------------------------------------------------------------------------ -// Constructors and destructors. - -ProcessLinux::ProcessLinux(Target& target, Listener &listener, const FileSpec *core_file) - : ProcessPOSIX(target, listener, GetStaticLinuxSignalsSP ()), 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; -} - -Error -ProcessLinux::DoDetach(bool keep_stopped) -{ - Error error; - if (keep_stopped) - { - // FIXME: If you want to implement keep_stopped, - // this would be the place to do it. - error.SetErrorString("Detaching with keep_stopped true is not currently supported on Linux."); - return error; - } - - Mutex::Locker 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()); - error = m_monitor->Detach(thread->GetID()); - } - - if (error.Success()) - SetPrivateState(eStateDetached); - - return error; -} - - -// 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; - - // If we're using llgs for local debugging, we must not say that this process - // is used for debugging. - if (platform_linux::PlatformLinux::UseLlgsForLocalDebugging ()) - return false; - - return ProcessPOSIX::CanDebug(target, plugin_specified_by_name); -} - Index: source/Plugins/Process/Linux/ProcessMonitor.h =================================================================== --- source/Plugins/Process/Linux/ProcessMonitor.h +++ /dev/null @@ -1,334 +0,0 @@ -//===-- ProcessMonitor.h -------------------------------------- -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_ProcessMonitor_H_ -#define liblldb_ProcessMonitor_H_ - -// C Includes -#include -#include - -// C++ Includes -// Other libraries and framework includes -#include "lldb/lldb-types.h" -#include "lldb/Host/FileSpec.h" -#include "lldb/Host/HostThread.h" -#include "lldb/Host/Mutex.h" - -namespace lldb_private { - -class Error; -class Module; -class Scalar; - -namespace process_linux { - -class ProcessLinux; - -} // namespace process_linux - -} // namespace lldb_private - -class Operation; - -/// @class ProcessMonitor -/// @brief Manages communication with the inferior (debugee) process. -/// -/// Upon construction, this class prepares and launches an inferior process for -/// debugging. -/// -/// Changes in the inferior process state are propagated to the associated -/// ProcessLinux instance by calling ProcessLinux::SendMessage with the -/// appropriate ProcessMessage events. -/// -/// A purposely minimal set of operations are provided to interrogate and change -/// the inferior process state. -class ProcessMonitor -{ -public: - - /// Launches an inferior process ready for debugging. Forms the - /// implementation of Process::DoLaunch. - ProcessMonitor(ProcessPOSIX *process, - lldb_private::Module *module, - char const *argv[], - char const *envp[], - const lldb_private::FileSpec &stdin_file_spec, - const lldb_private::FileSpec &stdout_file_spec, - const lldb_private::FileSpec &stderr_file_spec, - const lldb_private::FileSpec &working_dir, - const lldb_private::ProcessLaunchInfo &launch_info, - lldb_private::Error &error); - - ProcessMonitor(ProcessPOSIX *process, - lldb::pid_t pid, - lldb_private::Error &error); - - ~ProcessMonitor(); - - enum ResumeSignals - { - eResumeSignalNone = 0 - }; - - /// Provides the process number of debugee. - lldb::pid_t - GetPID() const { return m_pid; } - - /// Returns the process associated with this ProcessMonitor. - lldb_private::process_linux::ProcessLinux & - GetProcess() { return *m_process; } - - /// Returns a file descriptor to the controlling terminal of the inferior - /// process. - /// - /// Reads from this file descriptor yield both the standard output and - /// standard error of this debugee. Even if stderr and stdout were - /// redirected on launch it may still happen that data is available on this - /// descriptor (if the inferior process opens /dev/tty, for example). This descriptor is - /// closed after a call to StopMonitor(). - /// - /// If this monitor was attached to an existing process this method returns - /// -1. - int - GetTerminalFD() const { return m_terminal_fd; } - - /// Reads @p size bytes from address @vm_adder in the inferior process - /// address space. - /// - /// This method is provided to implement Process::DoReadMemory. - size_t - ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, - lldb_private::Error &error); - - /// Writes @p size bytes from address @p vm_adder in the inferior process - /// address space. - /// - /// This method is provided to implement Process::DoWriteMemory. - size_t - WriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, - lldb_private::Error &error); - - /// Reads the contents from the register identified by the given (architecture - /// dependent) offset. - /// - /// This method is provided for use by RegisterContextLinux derivatives. - bool - ReadRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name, - unsigned size, lldb_private::RegisterValue &value); - - /// Writes the given value to the register identified by the given - /// (architecture dependent) offset. - /// - /// This method is provided for use by RegisterContextLinux derivatives. - bool - WriteRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name, - const lldb_private::RegisterValue &value); - - /// Reads all general purpose registers into the specified buffer. - bool - ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size); - - /// Reads generic floating point registers into the specified buffer. - bool - ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size); - -#if defined (__arm64__) || defined (__aarch64__) - /// Reads hardware breakpoints and watchpoints capability information. - bool - ReadHardwareDebugInfo (lldb::tid_t tid, unsigned int &watch_count , - unsigned int &break_count); - - /// Write hardware breakpoint/watchpoint control and address registers. - bool - WriteHardwareDebugRegs (lldb::tid_t tid, lldb::addr_t *addr_buf, - uint32_t *cntrl_buf, int type, int count); -#endif - - /// Reads the specified register set into the specified buffer. - /// For instance, the extended floating-point register set. - bool - ReadRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset); - - /// Writes all general purpose registers into the specified buffer. - bool - WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size); - - /// Writes generic floating point registers into the specified buffer. - bool - WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size); - - /// Writes the specified register set into the specified buffer. - /// For instance, the extended floating-point register set. - bool - WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset); - - /// Reads the value of the thread-specific pointer for a given thread ID. - bool - ReadThreadPointer(lldb::tid_t tid, lldb::addr_t &value); - - /// Writes a siginfo_t structure corresponding to the given thread ID to the - /// memory region pointed to by @p siginfo. - bool - GetSignalInfo(lldb::tid_t tid, void *siginfo, int &ptrace_err); - - /// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG) - /// corresponding to the given thread IDto the memory pointed to by @p - /// message. - bool - GetEventMessage(lldb::tid_t tid, unsigned long *message); - - /// Resumes the given thread. If @p signo is anything but - /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread. - bool - Resume(lldb::tid_t tid, uint32_t signo); - - /// Single steps the given thread. If @p signo is anything but - /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread. - bool - SingleStep(lldb::tid_t tid, uint32_t signo); - - /// Terminate the traced process. - bool - Kill(); - - lldb_private::Error - Detach(lldb::tid_t tid); - - /// Stops the monitoring the child process thread. - void - StopMonitor(); - - /// Stops the requested thread and waits for the stop signal. - bool - StopThread(lldb::tid_t tid); - - // Waits for the initial stop message from a new thread. - bool - WaitForInitialTIDStop(lldb::tid_t tid); - -private: - lldb_private::process_linux::ProcessLinux *m_process; - - lldb_private::HostThread m_operation_thread; - lldb_private::HostThread m_monitor_thread; - lldb::pid_t m_pid; - int m_terminal_fd; - - // current operation which must be executed on the priviliged thread - Operation *m_operation; - lldb_private::Mutex m_operation_mutex; - - // semaphores notified when Operation is ready to be processed and when - // the operation is complete. - sem_t m_operation_pending; - sem_t m_operation_done; - - - struct OperationArgs - { - OperationArgs(ProcessMonitor *monitor); - - ~OperationArgs(); - - ProcessMonitor *m_monitor; // The monitor performing the attach. - sem_t m_semaphore; // Posted to once operation complete. - lldb_private::Error m_error; // Set if process operation failed. - }; - - /// @class LauchArgs - /// - /// @brief Simple structure to pass data to the thread responsible for - /// launching a child process. - struct LaunchArgs : OperationArgs - { - LaunchArgs(ProcessMonitor *monitor, - lldb_private::Module *module, - char const **argv, - char const **envp, - const lldb_private::FileSpec &stdin_file_spec, - const lldb_private::FileSpec &stdout_file_spec, - const lldb_private::FileSpec &stderr_file_spec, - const lldb_private::FileSpec &working_dir, - const lldb_private::ProcessLaunchInfo &launch_info); - - ~LaunchArgs(); - - lldb_private::Module *m_module; // The executable image to launch. - char const **m_argv; // Process arguments. - char const **m_envp; // Process environment. - const lldb_private::FileSpec m_stdin_file_spec; // Redirect stdin or empty. - const lldb_private::FileSpec m_stdout_file_spec; // Redirect stdout or empty. - const lldb_private::FileSpec m_stderr_file_spec; // Redirect stderr or empty. - const lldb_private::FileSpec m_working_dir; // Working directory or empty. - const lldb_private::ProcessLaunchInfo &m_launch_info; - }; - - void - StartLaunchOpThread(LaunchArgs *args, lldb_private::Error &error); - - static void * - LaunchOpThread(void *arg); - - static bool - Launch(LaunchArgs *args); - - struct AttachArgs : OperationArgs - { - AttachArgs(ProcessMonitor *monitor, - lldb::pid_t pid); - - ~AttachArgs(); - - lldb::pid_t m_pid; // pid of the process to be attached. - }; - - void - StartAttachOpThread(AttachArgs *args, lldb_private::Error &error); - - static void * - AttachOpThread(void *args); - - static bool - Attach(AttachArgs *args); - - static bool - SetDefaultPtraceOpts(const lldb::pid_t); - - static void - ServeOperation(OperationArgs *args); - - static bool - DupDescriptor(const lldb_private::FileSpec &file_spec, int fd, int flags); - - static bool - MonitorCallback(void *callback_baton, - lldb::pid_t pid, bool exited, int signal, int status); - - static ProcessMessage - MonitorSIGTRAP(ProcessMonitor *monitor, - const siginfo_t *info, lldb::pid_t pid); - - static ProcessMessage - MonitorSignal(ProcessMonitor *monitor, - const siginfo_t *info, lldb::pid_t pid); - - void - DoOperation(Operation *op); - - /// Stops the child monitor thread. - void - StopMonitoringChildProcess(); - - /// Stops the operation thread used to attach/launch a process. - void - StopOpThread(); -}; - -#endif // #ifndef liblldb_ProcessMonitor_H_ Index: source/Plugins/Process/Linux/ProcessMonitor.cpp =================================================================== --- source/Plugins/Process/Linux/ProcessMonitor.cpp +++ /dev/null @@ -1,2451 +0,0 @@ -//===-- ProcessMonitor.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 -#include -#include -#include -#include -#include - -// C++ Includes -// Other libraries and framework includes -#include "lldb/Core/Debugger.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/RegisterValue.h" -#include "lldb/Core/Scalar.h" -#include "lldb/Host/Host.h" -#include "lldb/Host/HostNativeThread.h" -#include "lldb/Host/HostThread.h" -#include "lldb/Host/ThreadLauncher.h" -#include "lldb/Target/Thread.h" -#include "lldb/Target/RegisterContext.h" -#include "lldb/Target/UnixSignals.h" -#include "lldb/Utility/PseudoTerminal.h" - -#include "Plugins/Process/POSIX/CrashReason.h" -#include "Plugins/Process/POSIX/POSIXThread.h" -#include "ProcessLinux.h" -#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" -#include "ProcessMonitor.h" -#include "Procfs.h" - -// System includes - They have to be included after framework includes because they define some -// macros which collide with variable names in other modules - -#include "lldb/Host/linux/Personality.h" -#include "lldb/Host/linux/Ptrace.h" -#include "lldb/Host/linux/Signalfd.h" -#include "lldb/Host/android/Android.h" - -#include -#include -#include -#include -#include -#include - -#define LLDB_PERSONALITY_GET_CURRENT_SETTINGS 0xffffffff - -// Support hardware breakpoints in case it has not been defined -#ifndef TRAP_HWBKPT - #define TRAP_HWBKPT 4 -#endif - -// Try to define a macro to encapsulate the tgkill syscall -// fall back on kill() if tgkill isn't available -#define tgkill(pid, tid, sig) \ - syscall(SYS_tgkill, static_cast<::pid_t>(pid), static_cast<::pid_t>(tid), sig) - -using namespace lldb_private; -using namespace lldb_private::process_linux; - -static Operation* EXIT_OPERATION = nullptr; - -// FIXME: this code is host-dependent with respect to types and -// endianness and needs to be fixed. For example, lldb::addr_t is -// hard-coded to uint64_t, but on a 32-bit Linux host, ptrace requires -// 32-bit pointer arguments. This code uses casts to work around the -// problem. - -// We disable the tracing of ptrace calls for integration builds to -// avoid the additional indirection and checks. -#ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION - -static void -DisplayBytes (lldb_private::StreamString &s, void *bytes, uint32_t count) -{ - uint8_t *ptr = (uint8_t *)bytes; - const uint32_t loop_count = std::min(DEBUG_PTRACE_MAXBYTES, count); - for(uint32_t i=0; iPrintf("PTRACE_POKETEXT %s", buf.GetData()); - break; - } - case PTRACE_POKEDATA: - { - DisplayBytes(buf, &data, 8); - verbose_log->Printf("PTRACE_POKEDATA %s", buf.GetData()); - break; - } - case PTRACE_POKEUSER: - { - DisplayBytes(buf, &data, 8); - verbose_log->Printf("PTRACE_POKEUSER %s", buf.GetData()); - break; - } -#if !defined (__arm64__) && !defined (__aarch64__) - case PTRACE_SETREGS: - { - DisplayBytes(buf, data, data_size); - verbose_log->Printf("PTRACE_SETREGS %s", buf.GetData()); - break; - } - case PTRACE_SETFPREGS: - { - DisplayBytes(buf, data, data_size); - verbose_log->Printf("PTRACE_SETFPREGS %s", buf.GetData()); - break; - } -#endif - case PTRACE_SETSIGINFO: - { - DisplayBytes(buf, data, sizeof(siginfo_t)); - verbose_log->Printf("PTRACE_SETSIGINFO %s", buf.GetData()); - break; - } - case PTRACE_SETREGSET: - { - // Extract iov_base from data, which is a pointer to the struct IOVEC - DisplayBytes(buf, *(void **)data, data_size); - verbose_log->Printf("PTRACE_SETREGSET %s", buf.GetData()); - break; - } - default: - { - } - } - } -} - -// Wrapper for ptrace to catch errors and log calls. -// Note that ptrace sets errno on error because -1 can be a valid result (i.e. for PTRACE_PEEK*) -extern long -PtraceWrapper(int req, lldb::pid_t pid, void *addr, void *data, size_t data_size, - const char* reqName, const char* file, int line) -{ - long int result; - - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PTRACE)); - - PtraceDisplayBytes(req, data, data_size); - - errno = 0; - if (req == PTRACE_GETREGSET || req == PTRACE_SETREGSET) - result = ptrace(static_cast<__ptrace_request>(req), static_cast(pid), *(unsigned int *)addr, data); - else - result = ptrace(static_cast<__ptrace_request>(req), static_cast(pid), addr, data); - - if (log) - log->Printf("ptrace(%s, %" PRIu64 ", %p, %p, %zu)=%lX called from file %s line %d", - reqName, pid, addr, data, data_size, result, file, line); - - PtraceDisplayBytes(req, data, data_size); - - if (log && errno != 0) - { - const char* str; - switch (errno) - { - case ESRCH: str = "ESRCH"; break; - case EINVAL: str = "EINVAL"; break; - case EBUSY: str = "EBUSY"; break; - case EPERM: str = "EPERM"; break; - default: str = ""; - } - log->Printf("ptrace() failed; errno=%d (%s)", errno, str); - } - - return result; -} - -// Wrapper for ptrace when logging is not required. -// Sets errno to 0 prior to calling ptrace. -extern long -PtraceWrapper(int req, pid_t pid, void *addr, void *data, size_t data_size) -{ - long result = 0; - errno = 0; - if (req == PTRACE_GETREGSET || req == PTRACE_SETREGSET) - result = ptrace(static_cast<__ptrace_request>(req), pid, *(unsigned int *)addr, data); - else - result = ptrace(static_cast<__ptrace_request>(req), pid, addr, data); - return result; -} - -#define PTRACE(req, pid, addr, data, data_size) \ - PtraceWrapper((req), (pid), (addr), (data), (data_size), #req, __FILE__, __LINE__) -#else - PtraceWrapper((req), (pid), (addr), (data), (data_size)) -#endif - -//------------------------------------------------------------------------------ -// Static implementations of ProcessMonitor::ReadMemory and -// ProcessMonitor::WriteMemory. This enables mutual recursion between these -// functions without needed to go thru the thread funnel. - -static size_t -DoReadMemory(lldb::pid_t pid, - lldb::addr_t vm_addr, void *buf, size_t size, Error &error) -{ - // ptrace word size is determined by the host, not the child - static const unsigned word_size = sizeof(void*); - unsigned char *dst = static_cast(buf); - size_t bytes_read; - size_t remainder; - long data; - - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL)); - if (log) - ProcessPOSIXLog::IncNestLevel(); - if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY)) - log->Printf ("ProcessMonitor::%s(%" PRIu64 ", %d, %p, %p, %zd, _)", __FUNCTION__, - pid, word_size, (void*)vm_addr, buf, size); - - assert(sizeof(data) >= word_size); - for (bytes_read = 0; bytes_read < size; bytes_read += remainder) - { - errno = 0; - data = PTRACE(PTRACE_PEEKDATA, pid, (void*)vm_addr, NULL, 0); - if (errno) - { - error.SetErrorToErrno(); - if (log) - ProcessPOSIXLog::DecNestLevel(); - return bytes_read; - } - - remainder = size - bytes_read; - remainder = remainder > word_size ? word_size : remainder; - - // Copy the data into our buffer - for (unsigned i = 0; i < remainder; ++i) - dst[i] = ((data >> i*8) & 0xFF); - - if (log && ProcessPOSIXLog::AtTopNestLevel() && - (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) || - (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) && - size <= POSIX_LOG_MEMORY_SHORT_BYTES))) - { - uintptr_t print_dst = 0; - // Format bytes from data by moving into print_dst for log output - for (unsigned i = 0; i < remainder; ++i) - print_dst |= (((data >> i*8) & 0xFF) << i*8); - log->Printf ("ProcessMonitor::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__, - (void*)vm_addr, print_dst, (unsigned long)data); - } - - vm_addr += word_size; - dst += word_size; - } - - if (log) - ProcessPOSIXLog::DecNestLevel(); - return bytes_read; -} - -static size_t -DoWriteMemory(lldb::pid_t pid, - lldb::addr_t vm_addr, const void *buf, size_t size, Error &error) -{ - // ptrace word size is determined by the host, not the child - static const unsigned word_size = sizeof(void*); - const unsigned char *src = static_cast(buf); - size_t bytes_written = 0; - size_t remainder; - - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL)); - if (log) - ProcessPOSIXLog::IncNestLevel(); - if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY)) - log->Printf ("ProcessMonitor::%s(%" PRIu64 ", %d, %p, %p, %zd, _)", __FUNCTION__, - pid, word_size, (void*)vm_addr, buf, size); - - for (bytes_written = 0; bytes_written < size; bytes_written += remainder) - { - remainder = size - bytes_written; - remainder = remainder > word_size ? word_size : remainder; - - if (remainder == word_size) - { - unsigned long data = 0; - assert(sizeof(data) >= word_size); - for (unsigned i = 0; i < word_size; ++i) - data |= (unsigned long)src[i] << i*8; - - if (log && ProcessPOSIXLog::AtTopNestLevel() && - (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) || - (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) && - size <= POSIX_LOG_MEMORY_SHORT_BYTES))) - log->Printf ("ProcessMonitor::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__, - (void*)vm_addr, *(unsigned long*)src, data); - - if (PTRACE(PTRACE_POKEDATA, pid, (void*)vm_addr, (void*)data, 0)) - { - error.SetErrorToErrno(); - if (log) - ProcessPOSIXLog::DecNestLevel(); - return bytes_written; - } - } - else - { - unsigned char buff[8]; - if (DoReadMemory(pid, vm_addr, - buff, word_size, error) != word_size) - { - if (log) - ProcessPOSIXLog::DecNestLevel(); - return bytes_written; - } - - memcpy(buff, src, remainder); - - if (DoWriteMemory(pid, vm_addr, - buff, word_size, error) != word_size) - { - if (log) - ProcessPOSIXLog::DecNestLevel(); - return bytes_written; - } - - if (log && ProcessPOSIXLog::AtTopNestLevel() && - (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) || - (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) && - size <= POSIX_LOG_MEMORY_SHORT_BYTES))) - log->Printf ("ProcessMonitor::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__, - (void*)vm_addr, *(const unsigned long*)src, *(const unsigned long*)buff); - } - - vm_addr += word_size; - src += word_size; - } - if (log) - ProcessPOSIXLog::DecNestLevel(); - return bytes_written; -} - -// Simple helper function to ensure flags are enabled on the given file -// descriptor. -static bool -EnsureFDFlags(int fd, int flags, Error &error) -{ - int status; - - if ((status = fcntl(fd, F_GETFL)) == -1) - { - error.SetErrorToErrno(); - return false; - } - - if (fcntl(fd, F_SETFL, status | flags) == -1) - { - error.SetErrorToErrno(); - return false; - } - - return true; -} - -//------------------------------------------------------------------------------ -/// @class Operation -/// @brief Represents a ProcessMonitor operation. -/// -/// Under Linux, it is not possible to ptrace() from any other thread but the -/// one that spawned or attached to the process from the start. Therefore, when -/// a ProcessMonitor is asked to deliver or change the state of an inferior -/// process the operation must be "funneled" to a specific thread to perform the -/// task. The Operation class provides an abstract base for all services the -/// ProcessMonitor must perform via the single virtual function Execute, thus -/// encapsulating the code that needs to run in the privileged context. -class Operation -{ -public: - virtual ~Operation() {} - virtual void Execute(ProcessMonitor *monitor) = 0; -}; - -//------------------------------------------------------------------------------ -/// @class ReadOperation -/// @brief Implements ProcessMonitor::ReadMemory. -class ReadOperation : public Operation -{ -public: - ReadOperation(lldb::addr_t addr, void *buff, size_t size, - Error &error, size_t &result) - : m_addr(addr), m_buff(buff), m_size(size), - m_error(error), m_result(result) - { } - - void Execute(ProcessMonitor *monitor) override; - -private: - lldb::addr_t m_addr; - void *m_buff; - size_t m_size; - Error &m_error; - size_t &m_result; -}; - -void -ReadOperation::Execute(ProcessMonitor *monitor) -{ - lldb::pid_t pid = monitor->GetPID(); - - m_result = DoReadMemory(pid, m_addr, m_buff, m_size, m_error); -} - -//------------------------------------------------------------------------------ -/// @class WriteOperation -/// @brief Implements ProcessMonitor::WriteMemory. -class WriteOperation : public Operation -{ -public: - WriteOperation(lldb::addr_t addr, const void *buff, size_t size, - Error &error, size_t &result) - : m_addr(addr), m_buff(buff), m_size(size), - m_error(error), m_result(result) - { } - - void Execute(ProcessMonitor *monitor) override; - -private: - lldb::addr_t m_addr; - const void *m_buff; - size_t m_size; - Error &m_error; - size_t &m_result; -}; - -void -WriteOperation::Execute(ProcessMonitor *monitor) -{ - lldb::pid_t pid = monitor->GetPID(); - - m_result = DoWriteMemory(pid, m_addr, m_buff, m_size, m_error); -} - - -//------------------------------------------------------------------------------ -/// @class ReadRegOperation -/// @brief Implements ProcessMonitor::ReadRegisterValue. -class ReadRegOperation : public Operation -{ -public: - ReadRegOperation(lldb::tid_t tid, unsigned offset, const char *reg_name, - RegisterValue &value, bool &result) - : m_tid(tid), m_offset(offset), m_reg_name(reg_name), - m_value(value), m_result(result) - { } - - void Execute(ProcessMonitor *monitor) override; - -private: - lldb::tid_t m_tid; - uintptr_t m_offset; - const char *m_reg_name; - RegisterValue &m_value; - bool &m_result; -}; - -void -ReadRegOperation::Execute(ProcessMonitor *monitor) -{ -#if defined (__arm64__) || defined (__aarch64__) - if (m_offset > sizeof(struct user_pt_regs)) - { - uintptr_t offset = m_offset - sizeof(struct user_pt_regs); - if (offset > sizeof(struct user_fpsimd_state)) - { - m_result = false; - } - else - { - elf_fpregset_t regs; - int regset = NT_FPREGSET; - struct iovec ioVec; - - ioVec.iov_base = ®s; - ioVec.iov_len = sizeof regs; - if (PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, sizeof regs) < 0) - m_result = false; - else - { - m_result = true; - m_value.SetBytes((void *)(((unsigned char *)(®s)) + offset), 16, monitor->GetProcess().GetByteOrder()); - } - } - } - else - { - elf_gregset_t regs; - int regset = NT_PRSTATUS; - struct iovec ioVec; - - ioVec.iov_base = ®s; - ioVec.iov_len = sizeof regs; - if (PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, sizeof regs) < 0) - m_result = false; - else - { - m_result = true; - m_value.SetBytes((void *)(((unsigned char *)(regs)) + m_offset), 8, monitor->GetProcess().GetByteOrder()); - } - } -#else - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS)); - - // Set errno to zero so that we can detect a failed peek. - errno = 0; - lldb::addr_t data = PTRACE(PTRACE_PEEKUSER, m_tid, (void*)m_offset, NULL, 0); - if (errno) - m_result = false; - else - { - m_value = data; - m_result = true; - } - if (log) - log->Printf ("ProcessMonitor::%s() reg %s: 0x%" PRIx64, __FUNCTION__, - m_reg_name, data); -#endif -} - -#if defined (__arm64__) || defined (__aarch64__) - //------------------------------------------------------------------------------ - /// @class ReadDBGROperation - /// @brief Implements NativeProcessLinux::ReadDBGR. - class ReadDBGROperation : public Operation - { - public: - ReadDBGROperation(lldb::tid_t tid, unsigned int &count_wp, unsigned int &count_bp) - : m_tid(tid), - m_count_wp(count_wp), - m_count_bp(count_bp) - { } - - void Execute(ProcessMonitor *monitor) override; - - private: - lldb::tid_t m_tid; - unsigned int &m_count_wp; - unsigned int &m_count_bp; - }; - - void - ReadDBGROperation::Execute(ProcessMonitor *monitor) - { - int regset = NT_ARM_HW_WATCH; - struct iovec ioVec; - struct user_hwdebug_state dreg_state; - - ioVec.iov_base = &dreg_state; - ioVec.iov_len = sizeof (dreg_state); - - PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, ioVec.iov_len); - - m_count_wp = dreg_state.dbg_info & 0xff; - regset = NT_ARM_HW_BREAK; - - PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, ioVec.iov_len); - m_count_bp = dreg_state.dbg_info & 0xff; - } -#endif - -#if defined (__arm64__) || defined (__aarch64__) - //------------------------------------------------------------------------------ - /// @class WriteDBGROperation - /// @brief Implements NativeProcessLinux::WriteFPR. - class WriteDBGROperation : public Operation - { - public: - WriteDBGROperation(lldb::tid_t tid, lldb::addr_t *addr_buf, uint32_t *cntrl_buf, int type, int count) - : m_tid(tid), - m_addr_buf(addr_buf), - m_cntrl_buf(cntrl_buf), - m_type(type), - m_count(count) - { } - - void Execute(ProcessMonitor *monitor) override; - - private: - lldb::tid_t m_tid; - lldb::addr_t *m_addr_buf; - uint32_t *m_cntrl_buf; - int m_type; - int m_count; - }; - - void - WriteDBGROperation::Execute(ProcessMonitor *monitor) - { - struct iovec ioVec; - struct user_hwdebug_state dreg_state; - - memset (&dreg_state, 0, sizeof (dreg_state)); - ioVec.iov_base = &dreg_state; - ioVec.iov_len = sizeof(dreg_state); - - if (m_type == 0) - m_type = NT_ARM_HW_WATCH; - else - m_type = NT_ARM_HW_BREAK; - - for (int i = 0; i < m_count; i++) - { - dreg_state.dbg_regs[i].addr = m_addr_buf[i]; - dreg_state.dbg_regs[i].ctrl = m_cntrl_buf[i]; - } - - PTRACE(PTRACE_SETREGSET, m_tid, &m_type, &ioVec, ioVec.iov_len); - } -#endif//------------------------------------------------------------------------------ -/// @class WriteRegOperation -/// @brief Implements ProcessMonitor::WriteRegisterValue. -class WriteRegOperation : public Operation -{ -public: - WriteRegOperation(lldb::tid_t tid, unsigned offset, const char *reg_name, - const RegisterValue &value, bool &result) - : m_tid(tid), m_offset(offset), m_reg_name(reg_name), - m_value(value), m_result(result) - { } - - void Execute(ProcessMonitor *monitor) override; - -private: - lldb::tid_t m_tid; - uintptr_t m_offset; - const char *m_reg_name; - const RegisterValue &m_value; - bool &m_result; -}; - -void -WriteRegOperation::Execute(ProcessMonitor *monitor) -{ -#if defined (__arm64__) || defined (__aarch64__) - if (m_offset > sizeof(struct user_pt_regs)) - { - uintptr_t offset = m_offset - sizeof(struct user_pt_regs); - if (offset > sizeof(struct user_fpsimd_state)) - { - m_result = false; - } - else - { - elf_fpregset_t regs; - int regset = NT_FPREGSET; - struct iovec ioVec; - - ioVec.iov_base = ®s; - ioVec.iov_len = sizeof regs; - if (PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, sizeof regs) < 0) - m_result = false; - else - { - ::memcpy((void *)(((unsigned char *)(®s)) + offset), m_value.GetBytes(), 16); - if (PTRACE(PTRACE_SETREGSET, m_tid, ®set, &ioVec, sizeof regs) < 0) - m_result = false; - else - m_result = true; - } - } - } - else - { - elf_gregset_t regs; - int regset = NT_PRSTATUS; - struct iovec ioVec; - - ioVec.iov_base = ®s; - ioVec.iov_len = sizeof regs; - if (PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, sizeof regs) < 0) - m_result = false; - else - { - ::memcpy((void *)(((unsigned char *)(®s)) + m_offset), m_value.GetBytes(), 8); - if (PTRACE(PTRACE_SETREGSET, m_tid, ®set, &ioVec, sizeof regs) < 0) - m_result = false; - else - m_result = true; - } - } -#else - void* buf; - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS)); - - buf = (void*) m_value.GetAsUInt64(); - - if (log) - log->Printf ("ProcessMonitor::%s() reg %s: %p", __FUNCTION__, m_reg_name, buf); - if (PTRACE(PTRACE_POKEUSER, m_tid, (void*)m_offset, buf, 0)) - m_result = false; - else - m_result = true; -#endif -} - -//------------------------------------------------------------------------------ -/// @class ReadGPROperation -/// @brief Implements ProcessMonitor::ReadGPR. -class ReadGPROperation : public Operation -{ -public: - ReadGPROperation(lldb::tid_t tid, void *buf, size_t buf_size, bool &result) - : m_tid(tid), m_buf(buf), m_buf_size(buf_size), m_result(result) - { } - - void Execute(ProcessMonitor *monitor) override; - -private: - lldb::tid_t m_tid; - void *m_buf; - size_t m_buf_size; - bool &m_result; -}; - -void -ReadGPROperation::Execute(ProcessMonitor *monitor) -{ -#if defined (__arm64__) || defined (__aarch64__) - int regset = NT_PRSTATUS; - struct iovec ioVec; - - ioVec.iov_base = m_buf; - ioVec.iov_len = m_buf_size; - if (PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, m_buf_size) < 0) - m_result = false; - else - m_result = true; -#else - if (PTRACE(PTRACE_GETREGS, m_tid, NULL, m_buf, m_buf_size) < 0) - m_result = false; - else - m_result = true; -#endif -} - -//------------------------------------------------------------------------------ -/// @class ReadFPROperation -/// @brief Implements ProcessMonitor::ReadFPR. -class ReadFPROperation : public Operation -{ -public: - ReadFPROperation(lldb::tid_t tid, void *buf, size_t buf_size, bool &result) - : m_tid(tid), m_buf(buf), m_buf_size(buf_size), m_result(result) - { } - - void Execute(ProcessMonitor *monitor) override; - -private: - lldb::tid_t m_tid; - void *m_buf; - size_t m_buf_size; - bool &m_result; -}; - -void -ReadFPROperation::Execute(ProcessMonitor *monitor) -{ -#if defined (__arm64__) || defined (__aarch64__) - int regset = NT_FPREGSET; - struct iovec ioVec; - - ioVec.iov_base = m_buf; - ioVec.iov_len = m_buf_size; - if (PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, m_buf_size) < 0) - m_result = false; - else - m_result = true; -#else - if (PTRACE(PTRACE_GETFPREGS, m_tid, NULL, m_buf, m_buf_size) < 0) - m_result = false; - else - m_result = true; -#endif -} - -//------------------------------------------------------------------------------ -/// @class ReadRegisterSetOperation -/// @brief Implements ProcessMonitor::ReadRegisterSet. -class ReadRegisterSetOperation : public Operation -{ -public: - ReadRegisterSetOperation(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset, bool &result) - : m_tid(tid), m_buf(buf), m_buf_size(buf_size), m_regset(regset), m_result(result) - { } - - void Execute(ProcessMonitor *monitor) override; - -private: - lldb::tid_t m_tid; - void *m_buf; - size_t m_buf_size; - const unsigned int m_regset; - bool &m_result; -}; - -void -ReadRegisterSetOperation::Execute(ProcessMonitor *monitor) -{ - if (PTRACE(PTRACE_GETREGSET, m_tid, (void *)&m_regset, m_buf, m_buf_size) < 0) - m_result = false; - else - m_result = true; -} - -//------------------------------------------------------------------------------ -/// @class WriteGPROperation -/// @brief Implements ProcessMonitor::WriteGPR. -class WriteGPROperation : public Operation -{ -public: - WriteGPROperation(lldb::tid_t tid, void *buf, size_t buf_size, bool &result) - : m_tid(tid), m_buf(buf), m_buf_size(buf_size), m_result(result) - { } - - void Execute(ProcessMonitor *monitor) override; - -private: - lldb::tid_t m_tid; - void *m_buf; - size_t m_buf_size; - bool &m_result; -}; - -void -WriteGPROperation::Execute(ProcessMonitor *monitor) -{ -#if defined (__arm64__) || defined (__aarch64__) - int regset = NT_PRSTATUS; - struct iovec ioVec; - - ioVec.iov_base = m_buf; - ioVec.iov_len = m_buf_size; - if (PTRACE(PTRACE_SETREGSET, m_tid, ®set, &ioVec, m_buf_size) < 0) - m_result = false; - else - m_result = true; -#else - if (PTRACE(PTRACE_SETREGS, m_tid, NULL, m_buf, m_buf_size) < 0) - m_result = false; - else - m_result = true; -#endif -} - -//------------------------------------------------------------------------------ -/// @class WriteFPROperation -/// @brief Implements ProcessMonitor::WriteFPR. -class WriteFPROperation : public Operation -{ -public: - WriteFPROperation(lldb::tid_t tid, void *buf, size_t buf_size, bool &result) - : m_tid(tid), m_buf(buf), m_buf_size(buf_size), m_result(result) - { } - - void Execute(ProcessMonitor *monitor) override; - -private: - lldb::tid_t m_tid; - void *m_buf; - size_t m_buf_size; - bool &m_result; -}; - -void -WriteFPROperation::Execute(ProcessMonitor *monitor) -{ -#if defined (__arm64__) || defined (__aarch64__) - int regset = NT_FPREGSET; - struct iovec ioVec; - - ioVec.iov_base = m_buf; - ioVec.iov_len = m_buf_size; - if (PTRACE(PTRACE_SETREGSET, m_tid, ®set, &ioVec, m_buf_size) < 0) - m_result = false; - else - m_result = true; -#else - if (PTRACE(PTRACE_SETFPREGS, m_tid, NULL, m_buf, m_buf_size) < 0) - m_result = false; - else - m_result = true; -#endif -} - -//------------------------------------------------------------------------------ -/// @class WriteRegisterSetOperation -/// @brief Implements ProcessMonitor::WriteRegisterSet. -class WriteRegisterSetOperation : public Operation -{ -public: - WriteRegisterSetOperation(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset, bool &result) - : m_tid(tid), m_buf(buf), m_buf_size(buf_size), m_regset(regset), m_result(result) - { } - - void Execute(ProcessMonitor *monitor) override; - -private: - lldb::tid_t m_tid; - void *m_buf; - size_t m_buf_size; - const unsigned int m_regset; - bool &m_result; -}; - -void -WriteRegisterSetOperation::Execute(ProcessMonitor *monitor) -{ - if (PTRACE(PTRACE_SETREGSET, m_tid, (void *)&m_regset, m_buf, m_buf_size) < 0) - m_result = false; - else - m_result = true; -} - -//------------------------------------------------------------------------------ -/// @class ReadThreadPointerOperation -/// @brief Implements ProcessMonitor::ReadThreadPointer. -class ReadThreadPointerOperation : public Operation -{ -public: - ReadThreadPointerOperation(lldb::tid_t tid, lldb::addr_t *addr, bool &result) - : m_tid(tid), m_addr(addr), m_result(result) - { } - - void Execute(ProcessMonitor *monitor) override; - -private: - lldb::tid_t m_tid; - lldb::addr_t *m_addr; - bool &m_result; -}; - -void -ReadThreadPointerOperation::Execute(ProcessMonitor *monitor) -{ - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS)); - if (log) - log->Printf ("ProcessMonitor::%s()", __FUNCTION__); - - // The process for getting the thread area on Linux is - // somewhat... obscure. There's several different ways depending on - // what arch you're on, and what kernel version you have. - - const ArchSpec& arch = monitor->GetProcess().GetTarget().GetArchitecture(); - switch(arch.GetMachine()) - { - case llvm::Triple::aarch64: - { - int regset = LLDB_PTRACE_NT_ARM_TLS; - struct iovec ioVec; - - ioVec.iov_base = m_addr; - ioVec.iov_len = sizeof(lldb::addr_t); - if (PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, ioVec.iov_len) < 0) - m_result = false; - else - m_result = true; - break; - } -#if defined(__i386__) || defined(__x86_64__) - // Note that struct user below has a field named i387 which is x86-specific. - // Therefore, this case should be compiled only for x86-based systems. - case llvm::Triple::x86: - { - // Find the GS register location for our host architecture. - size_t gs_user_offset = offsetof(struct user, regs); -#ifdef __x86_64__ - gs_user_offset += offsetof(struct user_regs_struct, gs); -#endif -#ifdef __i386__ - gs_user_offset += offsetof(struct user_regs_struct, xgs); -#endif - - // Read the GS register value to get the selector. - errno = 0; - long gs = PTRACE(PTRACE_PEEKUSER, m_tid, (void*)gs_user_offset, NULL, 0); - if (errno) - { - m_result = false; - break; - } - - // Read the LDT base for that selector. - uint32_t tmp[4]; - m_result = (PTRACE(PTRACE_GET_THREAD_AREA, m_tid, (void *)(gs >> 3), &tmp, 0) == 0); - *m_addr = tmp[1]; - break; - } -#endif - case llvm::Triple::x86_64: - // Read the FS register base. - m_result = (PTRACE(PTRACE_ARCH_PRCTL, m_tid, m_addr, (void *)ARCH_GET_FS, 0) == 0); - break; - default: - m_result = false; - break; - } -} - -//------------------------------------------------------------------------------ -/// @class ResumeOperation -/// @brief Implements ProcessMonitor::Resume. -class ResumeOperation : public Operation -{ -public: - ResumeOperation(lldb::tid_t tid, uint32_t signo, bool &result) : - m_tid(tid), m_signo(signo), m_result(result) { } - - void Execute(ProcessMonitor *monitor) override; - -private: - lldb::tid_t m_tid; - uint32_t m_signo; - bool &m_result; -}; - -void -ResumeOperation::Execute(ProcessMonitor *monitor) -{ - intptr_t data = 0; - - if (m_signo != LLDB_INVALID_SIGNAL_NUMBER) - data = m_signo; - - if (PTRACE(PTRACE_CONT, m_tid, NULL, (void*)data, 0)) - { - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); - - if (log) - log->Printf ("ResumeOperation (%" PRIu64 ") failed: %s", m_tid, strerror(errno)); - m_result = false; - } - else - m_result = true; -} - -//------------------------------------------------------------------------------ -/// @class SingleStepOperation -/// @brief Implements ProcessMonitor::SingleStep. -class SingleStepOperation : public Operation -{ -public: - SingleStepOperation(lldb::tid_t tid, uint32_t signo, bool &result) - : m_tid(tid), m_signo(signo), m_result(result) { } - - void Execute(ProcessMonitor *monitor) override; - -private: - lldb::tid_t m_tid; - uint32_t m_signo; - bool &m_result; -}; - -void -SingleStepOperation::Execute(ProcessMonitor *monitor) -{ - intptr_t data = 0; - - if (m_signo != LLDB_INVALID_SIGNAL_NUMBER) - data = m_signo; - - if (PTRACE(PTRACE_SINGLESTEP, m_tid, NULL, (void*)data, 0)) - m_result = false; - else - m_result = true; -} - -//------------------------------------------------------------------------------ -/// @class SiginfoOperation -/// @brief Implements ProcessMonitor::GetSignalInfo. -class SiginfoOperation : public Operation -{ -public: - SiginfoOperation(lldb::tid_t tid, void *info, bool &result, int &ptrace_err) - : m_tid(tid), m_info(info), m_result(result), m_err(ptrace_err) { } - - void Execute(ProcessMonitor *monitor) override; - -private: - lldb::tid_t m_tid; - void *m_info; - bool &m_result; - int &m_err; -}; - -void -SiginfoOperation::Execute(ProcessMonitor *monitor) -{ - if (PTRACE(PTRACE_GETSIGINFO, m_tid, NULL, m_info, 0)) { - m_result = false; - m_err = errno; - } - else - m_result = true; -} - -//------------------------------------------------------------------------------ -/// @class EventMessageOperation -/// @brief Implements ProcessMonitor::GetEventMessage. -class EventMessageOperation : public Operation -{ -public: - EventMessageOperation(lldb::tid_t tid, unsigned long *message, bool &result) - : m_tid(tid), m_message(message), m_result(result) { } - - void Execute(ProcessMonitor *monitor) override; - -private: - lldb::tid_t m_tid; - unsigned long *m_message; - bool &m_result; -}; - -void -EventMessageOperation::Execute(ProcessMonitor *monitor) -{ - if (PTRACE(PTRACE_GETEVENTMSG, m_tid, NULL, m_message, 0)) - m_result = false; - else - m_result = true; -} - -//------------------------------------------------------------------------------ -/// @class DetachOperation -/// @brief Implements ProcessMonitor::Detach. -class DetachOperation : public Operation -{ -public: - DetachOperation(lldb::tid_t tid, Error &result) : m_tid(tid), m_error(result) { } - - void Execute(ProcessMonitor *monitor) override; - -private: - lldb::tid_t m_tid; - Error &m_error; -}; - -void -DetachOperation::Execute(ProcessMonitor *monitor) -{ - if (ptrace(PT_DETACH, m_tid, NULL, 0) < 0) - m_error.SetErrorToErrno(); -} - -ProcessMonitor::OperationArgs::OperationArgs(ProcessMonitor *monitor) - : m_monitor(monitor) -{ - sem_init(&m_semaphore, 0, 0); -} - -ProcessMonitor::OperationArgs::~OperationArgs() -{ - sem_destroy(&m_semaphore); -} - -ProcessMonitor::LaunchArgs::LaunchArgs(ProcessMonitor *monitor, - lldb_private::Module *module, - char const **argv, - char const **envp, - const FileSpec &stdin_file_spec, - const FileSpec &stdout_file_spec, - const FileSpec &stderr_file_spec, - const FileSpec &working_dir, - const lldb_private::ProcessLaunchInfo &launch_info) - : OperationArgs(monitor), - m_module(module), - m_argv(argv), - m_envp(envp), - m_stdin_file_spec(stdin_file_spec), - m_stdout_file_spec(stdout_file_spec), - m_stderr_file_spec(stderr_file_spec), - m_working_dir(working_dir), - m_launch_info(launch_info) -{ -} - -ProcessMonitor::LaunchArgs::~LaunchArgs() -{ } - -ProcessMonitor::AttachArgs::AttachArgs(ProcessMonitor *monitor, - lldb::pid_t pid) - : OperationArgs(monitor), m_pid(pid) { } - -ProcessMonitor::AttachArgs::~AttachArgs() -{ } - -//------------------------------------------------------------------------------ -/// The basic design of the ProcessMonitor is built around two threads. -/// -/// One thread (@see SignalThread) simply blocks on a call to waitpid() looking -/// for changes in the debugee state. When a change is detected a -/// ProcessMessage is sent to the associated ProcessLinux instance. This thread -/// "drives" state changes in the debugger. -/// -/// The second thread (@see OperationThread) is responsible for two things 1) -/// launching or attaching to the inferior process, and then 2) servicing -/// operations such as register reads/writes, stepping, etc. See the comments -/// on the Operation class for more info as to why this is needed. -ProcessMonitor::ProcessMonitor(ProcessPOSIX *process, - Module *module, - const char *argv[], - const char *envp[], - const FileSpec &stdin_file_spec, - const FileSpec &stdout_file_spec, - const FileSpec &stderr_file_spec, - const FileSpec &working_dir, - const lldb_private::ProcessLaunchInfo &launch_info, - lldb_private::Error &error) - : m_process(static_cast(process)), - m_operation_thread(LLDB_INVALID_HOST_THREAD), - m_monitor_thread(LLDB_INVALID_HOST_THREAD), - m_pid(LLDB_INVALID_PROCESS_ID), - m_terminal_fd(-1), - m_operation(0) -{ - std::unique_ptr args(new LaunchArgs(this, module, argv, envp, - stdin_file_spec, - stdout_file_spec, - stderr_file_spec, - working_dir, - launch_info)); - - sem_init(&m_operation_pending, 0, 0); - sem_init(&m_operation_done, 0, 0); - - StartLaunchOpThread(args.get(), error); - if (!error.Success()) - return; - -WAIT_AGAIN: - // Wait for the operation thread to initialize. - if (sem_wait(&args->m_semaphore)) - { - if (errno == EINTR) - goto WAIT_AGAIN; - else - { - error.SetErrorToErrno(); - return; - } - } - - // Check that the launch was a success. - if (!args->m_error.Success()) - { - StopOpThread(); - error = args->m_error; - return; - } - - // Finally, start monitoring the child process for change in state. - m_monitor_thread = Host::StartMonitoringChildProcess( - ProcessMonitor::MonitorCallback, this, GetPID(), true); - if (!m_monitor_thread.IsJoinable()) - { - error.SetErrorToGenericError(); - error.SetErrorString("Process launch failed."); - return; - } -} - -ProcessMonitor::ProcessMonitor(ProcessPOSIX *process, - lldb::pid_t pid, - lldb_private::Error &error) - : m_process(static_cast(process)), - m_operation_thread(LLDB_INVALID_HOST_THREAD), - m_monitor_thread(LLDB_INVALID_HOST_THREAD), - m_pid(LLDB_INVALID_PROCESS_ID), - m_terminal_fd(-1), - m_operation(0) -{ - sem_init(&m_operation_pending, 0, 0); - sem_init(&m_operation_done, 0, 0); - - std::unique_ptr args(new AttachArgs(this, pid)); - - StartAttachOpThread(args.get(), error); - if (!error.Success()) - return; - -WAIT_AGAIN: - // Wait for the operation thread to initialize. - if (sem_wait(&args->m_semaphore)) - { - if (errno == EINTR) - goto WAIT_AGAIN; - else - { - error.SetErrorToErrno(); - return; - } - } - - // Check that the attach was a success. - if (!args->m_error.Success()) - { - StopOpThread(); - error = args->m_error; - return; - } - - // Finally, start monitoring the child process for change in state. - m_monitor_thread = Host::StartMonitoringChildProcess( - ProcessMonitor::MonitorCallback, this, GetPID(), true); - if (!m_monitor_thread.IsJoinable()) - { - error.SetErrorToGenericError(); - error.SetErrorString("Process attach failed."); - return; - } -} - -ProcessMonitor::~ProcessMonitor() -{ - StopMonitor(); -} - -//------------------------------------------------------------------------------ -// Thread setup and tear down. -void -ProcessMonitor::StartLaunchOpThread(LaunchArgs *args, Error &error) -{ - static const char *g_thread_name = "lldb.process.linux.operation"; - - if (m_operation_thread.IsJoinable()) - return; - - m_operation_thread = ThreadLauncher::LaunchThread(g_thread_name, LaunchOpThread, args, &error); -} - -void * -ProcessMonitor::LaunchOpThread(void *arg) -{ - LaunchArgs *args = static_cast(arg); - - if (!Launch(args)) { - sem_post(&args->m_semaphore); - return NULL; - } - - ServeOperation(args); - return NULL; -} - -bool -ProcessMonitor::Launch(LaunchArgs *args) -{ - assert (args && "null args"); - if (!args) - return false; - - ProcessMonitor *monitor = args->m_monitor; - ProcessLinux &process = monitor->GetProcess(); - const char **argv = args->m_argv; - const char **envp = args->m_envp; - const FileSpec &stdin_file_spec = args->m_stdin_file_spec; - const FileSpec &stdout_file_spec = args->m_stdout_file_spec; - const FileSpec &stderr_file_spec = args->m_stderr_file_spec; - const FileSpec &working_dir = args->m_working_dir; - - lldb_utility::PseudoTerminal terminal; - const size_t err_len = 1024; - char err_str[err_len]; - lldb::pid_t pid; - - lldb::ThreadSP inferior; - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); - - // Propagate the environment if one is not supplied. - if (envp == NULL || envp[0] == NULL) - envp = const_cast(environ); - - if ((pid = terminal.Fork(err_str, err_len)) == static_cast(-1)) - { - args->m_error.SetErrorToGenericError(); - args->m_error.SetErrorString("Process fork failed."); - goto FINISH; - } - - // Recognized child exit status codes. - enum { - ePtraceFailed = 1, - eDupStdinFailed, - eDupStdoutFailed, - eDupStderrFailed, - eChdirFailed, - eExecFailed, - eSetGidFailed - }; - - // Child process. - if (pid == 0) - { - // Trace this process. - if (PTRACE(PTRACE_TRACEME, 0, NULL, NULL, 0) < 0) - exit(ePtraceFailed); - - // terminal has already dupped the tty descriptors to stdin/out/err. - // This closes original fd from which they were copied (and avoids - // leaking descriptors to the debugged process. - terminal.CloseSlaveFileDescriptor(); - - // Do not inherit setgid powers. - if (setgid(getgid()) != 0) - exit(eSetGidFailed); - - // Let us have our own process group. - setpgid(0, 0); - - // Dup file descriptors if needed. - // - // FIXME: If two or more of the paths are the same we needlessly open - // the same file multiple times. - if (stdin_file_spec) - if (!DupDescriptor(stdin_file_spec, STDIN_FILENO, O_RDONLY)) - exit(eDupStdinFailed); - - if (stdout_file_spec) - if (!DupDescriptor(stdout_file_spec, STDOUT_FILENO, O_WRONLY | O_CREAT)) - exit(eDupStdoutFailed); - - if (stderr_file_spec) - if (!DupDescriptor(stderr_file_spec, STDERR_FILENO, O_WRONLY | O_CREAT)) - exit(eDupStderrFailed); - - // Change working directory - if (working_dir && 0 != ::chdir(working_dir.GetCString())) - exit(eChdirFailed); - - // Disable ASLR if requested. - if (args->m_launch_info.GetFlags ().Test (lldb::eLaunchFlagDisableASLR)) - { - const int old_personality = personality (LLDB_PERSONALITY_GET_CURRENT_SETTINGS); - if (old_personality == -1) - { - if (log) - log->Printf ("ProcessMonitor::%s retrieval of Linux personality () failed: %s. Cannot disable ASLR.", __FUNCTION__, strerror (errno)); - } - else - { - const int new_personality = personality (ADDR_NO_RANDOMIZE | old_personality); - if (new_personality == -1) - { - if (log) - log->Printf ("ProcessMonitor::%s setting of Linux personality () to disable ASLR failed, ignoring: %s", __FUNCTION__, strerror (errno)); - - } - else - { - if (log) - log->Printf ("ProcessMonitor::%s disabling ASLR: SUCCESS", __FUNCTION__); - - } - } - } - - // Execute. We should never return. - execve(argv[0], - const_cast(argv), - const_cast(envp)); - exit(eExecFailed); - } - - // Wait for the child process to to trap on its call to execve. - lldb::pid_t wpid; - ::pid_t raw_pid; - int status; - - raw_pid = waitpid(pid, &status, 0); - wpid = static_cast (raw_pid); - if (raw_pid < 0) - { - args->m_error.SetErrorToErrno(); - goto FINISH; - } - else if (WIFEXITED(status)) - { - // open, dup or execve likely failed for some reason. - args->m_error.SetErrorToGenericError(); - switch (WEXITSTATUS(status)) - { - case ePtraceFailed: - args->m_error.SetErrorString("Child ptrace failed."); - break; - case eDupStdinFailed: - args->m_error.SetErrorString("Child open stdin failed."); - break; - case eDupStdoutFailed: - args->m_error.SetErrorString("Child open stdout failed."); - break; - case eDupStderrFailed: - args->m_error.SetErrorString("Child open stderr failed."); - break; - case eChdirFailed: - args->m_error.SetErrorString("Child failed to set working directory."); - break; - case eExecFailed: - args->m_error.SetErrorString("Child exec failed."); - break; - case eSetGidFailed: - args->m_error.SetErrorString("Child setgid failed."); - break; - default: - args->m_error.SetErrorString("Child returned unknown exit status."); - break; - } - goto FINISH; - } - assert(WIFSTOPPED(status) && wpid == pid && - "Could not sync with inferior process."); - - if (!SetDefaultPtraceOpts(pid)) - { - args->m_error.SetErrorToErrno(); - goto FINISH; - } - - // Release the master terminal descriptor and pass it off to the - // ProcessMonitor instance. Similarly stash the inferior pid. - monitor->m_terminal_fd = terminal.ReleaseMasterFileDescriptor(); - monitor->m_pid = pid; - - // Set the terminal fd to be in non blocking mode (it simplifies the - // implementation of ProcessLinux::GetSTDOUT to have a non-blocking - // descriptor to read from). - if (!EnsureFDFlags(monitor->m_terminal_fd, O_NONBLOCK, args->m_error)) - goto FINISH; - - // Update the process thread list with this new thread. - // FIXME: should we be letting UpdateThreadList handle this? - // FIXME: by using pids instead of tids, we can only support one thread. - inferior.reset(process.CreateNewPOSIXThread(process, pid)); - - if (log) - log->Printf ("ProcessMonitor::%s() adding pid = %" PRIu64, __FUNCTION__, pid); - process.GetThreadList().AddThread(inferior); - - process.AddThreadForInitialStopIfNeeded(pid); - - // Let our process instance know the thread has stopped. - process.SendMessage(ProcessMessage::Trace(pid)); - -FINISH: - return args->m_error.Success(); -} - -void -ProcessMonitor::StartAttachOpThread(AttachArgs *args, lldb_private::Error &error) -{ - static const char *g_thread_name = "lldb.process.linux.operation"; - - if (m_operation_thread.IsJoinable()) - return; - - m_operation_thread = ThreadLauncher::LaunchThread(g_thread_name, AttachOpThread, args, &error); -} - -void * -ProcessMonitor::AttachOpThread(void *arg) -{ - AttachArgs *args = static_cast(arg); - - if (!Attach(args)) { - sem_post(&args->m_semaphore); - return NULL; - } - - ServeOperation(args); - return NULL; -} - -bool -ProcessMonitor::Attach(AttachArgs *args) -{ - lldb::pid_t pid = args->m_pid; - - ProcessMonitor *monitor = args->m_monitor; - ProcessLinux &process = monitor->GetProcess(); - lldb::ThreadSP inferior; - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); - - // Use a map to keep track of the threads which we have attached/need to attach. - Host::TidMap tids_to_attach; - if (pid <= 1) - { - args->m_error.SetErrorToGenericError(); - args->m_error.SetErrorString("Attaching to process 1 is not allowed."); - goto FINISH; - } - - while (Host::FindProcessThreads(pid, tids_to_attach)) - { - for (Host::TidMap::iterator it = tids_to_attach.begin(); - it != tids_to_attach.end(); ++it) - { - if (it->second == false) - { - lldb::tid_t tid = it->first; - - // Attach to the requested process. - // An attach will cause the thread to stop with a SIGSTOP. - if (PTRACE(PTRACE_ATTACH, tid, NULL, NULL, 0) < 0) - { - // No such thread. The thread may have exited. - // More error handling may be needed. - if (errno == ESRCH) - { - tids_to_attach.erase(it); - continue; - } - else - { - args->m_error.SetErrorToErrno(); - goto FINISH; - } - } - - ::pid_t wpid; - // Need to use __WALL otherwise we receive an error with errno=ECHLD - // At this point we should have a thread stopped if waitpid succeeds. - if ((wpid = waitpid(tid, NULL, __WALL)) < 0) - { - // No such thread. The thread may have exited. - // More error handling may be needed. - if (errno == ESRCH) - { - tids_to_attach.erase(it); - continue; - } - else - { - args->m_error.SetErrorToErrno(); - goto FINISH; - } - } - - if (!SetDefaultPtraceOpts(tid)) - { - args->m_error.SetErrorToErrno(); - goto FINISH; - } - - // Update the process thread list with the attached thread. - inferior.reset(process.CreateNewPOSIXThread(process, tid)); - - if (log) - log->Printf ("ProcessMonitor::%s() adding tid = %" PRIu64, __FUNCTION__, tid); - process.GetThreadList().AddThread(inferior); - it->second = true; - process.AddThreadForInitialStopIfNeeded(tid); - } - } - } - - if (tids_to_attach.size() > 0) - { - monitor->m_pid = pid; - // Let our process instance know the thread has stopped. - process.SendMessage(ProcessMessage::Trace(pid)); - } - else - { - args->m_error.SetErrorToGenericError(); - args->m_error.SetErrorString("No such process."); - } - - FINISH: - return args->m_error.Success(); -} - -bool -ProcessMonitor::SetDefaultPtraceOpts(lldb::pid_t pid) -{ - long ptrace_opts = 0; - - // Have the child raise an event on exit. This is used to keep the child in - // limbo until it is destroyed. - ptrace_opts |= PTRACE_O_TRACEEXIT; - - // Have the tracer trace threads which spawn in the inferior process. - // TODO: if we want to support tracing the inferiors' child, add the - // appropriate ptrace flags here (PTRACE_O_TRACEFORK, PTRACE_O_TRACEVFORK) - ptrace_opts |= PTRACE_O_TRACECLONE; - - // Have the tracer notify us before execve returns - // (needed to disable legacy SIGTRAP generation) - ptrace_opts |= PTRACE_O_TRACEEXEC; - - return PTRACE(PTRACE_SETOPTIONS, pid, NULL, (void*)ptrace_opts, 0) >= 0; -} - -bool -ProcessMonitor::MonitorCallback(void *callback_baton, - lldb::pid_t pid, - bool exited, - int signal, - int status) -{ - ProcessMessage message; - ProcessMonitor *monitor = static_cast(callback_baton); - ProcessLinux *process = monitor->m_process; - assert(process); - bool stop_monitoring; - siginfo_t info; - int ptrace_err; - - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); - - if (exited) - { - if (log) - log->Printf ("ProcessMonitor::%s() got exit signal, tid = %" PRIu64, __FUNCTION__, pid); - message = ProcessMessage::Exit(pid, status); - process->SendMessage(message); - return pid == process->GetID(); - } - - if (!monitor->GetSignalInfo(pid, &info, ptrace_err)) { - if (ptrace_err == EINVAL) { - if (log) - log->Printf ("ProcessMonitor::%s() resuming from group-stop", __FUNCTION__); - // inferior process is in 'group-stop', so deliver SIGSTOP signal - if (!monitor->Resume(pid, SIGSTOP)) { - assert(0 && "SIGSTOP delivery failed while in 'group-stop' state"); - } - stop_monitoring = false; - } else { - // ptrace(GETSIGINFO) failed (but not due to group-stop). Most likely, - // this means the child pid is gone (or not being debugged) therefore - // stop the monitor thread if this is the main pid. - if (log) - log->Printf ("ProcessMonitor::%s() GetSignalInfo failed: %s, tid = %" PRIu64 ", signal = %d, status = %d", - __FUNCTION__, strerror(ptrace_err), pid, signal, status); - stop_monitoring = pid == monitor->m_process->GetID(); - // If we are going to stop monitoring, we need to notify our process object - if (stop_monitoring) - { - message = ProcessMessage::Exit(pid, status); - process->SendMessage(message); - } - } - } - else { - switch (info.si_signo) - { - case SIGTRAP: - message = MonitorSIGTRAP(monitor, &info, pid); - break; - - default: - message = MonitorSignal(monitor, &info, pid); - break; - } - - process->SendMessage(message); - stop_monitoring = false; - } - - return stop_monitoring; -} - -ProcessMessage -ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor, - const siginfo_t *info, lldb::pid_t pid) -{ - ProcessMessage message; - - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); - - assert(monitor); - assert(info && info->si_signo == SIGTRAP && "Unexpected child signal!"); - - switch (info->si_code) - { - default: - assert(false && "Unexpected SIGTRAP code!"); - break; - - // TODO: these two cases are required if we want to support tracing - // of the inferiors' children - // case (SIGTRAP | (PTRACE_EVENT_FORK << 8)): - // case (SIGTRAP | (PTRACE_EVENT_VFORK << 8)): - - case (SIGTRAP | (PTRACE_EVENT_CLONE << 8)): - { - if (log) - log->Printf ("ProcessMonitor::%s() received thread creation event, code = %d", __FUNCTION__, info->si_code ^ SIGTRAP); - - unsigned long tid = 0; - if (!monitor->GetEventMessage(pid, &tid)) - tid = -1; - message = ProcessMessage::NewThread(pid, tid); - break; - } - - case (SIGTRAP | (PTRACE_EVENT_EXEC << 8)): - if (log) - log->Printf ("ProcessMonitor::%s() received exec event, code = %d", __FUNCTION__, info->si_code ^ SIGTRAP); - - message = ProcessMessage::Exec(pid); - break; - - case (SIGTRAP | (PTRACE_EVENT_EXIT << 8)): - { - // The inferior process or one of its threads is about to exit. - // Maintain the process or thread in a state of "limbo" until we are - // explicitly commanded to detach, destroy, resume, etc. - unsigned long data = 0; - if (!monitor->GetEventMessage(pid, &data)) - data = -1; - if (log) - log->Printf ("ProcessMonitor::%s() received limbo event, data = %lx, pid = %" PRIu64, __FUNCTION__, data, pid); - message = ProcessMessage::Limbo(pid, (data >> 8)); - break; - } - - case 0: - case TRAP_TRACE: - if (log) - log->Printf ("ProcessMonitor::%s() received trace event, pid = %" PRIu64, __FUNCTION__, pid); - message = ProcessMessage::Trace(pid); - break; - - case SI_KERNEL: - case TRAP_BRKPT: - if (log) - log->Printf ("ProcessMonitor::%s() received breakpoint event, pid = %" PRIu64, __FUNCTION__, pid); - message = ProcessMessage::Break(pid); - break; - - case TRAP_HWBKPT: - if (log) - log->Printf ("ProcessMonitor::%s() received watchpoint event, pid = %" PRIu64, __FUNCTION__, pid); - message = ProcessMessage::Watch(pid, (lldb::addr_t)info->si_addr); - break; - - case SIGTRAP: - case (SIGTRAP | 0x80): - if (log) - log->Printf ("ProcessMonitor::%s() received system call stop event, pid = %" PRIu64, __FUNCTION__, pid); - // Ignore these signals until we know more about them - monitor->Resume(pid, eResumeSignalNone); - } - - return message; -} - -ProcessMessage -ProcessMonitor::MonitorSignal(ProcessMonitor *monitor, - const siginfo_t *info, lldb::pid_t pid) -{ - ProcessMessage message; - int signo = info->si_signo; - - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); - - // POSIX says that process behaviour is undefined after it ignores a SIGFPE, - // SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a - // kill(2) or raise(3). Similarly for tgkill(2) on Linux. - // - // IOW, user generated signals never generate what we consider to be a - // "crash". - // - // Similarly, ACK signals generated by this monitor. - if (info->si_code == SI_TKILL || info->si_code == SI_USER) - { - if (log) - log->Printf ("ProcessMonitor::%s() received signal %s with code %s, pid = %d", - __FUNCTION__, - monitor->m_process->GetUnixSignals().GetSignalAsCString (signo), - (info->si_code == SI_TKILL ? "SI_TKILL" : "SI_USER"), - info->si_pid); - - if (info->si_pid == getpid()) - return ProcessMessage::SignalDelivered(pid, signo); - else - return ProcessMessage::Signal(pid, signo); - } - - if (log) - log->Printf ("ProcessMonitor::%s() received signal %s", __FUNCTION__, monitor->m_process->GetUnixSignals().GetSignalAsCString (signo)); - - switch (signo) - { - case SIGSEGV: - case SIGILL: - case SIGFPE: - case SIGBUS: - lldb::addr_t fault_addr = reinterpret_cast(info->si_addr); - const auto reason = GetCrashReason(*info); - return ProcessMessage::Crash(pid, reason, signo, fault_addr); - } - - // Everything else is "normal" and does not require any special action on - // our part. - return ProcessMessage::Signal(pid, signo); -} - -// On Linux, when a new thread is created, we receive to notifications, -// (1) a SIGTRAP|PTRACE_EVENT_CLONE from the main process thread with the -// child thread id as additional information, and (2) a SIGSTOP|SI_USER from -// the new child thread indicating that it has is stopped because we attached. -// We have no guarantee of the order in which these arrive, but we need both -// before we are ready to proceed. We currently keep a list of threads which -// have sent the initial SIGSTOP|SI_USER event. Then when we receive the -// SIGTRAP|PTRACE_EVENT_CLONE notification, if the initial stop has not occurred -// we call ProcessMonitor::WaitForInitialTIDStop() to wait for it. - -bool -ProcessMonitor::WaitForInitialTIDStop(lldb::tid_t tid) -{ - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); - if (log) - log->Printf ("ProcessMonitor::%s(%" PRIu64 ") waiting for thread to stop...", __FUNCTION__, tid); - - // Wait for the thread to stop - while (true) - { - int status = -1; - if (log) - log->Printf ("ProcessMonitor::%s(%" PRIu64 ") waitpid...", __FUNCTION__, tid); - ::pid_t wait_pid = waitpid(tid, &status, __WALL); - if (status == -1) - { - // If we got interrupted by a signal (in our process, not the - // inferior) try again. - if (errno == EINTR) - continue; - else - { - if (log) - log->Printf("ProcessMonitor::%s(%" PRIu64 ") waitpid error -- %s", __FUNCTION__, tid, strerror(errno)); - return false; // This is bad, but there's nothing we can do. - } - } - - if (log) - log->Printf ("ProcessMonitor::%s(%" PRIu64 ") waitpid, status = %d", __FUNCTION__, tid, status); - - assert(static_cast(wait_pid) == tid); - - siginfo_t info; - int ptrace_err; - if (!GetSignalInfo(wait_pid, &info, ptrace_err)) - { - if (log) - { - log->Printf ("ProcessMonitor::%s() GetSignalInfo failed. errno=%d (%s)", __FUNCTION__, ptrace_err, strerror(ptrace_err)); - } - return false; - } - - // If this is a thread exit, we won't get any more information. - if (WIFEXITED(status)) - { - m_process->SendMessage(ProcessMessage::Exit(wait_pid, WEXITSTATUS(status))); - if (static_cast(wait_pid) == tid) - return true; - continue; - } - - assert(info.si_code == SI_USER); - assert(WSTOPSIG(status) == SIGSTOP); - - if (log) - log->Printf ("ProcessMonitor::%s(bp) received thread stop signal", __FUNCTION__); - m_process->AddThreadForInitialStopIfNeeded(wait_pid); - return true; - } - return false; -} - -bool -ProcessMonitor::StopThread(lldb::tid_t tid) -{ - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); - - // FIXME: Try to use tgkill or tkill - int ret = tgkill(m_pid, tid, SIGSTOP); - if (log) - log->Printf ("ProcessMonitor::%s(bp) stopping thread, tid = %" PRIu64 ", ret = %d", __FUNCTION__, tid, ret); - - // This can happen if a thread exited while we were trying to stop it. That's OK. - // We'll get the signal for that later. - if (ret < 0) - return false; - - // Wait for the thread to stop - while (true) - { - int status = -1; - if (log) - log->Printf ("ProcessMonitor::%s(bp) waitpid...", __FUNCTION__); - ::pid_t wait_pid = ::waitpid (-1*getpgid(m_pid), &status, __WALL); - if (log) - log->Printf ("ProcessMonitor::%s(bp) waitpid, pid = %" PRIu64 ", status = %d", - __FUNCTION__, static_cast(wait_pid), status); - - if (wait_pid == -1) - { - // If we got interrupted by a signal (in our process, not the - // inferior) try again. - if (errno == EINTR) - continue; - else - return false; // This is bad, but there's nothing we can do. - } - - // If this is a thread exit, we won't get any more information. - if (WIFEXITED(status)) - { - m_process->SendMessage(ProcessMessage::Exit(wait_pid, WEXITSTATUS(status))); - if (static_cast(wait_pid) == tid) - return true; - continue; - } - - siginfo_t info; - int ptrace_err; - if (!GetSignalInfo(wait_pid, &info, ptrace_err)) - { - // another signal causing a StopAllThreads may have been received - // before wait_pid's group-stop was processed, handle it now - if (ptrace_err == EINVAL) - { - assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP); - - if (log) - log->Printf ("ProcessMonitor::%s() resuming from group-stop", __FUNCTION__); - // inferior process is in 'group-stop', so deliver SIGSTOP signal - if (!Resume(wait_pid, SIGSTOP)) { - assert(0 && "SIGSTOP delivery failed while in 'group-stop' state"); - } - continue; - } - - if (log) - log->Printf ("ProcessMonitor::%s() GetSignalInfo failed.", __FUNCTION__); - return false; - } - - // Handle events from other threads - if (log) - log->Printf ("ProcessMonitor::%s(bp) handling event, tid == %" PRIu64, - __FUNCTION__, static_cast(wait_pid)); - - ProcessMessage message; - if (info.si_signo == SIGTRAP) - message = MonitorSIGTRAP(this, &info, wait_pid); - else - message = MonitorSignal(this, &info, wait_pid); - - POSIXThread *thread = static_cast(m_process->GetThreadList().FindThreadByID(wait_pid).get()); - - // When a new thread is created, we may get a SIGSTOP for the new thread - // just before we get the SIGTRAP that we use to add the thread to our - // process thread list. We don't need to worry about that signal here. - assert(thread || message.GetKind() == ProcessMessage::eSignalMessage); - - if (!thread) - { - m_process->SendMessage(message); - continue; - } - - switch (message.GetKind()) - { - case ProcessMessage::eExecMessage: - llvm_unreachable("unexpected message"); - case ProcessMessage::eAttachMessage: - case ProcessMessage::eInvalidMessage: - break; - - // These need special handling because we don't want to send a - // resume even if we already sent a SIGSTOP to this thread. In - // this case the resume will cause the thread to disappear. It is - // unlikely that we'll ever get eExitMessage here, but the same - // reasoning applies. - case ProcessMessage::eLimboMessage: - case ProcessMessage::eExitMessage: - if (log) - log->Printf ("ProcessMonitor::%s(bp) handling message", __FUNCTION__); - // SendMessage will set the thread state as needed. - m_process->SendMessage(message); - // If this is the thread we're waiting for, stop waiting. Even - // though this wasn't the signal we expected, it's the last - // signal we'll see while this thread is alive. - if (static_cast(wait_pid) == tid) - return true; - break; - - case ProcessMessage::eSignalMessage: - if (log) - log->Printf ("ProcessMonitor::%s(bp) handling message", __FUNCTION__); - if (WSTOPSIG(status) == SIGSTOP) - { - m_process->AddThreadForInitialStopIfNeeded(tid); - thread->SetState(lldb::eStateStopped); - } - else - { - m_process->SendMessage(message); - // This isn't the stop we were expecting, but the thread is - // stopped. SendMessage will handle processing of this event, - // but we need to resume here to get the stop we are waiting - // for (otherwise the thread will stop again immediately when - // we try to resume). - if (static_cast(wait_pid) == tid) - Resume(wait_pid, eResumeSignalNone); - } - break; - - case ProcessMessage::eSignalDeliveredMessage: - // This is the stop we're expecting. - if (static_cast(wait_pid) == tid && - WIFSTOPPED(status) && - WSTOPSIG(status) == SIGSTOP && - info.si_code == SI_TKILL) - { - if (log) - log->Printf ("ProcessMonitor::%s(bp) received signal, done waiting", __FUNCTION__); - thread->SetState(lldb::eStateStopped); - return true; - } - // else fall-through - case ProcessMessage::eBreakpointMessage: - case ProcessMessage::eTraceMessage: - case ProcessMessage::eWatchpointMessage: - case ProcessMessage::eCrashMessage: - case ProcessMessage::eNewThreadMessage: - if (log) - log->Printf ("ProcessMonitor::%s(bp) handling message", __FUNCTION__); - // SendMessage will set the thread state as needed. - m_process->SendMessage(message); - // This isn't the stop we were expecting, but the thread is - // stopped. SendMessage will handle processing of this event, - // but we need to resume here to get the stop we are waiting - // for (otherwise the thread will stop again immediately when - // we try to resume). - if (static_cast(wait_pid) == tid) - Resume(wait_pid, eResumeSignalNone); - break; - } - } - return false; -} - -void -ProcessMonitor::ServeOperation(OperationArgs *args) -{ - ProcessMonitor *monitor = args->m_monitor; - - // We are finised with the arguments and are ready to go. Sync with the - // parent thread and start serving operations on the inferior. - sem_post(&args->m_semaphore); - - for(;;) - { - // wait for next pending operation - if (sem_wait(&monitor->m_operation_pending)) - { - if (errno == EINTR) - continue; - assert(false && "Unexpected errno from sem_wait"); - } - - monitor->m_operation->Execute(monitor); - - // notify calling thread that operation is complete - sem_post(&monitor->m_operation_done); - } -} - -void -ProcessMonitor::DoOperation(Operation *op) -{ - Mutex::Locker lock(m_operation_mutex); - - m_operation = op; - - // notify operation thread that an operation is ready to be processed - sem_post(&m_operation_pending); - - // wait for operation to complete - while (sem_wait(&m_operation_done)) - { - if (errno == EINTR) - continue; - assert(false && "Unexpected errno from sem_wait"); - } -} - -size_t -ProcessMonitor::ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, - Error &error) -{ - size_t result; - ReadOperation op(vm_addr, buf, size, error, result); - DoOperation(&op); - return result; -} - -size_t -ProcessMonitor::WriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, - lldb_private::Error &error) -{ - size_t result; - WriteOperation op(vm_addr, buf, size, error, result); - DoOperation(&op); - return result; -} - -bool -ProcessMonitor::ReadRegisterValue(lldb::tid_t tid, unsigned offset, const char* reg_name, - unsigned size, RegisterValue &value) -{ - bool result; - ReadRegOperation op(tid, offset, reg_name, value, result); - DoOperation(&op); - return result; -} - -#if defined (__arm64__) || defined (__aarch64__) - -bool -ProcessMonitor::ReadHardwareDebugInfo (lldb::tid_t tid, unsigned int &watch_count , unsigned int &break_count) -{ - bool result = true; - ReadDBGROperation op(tid, watch_count, break_count); - DoOperation(&op); - return result; -} - -bool -ProcessMonitor::WriteHardwareDebugRegs (lldb::tid_t tid, lldb::addr_t *addr_buf, uint32_t *cntrl_buf, int type, int count) -{ - bool result = true; - WriteDBGROperation op(tid, addr_buf, cntrl_buf, type, count); - DoOperation(&op); - return result; -} - -#endif -bool -ProcessMonitor::WriteRegisterValue(lldb::tid_t tid, unsigned offset, - const char* reg_name, const RegisterValue &value) -{ - bool result; - WriteRegOperation op(tid, offset, reg_name, value, result); - DoOperation(&op); - return result; -} - -bool -ProcessMonitor::ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size) -{ - bool result; - ReadGPROperation op(tid, buf, buf_size, result); - DoOperation(&op); - return result; -} - -bool -ProcessMonitor::ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size) -{ - bool result; - ReadFPROperation op(tid, buf, buf_size, result); - DoOperation(&op); - return result; -} - -bool -ProcessMonitor::ReadRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset) -{ - bool result; - ReadRegisterSetOperation op(tid, buf, buf_size, regset, result); - DoOperation(&op); - return result; -} - -bool -ProcessMonitor::WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size) -{ - bool result; - WriteGPROperation op(tid, buf, buf_size, result); - DoOperation(&op); - return result; -} - -bool -ProcessMonitor::WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size) -{ - bool result; - WriteFPROperation op(tid, buf, buf_size, result); - DoOperation(&op); - return result; -} - -bool -ProcessMonitor::WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset) -{ - bool result; - WriteRegisterSetOperation op(tid, buf, buf_size, regset, result); - DoOperation(&op); - return result; -} - -bool -ProcessMonitor::ReadThreadPointer(lldb::tid_t tid, lldb::addr_t &value) -{ - bool result; - ReadThreadPointerOperation op(tid, &value, result); - DoOperation(&op); - return result; -} - -bool -ProcessMonitor::Resume(lldb::tid_t tid, uint32_t signo) -{ - bool result; - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); - - if (log) - log->Printf ("ProcessMonitor::%s() resuming thread = %" PRIu64 " with signal %s", __FUNCTION__, tid, - m_process->GetUnixSignals().GetSignalAsCString (signo)); - ResumeOperation op(tid, signo, result); - DoOperation(&op); - if (log) - log->Printf ("ProcessMonitor::%s() resuming result = %s", __FUNCTION__, result ? "true" : "false"); - return result; -} - -bool -ProcessMonitor::SingleStep(lldb::tid_t tid, uint32_t signo) -{ - bool result; - SingleStepOperation op(tid, signo, result); - DoOperation(&op); - return result; -} - -bool -ProcessMonitor::Kill() -{ - return kill(GetPID(), SIGKILL) == 0; -} - -bool -ProcessMonitor::GetSignalInfo(lldb::tid_t tid, void *siginfo, int &ptrace_err) -{ - bool result; - SiginfoOperation op(tid, siginfo, result, ptrace_err); - DoOperation(&op); - return result; -} - -bool -ProcessMonitor::GetEventMessage(lldb::tid_t tid, unsigned long *message) -{ - bool result; - EventMessageOperation op(tid, message, result); - DoOperation(&op); - return result; -} - -lldb_private::Error -ProcessMonitor::Detach(lldb::tid_t tid) -{ - lldb_private::Error error; - if (tid != LLDB_INVALID_THREAD_ID) - { - DetachOperation op(tid, error); - DoOperation(&op); - } - return error; -} - -bool -ProcessMonitor::DupDescriptor(const FileSpec &file_spec, int fd, int flags) -{ - int target_fd = open(file_spec.GetCString(), flags, 0666); - - if (target_fd == -1) - return false; - - if (dup2(target_fd, fd) == -1) - return false; - - return (close(target_fd) == -1) ? false : true; -} - -void -ProcessMonitor::StopMonitoringChildProcess() -{ - if (m_monitor_thread.IsJoinable()) - { - ::pthread_kill(m_monitor_thread.GetNativeThread().GetSystemHandle(), SIGUSR1); - m_monitor_thread.Join(nullptr); - } -} - -void -ProcessMonitor::StopMonitor() -{ - StopMonitoringChildProcess(); - StopOpThread(); - sem_destroy(&m_operation_pending); - sem_destroy(&m_operation_done); - if (m_terminal_fd >= 0) { - close(m_terminal_fd); - m_terminal_fd = -1; - } -} - -void -ProcessMonitor::StopOpThread() -{ - if (!m_operation_thread.IsJoinable()) - return; - - DoOperation(EXIT_OPERATION); - m_operation_thread.Join(nullptr); -} Index: source/Plugins/Process/POSIX/CMakeLists.txt =================================================================== --- source/Plugins/Process/POSIX/CMakeLists.txt +++ source/Plugins/Process/POSIX/CMakeLists.txt @@ -1,19 +1,10 @@ set(LLVM_NO_RTTI 1) include_directories(.) -include_directories(../Linux) include_directories(../Utility) add_lldb_library(lldbPluginProcessPOSIX CrashReason.cpp - POSIXStopInfo.cpp - POSIXThread.cpp ProcessMessage.cpp - ProcessPOSIX.cpp ProcessPOSIXLog.cpp - RegisterContextPOSIXProcessMonitor_arm.cpp - RegisterContextPOSIXProcessMonitor_arm64.cpp - RegisterContextPOSIXProcessMonitor_mips64.cpp - RegisterContextPOSIXProcessMonitor_powerpc.cpp - RegisterContextPOSIXProcessMonitor_x86.cpp ) Index: source/Plugins/Process/POSIX/POSIXStopInfo.h =================================================================== --- /dev/null +++ source/Plugins/Process/POSIX/POSIXStopInfo.h @@ -1,110 +0,0 @@ -//===-- POSIXStopInfo.h -----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_POSIXStopInfo_H_ -#define liblldb_POSIXStopInfo_H_ - -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes -#include "lldb/Target/StopInfo.h" - -#include "CrashReason.h" -#include "POSIXThread.h" - -#include - -//===----------------------------------------------------------------------===// -/// @class POSIXStopInfo -/// @brief Simple base class for all POSIX-specific StopInfo objects. -/// -class POSIXStopInfo - : public lldb_private::StopInfo -{ -public: - POSIXStopInfo(lldb_private::Thread &thread, uint32_t status) - : StopInfo(thread, status) - { } -}; - -//===----------------------------------------------------------------------===// -/// @class POSIXLimboStopInfo -/// @brief Represents the stop state of a process ready to exit. -/// -class POSIXLimboStopInfo - : public POSIXStopInfo -{ -public: - POSIXLimboStopInfo(POSIXThread &thread) - : POSIXStopInfo(thread, 0) - { } - - ~POSIXLimboStopInfo(); - - lldb::StopReason - GetStopReason() const; - - const char * - GetDescription(); - - bool - ShouldStop(lldb_private::Event *event_ptr); - - bool - ShouldNotify(lldb_private::Event *event_ptr); -}; - - -//===----------------------------------------------------------------------===// -/// @class POSIXCrashStopInfo -/// @brief Represents the stop state of process that is ready to crash. -/// -class POSIXCrashStopInfo - : public POSIXStopInfo -{ -public: - POSIXCrashStopInfo(POSIXThread &thread, uint32_t status, - CrashReason reason, - lldb::addr_t fault_addr); - ~POSIXCrashStopInfo(); - - lldb::StopReason - GetStopReason() const; -}; - -//===----------------------------------------------------------------------===// -/// @class POSIXNewThreadStopInfo -/// @brief Represents the stop state of process when a new thread is spawned. -/// - -class POSIXNewThreadStopInfo - : public POSIXStopInfo -{ -public: - POSIXNewThreadStopInfo (POSIXThread &thread) - : POSIXStopInfo (thread, 0) - { } - - ~POSIXNewThreadStopInfo(); - - lldb::StopReason - GetStopReason() const; - - const char * - GetDescription(); - - bool - ShouldStop(lldb_private::Event *event_ptr); - - bool - ShouldNotify(lldb_private::Event *event_ptr); -}; - -#endif Index: source/Plugins/Process/POSIX/POSIXStopInfo.cpp =================================================================== --- /dev/null +++ source/Plugins/Process/POSIX/POSIXStopInfo.cpp @@ -1,92 +0,0 @@ -//===-- POSIXStopInfo.cpp ---------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "POSIXStopInfo.h" - -using namespace lldb; -using namespace lldb_private; - - -//===----------------------------------------------------------------------===// -// POSIXLimboStopInfo - -POSIXLimboStopInfo::~POSIXLimboStopInfo() { } - -lldb::StopReason -POSIXLimboStopInfo::GetStopReason() const -{ - return lldb::eStopReasonThreadExiting; -} - -const char * -POSIXLimboStopInfo::GetDescription() -{ - return "thread exiting"; -} - -bool -POSIXLimboStopInfo::ShouldStop(Event *event_ptr) -{ - return false; -} - -bool -POSIXLimboStopInfo::ShouldNotify(Event *event_ptr) -{ - return false; -} - -//===----------------------------------------------------------------------===// -// POSIXCrashStopInfo - -POSIXCrashStopInfo::POSIXCrashStopInfo(POSIXThread &thread, - uint32_t status, - CrashReason reason, - lldb::addr_t fault_addr) - : POSIXStopInfo(thread, status) -{ - m_description = ::GetCrashReasonString(reason, fault_addr); -} - -POSIXCrashStopInfo::~POSIXCrashStopInfo() { } - -lldb::StopReason -POSIXCrashStopInfo::GetStopReason() const -{ - return lldb::eStopReasonException; -} - -//===----------------------------------------------------------------------===// -// POSIXNewThreadStopInfo - -POSIXNewThreadStopInfo::~POSIXNewThreadStopInfo() { } - -lldb::StopReason -POSIXNewThreadStopInfo::GetStopReason() const -{ - return lldb::eStopReasonNone; -} - -const char * -POSIXNewThreadStopInfo::GetDescription() -{ - return "thread spawned"; -} - -bool -POSIXNewThreadStopInfo::ShouldStop(Event *event_ptr) -{ - return false; -} - -bool -POSIXNewThreadStopInfo::ShouldNotify(Event *event_ptr) -{ - return false; -} Index: source/Plugins/Process/POSIX/ProcessPOSIX.h =================================================================== --- /dev/null +++ source/Plugins/Process/POSIX/ProcessPOSIX.h @@ -1,210 +0,0 @@ -//===-- ProcessPOSIX.h ------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_ProcessPOSIX_H_ -#define liblldb_ProcessPOSIX_H_ - -// C Includes - -// C++ Includes -#include -#include - -// Other libraries and framework includes -#include "lldb/Target/Process.h" -#include "ProcessMessage.h" - -class ProcessMonitor; -class POSIXThread; - -class ProcessPOSIX : - public lldb_private::Process -{ -public: - - //------------------------------------------------------------------ - // Constructors and destructors - //------------------------------------------------------------------ - ProcessPOSIX(lldb_private::Target& target, - lldb_private::Listener &listener, - lldb_private::UnixSignalsSP &unix_signals_sp); - - virtual - ~ProcessPOSIX(); - - //------------------------------------------------------------------ - // Process protocol. - //------------------------------------------------------------------ - void - Finalize() override; - - bool - CanDebug(lldb_private::Target &target, bool plugin_specified_by_name) override; - - lldb_private::Error - WillLaunch(lldb_private::Module *module) override; - - lldb_private::Error - DoAttachToProcessWithID (lldb::pid_t pid, const lldb_private::ProcessAttachInfo &attach_info) override; - - lldb_private::Error - DoLaunch (lldb_private::Module *exe_module, - lldb_private::ProcessLaunchInfo &launch_info) override; - - void - DidLaunch() override; - - lldb_private::Error - DoResume() override; - - lldb_private::Error - DoHalt(bool &caused_stop) override; - - lldb_private::Error - DoDetach(bool keep_stopped) override = 0; - - lldb_private::Error - DoSignal(int signal) override; - - lldb_private::Error - DoDestroy() override; - - void - DoDidExec() override; - - void - RefreshStateAfterStop() override; - - bool - IsAlive() override; - - size_t - DoReadMemory(lldb::addr_t vm_addr, - void *buf, - size_t size, - lldb_private::Error &error) override; - - size_t - DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, - lldb_private::Error &error) override; - - lldb::addr_t - DoAllocateMemory(size_t size, uint32_t permissions, - lldb_private::Error &error) override; - - lldb_private::Error - DoDeallocateMemory(lldb::addr_t ptr) override; - - virtual size_t - GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite* bp_site); - - lldb_private::Error - EnableBreakpointSite(lldb_private::BreakpointSite *bp_site) override; - - lldb_private::Error - DisableBreakpointSite(lldb_private::BreakpointSite *bp_site) override; - - lldb_private::Error - EnableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true) override; - - lldb_private::Error - DisableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true) override; - - lldb_private::Error - GetWatchpointSupportInfo(uint32_t &num) override; - - lldb_private::Error - GetWatchpointSupportInfo(uint32_t &num, bool &after) override; - - virtual uint32_t - UpdateThreadListIfNeeded(); - - bool - UpdateThreadList(lldb_private::ThreadList &old_thread_list, - lldb_private::ThreadList &new_thread_list) override = 0; - - virtual lldb::ByteOrder - GetByteOrder() const; - - lldb::addr_t - GetImageInfoAddress() override; - - size_t - PutSTDIN(const char *buf, size_t len, lldb_private::Error &error) override; - - const lldb::DataBufferSP - GetAuxvData () override; - - //-------------------------------------------------------------------------- - // ProcessPOSIX internal API. - - /// Registers the given message with this process. - virtual void - SendMessage(const ProcessMessage &message); - - ProcessMonitor & - GetMonitor() { assert(m_monitor); return *m_monitor; } - - lldb_private::FileSpec - GetFileSpec(const lldb_private::FileAction *file_action, - const lldb_private::FileSpec &default_file_spec, - const lldb_private::FileSpec &dbg_pts_file_spec); - - /// Stops all threads in the process. - /// The \p stop_tid parameter indicates the thread which initiated the stop. - virtual void - StopAllThreads(lldb::tid_t stop_tid); - - /// Adds the thread to the list of threads for which we have received the initial stopping signal. - /// The \p stop_tid parameter indicates the thread which the stop happened for. - bool - AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid); - - bool - WaitingForInitialStop(lldb::tid_t stop_tid); - - virtual POSIXThread * - CreateNewPOSIXThread(lldb_private::Process &process, lldb::tid_t tid); - -protected: - /// Target byte order. - lldb::ByteOrder m_byte_order; - - /// Process monitor; - ProcessMonitor *m_monitor; - - /// The module we are executing. - lldb_private::Module *m_module; - - /// Message queue notifying this instance of inferior process state changes. - lldb_private::Mutex m_message_mutex; - std::queue m_message_queue; - - /// Drive any exit events to completion. - bool m_exit_now; - - /// Returns true if the process has exited. - bool HasExited(); - - /// Returns true if the process is stopped. - bool IsStopped(); - - /// Returns true if at least one running is currently running - bool IsAThreadRunning(); - - typedef std::map MMapMap; - MMapMap m_addr_to_mmap_size; - - typedef std::set ThreadStopSet; - /// Every thread begins with a stop signal. This keeps track - /// of the threads for which we have received the stop signal. - ThreadStopSet m_seen_initial_stop; -}; - -#endif // liblldb_MacOSXProcess_H_ Index: source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp =================================================================== --- source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp +++ source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp @@ -14,7 +14,6 @@ #include "lldb/Interpreter/Args.h" #include "lldb/Core/StreamFile.h" -#include "ProcessPOSIX.h" #include "ProcessPOSIXLog.h" using namespace lldb; Index: source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm.h =================================================================== --- /dev/null +++ source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm.h @@ -1,95 +0,0 @@ -//===-- RegisterContextPOSIXProcessMonitor_arm.h --------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_RegisterContextPOSIXProcessMonitor_arm_H_ -#define liblldb_RegisterContextPOSIXProcessMonitor_arm_H_ - -#include "Plugins/Process/Utility/RegisterContextPOSIX_arm.h" - -class RegisterContextPOSIXProcessMonitor_arm: - public RegisterContextPOSIX_arm, - public POSIXBreakpointProtocol -{ -public: - RegisterContextPOSIXProcessMonitor_arm(lldb_private::Thread &thread, - uint32_t concrete_frame_idx, - lldb_private::RegisterInfoInterface *register_info); - -protected: - bool - ReadGPR(); - - bool - ReadFPR(); - - bool - WriteGPR(); - - bool - WriteFPR(); - - // lldb_private::RegisterContext - bool - ReadRegister(const unsigned reg, lldb_private::RegisterValue &value); - - bool - WriteRegister(const unsigned reg, const lldb_private::RegisterValue &value); - - bool - ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value); - - bool - WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value); - - bool - ReadAllRegisterValues(lldb::DataBufferSP &data_sp); - - bool - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); - - uint32_t - SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write); - - bool - ClearHardwareWatchpoint(uint32_t hw_index); - - bool - HardwareSingleStep(bool enable); - - // POSIXBreakpointProtocol - bool - UpdateAfterBreakpoint(); - - unsigned - GetRegisterIndexFromOffset(unsigned offset); - - bool - IsWatchpointHit(uint32_t hw_index); - - bool - ClearWatchpointHits(); - - lldb::addr_t - GetWatchpointAddress(uint32_t hw_index); - - bool - IsWatchpointVacant(uint32_t hw_index); - - bool - SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read, bool write, uint32_t hw_index); - - uint32_t - NumSupportedHardwareWatchpoints(); - -private: - ProcessMonitor & - GetMonitor(); -}; - -#endif Index: source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm.cpp =================================================================== --- /dev/null +++ source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm.cpp @@ -1,322 +0,0 @@ -//===-- RegisterContextPOSIXProcessMonitor_arm.cpp -----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===---------------------------------------------------------------------===// - -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/RegisterValue.h" -#include "lldb/Target/Thread.h" - -#include "RegisterContextPOSIX_arm.h" -#include "ProcessPOSIX.h" -#include "RegisterContextPOSIXProcessMonitor_arm.h" -#include "ProcessMonitor.h" - -using namespace lldb_private; -using namespace lldb; - -#define REG_CONTEXT_SIZE (GetGPRSize()) - -RegisterContextPOSIXProcessMonitor_arm::RegisterContextPOSIXProcessMonitor_arm(Thread &thread, - uint32_t concrete_frame_idx, - lldb_private::RegisterInfoInterface *register_info) - : RegisterContextPOSIX_arm(thread, concrete_frame_idx, register_info) -{ -} - -ProcessMonitor & -RegisterContextPOSIXProcessMonitor_arm::GetMonitor() -{ - ProcessSP base = CalculateProcess(); - ProcessPOSIX *process = static_cast(base.get()); - return process->GetMonitor(); -} - -bool -RegisterContextPOSIXProcessMonitor_arm::ReadGPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadGPR(m_thread.GetID(), &m_gpr_arm, GetGPRSize()); -} - -bool -RegisterContextPOSIXProcessMonitor_arm::ReadFPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadFPR(m_thread.GetID(), &m_fpr, sizeof(m_fpr)); -} - -bool -RegisterContextPOSIXProcessMonitor_arm::WriteGPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteGPR(m_thread.GetID(), &m_gpr_arm, GetGPRSize()); -} - -bool -RegisterContextPOSIXProcessMonitor_arm::WriteFPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteFPR(m_thread.GetID(), &m_fpr, sizeof(m_fpr)); -} - -bool -RegisterContextPOSIXProcessMonitor_arm::ReadRegister(const unsigned reg, - RegisterValue &value) -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadRegisterValue(m_thread.GetID(), - GetRegisterOffset(reg), - GetRegisterName(reg), - GetRegisterSize(reg), - value); -} - -bool -RegisterContextPOSIXProcessMonitor_arm::WriteRegister(const unsigned reg, - const RegisterValue &value) -{ - unsigned reg_to_write = reg; - RegisterValue value_to_write = value; - - // Check if this is a subregister of a full register. - const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg); - if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) - { - RegisterValue full_value; - uint32_t full_reg = reg_info->invalidate_regs[0]; - const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg); - - // Read the full register. - if (ReadRegister(full_reg_info, full_value)) - { - Error error; - ByteOrder byte_order = GetByteOrder(); - uint8_t dst[RegisterValue::kMaxRegisterByteSize]; - - // Get the bytes for the full register. - const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info, - dst, - sizeof(dst), - byte_order, - error); - if (error.Success() && dest_size) - { - uint8_t src[RegisterValue::kMaxRegisterByteSize]; - - // Get the bytes for the source data. - const uint32_t src_size = value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error); - if (error.Success() && src_size && (src_size < dest_size)) - { - // Copy the src bytes to the destination. - memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size); - // Set this full register as the value to write. - value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order); - value_to_write.SetType(full_reg_info); - reg_to_write = full_reg; - } - } - } - } - - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteRegisterValue(m_thread.GetID(), - GetRegisterOffset(reg_to_write), - GetRegisterName(reg_to_write), - value_to_write); -} - -bool -RegisterContextPOSIXProcessMonitor_arm::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value) -{ - if (!reg_info) - return false; - - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - - if (IsFPR(reg)) - { - if (!ReadFPR()) - return false; - } - else - { - return ReadRegister(reg, value); - } - - // Get pointer to m_fpr variable and set the data from it. - assert (reg_info->byte_offset < sizeof m_fpr); - uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset; - switch (reg_info->byte_size) - { - case 2: - value.SetUInt16(*(uint16_t *)src); - return true; - case 4: - value.SetUInt32(*(uint32_t *)src); - return true; - case 8: - value.SetUInt64(*(uint64_t *)src); - return true; - default: - assert(false && "Unhandled data size."); - return false; - } -} - -bool -RegisterContextPOSIXProcessMonitor_arm::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value) -{ - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - - if (IsGPR(reg)) - { - return WriteRegister(reg, value); - } - else if (IsFPR(reg)) - { - return WriteFPR(); - } - - return false; -} - -bool -RegisterContextPOSIXProcessMonitor_arm::ReadAllRegisterValues(DataBufferSP &data_sp) -{ - bool success = false; - data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); - if (data_sp && ReadGPR () && ReadFPR ()) - { - uint8_t *dst = data_sp->GetBytes(); - success = dst != 0; - - if (success) - { - ::memcpy (dst, &m_gpr_arm, GetGPRSize()); - dst += GetGPRSize(); - ::memcpy (dst, &m_fpr, sizeof(m_fpr)); - } - } - return success; -} - -bool -RegisterContextPOSIXProcessMonitor_arm::WriteAllRegisterValues(const DataBufferSP &data_sp) -{ - bool success = false; - if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) - { - uint8_t *src = data_sp->GetBytes(); - if (src) - { - ::memcpy (&m_gpr_arm, src, GetGPRSize()); - - if (WriteGPR()) - { - src += GetGPRSize(); - ::memcpy (&m_fpr, src, sizeof(m_fpr)); - - success = WriteFPR(); - } - } - } - return success; -} - -uint32_t -RegisterContextPOSIXProcessMonitor_arm::SetHardwareWatchpoint(addr_t addr, size_t size, - bool read, bool write) -{ - const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); - uint32_t hw_index; - - for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index) - { - if (IsWatchpointVacant(hw_index)) - return SetHardwareWatchpointWithIndex(addr, size, - read, write, - hw_index); - } - - return LLDB_INVALID_INDEX32; -} - -bool -RegisterContextPOSIXProcessMonitor_arm::ClearHardwareWatchpoint(uint32_t hw_index) -{ - return false; -} - -bool -RegisterContextPOSIXProcessMonitor_arm::HardwareSingleStep(bool enable) -{ - return false; -} - -bool -RegisterContextPOSIXProcessMonitor_arm::UpdateAfterBreakpoint() -{ - lldb::addr_t pc; - - if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) - return false; - - return true; -} - -unsigned -RegisterContextPOSIXProcessMonitor_arm::GetRegisterIndexFromOffset(unsigned offset) -{ - unsigned reg; - for (reg = 0; reg < k_num_registers_arm; reg++) - { - if (GetRegisterInfo()[reg].byte_offset == offset) - break; - } - assert(reg < k_num_registers_arm && "Invalid register offset."); - return reg; -} - -bool -RegisterContextPOSIXProcessMonitor_arm::IsWatchpointHit(uint32_t hw_index) -{ - return false; -} - -bool -RegisterContextPOSIXProcessMonitor_arm::ClearWatchpointHits() -{ - return false; -} - -addr_t -RegisterContextPOSIXProcessMonitor_arm::GetWatchpointAddress(uint32_t hw_index) -{ - return LLDB_INVALID_ADDRESS; -} - -bool -RegisterContextPOSIXProcessMonitor_arm::IsWatchpointVacant(uint32_t hw_index) -{ - return false; -} - -bool -RegisterContextPOSIXProcessMonitor_arm::SetHardwareWatchpointWithIndex(addr_t addr, size_t size, - bool read, bool write, - uint32_t hw_index) -{ - return false; -} - -uint32_t -RegisterContextPOSIXProcessMonitor_arm::NumSupportedHardwareWatchpoints() -{ - return 0; -} - Index: source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm64.h =================================================================== --- /dev/null +++ source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm64.h @@ -1,95 +0,0 @@ -//===-- RegisterContextPOSIXProcessMonitor_arm64.h --------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_RegisterContextPOSIXProcessMonitor_arm64_H_ -#define liblldb_RegisterContextPOSIXProcessMonitor_arm64_H_ - -#include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h" - -class RegisterContextPOSIXProcessMonitor_arm64: - public RegisterContextPOSIX_arm64, - public POSIXBreakpointProtocol -{ -public: - RegisterContextPOSIXProcessMonitor_arm64(lldb_private::Thread &thread, - uint32_t concrete_frame_idx, - lldb_private::RegisterInfoInterface *register_info); - -protected: - bool - ReadGPR(); - - bool - ReadFPR(); - - bool - WriteGPR(); - - bool - WriteFPR(); - - // lldb_private::RegisterContext - bool - ReadRegister(const unsigned reg, lldb_private::RegisterValue &value); - - bool - WriteRegister(const unsigned reg, const lldb_private::RegisterValue &value); - - bool - ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value); - - bool - WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value); - - bool - ReadAllRegisterValues(lldb::DataBufferSP &data_sp); - - bool - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); - - uint32_t - SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write); - - bool - ClearHardwareWatchpoint(uint32_t hw_index); - - bool - HardwareSingleStep(bool enable); - - // POSIXBreakpointProtocol - bool - UpdateAfterBreakpoint(); - - unsigned - GetRegisterIndexFromOffset(unsigned offset); - - bool - IsWatchpointHit(uint32_t hw_index); - - bool - ClearWatchpointHits(); - - lldb::addr_t - GetWatchpointAddress(uint32_t hw_index); - - bool - IsWatchpointVacant(uint32_t hw_index); - - bool - SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read, bool write, uint32_t hw_index); - - uint32_t - NumSupportedHardwareWatchpoints(); - -private: - ProcessMonitor & - GetMonitor(); -}; - -#endif Index: source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.h =================================================================== --- /dev/null +++ source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.h @@ -1,95 +0,0 @@ -//===-- RegisterContextPOSIXProcessMonitor_mips64.h -------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_RegisterContextPOSIXProcessMonitor_mips64_H_ -#define liblldb_RegisterContextPOSIXProcessMonitor_mips64_H_ - -#include "Plugins/Process/Utility/RegisterContextPOSIX_mips64.h" - -class RegisterContextPOSIXProcessMonitor_mips64: - public RegisterContextPOSIX_mips64, - public POSIXBreakpointProtocol -{ -public: - RegisterContextPOSIXProcessMonitor_mips64(lldb_private::Thread &thread, - uint32_t concrete_frame_idx, - lldb_private::RegisterInfoInterface *register_info); - -protected: - bool - ReadGPR(); - - bool - ReadFPR(); - - bool - WriteGPR(); - - bool - WriteFPR(); - - // lldb_private::RegisterContext - bool - ReadRegister(const unsigned reg, lldb_private::RegisterValue &value); - - bool - WriteRegister(const unsigned reg, const lldb_private::RegisterValue &value); - - bool - ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value); - - bool - WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value); - - bool - ReadAllRegisterValues(lldb::DataBufferSP &data_sp); - - bool - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); - - uint32_t - SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write); - - bool - ClearHardwareWatchpoint(uint32_t hw_index); - - bool - HardwareSingleStep(bool enable); - - // POSIXBreakpointProtocol - bool - UpdateAfterBreakpoint(); - - unsigned - GetRegisterIndexFromOffset(unsigned offset); - - bool - IsWatchpointHit(uint32_t hw_index); - - bool - ClearWatchpointHits(); - - lldb::addr_t - GetWatchpointAddress(uint32_t hw_index); - - bool - IsWatchpointVacant(uint32_t hw_index); - - bool - SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read, bool write, uint32_t hw_index); - - uint32_t - NumSupportedHardwareWatchpoints(); - -private: - ProcessMonitor & - GetMonitor(); -}; - -#endif Index: source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.h =================================================================== --- /dev/null +++ source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.h @@ -1,104 +0,0 @@ -//===-- RegisterContextPOSIXProcessMonitor_powerpc.h -------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_RegisterContextPOSIXProcessMonitor_powerpc_H_ -#define liblldb_RegisterContextPOSIXProcessMonitor_powerpc_H_ - -#include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h" - -class RegisterContextPOSIXProcessMonitor_powerpc: - public RegisterContextPOSIX_powerpc, - public POSIXBreakpointProtocol -{ -public: - RegisterContextPOSIXProcessMonitor_powerpc(lldb_private::Thread &thread, - uint32_t concrete_frame_idx, - lldb_private::RegisterInfoInterface *register_info); - -protected: - bool - IsVMX(); - - bool - ReadGPR(); - - bool - ReadFPR(); - - bool - ReadVMX(); - - bool - WriteGPR(); - - bool - WriteFPR(); - - bool - WriteVMX(); - - // lldb_private::RegisterContext - bool - ReadRegister(const unsigned reg, lldb_private::RegisterValue &value); - - bool - WriteRegister(const unsigned reg, const lldb_private::RegisterValue &value); - - bool - ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value); - - bool - WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value); - - bool - ReadAllRegisterValues(lldb::DataBufferSP &data_sp); - - bool - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); - - uint32_t - SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write); - - bool - ClearHardwareWatchpoint(uint32_t hw_index); - - bool - HardwareSingleStep(bool enable); - - // POSIXBreakpointProtocol - bool - UpdateAfterBreakpoint(); - - unsigned - GetRegisterIndexFromOffset(unsigned offset); - - bool - IsWatchpointHit(uint32_t hw_index); - - bool - ClearWatchpointHits(); - - lldb::addr_t - GetWatchpointAddress(uint32_t hw_index); - - bool - IsWatchpointVacant(uint32_t hw_index); - - bool - SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read, bool write, uint32_t hw_index); - - uint32_t - NumSupportedHardwareWatchpoints(); - -private: - ProcessMonitor & - GetMonitor(); -}; - -#endif Index: source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp =================================================================== --- /dev/null +++ source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp @@ -1,337 +0,0 @@ -//===-- RegisterContextPOSIXProcessMonitor_powerpc.h ------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===---------------------------------------------------------------------===// - -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/RegisterValue.h" -#include "lldb/Target/Thread.h" - -#include "RegisterContextPOSIX_powerpc.h" -#include "ProcessPOSIX.h" -#include "RegisterContextPOSIXProcessMonitor_powerpc.h" -#include "ProcessMonitor.h" - -using namespace lldb_private; -using namespace lldb; - -#define REG_CONTEXT_SIZE (GetGPRSize()) - -RegisterContextPOSIXProcessMonitor_powerpc::RegisterContextPOSIXProcessMonitor_powerpc(Thread &thread, - uint32_t concrete_frame_idx, - lldb_private::RegisterInfoInterface *register_info) - : RegisterContextPOSIX_powerpc(thread, concrete_frame_idx, register_info) -{ -} - -ProcessMonitor & -RegisterContextPOSIXProcessMonitor_powerpc::GetMonitor() -{ - ProcessSP base = CalculateProcess(); - ProcessPOSIX *process = static_cast(base.get()); - return process->GetMonitor(); -} - -bool -RegisterContextPOSIXProcessMonitor_powerpc::ReadGPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadGPR(m_thread.GetID(), &m_gpr_powerpc, GetGPRSize()); -} - -bool -RegisterContextPOSIXProcessMonitor_powerpc::ReadFPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadFPR(m_thread.GetID(), &m_fpr_powerpc, sizeof(m_fpr_powerpc)); -} - -bool -RegisterContextPOSIXProcessMonitor_powerpc::ReadVMX() -{ - // XXX: Need a way to read/write process VMX registers with ptrace. - return false; -} - -bool -RegisterContextPOSIXProcessMonitor_powerpc::WriteGPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteGPR(m_thread.GetID(), &m_gpr_powerpc, GetGPRSize()); -} - -bool -RegisterContextPOSIXProcessMonitor_powerpc::WriteFPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteFPR(m_thread.GetID(), &m_fpr_powerpc, sizeof(m_fpr_powerpc)); -} - -bool -RegisterContextPOSIXProcessMonitor_powerpc::WriteVMX() -{ - // XXX: Need a way to read/write process VMX registers with ptrace. - return false; -} - -bool -RegisterContextPOSIXProcessMonitor_powerpc::ReadRegister(const unsigned reg, - RegisterValue &value) -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadRegisterValue(m_thread.GetID(), - GetRegisterOffset(reg), - GetRegisterName(reg), - GetRegisterSize(reg), - value); -} - -bool -RegisterContextPOSIXProcessMonitor_powerpc::WriteRegister(const unsigned reg, - const RegisterValue &value) -{ - unsigned reg_to_write = reg; - RegisterValue value_to_write = value; - - // Check if this is a subregister of a full register. - const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg); - if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) - { - RegisterValue full_value; - uint32_t full_reg = reg_info->invalidate_regs[0]; - const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg); - - // Read the full register. - if (ReadRegister(full_reg_info, full_value)) - { - Error error; - ByteOrder byte_order = GetByteOrder(); - uint8_t dst[RegisterValue::kMaxRegisterByteSize]; - - // Get the bytes for the full register. - const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info, - dst, - sizeof(dst), - byte_order, - error); - if (error.Success() && dest_size) - { - uint8_t src[RegisterValue::kMaxRegisterByteSize]; - - // Get the bytes for the source data. - const uint32_t src_size = value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error); - if (error.Success() && src_size && (src_size < dest_size)) - { - // Copy the src bytes to the destination. - memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size); - // Set this full register as the value to write. - value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order); - value_to_write.SetType(full_reg_info); - reg_to_write = full_reg; - } - } - } - } - - ProcessMonitor &monitor = GetMonitor(); - // Account for the fact that 32-bit targets on powerpc64 really use 64-bit - // registers in ptrace, but expose here 32-bit registers with a higher - // offset. - uint64_t offset = GetRegisterOffset(reg_to_write); - offset &= ~(sizeof(uintptr_t) - 1); - return monitor.WriteRegisterValue(m_thread.GetID(), - offset, - GetRegisterName(reg_to_write), - value_to_write); -} - -bool -RegisterContextPOSIXProcessMonitor_powerpc::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value) -{ - if (!reg_info) - return false; - - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - - if (IsFPR(reg)) - { - if (!ReadFPR()) - return false; - uint8_t *src = (uint8_t *)&m_fpr_powerpc + reg_info->byte_offset; - value.SetUInt64(*(uint64_t*)src); - } - else if (IsGPR(reg)) - { - bool success = ReadRegister(reg, value); - - if (success) - { - // If our return byte size was greater than the return value reg size, then - // use the type specified by reg_info rather than the uint64_t default - if (value.GetByteSize() > reg_info->byte_size) - value.SetType(reg_info); - } - return success; - } - - return false; -} - -bool -RegisterContextPOSIXProcessMonitor_powerpc::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value) -{ - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - - if (IsGPR(reg)) - { - return WriteRegister(reg, value); - } - else if (IsFPR(reg)) - { - assert (reg_info->byte_offset < sizeof(m_fpr_powerpc)); - uint8_t *dst = (uint8_t *)&m_fpr_powerpc + reg_info->byte_offset; - *(uint64_t *)dst = value.GetAsUInt64(); - return WriteFPR(); - } - - return false; -} - -bool -RegisterContextPOSIXProcessMonitor_powerpc::ReadAllRegisterValues(DataBufferSP &data_sp) -{ - bool success = false; - data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); - if (data_sp && ReadGPR () && ReadFPR ()) - { - uint8_t *dst = data_sp->GetBytes(); - success = dst != 0; - - if (success) - { - ::memcpy (dst, &m_gpr_powerpc, GetGPRSize()); - dst += GetGPRSize(); - } - } - return success; -} - -bool -RegisterContextPOSIXProcessMonitor_powerpc::WriteAllRegisterValues(const DataBufferSP &data_sp) -{ - bool success = false; - if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) - { - uint8_t *src = data_sp->GetBytes(); - if (src) - { - ::memcpy (&m_gpr_powerpc, src, GetGPRSize()); - - if (WriteGPR()) - { - src += GetGPRSize(); - ::memcpy (&m_fpr_powerpc, src, sizeof(m_fpr_powerpc)); - - success = WriteFPR(); - } - } - } - return success; -} - -uint32_t -RegisterContextPOSIXProcessMonitor_powerpc::SetHardwareWatchpoint(addr_t addr, size_t size, - bool read, bool write) -{ - const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); - uint32_t hw_index; - - for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index) - { - if (IsWatchpointVacant(hw_index)) - return SetHardwareWatchpointWithIndex(addr, size, - read, write, - hw_index); - } - - return LLDB_INVALID_INDEX32; -} - -bool -RegisterContextPOSIXProcessMonitor_powerpc::ClearHardwareWatchpoint(uint32_t hw_index) -{ - return false; -} - -bool -RegisterContextPOSIXProcessMonitor_powerpc::HardwareSingleStep(bool enable) -{ - return false; -} - -bool -RegisterContextPOSIXProcessMonitor_powerpc::UpdateAfterBreakpoint() -{ - lldb::addr_t pc; - - if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) - return false; - - return true; -} - -unsigned -RegisterContextPOSIXProcessMonitor_powerpc::GetRegisterIndexFromOffset(unsigned offset) -{ - unsigned reg; - for (reg = 0; reg < k_num_registers_powerpc; reg++) - { - if (GetRegisterInfo()[reg].byte_offset == offset) - break; - } - assert(reg < k_num_registers_powerpc && "Invalid register offset."); - return reg; -} - -bool -RegisterContextPOSIXProcessMonitor_powerpc::IsWatchpointHit(uint32_t hw_index) -{ - return false; -} - -bool -RegisterContextPOSIXProcessMonitor_powerpc::ClearWatchpointHits() -{ - return false; -} - -addr_t -RegisterContextPOSIXProcessMonitor_powerpc::GetWatchpointAddress(uint32_t hw_index) -{ - return LLDB_INVALID_ADDRESS; -} - -bool -RegisterContextPOSIXProcessMonitor_powerpc::IsWatchpointVacant(uint32_t hw_index) -{ - return false; -} - -bool -RegisterContextPOSIXProcessMonitor_powerpc::SetHardwareWatchpointWithIndex(addr_t addr, size_t size, - bool read, bool write, - uint32_t hw_index) -{ - return false; -} - -uint32_t -RegisterContextPOSIXProcessMonitor_powerpc::NumSupportedHardwareWatchpoints() -{ - return 0; -} - Index: source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.h =================================================================== --- /dev/null +++ source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.h @@ -1,95 +0,0 @@ -//===-- RegisterContextPOSIXProcessMonitor_x86.h ----------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_RegisterContextPOSIXProcessMonitor_x86_H_ -#define liblldb_RegisterContextPOSIXProcessMonitor_x86_H_ - -#include "Plugins/Process/Utility/RegisterContextPOSIX_x86.h" - -class RegisterContextPOSIXProcessMonitor_x86_64: - public RegisterContextPOSIX_x86, - public POSIXBreakpointProtocol -{ -public: - RegisterContextPOSIXProcessMonitor_x86_64(lldb_private::Thread &thread, - uint32_t concrete_frame_idx, - lldb_private::RegisterInfoInterface *register_info); - -protected: - bool - ReadGPR(); - - bool - ReadFPR(); - - bool - WriteGPR(); - - bool - WriteFPR(); - - // lldb_private::RegisterContext - bool - ReadRegister(const unsigned reg, lldb_private::RegisterValue &value); - - bool - WriteRegister(const unsigned reg, const lldb_private::RegisterValue &value); - - bool - ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value); - - bool - WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value); - - bool - ReadAllRegisterValues(lldb::DataBufferSP &data_sp); - - bool - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); - - uint32_t - SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write); - - bool - ClearHardwareWatchpoint(uint32_t hw_index); - - bool - HardwareSingleStep(bool enable); - - // POSIXBreakpointProtocol - bool - UpdateAfterBreakpoint(); - - unsigned - GetRegisterIndexFromOffset(unsigned offset); - - bool - IsWatchpointHit(uint32_t hw_index); - - bool - ClearWatchpointHits(); - - lldb::addr_t - GetWatchpointAddress(uint32_t hw_index); - - bool - IsWatchpointVacant(uint32_t hw_index); - - bool - SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read, bool write, uint32_t hw_index); - - uint32_t - NumSupportedHardwareWatchpoints(); - -private: - ProcessMonitor & - GetMonitor(); -}; - -#endif Index: test/functionalities/process_launch/TestProcessLaunch.py =================================================================== --- test/functionalities/process_launch/TestProcessLaunch.py +++ test/functionalities/process_launch/TestProcessLaunch.py @@ -128,7 +128,7 @@ @skipIfFreeBSD # llvm.org/pr16684 @expectedFailureDarwin("llvm.org/pr20265") - @expectedFailureLLGS("llvm.org/pr20265") + @expectedFailureLinux("llvm.org/pr20265") @dwarf_test def test_set_working_dir_with_dwarf (self): """Test that '-w dir' sets the working dir when running the inferior.""" Index: test/functionalities/thread/break_after_join/TestBreakAfterJoin.py =================================================================== --- test/functionalities/thread/break_after_join/TestBreakAfterJoin.py +++ test/functionalities/thread/break_after_join/TestBreakAfterJoin.py @@ -22,7 +22,7 @@ @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained @expectedFailureFreeBSD("llvm.org/pr18190") # thread states not properly maintained - @expectedFailureLLGS("llvm.org/pr15824") # thread states not properly maintained + @expectedFailureLinux("llvm.org/pr15824") # thread states not properly maintained @dwarf_test def test_with_dwarf(self): """Test breakpoint handling after a thread join.""" Index: test/functionalities/thread/create_during_step/TestCreateDuringStep.py =================================================================== --- test/functionalities/thread/create_during_step/TestCreateDuringStep.py +++ test/functionalities/thread/create_during_step/TestCreateDuringStep.py @@ -38,7 +38,7 @@ @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained @expectedFailureFreeBSD("llvm.org/pr18190") # thread states not properly maintained - @expectedFailureLLGS("llvm.org/pr15824") # thread states not properly maintained + @expectedFailureLinux("llvm.org/pr15824") # thread states not properly maintained @dwarf_test def test_step_inst_with_dwarf(self): """Test thread creation during step-inst handling.""" @@ -47,7 +47,7 @@ @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained @expectedFailureFreeBSD("llvm.org/pr18190") # thread states not properly maintained - @expectedFailureLLGS("llvm.org/pr15824") # thread states not properly maintained + @expectedFailureLinux("llvm.org/pr15824") # thread states not properly maintained @dwarf_test def test_step_over_with_dwarf(self): """Test thread creation during step-over handling.""" @@ -56,7 +56,7 @@ @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained @expectedFailureFreeBSD("llvm.org/pr18190") # thread states not properly maintained - @expectedFailureLLGS("llvm.org/pr15824") # thread states not properly maintained + @expectedFailureLinux("llvm.org/pr15824") # thread states not properly maintained @dwarf_test def test_step_in_with_dwarf(self): """Test thread creation during step-in handling.""" Index: test/functionalities/thread/exit_during_break/TestExitDuringBreak.py =================================================================== --- test/functionalities/thread/exit_during_break/TestExitDuringBreak.py +++ test/functionalities/thread/exit_during_break/TestExitDuringBreak.py @@ -22,7 +22,7 @@ @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained @expectedFailureFreeBSD("llvm.org/pr18190") # thread states not properly maintained - @expectedFailureLLGS("llvm.org/pr15824") # thread states not properly maintained + @expectedFailureLinux("llvm.org/pr15824") # thread states not properly maintained @dwarf_test def test_with_dwarf(self): """Test thread exit during breakpoint handling.""" Index: test/functionalities/thread/exit_during_step/TestExitDuringStep.py =================================================================== --- test/functionalities/thread/exit_during_step/TestExitDuringStep.py +++ test/functionalities/thread/exit_during_step/TestExitDuringStep.py @@ -22,7 +22,7 @@ @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained @expectedFailureFreeBSD("llvm.org/pr18190") # thread states not properly maintained - @expectedFailureLLGS("llvm.org/pr15824") # thread states not properly maintained + @expectedFailureLinux("llvm.org/pr15824") # thread states not properly maintained @dwarf_test def test_thread_state_is_stopped_with_dwarf(self): """Test thread exit during step handling.""" @@ -58,7 +58,7 @@ self.exit_during_step_inst_test() @skipIfFreeBSD # llvm.org/pr21411: test is hanging - @expectedFailureLLGS("llvm.org/pr15824") # thread states not properly maintained + @expectedFailureLinux("llvm.org/pr15824") # thread states not properly maintained @dwarf_test def test_step_over_with_dwarf(self): """Test thread exit during step-over handling.""" @@ -66,7 +66,7 @@ self.exit_during_step_over_test() @skipIfFreeBSD # llvm.org/pr21411: test is hanging - @expectedFailureLLGS("llvm.org/pr15824") # thread states not properly maintained + @expectedFailureLinux("llvm.org/pr15824") # thread states not properly maintained @dwarf_test def test_step_in_with_dwarf(self): """Test thread exit during step-in handling.""" Index: test/functionalities/thread/multi_break/TestMultipleBreakpoints.py =================================================================== --- test/functionalities/thread/multi_break/TestMultipleBreakpoints.py +++ test/functionalities/thread/multi_break/TestMultipleBreakpoints.py @@ -22,7 +22,7 @@ @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained @expectedFailureFreeBSD("llvm.org/pr18190") # thread states not properly maintained - @expectedFailureLLGS("llvm.org/pr15824") # thread states not properly maintained + @expectedFailureLinux("llvm.org/pr15824") # thread states not properly maintained @dwarf_test def test_with_dwarf(self): """Test simultaneous breakpoints in multiple threads.""" Index: test/functionalities/thread/state/TestThreadStates.py =================================================================== --- test/functionalities/thread/state/TestThreadStates.py +++ test/functionalities/thread/state/TestThreadStates.py @@ -22,7 +22,7 @@ @expectedFailureDarwin("rdar://15367566") @expectedFailureFreeBSD('llvm.org/pr15824') - @expectedFailureLLGS("llvm.org/pr15824") # thread states not properly maintained + @expectedFailureLinux("llvm.org/pr15824") # thread states not properly maintained @dwarf_test def test_state_after_breakpoint_with_dwarf(self): """Test thread state after breakpoint.""" Index: test/lldbtest.py =================================================================== --- test/lldbtest.py +++ test/lldbtest.py @@ -712,15 +712,6 @@ return expectedFailure(fn, bugnumber) -def expectedFailureLLGS(bugnumber=None, compilers=None): - def fn(self): - # llgs local is only an option on Linux targets - if self.getPlatform() != 'linux': - return False - self.runCmd('settings show platform.plugin.linux.use-llgs-for-local') - return 'true' in self.res.GetOutput() and self.expectedCompiler(compilers) - return expectedFailure(fn, bugnumber) - def skipIfRemote(func): """Decorate the item to skip tests if testing remotely.""" if isinstance(func, type) and issubclass(func, unittest2.TestCase):