diff --git a/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h b/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h --- a/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h +++ b/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h @@ -44,9 +44,6 @@ bool CanDebugProcess() override; - size_t GetSoftwareBreakpointTrapOpcode(Target &target, - BreakpointSite *bp_site) override; - void CalculateTrapHandlerSymbolNames() override; MmapArgList GetMmapArgumentList(const ArchSpec &arch, lldb::addr_t addr, diff --git a/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp b/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp --- a/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp +++ b/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp @@ -214,58 +214,9 @@ #endif } -size_t -PlatformFreeBSD::GetSoftwareBreakpointTrapOpcode(Target &target, - BreakpointSite *bp_site) { - switch (target.GetArchitecture().GetMachine()) { - case llvm::Triple::arm: { - lldb::BreakpointLocationSP bp_loc_sp(bp_site->GetOwnerAtIndex(0)); - AddressClass addr_class = AddressClass::eUnknown; - - if (bp_loc_sp) { - addr_class = bp_loc_sp->GetAddress().GetAddressClass(); - if (addr_class == AddressClass::eUnknown && - (bp_loc_sp->GetAddress().GetFileAddress() & 1)) - addr_class = AddressClass::eCodeAlternateISA; - } - - if (addr_class == AddressClass::eCodeAlternateISA) { - // TODO: Enable when FreeBSD supports thumb breakpoints. - // FreeBSD kernel as of 10.x, does not support thumb breakpoints - return 0; - } - - static const uint8_t g_arm_breakpoint_opcode[] = {0xFE, 0xDE, 0xFF, 0xE7}; - size_t trap_opcode_size = sizeof(g_arm_breakpoint_opcode); - assert(bp_site); - if (bp_site->SetTrapOpcode(g_arm_breakpoint_opcode, trap_opcode_size)) - return trap_opcode_size; - } - LLVM_FALLTHROUGH; - default: - return Platform::GetSoftwareBreakpointTrapOpcode(target, bp_site); - } -} - bool PlatformFreeBSD::CanDebugProcess() { if (IsHost()) { - llvm::Triple host_triple{llvm::sys::getProcessTriple()}; - bool use_legacy_plugin; - - switch (host_triple.getArch()) { - case llvm::Triple::aarch64: - case llvm::Triple::arm: - case llvm::Triple::mips64: - case llvm::Triple::ppc: - case llvm::Triple::x86: - case llvm::Triple::x86_64: - use_legacy_plugin = !!getenv("FREEBSD_LEGACY_PLUGIN"); - break; - default: - use_legacy_plugin = true; - } - - return !use_legacy_plugin; + return true; } else { // If we're connected, we can debug. return IsConnected(); diff --git a/lldb/source/Plugins/Process/CMakeLists.txt b/lldb/source/Plugins/Process/CMakeLists.txt --- a/lldb/source/Plugins/Process/CMakeLists.txt +++ b/lldb/source/Plugins/Process/CMakeLists.txt @@ -3,7 +3,6 @@ add_subdirectory(POSIX) elseif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") add_subdirectory(FreeBSDRemote) - add_subdirectory(FreeBSD) add_subdirectory(POSIX) elseif (CMAKE_SYSTEM_NAME MATCHES "NetBSD") add_subdirectory(NetBSD) diff --git a/lldb/source/Plugins/Process/FreeBSD/CMakeLists.txt b/lldb/source/Plugins/Process/FreeBSD/CMakeLists.txt deleted file mode 100644 --- a/lldb/source/Plugins/Process/FreeBSD/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ -add_lldb_library(lldbPluginProcessFreeBSD PLUGIN - ProcessFreeBSD.cpp - FreeBSDThread.cpp - ProcessMonitor.cpp - - POSIXStopInfo.cpp - RegisterContextPOSIXProcessMonitor_arm.cpp - RegisterContextPOSIXProcessMonitor_arm64.cpp - RegisterContextPOSIXProcessMonitor_powerpc.cpp - RegisterContextPOSIXProcessMonitor_x86.cpp - RegisterContextPOSIXProcessMonitor_mips64.cpp - - LINK_LIBS - lldbBreakpoint - lldbCore - lldbHost - lldbSymbol - lldbTarget - lldbUtility - lldbPluginProcessUtility - lldbPluginProcessPOSIX - LINK_COMPONENTS - Support - ) diff --git a/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.h b/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.h deleted file mode 100644 --- a/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.h +++ /dev/null @@ -1,111 +0,0 @@ -//===-- FreeBSDThread.h -----------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_FreeBSDThread_H_ -#define liblldb_FreeBSDThread_H_ - -#include -#include - -#include "RegisterContextPOSIX.h" -#include "lldb/Target/Thread.h" - -class ProcessMessage; -class ProcessMonitor; -class POSIXBreakpointProtocol; - -// @class FreeBSDThread -// Abstraction of a FreeBSD thread. -class FreeBSDThread : public lldb_private::Thread { -public: - // Constructors and destructors - FreeBSDThread(lldb_private::Process &process, lldb::tid_t tid); - - virtual ~FreeBSDThread(); - - // POSIXThread - void RefreshStateAfterStop() override; - - // This notifies the thread when a private stop occurs. - void DidStop() override; - - const char *GetInfo() override; - - void SetName(const char *name) override; - - const char *GetName() override; - - lldb::RegisterContextSP GetRegisterContext() override; - - lldb::RegisterContextSP - CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override; - - lldb::addr_t GetThreadPointer() override; - - // These functions provide a mapping from the register offset - // back to the register index or name for use in debugging or log - // output. - - unsigned GetRegisterIndexFromOffset(unsigned offset); - - const char *GetRegisterName(unsigned reg); - - const char *GetRegisterNameFromOffset(unsigned offset); - - // These methods form a specialized interface to POSIX threads. - // - bool Resume(); - - void Notify(const ProcessMessage &message); - - // These methods provide an interface to watchpoints - // - bool EnableHardwareWatchpoint(lldb_private::Watchpoint *wp); - - bool DisableHardwareWatchpoint(lldb_private::Watchpoint *wp); - - uint32_t NumSupportedHardwareWatchpoints(); - - uint32_t FindVacantWatchpointIndex(); - -protected: - POSIXBreakpointProtocol *GetPOSIXBreakpointProtocol() { - if (!m_reg_context_sp) - m_reg_context_sp = GetRegisterContext(); - return m_posix_thread; - } - - std::unique_ptr m_frame_up; - - lldb::BreakpointSiteSP m_breakpoint; - - bool m_thread_name_valid; - std::string m_thread_name; - POSIXBreakpointProtocol *m_posix_thread; - - ProcessMonitor &GetMonitor(); - - bool CalculateStopInfo() override; - - void BreakNotify(const ProcessMessage &message); - void WatchNotify(const ProcessMessage &message); - virtual void TraceNotify(const ProcessMessage &message); - void LimboNotify(const ProcessMessage &message); - void SignalNotify(const ProcessMessage &message); - void SignalDeliveredNotify(const ProcessMessage &message); - void CrashNotify(const ProcessMessage &message); - void ExitNotify(const ProcessMessage &message); - void ExecNotify(const ProcessMessage &message); - - // FreeBSDThread internal API. - - // POSIXThread override - virtual void WillResume(lldb::StateType resume_state) override; -}; - -#endif // #ifndef liblldb_FreeBSDThread_H_ diff --git a/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp b/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp deleted file mode 100644 --- a/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp +++ /dev/null @@ -1,616 +0,0 @@ -//===-- FreeBSDThread.cpp -------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include -#include -#include -#include -#include -#include -#include - -#include "FreeBSDThread.h" -#include "POSIXStopInfo.h" -#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" -#include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h" -#include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h" -#include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h" -#include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h" -#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h" -#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h" -#include "ProcessFreeBSD.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 "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Breakpoint/Watchpoint.h" -#include "lldb/Core/Debugger.h" -#include "lldb/Host/Host.h" -#include "lldb/Host/HostInfo.h" -#include "lldb/Host/HostNativeThread.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/StopInfo.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/ThreadSpec.h" -#include "lldb/Target/UnixSignals.h" -#include "lldb/Target/Unwind.h" -#include "lldb/Utility/State.h" -#include "llvm/ADT/SmallString.h" - -using namespace lldb; -using namespace lldb_private; - -FreeBSDThread::FreeBSDThread(Process &process, lldb::tid_t tid) - : Thread(process, tid), m_frame_up(), m_breakpoint(), - m_thread_name_valid(false), m_thread_name(), m_posix_thread(nullptr) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); - LLDB_LOGV(log, "tid = {0}", tid); - - // Set the current watchpoints for this thread. - Target &target = GetProcess()->GetTarget(); - const WatchpointList &wp_list = target.GetWatchpointList(); - size_t wp_size = wp_list.GetSize(); - - for (uint32_t wp_idx = 0; wp_idx < wp_size; wp_idx++) { - lldb::WatchpointSP wp = wp_list.GetByIndex(wp_idx); - if (wp.get() && wp->IsEnabled()) { - // This watchpoint as been enabled; obviously this "new" thread has been - // created since that watchpoint was enabled. Since the - // POSIXBreakpointProtocol has yet to be initialized, its - // m_watchpoints_initialized member will be FALSE. Attempting to read - // the debug status register to determine if a watchpoint has been hit - // would result in the zeroing of that register. Since the active debug - // registers would have been cloned when this thread was created, simply - // force the m_watchpoints_initized member to TRUE and avoid resetting - // dr6 and dr7. - GetPOSIXBreakpointProtocol()->ForceWatchpointsInitialized(); - } - } -} - -FreeBSDThread::~FreeBSDThread() { DestroyThread(); } - -ProcessMonitor &FreeBSDThread::GetMonitor() { - ProcessSP base = GetProcess(); - ProcessFreeBSD &process = static_cast(*base); - return process.GetMonitor(); -} - -void FreeBSDThread::RefreshStateAfterStop() { - // Invalidate all registers in our register context. We don't set "force" to - // true because the stop reply packet might have had some register values - // that were expedited and these will already be copied into the register - // context by the time this function gets called. The KDPRegisterContext - // class has been made smart enough to detect when it needs to invalidate - // which registers are valid by putting hooks in the register read and - // register supply functions where they check the process stop ID and do the - // right thing. if (StateIsStoppedState(GetState()) - { - const bool force = false; - GetRegisterContext()->InvalidateIfNeeded(force); - } -} - -const char *FreeBSDThread::GetInfo() { return nullptr; } - -void FreeBSDThread::SetName(const char *name) { - m_thread_name_valid = (name && name[0]); - if (m_thread_name_valid) - m_thread_name.assign(name); - else - m_thread_name.clear(); -} - -const char *FreeBSDThread::GetName() { - if (!m_thread_name_valid) { - m_thread_name.clear(); - int pid = GetProcess()->GetID(); - - struct kinfo_proc *kp = nullptr, *nkp; - size_t len = 0; - int error; - int ctl[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID | KERN_PROC_INC_THREAD, - pid}; - - while (1) { - error = sysctl(ctl, 4, kp, &len, nullptr, 0); - if (kp == nullptr || (error != 0 && errno == ENOMEM)) { - // Add extra space in case threads are added before next call. - len += sizeof(*kp) + len / 10; - nkp = (struct kinfo_proc *)realloc(kp, len); - if (nkp == nullptr) { - free(kp); - return nullptr; - } - kp = nkp; - continue; - } - if (error != 0) - len = 0; - break; - } - - for (size_t i = 0; i < len / sizeof(*kp); i++) { - if (kp[i].ki_tid == (lwpid_t)GetID()) { - m_thread_name.append(kp[i].ki_tdname, - kp[i].ki_tdname + strlen(kp[i].ki_tdname)); - break; - } - } - free(kp); - m_thread_name_valid = true; - } - - if (m_thread_name.empty()) - return nullptr; - return m_thread_name.c_str(); -} - -lldb::RegisterContextSP FreeBSDThread::GetRegisterContext() { - if (!m_reg_context_sp) { - m_posix_thread = nullptr; - - RegisterInfoInterface *reg_interface = nullptr; - const ArchSpec &target_arch = GetProcess()->GetTarget().GetArchitecture(); - - assert(target_arch.GetTriple().getOS() == llvm::Triple::FreeBSD); - switch (target_arch.GetMachine()) { - case llvm::Triple::aarch64: - case llvm::Triple::arm: - break; - case llvm::Triple::ppc: -#ifndef __powerpc64__ - reg_interface = new RegisterContextFreeBSD_powerpc32(target_arch); - break; -#endif - case llvm::Triple::ppc64: - reg_interface = new RegisterContextFreeBSD_powerpc64(target_arch); - break; - case llvm::Triple::mips64: - reg_interface = new RegisterContextFreeBSD_mips64(target_arch); - break; - case llvm::Triple::x86: - reg_interface = new RegisterContextFreeBSD_i386(target_arch); - break; - case llvm::Triple::x86_64: - reg_interface = new RegisterContextFreeBSD_x86_64(target_arch); - break; - default: - llvm_unreachable("CPU not supported"); - } - - switch (target_arch.GetMachine()) { - case llvm::Triple::aarch64: { - RegisterContextPOSIXProcessMonitor_arm64 *reg_ctx = - new RegisterContextPOSIXProcessMonitor_arm64( - *this, std::make_unique(target_arch)); - m_posix_thread = reg_ctx; - m_reg_context_sp.reset(reg_ctx); - break; - } - case llvm::Triple::arm: { - RegisterContextPOSIXProcessMonitor_arm *reg_ctx = - new RegisterContextPOSIXProcessMonitor_arm( - *this, std::make_unique(target_arch)); - m_posix_thread = reg_ctx; - m_reg_context_sp.reset(reg_ctx); - break; - } - case llvm::Triple::mips64: { - RegisterContextPOSIXProcessMonitor_mips64 *reg_ctx = - new RegisterContextPOSIXProcessMonitor_mips64(*this, 0, - reg_interface); - m_posix_thread = reg_ctx; - m_reg_context_sp.reset(reg_ctx); - break; - } - case llvm::Triple::ppc: - case llvm::Triple::ppc64: { - RegisterContextPOSIXProcessMonitor_powerpc *reg_ctx = - new RegisterContextPOSIXProcessMonitor_powerpc(*this, 0, - reg_interface); - m_posix_thread = reg_ctx; - m_reg_context_sp.reset(reg_ctx); - break; - } - case llvm::Triple::x86: - case llvm::Triple::x86_64: { - RegisterContextPOSIXProcessMonitor_x86_64 *reg_ctx = - new RegisterContextPOSIXProcessMonitor_x86_64(*this, 0, - reg_interface); - m_posix_thread = reg_ctx; - m_reg_context_sp.reset(reg_ctx); - break; - } - default: - break; - } - } - return m_reg_context_sp; -} - -lldb::RegisterContextSP -FreeBSDThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame) { - lldb::RegisterContextSP reg_ctx_sp; - uint32_t concrete_frame_idx = 0; - - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); - LLDB_LOGV(log, "called"); - - if (frame) - concrete_frame_idx = frame->GetConcreteFrameIndex(); - - if (concrete_frame_idx == 0) - reg_ctx_sp = GetRegisterContext(); - else { - reg_ctx_sp = GetUnwinder().CreateRegisterContextForFrame(frame); - } - - return reg_ctx_sp; -} - -lldb::addr_t FreeBSDThread::GetThreadPointer() { - ProcessMonitor &monitor = GetMonitor(); - addr_t addr; - if (monitor.ReadThreadPointer(GetID(), addr)) - return addr; - else - return LLDB_INVALID_ADDRESS; -} - -bool FreeBSDThread::CalculateStopInfo() { - SetStopInfo(m_stop_info_sp); - return true; -} - -void FreeBSDThread::DidStop() { - // Don't set the thread state to stopped unless we really stopped. -} - -void FreeBSDThread::WillResume(lldb::StateType resume_state) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); - LLDB_LOGF(log, "tid %lu resume_state = %s", GetID(), - lldb_private::StateAsCString(resume_state)); - ProcessSP process_sp(GetProcess()); - ProcessFreeBSD *process = static_cast(process_sp.get()); - int signo = GetResumeSignal(); - bool signo_valid = process->GetUnixSignals()->SignalIsValid(signo); - - switch (resume_state) { - case eStateSuspended: - case eStateStopped: - process->m_suspend_tids.push_back(GetID()); - break; - case eStateRunning: - process->m_run_tids.push_back(GetID()); - if (signo_valid) - process->m_resume_signo = signo; - break; - case eStateStepping: - process->m_step_tids.push_back(GetID()); - if (signo_valid) - process->m_resume_signo = signo; - break; - default: - break; - } -} - -bool FreeBSDThread::Resume() { - lldb::StateType resume_state = GetResumeState(); - ProcessMonitor &monitor = GetMonitor(); - bool status; - - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); - LLDB_LOGF(log, "FreeBSDThread::%s (), resume_state = %s", __FUNCTION__, - StateAsCString(resume_state)); - - switch (resume_state) { - default: - assert(false && "Unexpected state for resume!"); - status = false; - break; - - case lldb::eStateRunning: - SetState(resume_state); - status = monitor.Resume(GetID(), GetResumeSignal()); - break; - - case lldb::eStateStepping: - SetState(resume_state); - status = monitor.SingleStep(GetID(), GetResumeSignal()); - break; - case lldb::eStateStopped: - case lldb::eStateSuspended: - status = true; - break; - } - - return status; -} - -void FreeBSDThread::Notify(const ProcessMessage &message) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); - LLDB_LOGF(log, "FreeBSDThread::%s () message kind = '%s' for tid %" PRIu64, - __FUNCTION__, message.PrintKind(), GetID()); - - switch (message.GetKind()) { - default: - assert(false && "Unexpected message kind!"); - break; - - case ProcessMessage::eExitMessage: - // Nothing to be done. - break; - - case ProcessMessage::eLimboMessage: - LimboNotify(message); - break; - - case ProcessMessage::eCrashMessage: - case ProcessMessage::eSignalMessage: - SignalNotify(message); - break; - - case ProcessMessage::eSignalDeliveredMessage: - SignalDeliveredNotify(message); - break; - - case ProcessMessage::eTraceMessage: - TraceNotify(message); - break; - - case ProcessMessage::eBreakpointMessage: - BreakNotify(message); - break; - - case ProcessMessage::eWatchpointMessage: - WatchNotify(message); - break; - - case ProcessMessage::eExecMessage: - ExecNotify(message); - break; - } -} - -bool FreeBSDThread::EnableHardwareWatchpoint(Watchpoint *wp) { - bool wp_set = false; - if (wp) { - addr_t wp_addr = wp->GetLoadAddress(); - size_t wp_size = wp->GetByteSize(); - bool wp_read = wp->WatchpointRead(); - bool wp_write = wp->WatchpointWrite(); - uint32_t wp_hw_index = wp->GetHardwareIndex(); - POSIXBreakpointProtocol *reg_ctx = GetPOSIXBreakpointProtocol(); - if (reg_ctx) - wp_set = reg_ctx->SetHardwareWatchpointWithIndex( - wp_addr, wp_size, wp_read, wp_write, wp_hw_index); - } - return wp_set; -} - -bool FreeBSDThread::DisableHardwareWatchpoint(Watchpoint *wp) { - bool result = false; - if (wp) { - lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext(); - if (reg_ctx_sp.get()) - result = reg_ctx_sp->ClearHardwareWatchpoint(wp->GetHardwareIndex()); - } - return result; -} - -uint32_t FreeBSDThread::NumSupportedHardwareWatchpoints() { - lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext(); - if (reg_ctx_sp.get()) - return reg_ctx_sp->NumSupportedHardwareWatchpoints(); - return 0; -} - -uint32_t FreeBSDThread::FindVacantWatchpointIndex() { - uint32_t hw_index = LLDB_INVALID_INDEX32; - uint32_t num_hw_wps = NumSupportedHardwareWatchpoints(); - uint32_t wp_idx; - POSIXBreakpointProtocol *reg_ctx = GetPOSIXBreakpointProtocol(); - if (reg_ctx) { - for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++) { - if (reg_ctx->IsWatchpointVacant(wp_idx)) { - hw_index = wp_idx; - break; - } - } - } - return hw_index; -} - -void FreeBSDThread::BreakNotify(const ProcessMessage &message) { - bool status; - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); - - assert(GetRegisterContext()); - status = GetPOSIXBreakpointProtocol()->UpdateAfterBreakpoint(); - assert(status && "Breakpoint update failed!"); - - // With our register state restored, resolve the breakpoint object - // corresponding to our current PC. - assert(GetRegisterContext()); - lldb::addr_t pc = GetRegisterContext()->GetPC(); - LLDB_LOGF(log, "FreeBSDThread::%s () PC=0x%8.8" PRIx64, __FUNCTION__, pc); - lldb::BreakpointSiteSP bp_site( - GetProcess()->GetBreakpointSiteList().FindByAddress(pc)); - - // If the breakpoint is for this thread, then we'll report the hit, but if it - // is for another thread, we create a stop reason with should_stop=false. If - // there is no breakpoint location, then report an invalid stop reason. We - // don't need to worry about stepping over the breakpoint here, that will be - // taken care of when the thread resumes and notices that there's a - // breakpoint under the pc. - if (bp_site) { - lldb::break_id_t bp_id = bp_site->GetID(); - // If we have an operating system plug-in, we might have set a thread - // specific breakpoint using the operating system thread ID, so we can't - // make any assumptions about the thread ID so we must always report the - // breakpoint regardless of the thread. - if (bp_site->ValidForThisThread(this) || - GetProcess()->GetOperatingSystem() != nullptr) - SetStopInfo(StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id)); - else { - const bool should_stop = false; - SetStopInfo(StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id, - should_stop)); - } - } else - SetStopInfo(StopInfoSP()); -} - -void FreeBSDThread::WatchNotify(const ProcessMessage &message) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); - - lldb::addr_t halt_addr = message.GetHWAddress(); - LLDB_LOGF(log, - "FreeBSDThread::%s () Hardware Watchpoint Address = 0x%8.8" PRIx64, - __FUNCTION__, halt_addr); - - POSIXBreakpointProtocol *reg_ctx = GetPOSIXBreakpointProtocol(); - if (reg_ctx) { - uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints(); - uint32_t wp_idx; - for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++) { - if (reg_ctx->IsWatchpointHit(wp_idx)) { - // Clear the watchpoint hit here - reg_ctx->ClearWatchpointHits(); - break; - } - } - - if (wp_idx == num_hw_wps) - return; - - Target &target = GetProcess()->GetTarget(); - lldb::addr_t wp_monitor_addr = reg_ctx->GetWatchpointAddress(wp_idx); - const WatchpointList &wp_list = target.GetWatchpointList(); - lldb::WatchpointSP wp_sp = wp_list.FindByAddress(wp_monitor_addr); - - assert(wp_sp.get() && "No watchpoint found"); - SetStopInfo( - StopInfo::CreateStopReasonWithWatchpointID(*this, wp_sp->GetID())); - } -} - -void FreeBSDThread::TraceNotify(const ProcessMessage &message) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); - - // Try to resolve the breakpoint object corresponding to the current PC. - assert(GetRegisterContext()); - lldb::addr_t pc = GetRegisterContext()->GetPC(); - LLDB_LOGF(log, "FreeBSDThread::%s () PC=0x%8.8" PRIx64, __FUNCTION__, pc); - lldb::BreakpointSiteSP bp_site( - GetProcess()->GetBreakpointSiteList().FindByAddress(pc)); - - // If the current pc is a breakpoint site then set the StopInfo to - // Breakpoint. Otherwise, set the StopInfo to Watchpoint or Trace. If we have - // an operating system plug-in, we might have set a thread specific - // breakpoint using the operating system thread ID, so we can't make any - // assumptions about the thread ID so we must always report the breakpoint - // regardless of the thread. - if (bp_site && (bp_site->ValidForThisThread(this) || - GetProcess()->GetOperatingSystem() != nullptr)) - SetStopInfo(StopInfo::CreateStopReasonWithBreakpointSiteID( - *this, bp_site->GetID())); - else { - POSIXBreakpointProtocol *reg_ctx = GetPOSIXBreakpointProtocol(); - if (reg_ctx) { - uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints(); - uint32_t wp_idx; - for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++) { - if (reg_ctx->IsWatchpointHit(wp_idx)) { - WatchNotify(message); - return; - } - } - } - SetStopInfo(StopInfo::CreateStopReasonToTrace(*this)); - } -} - -void FreeBSDThread::LimboNotify(const ProcessMessage &message) { - SetStopInfo(lldb::StopInfoSP(new POSIXLimboStopInfo(*this))); -} - -void FreeBSDThread::SignalNotify(const ProcessMessage &message) { - int signo = message.GetSignal(); - if (message.GetKind() == ProcessMessage::eCrashMessage) { - std::string stop_description = GetCrashReasonString( - message.GetCrashReason(), message.GetFaultAddress()); - SetStopInfo(StopInfo::CreateStopReasonWithSignal( - *this, signo, stop_description.c_str())); - } else { - SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, signo)); - } -} - -void FreeBSDThread::SignalDeliveredNotify(const ProcessMessage &message) { - int signo = message.GetSignal(); - SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, signo)); -} - -unsigned FreeBSDThread::GetRegisterIndexFromOffset(unsigned offset) { - unsigned reg = LLDB_INVALID_REGNUM; - ArchSpec arch = HostInfo::GetArchitecture(); - - switch (arch.GetMachine()) { - default: - llvm_unreachable("CPU type not supported!"); - break; - - case llvm::Triple::aarch64: - case llvm::Triple::arm: - case llvm::Triple::mips64: - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - case llvm::Triple::x86: - case llvm::Triple::x86_64: { - POSIXBreakpointProtocol *reg_ctx = GetPOSIXBreakpointProtocol(); - reg = reg_ctx->GetRegisterIndexFromOffset(offset); - } break; - } - return reg; -} - -void FreeBSDThread::ExecNotify(const ProcessMessage &message) { - SetStopInfo(StopInfo::CreateStopReasonWithExec(*this)); -} - -const char *FreeBSDThread::GetRegisterName(unsigned reg) { - const char *name = nullptr; - ArchSpec arch = HostInfo::GetArchitecture(); - - switch (arch.GetMachine()) { - default: - assert(false && "CPU type not supported!"); - break; - - case llvm::Triple::aarch64: - case llvm::Triple::arm: - case llvm::Triple::mips64: - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - case llvm::Triple::x86: - case llvm::Triple::x86_64: - name = GetRegisterContext()->GetRegisterName(reg); - break; - } - return name; -} - -const char *FreeBSDThread::GetRegisterNameFromOffset(unsigned offset) { - return GetRegisterName(GetRegisterIndexFromOffset(offset)); -} diff --git a/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.h b/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.h deleted file mode 100644 --- a/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.h +++ /dev/null @@ -1,66 +0,0 @@ -//===-- POSIXStopInfo.h -----------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_POSIXStopInfo_H_ -#define liblldb_POSIXStopInfo_H_ - -#include "FreeBSDThread.h" -#include "Plugins/Process/POSIX/CrashReason.h" -#include "lldb/Target/StopInfo.h" -#include - -//===----------------------------------------------------------------------===// -/// \class POSIXStopInfo -/// 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 -/// Represents the stop state of a process ready to exit. -/// -class POSIXLimboStopInfo : public POSIXStopInfo { -public: - POSIXLimboStopInfo(FreeBSDThread &thread) : POSIXStopInfo(thread, 0) {} - - ~POSIXLimboStopInfo(); - - lldb::StopReason GetStopReason() const override; - - const char *GetDescription() override; - - bool ShouldStop(lldb_private::Event *event_ptr) override; - - bool ShouldNotify(lldb_private::Event *event_ptr) override; -}; - -//===----------------------------------------------------------------------===// -/// \class POSIXNewThreadStopInfo -/// Represents the stop state of process when a new thread is spawned. -/// - -class POSIXNewThreadStopInfo : public POSIXStopInfo { -public: - POSIXNewThreadStopInfo(FreeBSDThread &thread) : POSIXStopInfo(thread, 0) {} - - ~POSIXNewThreadStopInfo(); - - lldb::StopReason GetStopReason() const override; - - const char *GetDescription() override; - - bool ShouldStop(lldb_private::Event *event_ptr) override; - - bool ShouldNotify(lldb_private::Event *event_ptr) override; -}; - -#endif diff --git a/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp b/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp deleted file mode 100644 --- a/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp +++ /dev/null @@ -1,44 +0,0 @@ -//===-- POSIXStopInfo.cpp -------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#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; } - -//===----------------------------------------------------------------------===// -// 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; } diff --git a/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h b/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h deleted file mode 100644 --- a/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h +++ /dev/null @@ -1,221 +0,0 @@ -//===-- ProcessFreeBSD.h ------------------------------------------*- C++ -//-*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_ProcessFreeBSD_H_ -#define liblldb_ProcessFreeBSD_H_ - -#include "Plugins/Process/POSIX/ProcessMessage.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/ThreadList.h" -#include -#include -#include - -class ProcessMonitor; -class FreeBSDThread; - -class ProcessFreeBSD : public lldb_private::Process { - -public: - // Static functions. - static lldb::ProcessSP - CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, - const lldb_private::FileSpec *crash_file_path, - bool can_connect); - - static void Initialize(); - - static void Terminate(); - - static lldb_private::ConstString GetPluginNameStatic(); - - static const char *GetPluginDescriptionStatic(); - - // Constructors and destructors - ProcessFreeBSD(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, - lldb::UnixSignalsSP &unix_signals_sp); - - ~ProcessFreeBSD(); - - virtual lldb_private::Status WillResume() override; - - // PluginInterface protocol - virtual lldb_private::ConstString GetPluginName() override; - - virtual uint32_t GetPluginVersion() override; - -public: - // Process protocol. - void Finalize() override; - - bool CanDebug(lldb::TargetSP target_sp, - bool plugin_specified_by_name) override; - - lldb_private::Status WillLaunch(lldb_private::Module *module) override; - - lldb_private::Status DoAttachToProcessWithID( - lldb::pid_t pid, - const lldb_private::ProcessAttachInfo &attach_info) override; - - lldb_private::Status - DoLaunch(lldb_private::Module *exe_module, - lldb_private::ProcessLaunchInfo &launch_info) override; - - void DidLaunch() override; - - lldb_private::Status DoResume() override; - - lldb_private::Status DoHalt(bool &caused_stop) override; - - lldb_private::Status DoDetach(bool keep_stopped) override; - - lldb_private::Status DoSignal(int signal) override; - - lldb_private::Status 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::Status &error) override; - - size_t DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, - lldb_private::Status &error) override; - - lldb::addr_t DoAllocateMemory(size_t size, uint32_t permissions, - lldb_private::Status &error) override; - - lldb_private::Status DoDeallocateMemory(lldb::addr_t ptr) override; - - virtual size_t - GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite *bp_site); - - lldb_private::Status - EnableBreakpointSite(lldb_private::BreakpointSite *bp_site) override; - - lldb_private::Status - DisableBreakpointSite(lldb_private::BreakpointSite *bp_site) override; - - lldb_private::Status EnableWatchpoint(lldb_private::Watchpoint *wp, - bool notify = true) override; - - lldb_private::Status DisableWatchpoint(lldb_private::Watchpoint *wp, - bool notify = true) override; - - lldb_private::Status GetWatchpointSupportInfo(uint32_t &num) override; - - lldb_private::Status GetWatchpointSupportInfo(uint32_t &num, - bool &after) override; - - virtual uint32_t UpdateThreadListIfNeeded(); - - bool DoUpdateThreadList(lldb_private::ThreadList &old_thread_list, - lldb_private::ThreadList &new_thread_list) override; - - virtual lldb::ByteOrder GetByteOrder() const; - - lldb::addr_t GetImageInfoAddress() override; - - size_t PutSTDIN(const char *buf, size_t len, - lldb_private::Status &error) override; - - lldb_private::DataExtractor GetAuxvData() override; - - // ProcessFreeBSD 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); - - /// 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 FreeBSDThread *CreateNewFreeBSDThread(lldb_private::Process &process, - lldb::tid_t tid); - - static bool SingleStepBreakpointHit( - void *baton, lldb_private::StoppointCallbackContext *context, - lldb::user_id_t break_id, lldb::user_id_t break_loc_id); - - lldb_private::Status SetupSoftwareSingleStepping(lldb::tid_t tid); - - lldb_private::Status SetSoftwareSingleStepBreakpoint(lldb::tid_t tid, - lldb::addr_t addr); - - bool IsSoftwareStepBreakpoint(lldb::tid_t tid); - - bool SupportHardwareSingleStepping() const; - - typedef std::vector tid_collection; - tid_collection &GetStepTids() { return m_step_tids; } - -protected: - static const size_t MAX_TRAP_OPCODE_SIZE = 8; - - /// 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. - std::recursive_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; - - friend class FreeBSDThread; - - tid_collection m_suspend_tids; - tid_collection m_run_tids; - tid_collection m_step_tids; - std::map m_threads_stepping_with_breakpoint; - - int m_resume_signo; -}; - -#endif // liblldb_ProcessFreeBSD_H_ diff --git a/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp b/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp deleted file mode 100644 --- a/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp +++ /dev/null @@ -1,1080 +0,0 @@ -//===-- ProcessFreeBSD.cpp ------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "lldb/Core/PluginManager.h" -#include "lldb/Host/FileSystem.h" -#include "lldb/Host/Host.h" -#include "lldb/Symbol/ObjectFile.h" -#include "lldb/Target/DynamicLoader.h" -#include "lldb/Target/Target.h" -#include "lldb/Utility/RegisterValue.h" -#include "lldb/Utility/State.h" - -#include "FreeBSDThread.h" -#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" -#include "Plugins/Process/Utility/FreeBSDSignals.h" -#include "Plugins/Process/Utility/InferiorCallPOSIX.h" -#include "ProcessFreeBSD.h" -#include "ProcessMonitor.h" - -#include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Breakpoint/Watchpoint.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/PluginManager.h" -#include "lldb/Host/Host.h" -#include "lldb/Symbol/ObjectFile.h" -#include "lldb/Target/DynamicLoader.h" -#include "lldb/Target/Platform.h" -#include "lldb/Target/Target.h" -#include "lldb/Utility/DataBufferHeap.h" -#include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/State.h" - -#include "lldb/Host/posix/Fcntl.h" - -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/Threading.h" - -using namespace lldb; -using namespace lldb_private; - -LLDB_PLUGIN_DEFINE(ProcessFreeBSD) - -namespace { -UnixSignalsSP &GetFreeBSDSignals() { - static UnixSignalsSP s_freebsd_signals_sp(new FreeBSDSignals()); - return s_freebsd_signals_sp; -} -} - -// Static functions. - -lldb::ProcessSP -ProcessFreeBSD::CreateInstance(lldb::TargetSP target_sp, - lldb::ListenerSP listener_sp, - const FileSpec *crash_file_path, - bool can_connect) { - lldb::ProcessSP process_sp; - if (crash_file_path == NULL && !can_connect) - process_sp.reset( - new ProcessFreeBSD(target_sp, listener_sp, GetFreeBSDSignals())); - return process_sp; -} - -void ProcessFreeBSD::Initialize() { - static llvm::once_flag g_once_flag; - - llvm::call_once(g_once_flag, []() { - PluginManager::RegisterPlugin(GetPluginNameStatic(), - GetPluginDescriptionStatic(), CreateInstance); - }); -} - -lldb_private::ConstString ProcessFreeBSD::GetPluginNameStatic() { - static ConstString g_name("freebsd"); - return g_name; -} - -const char *ProcessFreeBSD::GetPluginDescriptionStatic() { - return "Process plugin for FreeBSD"; -} - -// ProcessInterface protocol. - -lldb_private::ConstString ProcessFreeBSD::GetPluginName() { - return GetPluginNameStatic(); -} - -uint32_t ProcessFreeBSD::GetPluginVersion() { return 1; } - -void ProcessFreeBSD::Terminate() {} - -Status ProcessFreeBSD::DoDetach(bool keep_stopped) { - Status error; - if (keep_stopped) { - error.SetErrorString("Detaching with keep_stopped true is not currently " - "supported on FreeBSD."); - return error; - } - - error = m_monitor->Detach(GetID()); - - if (error.Success()) - SetPrivateState(eStateDetached); - - return error; -} - -Status ProcessFreeBSD::DoResume() { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - - SetPrivateState(eStateRunning); - - std::lock_guard guard(m_thread_list.GetMutex()); - bool do_step = false; - bool software_single_step = !SupportHardwareSingleStepping(); - - for (tid_collection::const_iterator t_pos = m_run_tids.begin(), - t_end = m_run_tids.end(); - t_pos != t_end; ++t_pos) { - m_monitor->ThreadSuspend(*t_pos, false); - } - for (tid_collection::const_iterator t_pos = m_step_tids.begin(), - t_end = m_step_tids.end(); - t_pos != t_end; ++t_pos) { - m_monitor->ThreadSuspend(*t_pos, false); - do_step = true; - if (software_single_step) { - Status error = SetupSoftwareSingleStepping(*t_pos); - if (error.Fail()) - return error; - } - } - for (tid_collection::const_iterator t_pos = m_suspend_tids.begin(), - t_end = m_suspend_tids.end(); - t_pos != t_end; ++t_pos) { - m_monitor->ThreadSuspend(*t_pos, true); - // XXX Cannot PT_CONTINUE properly with suspended threads. - do_step = true; - } - - LLDB_LOGF(log, "process %" PRIu64 " resuming (%s)", GetID(), - do_step ? "step" : "continue"); - if (do_step && !software_single_step) - m_monitor->SingleStep(GetID(), m_resume_signo); - else - m_monitor->Resume(GetID(), m_resume_signo); - - return Status(); -} - -bool ProcessFreeBSD::DoUpdateThreadList(ThreadList &old_thread_list, - ThreadList &new_thread_list) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - LLDB_LOGF(log, "ProcessFreeBSD::%s (pid = %" PRIu64 ")", __FUNCTION__, - GetID()); - - std::vector tds; - if (!GetMonitor().GetCurrentThreadIDs(tds)) { - return false; - } - - ThreadList old_thread_list_copy(old_thread_list); - for (size_t i = 0; i < tds.size(); ++i) { - tid_t tid = tds[i]; - ThreadSP thread_sp(old_thread_list_copy.RemoveThreadByID(tid, false)); - if (!thread_sp) { - thread_sp.reset(new FreeBSDThread(*this, tid)); - LLDB_LOGF(log, "ProcessFreeBSD::%s new tid = %" PRIu64, __FUNCTION__, - tid); - } else { - LLDB_LOGF(log, "ProcessFreeBSD::%s existing tid = %" PRIu64, __FUNCTION__, - tid); - } - new_thread_list.AddThread(thread_sp); - } - for (size_t i = 0; i < old_thread_list_copy.GetSize(false); ++i) { - ThreadSP old_thread_sp(old_thread_list_copy.GetThreadAtIndex(i, false)); - if (old_thread_sp) { - LLDB_LOGF(log, "ProcessFreeBSD::%s remove tid", __FUNCTION__); - } - } - - return true; -} - -Status ProcessFreeBSD::WillResume() { - m_resume_signo = 0; - m_suspend_tids.clear(); - m_run_tids.clear(); - m_step_tids.clear(); - return Process::WillResume(); -} - -void ProcessFreeBSD::SendMessage(const ProcessMessage &message) { - std::lock_guard guard(m_message_mutex); - - switch (message.GetKind()) { - case ProcessMessage::eInvalidMessage: - return; - - case ProcessMessage::eAttachMessage: - SetPrivateState(eStateStopped); - return; - - case ProcessMessage::eLimboMessage: - case ProcessMessage::eExitMessage: - SetExitStatus(message.GetExitStatus(), NULL); - break; - - case ProcessMessage::eSignalMessage: - case ProcessMessage::eSignalDeliveredMessage: - case ProcessMessage::eBreakpointMessage: - case ProcessMessage::eTraceMessage: - case ProcessMessage::eWatchpointMessage: - case ProcessMessage::eCrashMessage: - SetPrivateState(eStateStopped); - break; - - case ProcessMessage::eNewThreadMessage: - llvm_unreachable("eNewThreadMessage unexpected on FreeBSD"); - break; - - case ProcessMessage::eExecMessage: - SetPrivateState(eStateStopped); - break; - } - - m_message_queue.push(message); -} - -// Constructors and destructors. - -ProcessFreeBSD::ProcessFreeBSD(lldb::TargetSP target_sp, - lldb::ListenerSP listener_sp, - UnixSignalsSP &unix_signals_sp) - : Process(target_sp, listener_sp, unix_signals_sp), - m_byte_order(endian::InlHostByteOrder()), m_monitor(NULL), m_module(NULL), - m_message_mutex(), m_exit_now(false), m_seen_initial_stop(), - m_resume_signo(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. - lldb::ModuleSP module = GetTarget().GetExecutableModule(); - if (module && module->GetObjectFile()) - m_byte_order = module->GetObjectFile()->GetByteOrder(); -} - -ProcessFreeBSD::~ProcessFreeBSD() { delete m_monitor; } - -// Process protocol. -void ProcessFreeBSD::Finalize() { - Process::Finalize(); - - if (m_monitor) - m_monitor->StopMonitor(); -} - -bool ProcessFreeBSD::CanDebug(lldb::TargetSP target_sp, - bool plugin_specified_by_name) { - // For now we are just making sure the file exists for a given module - ModuleSP exe_module_sp(target_sp->GetExecutableModule()); - if (exe_module_sp.get()) - return FileSystem::Instance().Exists(exe_module_sp->GetFileSpec()); - // If there is no executable module, we return true since we might be - // preparing to attach. - return true; -} - -Status -ProcessFreeBSD::DoAttachToProcessWithID(lldb::pid_t pid, - const ProcessAttachInfo &attach_info) { - Status error; - assert(m_monitor == NULL); - - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - LLDB_LOGV(log, "pid = {0}", GetID()); - - m_monitor = new ProcessMonitor(this, pid, error); - - if (!error.Success()) - return error; - - PlatformSP platform_sp(GetTarget().GetPlatform()); - assert(platform_sp.get()); - if (!platform_sp) - return error; // FIXME: Detatch? - - // Find out what we can about this process - ProcessInstanceInfo process_info; - platform_sp->GetProcessInfo(pid, process_info); - - // Resolve the executable module - ModuleSP exe_module_sp; - FileSpecList executable_search_paths( - Target::GetDefaultExecutableSearchPaths()); - ModuleSpec exe_module_spec(process_info.GetExecutableFile(), - GetTarget().GetArchitecture()); - error = platform_sp->ResolveExecutable( - exe_module_spec, exe_module_sp, - executable_search_paths.GetSize() ? &executable_search_paths : NULL); - if (!error.Success()) - return error; - - // Fix the target architecture if necessary - const ArchSpec &module_arch = exe_module_sp->GetArchitecture(); - if (module_arch.IsValid() && - !GetTarget().GetArchitecture().IsExactMatch(module_arch)) - GetTarget().SetArchitecture(module_arch); - - // Initialize the target module list - GetTarget().SetExecutableModule(exe_module_sp, eLoadDependentsYes); - - SetSTDIOFileDescriptor(m_monitor->GetTerminalFD()); - - SetID(pid); - - return error; -} - -Status ProcessFreeBSD::WillLaunch(Module *module) { - Status error; - return error; -} - -FileSpec -ProcessFreeBSD::GetFileSpec(const lldb_private::FileAction *file_action, - const FileSpec &default_file_spec, - const FileSpec &dbg_pts_file_spec) { - FileSpec file_spec{}; - - if (file_action && file_action->GetAction() == FileAction::eFileActionOpen) { - file_spec = file_action->GetFileSpec(); - // By default the stdio paths passed in will be pseudo-terminal (/dev/pts). - // If so, convert to using a different default path instead to redirect I/O - // to the debugger console. This should also handle user overrides to - // /dev/null or a different file. - if (!file_spec || file_spec == dbg_pts_file_spec) - file_spec = default_file_spec; - } - return file_spec; -} - -Status ProcessFreeBSD::DoLaunch(Module *module, - ProcessLaunchInfo &launch_info) { - Status error; - assert(m_monitor == NULL); - - FileSpec working_dir = launch_info.GetWorkingDirectory(); - if (working_dir) { - FileSystem::Instance().Resolve(working_dir); - if (!FileSystem::Instance().IsDirectory(working_dir.GetPath())) { - error.SetErrorStringWithFormat("No such file or directory: %s", - working_dir.GetCString()); - return error; - } - } - - SetPrivateState(eStateLaunching); - - const lldb_private::FileAction *file_action; - - // Default of empty will mean to use existing open file descriptors - FileSpec stdin_file_spec{}; - FileSpec stdout_file_spec{}; - FileSpec stderr_file_spec{}; - - const FileSpec dbg_pts_file_spec{launch_info.GetPTY().GetSecondaryName()}; - - file_action = launch_info.GetFileActionForFD(STDIN_FILENO); - stdin_file_spec = - GetFileSpec(file_action, stdin_file_spec, dbg_pts_file_spec); - - file_action = launch_info.GetFileActionForFD(STDOUT_FILENO); - stdout_file_spec = - GetFileSpec(file_action, stdout_file_spec, dbg_pts_file_spec); - - file_action = launch_info.GetFileActionForFD(STDERR_FILENO); - stderr_file_spec = - GetFileSpec(file_action, stderr_file_spec, dbg_pts_file_spec); - - m_monitor = new ProcessMonitor( - this, module, launch_info.GetArguments().GetConstArgumentVector(), - launch_info.GetEnvironment(), stdin_file_spec, stdout_file_spec, - stderr_file_spec, working_dir, launch_info, error); - - m_module = module; - - if (!error.Success()) - return error; - - int terminal = m_monitor->GetTerminalFD(); - if (terminal >= 0) { -// The reader thread will close the file descriptor when done, so we pass it a -// copy. -#ifdef F_DUPFD_CLOEXEC - int stdio = fcntl(terminal, F_DUPFD_CLOEXEC, 0); - if (stdio == -1) { - error.SetErrorToErrno(); - return error; - } -#else - // Special case when F_DUPFD_CLOEXEC does not exist (Debian kFreeBSD) - int stdio = fcntl(terminal, F_DUPFD, 0); - if (stdio == -1) { - error.SetErrorToErrno(); - return error; - } - stdio = fcntl(terminal, F_SETFD, FD_CLOEXEC); - if (stdio == -1) { - error.SetErrorToErrno(); - return error; - } -#endif - SetSTDIOFileDescriptor(stdio); - } - - SetID(m_monitor->GetPID()); - return error; -} - -void ProcessFreeBSD::DidLaunch() {} - -addr_t ProcessFreeBSD::GetImageInfoAddress() { - Target *target = &GetTarget(); - ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile(); - Address addr = obj_file->GetImageInfoAddress(target); - - if (addr.IsValid()) - return addr.GetLoadAddress(target); - return LLDB_INVALID_ADDRESS; -} - -Status ProcessFreeBSD::DoHalt(bool &caused_stop) { - Status error; - - if (IsStopped()) { - caused_stop = false; - } else if (kill(GetID(), SIGSTOP)) { - caused_stop = false; - error.SetErrorToErrno(); - } else { - caused_stop = true; - } - return error; -} - -Status ProcessFreeBSD::DoSignal(int signal) { - Status error; - - if (kill(GetID(), signal)) - error.SetErrorToErrno(); - - return error; -} - -Status ProcessFreeBSD::DoDestroy() { - Status error; - - if (!HasExited()) { - assert(m_monitor); - m_exit_now = true; - if (GetID() == LLDB_INVALID_PROCESS_ID) { - error.SetErrorString("invalid process id"); - return error; - } - if (!m_monitor->Kill()) { - error.SetErrorToErrno(); - return error; - } - - SetPrivateState(eStateExited); - } - - return error; -} - -void ProcessFreeBSD::DoDidExec() { - Target *target = &GetTarget(); - if (target) { - PlatformSP platform_sp(target->GetPlatform()); - assert(platform_sp.get()); - if (platform_sp) { - ProcessInstanceInfo process_info; - platform_sp->GetProcessInfo(GetID(), process_info); - ModuleSP exe_module_sp; - ModuleSpec exe_module_spec(process_info.GetExecutableFile(), - target->GetArchitecture()); - FileSpecList executable_search_paths( - Target::GetDefaultExecutableSearchPaths()); - Status error = platform_sp->ResolveExecutable( - exe_module_spec, exe_module_sp, - executable_search_paths.GetSize() ? &executable_search_paths : NULL); - if (!error.Success()) - return; - target->SetExecutableModule(exe_module_sp, eLoadDependentsYes); - } - } -} - -bool ProcessFreeBSD::AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid) { - bool added_to_set = false; - ThreadStopSet::iterator it = m_seen_initial_stop.find(stop_tid); - if (it == m_seen_initial_stop.end()) { - m_seen_initial_stop.insert(stop_tid); - added_to_set = true; - } - return added_to_set; -} - -bool ProcessFreeBSD::WaitingForInitialStop(lldb::tid_t stop_tid) { - return (m_seen_initial_stop.find(stop_tid) == m_seen_initial_stop.end()); -} - -FreeBSDThread * -ProcessFreeBSD::CreateNewFreeBSDThread(lldb_private::Process &process, - lldb::tid_t tid) { - return new FreeBSDThread(process, tid); -} - -void ProcessFreeBSD::RefreshStateAfterStop() { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - LLDB_LOGV(log, "message_queue size = {0}", m_message_queue.size()); - - std::lock_guard guard(m_message_mutex); - - // This method used to only handle one message. Changing it to loop allows - // it to handle the case where we hit a breakpoint while handling a different - // breakpoint. - while (!m_message_queue.empty()) { - ProcessMessage &message = m_message_queue.front(); - - // Resolve the thread this message corresponds to and pass it along. - lldb::tid_t tid = message.GetTID(); - LLDB_LOGV(log, " message_queue size = {0}, pid = {1}", - m_message_queue.size(), tid); - - m_thread_list.RefreshStateAfterStop(); - - FreeBSDThread *thread = static_cast( - GetThreadList().FindThreadByID(tid, false).get()); - if (thread) - thread->Notify(message); - - if (message.GetKind() == ProcessMessage::eExitMessage) { - // FIXME: We should tell the user about this, but the limbo message is - // probably better for that. - LLDB_LOG(log, "removing thread, tid = {0}", tid); - std::lock_guard guard(m_thread_list.GetMutex()); - - ThreadSP thread_sp = m_thread_list.RemoveThreadByID(tid, false); - thread_sp.reset(); - m_seen_initial_stop.erase(tid); - } - - m_message_queue.pop(); - } -} - -bool ProcessFreeBSD::IsAlive() { - StateType state = GetPrivateState(); - return state != eStateDetached && state != eStateExited && - state != eStateInvalid && state != eStateUnloaded; -} - -size_t ProcessFreeBSD::DoReadMemory(addr_t vm_addr, void *buf, size_t size, - Status &error) { - assert(m_monitor); - return m_monitor->ReadMemory(vm_addr, buf, size, error); -} - -size_t ProcessFreeBSD::DoWriteMemory(addr_t vm_addr, const void *buf, - size_t size, Status &error) { - assert(m_monitor); - return m_monitor->WriteMemory(vm_addr, buf, size, error); -} - -addr_t ProcessFreeBSD::DoAllocateMemory(size_t size, uint32_t permissions, - Status &error) { - addr_t allocated_addr = LLDB_INVALID_ADDRESS; - - unsigned prot = 0; - if (permissions & lldb::ePermissionsReadable) - prot |= eMmapProtRead; - if (permissions & lldb::ePermissionsWritable) - prot |= eMmapProtWrite; - if (permissions & lldb::ePermissionsExecutable) - prot |= eMmapProtExec; - - if (InferiorCallMmap(this, allocated_addr, 0, size, prot, - eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) { - m_addr_to_mmap_size[allocated_addr] = size; - error.Clear(); - } else { - allocated_addr = LLDB_INVALID_ADDRESS; - error.SetErrorStringWithFormat( - "unable to allocate %zu bytes of memory with permissions %s", size, - GetPermissionsAsCString(permissions)); - } - - return allocated_addr; -} - -Status ProcessFreeBSD::DoDeallocateMemory(lldb::addr_t addr) { - Status error; - MMapMap::iterator pos = m_addr_to_mmap_size.find(addr); - if (pos != m_addr_to_mmap_size.end() && - InferiorCallMunmap(this, addr, pos->second)) - m_addr_to_mmap_size.erase(pos); - else - error.SetErrorStringWithFormat("unable to deallocate memory at 0x%" PRIx64, - addr); - - return error; -} - -size_t -ProcessFreeBSD::GetSoftwareBreakpointTrapOpcode(BreakpointSite *bp_site) { - static const uint8_t g_aarch64_opcode[] = {0x00, 0x00, 0x20, 0xD4}; - static const uint8_t g_i386_opcode[] = {0xCC}; - - ArchSpec arch = GetTarget().GetArchitecture(); - const uint8_t *opcode = NULL; - size_t opcode_size = 0; - - switch (arch.GetMachine()) { - default: - assert(false && "CPU type not supported!"); - break; - - case llvm::Triple::arm: { - // The ARM reference recommends the use of 0xe7fddefe and 0xdefe but the - // linux kernel does otherwise. - static const uint8_t g_arm_breakpoint_opcode[] = {0xf0, 0x01, 0xf0, 0xe7}; - static const uint8_t g_thumb_breakpoint_opcode[] = {0x01, 0xde}; - - lldb::BreakpointLocationSP bp_loc_sp(bp_site->GetOwnerAtIndex(0)); - AddressClass addr_class = AddressClass::eUnknown; - - if (bp_loc_sp) - addr_class = bp_loc_sp->GetAddress().GetAddressClass(); - - if (addr_class == AddressClass::eCodeAlternateISA || - (addr_class == AddressClass::eUnknown && - bp_loc_sp->GetAddress().GetOffset() & 1)) { - opcode = g_thumb_breakpoint_opcode; - opcode_size = sizeof(g_thumb_breakpoint_opcode); - } else { - opcode = g_arm_breakpoint_opcode; - opcode_size = sizeof(g_arm_breakpoint_opcode); - } - } break; - case llvm::Triple::aarch64: - opcode = g_aarch64_opcode; - opcode_size = sizeof(g_aarch64_opcode); - break; - - case llvm::Triple::x86: - case llvm::Triple::x86_64: - opcode = g_i386_opcode; - opcode_size = sizeof(g_i386_opcode); - break; - } - - bp_site->SetTrapOpcode(opcode, opcode_size); - return opcode_size; -} - -Status ProcessFreeBSD::EnableBreakpointSite(BreakpointSite *bp_site) { - if (bp_site->HardwareRequired()) - return Status("Hardware breakpoints are not supported."); - - return EnableSoftwareBreakpoint(bp_site); -} - -Status ProcessFreeBSD::DisableBreakpointSite(BreakpointSite *bp_site) { - return DisableSoftwareBreakpoint(bp_site); -} - -Status ProcessFreeBSD::EnableWatchpoint(Watchpoint *wp, bool notify) { - Status error; - if (wp) { - user_id_t watchID = wp->GetID(); - addr_t addr = wp->GetLoadAddress(); - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - LLDB_LOGF(log, "ProcessFreeBSD::EnableWatchpoint(watchID = %" PRIu64 ")", - watchID); - if (wp->IsEnabled()) { - LLDB_LOGF(log, - "ProcessFreeBSD::EnableWatchpoint(watchID = %" PRIu64 - ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.", - watchID, (uint64_t)addr); - return error; - } - - // Try to find a vacant watchpoint slot in the inferiors' main thread - uint32_t wp_hw_index = LLDB_INVALID_INDEX32; - std::lock_guard guard(m_thread_list.GetMutex()); - FreeBSDThread *thread = static_cast( - m_thread_list.GetThreadAtIndex(0, false).get()); - - if (thread) - wp_hw_index = thread->FindVacantWatchpointIndex(); - - if (wp_hw_index == LLDB_INVALID_INDEX32) { - error.SetErrorString("Setting hardware watchpoint failed."); - } else { - wp->SetHardwareIndex(wp_hw_index); - bool wp_enabled = true; - uint32_t thread_count = m_thread_list.GetSize(false); - for (uint32_t i = 0; i < thread_count; ++i) { - thread = static_cast( - m_thread_list.GetThreadAtIndex(i, false).get()); - if (thread) - wp_enabled &= thread->EnableHardwareWatchpoint(wp); - else - wp_enabled = false; - } - if (wp_enabled) { - wp->SetEnabled(true, notify); - return error; - } else { - // Watchpoint enabling failed on at least one of the threads so roll - // back all of them - DisableWatchpoint(wp, false); - error.SetErrorString("Setting hardware watchpoint failed"); - } - } - } else - error.SetErrorString("Watchpoint argument was NULL."); - return error; -} - -Status ProcessFreeBSD::DisableWatchpoint(Watchpoint *wp, bool notify) { - Status error; - if (wp) { - user_id_t watchID = wp->GetID(); - addr_t addr = wp->GetLoadAddress(); - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - LLDB_LOGF(log, "ProcessFreeBSD::DisableWatchpoint(watchID = %" PRIu64 ")", - watchID); - if (!wp->IsEnabled()) { - LLDB_LOGF(log, - "ProcessFreeBSD::DisableWatchpoint(watchID = %" PRIu64 - ") addr = 0x%8.8" PRIx64 ": watchpoint already disabled.", - watchID, (uint64_t)addr); - // This is needed (for now) to keep watchpoints disabled correctly - wp->SetEnabled(false, notify); - return error; - } - - if (wp->IsHardware()) { - bool wp_disabled = true; - std::lock_guard guard(m_thread_list.GetMutex()); - uint32_t thread_count = m_thread_list.GetSize(false); - for (uint32_t i = 0; i < thread_count; ++i) { - FreeBSDThread *thread = static_cast( - m_thread_list.GetThreadAtIndex(i, false).get()); - if (thread) - wp_disabled &= thread->DisableHardwareWatchpoint(wp); - else - wp_disabled = false; - } - if (wp_disabled) { - wp->SetHardwareIndex(LLDB_INVALID_INDEX32); - wp->SetEnabled(false, notify); - return error; - } else - error.SetErrorString("Disabling hardware watchpoint failed"); - } - } else - error.SetErrorString("Watchpoint argument was NULL."); - return error; -} - -Status ProcessFreeBSD::GetWatchpointSupportInfo(uint32_t &num) { - Status error; - std::lock_guard guard(m_thread_list.GetMutex()); - FreeBSDThread *thread = static_cast( - m_thread_list.GetThreadAtIndex(0, false).get()); - if (thread) - num = thread->NumSupportedHardwareWatchpoints(); - else - error.SetErrorString("Process does not exist."); - return error; -} - -Status ProcessFreeBSD::GetWatchpointSupportInfo(uint32_t &num, bool &after) { - Status error = GetWatchpointSupportInfo(num); - // Watchpoints trigger and halt the inferior after the corresponding - // instruction has been executed. - after = true; - return error; -} - -uint32_t ProcessFreeBSD::UpdateThreadListIfNeeded() { - std::lock_guard guard(m_thread_list.GetMutex()); - // Do not allow recursive updates. - return m_thread_list.GetSize(false); -} - -ByteOrder ProcessFreeBSD::GetByteOrder() const { - // FIXME: We should be able to extract this value directly. See comment in - // ProcessFreeBSD(). - return m_byte_order; -} - -size_t ProcessFreeBSD::PutSTDIN(const char *buf, size_t len, Status &error) { - ssize_t status; - if ((status = write(m_monitor->GetTerminalFD(), buf, len)) < 0) { - error.SetErrorToErrno(); - return 0; - } - return status; -} - -// Utility functions. - -bool ProcessFreeBSD::HasExited() { - switch (GetPrivateState()) { - default: - break; - - case eStateDetached: - case eStateExited: - return true; - } - - return false; -} - -bool ProcessFreeBSD::IsStopped() { - switch (GetPrivateState()) { - default: - break; - - case eStateStopped: - case eStateCrashed: - case eStateSuspended: - return true; - } - - return false; -} - -bool ProcessFreeBSD::IsAThreadRunning() { - bool is_running = false; - std::lock_guard guard(m_thread_list.GetMutex()); - uint32_t thread_count = m_thread_list.GetSize(false); - for (uint32_t i = 0; i < thread_count; ++i) { - FreeBSDThread *thread = static_cast( - m_thread_list.GetThreadAtIndex(i, false).get()); - StateType thread_state = thread->GetState(); - if (thread_state == eStateRunning || thread_state == eStateStepping) { - is_running = true; - break; - } - } - return is_running; -} - -lldb_private::DataExtractor ProcessFreeBSD::GetAuxvData() { - // If we're the local platform, we can ask the host for auxv data. - PlatformSP platform_sp = GetTarget().GetPlatform(); - assert(platform_sp && platform_sp->IsHost()); - - int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_AUXV, (int)m_process->GetID()}; - size_t auxv_size = AT_COUNT * sizeof(Elf_Auxinfo); - DataBufferSP buf_sp(new DataBufferHeap(auxv_size, 0)); - - if (::sysctl(mib, 4, buf_sp->GetBytes(), &auxv_size, NULL, 0) != 0) { - perror("sysctl failed on auxv"); - buf_sp.reset(); - } - - return DataExtractor(buf_sp, GetByteOrder(), GetAddressByteSize()); -} - -struct EmulatorBaton { - ProcessFreeBSD *m_process; - RegisterContext *m_reg_context; - - // eRegisterKindDWARF -> RegisterValue - std::unordered_map m_register_values; - - EmulatorBaton(ProcessFreeBSD *process, RegisterContext *reg_context) - : m_process(process), m_reg_context(reg_context) {} -}; - -static size_t ReadMemoryCallback(EmulateInstruction *instruction, void *baton, - const EmulateInstruction::Context &context, - lldb::addr_t addr, void *dst, size_t length) { - EmulatorBaton *emulator_baton = static_cast(baton); - - Status error; - size_t bytes_read = - emulator_baton->m_process->DoReadMemory(addr, dst, length, error); - if (!error.Success()) - bytes_read = 0; - return bytes_read; -} - -static bool ReadRegisterCallback(EmulateInstruction *instruction, void *baton, - const RegisterInfo *reg_info, - RegisterValue ®_value) { - EmulatorBaton *emulator_baton = static_cast(baton); - - auto it = emulator_baton->m_register_values.find( - reg_info->kinds[eRegisterKindDWARF]); - if (it != emulator_baton->m_register_values.end()) { - reg_value = it->second; - return true; - } - - // The emulator only fills in the dwarf register numbers (and in some cases - // the generic register numbers). Get the full register info from the - // register context based on the dwarf register numbers. - const RegisterInfo *full_reg_info = - emulator_baton->m_reg_context->GetRegisterInfo( - eRegisterKindDWARF, reg_info->kinds[eRegisterKindDWARF]); - - bool error = - emulator_baton->m_reg_context->ReadRegister(full_reg_info, reg_value); - return error; -} - -static bool WriteRegisterCallback(EmulateInstruction *instruction, void *baton, - const EmulateInstruction::Context &context, - const RegisterInfo *reg_info, - const RegisterValue ®_value) { - EmulatorBaton *emulator_baton = static_cast(baton); - emulator_baton->m_register_values[reg_info->kinds[eRegisterKindDWARF]] = - reg_value; - return true; -} - -static size_t WriteMemoryCallback(EmulateInstruction *instruction, void *baton, - const EmulateInstruction::Context &context, - lldb::addr_t addr, const void *dst, - size_t length) { - return length; -} - -bool ProcessFreeBSD::SingleStepBreakpointHit( - void *baton, lldb_private::StoppointCallbackContext *context, - lldb::user_id_t break_id, lldb::user_id_t break_loc_id) { - return false; -} - -Status ProcessFreeBSD::SetSoftwareSingleStepBreakpoint(lldb::tid_t tid, - lldb::addr_t addr) { - Status error; - - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - if (log) { - LLDB_LOGF(log, "ProcessFreeBSD::%s addr = 0x%" PRIx64, __FUNCTION__, addr); - LLDB_LOGF(log, "SoftwareBreakpoint::%s addr = 0x%" PRIx64, __FUNCTION__, - addr); - } - - // Validate the address. - if (addr == LLDB_INVALID_ADDRESS) - return Status("ProcessFreeBSD::%s invalid load address specified.", - __FUNCTION__); - - Breakpoint *const sw_step_break = - m_process->GetTarget().CreateBreakpoint(addr, true, false).get(); - sw_step_break->SetCallback(SingleStepBreakpointHit, this, true); - sw_step_break->SetBreakpointKind("software-single-step"); - - LLDB_LOGF(log, "ProcessFreeBSD::%s addr = 0x%" PRIx64 " -- SUCCESS", - __FUNCTION__, addr); - - m_threads_stepping_with_breakpoint.insert({tid, sw_step_break->GetID()}); - return Status(); -} - -bool ProcessFreeBSD::IsSoftwareStepBreakpoint(lldb::tid_t tid) { - ThreadSP thread = GetThreadList().FindThreadByID(tid); - if (!thread) - return false; - - assert(thread->GetRegisterContext()); - lldb::addr_t stop_pc = thread->GetRegisterContext()->GetPC(); - - const auto &iter = m_threads_stepping_with_breakpoint.find(tid); - if (iter == m_threads_stepping_with_breakpoint.end()) - return false; - - lldb::break_id_t bp_id = iter->second; - BreakpointSP bp = GetTarget().GetBreakpointByID(bp_id); - if (!bp) - return false; - - BreakpointLocationSP bp_loc = bp->FindLocationByAddress(stop_pc); - if (!bp_loc) - return false; - - GetTarget().RemoveBreakpointByID(bp_id); - m_threads_stepping_with_breakpoint.erase(tid); - return true; -} - -bool ProcessFreeBSD::SupportHardwareSingleStepping() const { - lldb_private::ArchSpec arch = GetTarget().GetArchitecture(); - if (arch.GetMachine() == llvm::Triple::arm || arch.IsMIPS()) - return false; - return true; -} - -Status ProcessFreeBSD::SetupSoftwareSingleStepping(lldb::tid_t tid) { - std::unique_ptr emulator_up( - EmulateInstruction::FindPlugin(GetTarget().GetArchitecture(), - eInstructionTypePCModifying, nullptr)); - - if (emulator_up == nullptr) - return Status("Instruction emulator not found!"); - - FreeBSDThread *thread = static_cast( - m_thread_list.FindThreadByID(tid, false).get()); - if (thread == NULL) - return Status("Thread not found not found!"); - - lldb::RegisterContextSP register_context_sp = thread->GetRegisterContext(); - - EmulatorBaton baton(this, register_context_sp.get()); - emulator_up->SetBaton(&baton); - emulator_up->SetReadMemCallback(&ReadMemoryCallback); - emulator_up->SetReadRegCallback(&ReadRegisterCallback); - emulator_up->SetWriteMemCallback(&WriteMemoryCallback); - emulator_up->SetWriteRegCallback(&WriteRegisterCallback); - - if (!emulator_up->ReadInstruction()) - return Status("Read instruction failed!"); - - bool emulation_result = - emulator_up->EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC); - const RegisterInfo *reg_info_pc = register_context_sp->GetRegisterInfo( - eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); - auto pc_it = - baton.m_register_values.find(reg_info_pc->kinds[eRegisterKindDWARF]); - - lldb::addr_t next_pc; - if (emulation_result) { - assert(pc_it != baton.m_register_values.end() && - "Emulation was successful but PC wasn't updated"); - next_pc = pc_it->second.GetAsUInt64(); - } else if (pc_it == baton.m_register_values.end()) { - // Emulate instruction failed and it haven't changed PC. Advance PC with - // the size of the current opcode because the emulation of all - // PC modifying instruction should be successful. The failure most - // likely caused by a not supported instruction which don't modify PC. - next_pc = - register_context_sp->GetPC() + emulator_up->GetOpcode().GetByteSize(); - } else { - // The instruction emulation failed after it modified the PC. It is an - // unknown error where we can't continue because the next instruction is - // modifying the PC but we don't know how. - return Status("Instruction emulation failed unexpectedly"); - } - - SetSoftwareSingleStepBreakpoint(tid, next_pc); - return Status(); -} diff --git a/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.h b/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.h deleted file mode 100644 --- a/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.h +++ /dev/null @@ -1,279 +0,0 @@ -//===-- ProcessMonitor.h -------------------------------------- -*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_ProcessMonitor_H_ -#define liblldb_ProcessMonitor_H_ - -#include -#include - -#include - -#include "lldb/Host/HostThread.h" -#include "lldb/Utility/FileSpec.h" -#include "lldb/lldb-types.h" - -namespace lldb_private { -class Status; -class Module; -class Scalar; -} // End lldb_private namespace. - -class ProcessFreeBSD; -class Operation; - -/// \class ProcessMonitor -/// 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 -/// ProcessFreeBSD instance by calling ProcessFreeBSD::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(ProcessFreeBSD *process, lldb_private::Module *module, - char const *argv[], lldb_private::Environment env, - 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::Status &error); - - ProcessMonitor(ProcessFreeBSD *process, lldb::pid_t pid, - lldb_private::Status &error); - - ~ProcessMonitor(); - - /// Provides the process number of debugee. - lldb::pid_t GetPID() const { return m_pid; } - - /// Returns the process associated with this ProcessMonitor. - ProcessFreeBSD &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::Status &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::Status &error); - - /// Reads the contents from the register identified by the given - /// (architecture dependent) offset. - /// - /// This method is provided for use by RegisterContextFreeBSD 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 RegisterContextFreeBSD derivatives. - bool WriteRegisterValue(lldb::tid_t tid, unsigned offset, - const char *reg_name, - const lldb_private::RegisterValue &value); - - /// Reads the contents from the debug register identified by the given - /// (architecture dependent) offset. - /// - /// This method is provided for use by RegisterContextFreeBSD derivatives. - bool ReadDebugRegisterValue(lldb::tid_t tid, unsigned offset, - const char *reg_name, unsigned size, - lldb_private::RegisterValue &value); - - /// Writes the given value to the debug register identified by the given - /// (architecture dependent) offset. - /// - /// This method is provided for use by RegisterContextFreeBSD derivatives. - bool WriteDebugRegisterValue(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 all floating point registers into the specified buffer. - bool ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size); - - /// Reads the specified register set into the specified buffer. - /// - /// This method is provided for use by RegisterContextFreeBSD derivatives. - 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 all 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. - /// - /// This method is provided for use by RegisterContextFreeBSD derivatives. - 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); - - /// Returns current thread IDs in process - size_t GetCurrentThreadIDs(std::vector &thread_ids); - - /// Writes a ptrace_lwpinfo structure corresponding to the given thread ID - /// to the memory region pointed to by \p lwpinfo. - bool GetLwpInfo(lldb::tid_t tid, void *lwpinfo, int &error_no); - - /// Suspends or unsuspends a thread prior to process resume or step. - bool ThreadSuspend(lldb::tid_t tid, bool suspend); - - /// 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 process. If \p signo is anything but - /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the process. - bool Resume(lldb::tid_t unused, uint32_t signo); - - /// Single steps the process. If \p signo is anything but - /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the process. - bool SingleStep(lldb::tid_t unused, uint32_t signo); - - /// Terminate the traced process. - bool Kill(); - - lldb_private::Status Detach(lldb::tid_t tid); - - void StopMonitor(); - - // Waits for the initial stop message from a new thread. - bool WaitForInitialTIDStop(lldb::tid_t tid); - -private: - ProcessFreeBSD *m_process; - - llvm::Optional m_operation_thread; - llvm::Optional m_monitor_thread; - lldb::pid_t m_pid; - - int m_terminal_fd; - - // current operation which must be executed on the privileged thread - Operation *m_operation; - std::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::Status m_error; // Set if process operation failed. - }; - - /// \class LauchArgs - /// - /// 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, lldb_private::Environment env, - 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); - - ~LaunchArgs(); - - lldb_private::Module *m_module; // The executable image to launch. - char const **m_argv; // Process arguments. - lldb_private::Environment m_env; // 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. - }; - - void StartLaunchOpThread(LaunchArgs *args, lldb_private::Status &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::Status &error); - - static void *AttachOpThread(void *args); - - static void Attach(AttachArgs *args); - - static void ServeOperation(OperationArgs *args); - - static bool DupDescriptor(const lldb_private::FileSpec &file_spec, int fd, - int flags); - - static bool MonitorCallback(ProcessMonitor *monitor, 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_ diff --git a/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp deleted file mode 100644 --- a/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp +++ /dev/null @@ -1,1424 +0,0 @@ -//===-- ProcessMonitor.cpp ------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "lldb/Host/Host.h" -#include "lldb/Host/PseudoTerminal.h" -#include "lldb/Host/ThreadLauncher.h" -#include "lldb/Target/RegisterContext.h" -#include "lldb/Target/Thread.h" -#include "lldb/Target/UnixSignals.h" -#include "lldb/Utility/RegisterValue.h" -#include "lldb/Utility/Scalar.h" -#include "lldb/Utility/Status.h" -#include "llvm/Support/Errno.h" - -#include "FreeBSDThread.h" -#include "Plugins/Process/POSIX/CrashReason.h" -#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" -#include "ProcessFreeBSD.h" -#include "ProcessMonitor.h" - -using namespace lldb; -using namespace lldb_private; - -// Wrapper for ptrace to catch errors and log calls. - -const char *Get_PT_IO_OP(int op) { - switch (op) { - case PIOD_READ_D: - return "READ_D"; - case PIOD_WRITE_D: - return "WRITE_D"; - case PIOD_READ_I: - return "READ_I"; - case PIOD_WRITE_I: - return "WRITE_I"; - default: - return "Unknown op"; - } -} - -// Wrapper for ptrace to catch errors and log calls. Note that ptrace sets -// errno on error because -1 is reserved as a valid result. -extern long PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data, - const char *reqName, const char *file, int line) { - long int result; - - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); - - if (log) { - LLDB_LOGF(log, - "ptrace(%s, %" PRIu64 ", %p, %x) called from file %s line %d", - reqName, pid, addr, data, file, line); - if (req == PT_IO) { - struct ptrace_io_desc *pi = (struct ptrace_io_desc *)addr; - - LLDB_LOGF(log, "PT_IO: op=%s offs=%zx size=%zu", - Get_PT_IO_OP(pi->piod_op), (size_t)pi->piod_offs, pi->piod_len); - } - } - - // PtraceDisplayBytes(req, data); - - errno = 0; - result = ptrace(req, pid, (caddr_t)addr, data); - - // PtraceDisplayBytes(req, data); - - 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 = ""; - } - LLDB_LOGF(log, "ptrace() failed; errno=%d (%s)", errno, str); - } - - if (log) { -#ifdef __amd64__ - if (req == PT_GETREGS) { - struct reg *r = (struct reg *)addr; - - LLDB_LOGF(log, "PT_GETREGS: rip=0x%lx rsp=0x%lx rbp=0x%lx rax=0x%lx", - r->r_rip, r->r_rsp, r->r_rbp, r->r_rax); - } - if (req == PT_GETDBREGS || req == PT_SETDBREGS) { - struct dbreg *r = (struct dbreg *)addr; - char setget = (req == PT_GETDBREGS) ? 'G' : 'S'; - - for (int i = 0; i <= 7; i++) - LLDB_LOGF(log, "PT_%cETDBREGS: dr[%d]=0x%lx", setget, i, r->dr[i]); - } -#endif - } - - return result; -} - -// Wrapper for ptrace when logging is not required. Sets errno to 0 prior to -// calling ptrace. -extern long PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data) { - long result = 0; - errno = 0; - result = ptrace(req, pid, (caddr_t)addr, data); - return result; -} - -#define PTRACE(req, pid, addr, data) \ - PtraceWrapper((req), (pid), (addr), (data), #req, __FILE__, __LINE__) - -// 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, Status &error) { - struct ptrace_io_desc pi_desc; - - pi_desc.piod_op = PIOD_READ_D; - pi_desc.piod_offs = (void *)vm_addr; - pi_desc.piod_addr = buf; - pi_desc.piod_len = size; - - if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0) { - error.SetErrorToErrno(); - return 0; - } - return pi_desc.piod_len; -} - -static size_t DoWriteMemory(lldb::pid_t pid, lldb::addr_t vm_addr, - const void *buf, size_t size, Status &error) { - struct ptrace_io_desc pi_desc; - - pi_desc.piod_op = PIOD_WRITE_D; - pi_desc.piod_offs = (void *)vm_addr; - pi_desc.piod_addr = const_cast(buf); - pi_desc.piod_len = size; - - if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0) { - error.SetErrorToErrno(); - return 0; - } - return pi_desc.piod_len; -} - -// Simple helper function to ensure flags are enabled on the given file -// descriptor. -static bool EnsureFDFlags(int fd, int flags, Status &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 -/// Represents a ProcessMonitor operation. -/// -/// Under FreeBSD, 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 -/// Implements ProcessMonitor::ReadMemory. -class ReadOperation : public Operation { -public: - ReadOperation(lldb::addr_t addr, void *buff, size_t size, Status &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; - Status &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 -/// Implements ProcessMonitor::WriteMemory. -class WriteOperation : public Operation { -public: - WriteOperation(lldb::addr_t addr, const void *buff, size_t size, - Status &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; - Status &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 -/// Implements ProcessMonitor::ReadRegisterValue. -class ReadRegOperation : public Operation { -public: - ReadRegOperation(lldb::tid_t tid, unsigned offset, unsigned size, - RegisterValue &value, bool &result) - : m_tid(tid), m_offset(offset), m_size(size), m_value(value), - m_result(result) {} - - void Execute(ProcessMonitor *monitor); - -private: - lldb::tid_t m_tid; - unsigned m_offset; - unsigned m_size; - RegisterValue &m_value; - bool &m_result; -}; - -void ReadRegOperation::Execute(ProcessMonitor *monitor) { - struct reg regs; - int rc; - - if ((rc = PTRACE(PT_GETREGS, m_tid, (caddr_t)®s, 0)) < 0) { - m_result = false; - } else { - // 'struct reg' contains only 32- or 64-bit register values. Punt on - // others. Also, not all entries may be uintptr_t sized, such as 32-bit - // processes on powerpc64 (probably the same for i386 on amd64) - if (m_size == sizeof(uint32_t)) - m_value = *(uint32_t *)(((caddr_t)®s) + m_offset); - else if (m_size == sizeof(uint64_t)) - m_value = *(uint64_t *)(((caddr_t)®s) + m_offset); - else - memcpy((void *)&m_value, (((caddr_t)®s) + m_offset), m_size); - m_result = true; - } -} - -/// \class WriteRegOperation -/// Implements ProcessMonitor::WriteRegisterValue. -class WriteRegOperation : public Operation { -public: - WriteRegOperation(lldb::tid_t tid, unsigned offset, - const RegisterValue &value, bool &result) - : m_tid(tid), m_offset(offset), m_value(value), m_result(result) {} - - void Execute(ProcessMonitor *monitor) override; - -private: - lldb::tid_t m_tid; - unsigned m_offset; - const RegisterValue &m_value; - bool &m_result; -}; - -void WriteRegOperation::Execute(ProcessMonitor *monitor) { - struct reg regs; - - if (PTRACE(PT_GETREGS, m_tid, (caddr_t)®s, 0) < 0) { - m_result = false; - return; - } - *(uintptr_t *)(((caddr_t)®s) + m_offset) = - (uintptr_t)m_value.GetAsUInt64(); - if (PTRACE(PT_SETREGS, m_tid, (caddr_t)®s, 0) < 0) - m_result = false; - else - m_result = true; -} - -/// \class ReadDebugRegOperation -/// Implements ProcessMonitor::ReadDebugRegisterValue. -class ReadDebugRegOperation : public Operation { -public: - ReadDebugRegOperation(lldb::tid_t tid, unsigned offset, unsigned size, - RegisterValue &value, bool &result) - : m_tid(tid), m_offset(offset), m_size(size), m_value(value), - m_result(result) {} - - void Execute(ProcessMonitor *monitor) override; - -private: - lldb::tid_t m_tid; - unsigned m_offset; - unsigned m_size; - RegisterValue &m_value; - bool &m_result; -}; - -void ReadDebugRegOperation::Execute(ProcessMonitor *monitor) { - struct dbreg regs; - int rc; - - if ((rc = PTRACE(PT_GETDBREGS, m_tid, (caddr_t)®s, 0)) < 0) { - m_result = false; - } else { - if (m_size == sizeof(uintptr_t)) - m_value = *(uintptr_t *)(((caddr_t)®s) + m_offset); - else - memcpy((void *)&m_value, (((caddr_t)®s) + m_offset), m_size); - m_result = true; - } -} - -/// \class WriteDebugRegOperation -/// Implements ProcessMonitor::WriteDebugRegisterValue. -class WriteDebugRegOperation : public Operation { -public: - WriteDebugRegOperation(lldb::tid_t tid, unsigned offset, - const RegisterValue &value, bool &result) - : m_tid(tid), m_offset(offset), m_value(value), m_result(result) {} - - void Execute(ProcessMonitor *monitor) override; - -private: - lldb::tid_t m_tid; - unsigned m_offset; - const RegisterValue &m_value; - bool &m_result; -}; - -void WriteDebugRegOperation::Execute(ProcessMonitor *monitor) { - struct dbreg regs; - - if (PTRACE(PT_GETDBREGS, m_tid, (caddr_t)®s, 0) < 0) { - m_result = false; - return; - } - *(uintptr_t *)(((caddr_t)®s) + m_offset) = - (uintptr_t)m_value.GetAsUInt64(); - if (PTRACE(PT_SETDBREGS, m_tid, (caddr_t)®s, 0) < 0) - m_result = false; - else - m_result = true; -} - -/// \class ReadGPROperation -/// Implements ProcessMonitor::ReadGPR. -class ReadGPROperation : public Operation { -public: - ReadGPROperation(lldb::tid_t tid, void *buf, bool &result) - : m_tid(tid), m_buf(buf), m_result(result) {} - - void Execute(ProcessMonitor *monitor) override; - -private: - lldb::tid_t m_tid; - void *m_buf; - bool &m_result; -}; - -void ReadGPROperation::Execute(ProcessMonitor *monitor) { - int rc; - - errno = 0; - rc = PTRACE(PT_GETREGS, m_tid, (caddr_t)m_buf, 0); - if (errno != 0) - m_result = false; - else - m_result = true; -} - -/// \class ReadFPROperation -/// Implements ProcessMonitor::ReadFPR. -class ReadFPROperation : public Operation { -public: - ReadFPROperation(lldb::tid_t tid, void *buf, bool &result) - : m_tid(tid), m_buf(buf), m_result(result) {} - - void Execute(ProcessMonitor *monitor) override; - -private: - lldb::tid_t m_tid; - void *m_buf; - bool &m_result; -}; - -void ReadFPROperation::Execute(ProcessMonitor *monitor) { - if (PTRACE(PT_GETFPREGS, m_tid, (caddr_t)m_buf, 0) < 0) - m_result = false; - else - m_result = true; -} - -/// \class WriteGPROperation -/// Implements ProcessMonitor::WriteGPR. -class WriteGPROperation : public Operation { -public: - WriteGPROperation(lldb::tid_t tid, void *buf, bool &result) - : m_tid(tid), m_buf(buf), m_result(result) {} - - void Execute(ProcessMonitor *monitor) override; - -private: - lldb::tid_t m_tid; - void *m_buf; - bool &m_result; -}; - -void WriteGPROperation::Execute(ProcessMonitor *monitor) { - if (PTRACE(PT_SETREGS, m_tid, (caddr_t)m_buf, 0) < 0) - m_result = false; - else - m_result = true; -} - -/// \class WriteFPROperation -/// Implements ProcessMonitor::WriteFPR. -class WriteFPROperation : public Operation { -public: - WriteFPROperation(lldb::tid_t tid, void *buf, bool &result) - : m_tid(tid), m_buf(buf), m_result(result) {} - - void Execute(ProcessMonitor *monitor) override; - -private: - lldb::tid_t m_tid; - void *m_buf; - bool &m_result; -}; - -void WriteFPROperation::Execute(ProcessMonitor *monitor) { - if (PTRACE(PT_SETFPREGS, m_tid, (caddr_t)m_buf, 0) < 0) - m_result = false; - else - m_result = true; -} - -/// \class ResumeOperation -/// Implements ProcessMonitor::Resume. -class ResumeOperation : public Operation { -public: - ResumeOperation(uint32_t signo, bool &result) - : m_signo(signo), m_result(result) {} - - void Execute(ProcessMonitor *monitor) override; - -private: - uint32_t m_signo; - bool &m_result; -}; - -void ResumeOperation::Execute(ProcessMonitor *monitor) { - lldb::pid_t pid = monitor->GetPID(); - int data = 0; - - if (m_signo != LLDB_INVALID_SIGNAL_NUMBER) - data = m_signo; - - if (PTRACE(PT_CONTINUE, pid, (caddr_t)1, data)) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - LLDB_LOG(log, "ResumeOperation ({0}) failed: {1}", pid, - llvm::sys::StrError(errno)); - m_result = false; - } else - m_result = true; -} - -/// \class SingleStepOperation -/// Implements ProcessMonitor::SingleStep. -class SingleStepOperation : public Operation { -public: - SingleStepOperation(uint32_t signo, bool &result) - : m_signo(signo), m_result(result) {} - - void Execute(ProcessMonitor *monitor) override; - -private: - uint32_t m_signo; - bool &m_result; -}; - -void SingleStepOperation::Execute(ProcessMonitor *monitor) { - lldb::pid_t pid = monitor->GetPID(); - int data = 0; - - if (m_signo != LLDB_INVALID_SIGNAL_NUMBER) - data = m_signo; - - if (PTRACE(PT_STEP, pid, NULL, data)) - m_result = false; - else - m_result = true; -} - -/// \class LwpInfoOperation -/// Implements ProcessMonitor::GetLwpInfo. -class LwpInfoOperation : public Operation { -public: - LwpInfoOperation(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 LwpInfoOperation::Execute(ProcessMonitor *monitor) { - struct ptrace_lwpinfo plwp; - - if (PTRACE(PT_LWPINFO, m_tid, (caddr_t)&plwp, sizeof(plwp))) { - m_result = false; - m_err = errno; - } else { - memcpy(m_info, &plwp, sizeof(plwp)); - m_result = true; - } -} - -/// \class ThreadSuspendOperation -/// Implements ProcessMonitor::ThreadSuspend. -class ThreadSuspendOperation : public Operation { -public: - ThreadSuspendOperation(lldb::tid_t tid, bool suspend, bool &result) - : m_tid(tid), m_suspend(suspend), m_result(result) {} - - void Execute(ProcessMonitor *monitor) override; - -private: - lldb::tid_t m_tid; - bool m_suspend; - bool &m_result; -}; - -void ThreadSuspendOperation::Execute(ProcessMonitor *monitor) { - m_result = !PTRACE(m_suspend ? PT_SUSPEND : PT_RESUME, m_tid, NULL, 0); -} - -/// \class EventMessageOperation -/// 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) { - struct ptrace_lwpinfo plwp; - - if (PTRACE(PT_LWPINFO, m_tid, (caddr_t)&plwp, sizeof(plwp))) - m_result = false; - else { - if (plwp.pl_flags & PL_FLAG_FORKED) { - *m_message = plwp.pl_child_pid; - m_result = true; - } else - m_result = false; - } -} - -/// \class KillOperation -/// Implements ProcessMonitor::Kill. -class KillOperation : public Operation { -public: - KillOperation(bool &result) : m_result(result) {} - - void Execute(ProcessMonitor *monitor) override; - -private: - bool &m_result; -}; - -void KillOperation::Execute(ProcessMonitor *monitor) { - lldb::pid_t pid = monitor->GetPID(); - - if (PTRACE(PT_KILL, pid, NULL, 0)) - m_result = false; - else - m_result = true; -} - -/// \class DetachOperation -/// Implements ProcessMonitor::Detach. -class DetachOperation : public Operation { -public: - DetachOperation(Status &result) : m_error(result) {} - - void Execute(ProcessMonitor *monitor) override; - -private: - Status &m_error; -}; - -void DetachOperation::Execute(ProcessMonitor *monitor) { - lldb::pid_t pid = monitor->GetPID(); - - if (PTRACE(PT_DETACH, pid, NULL, 0) < 0) - m_error.SetErrorToErrno(); -} - -ProcessMonitor::OperationArgs::OperationArgs(ProcessMonitor *monitor) - : m_monitor(monitor) { - 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, Environment env, - const FileSpec &stdin_file_spec, - const FileSpec &stdout_file_spec, - const FileSpec &stderr_file_spec, - const FileSpec &working_dir) - : OperationArgs(monitor), m_module(module), m_argv(argv), - m_env(std::move(env)), 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) {} - -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 ProcessFreeBSD 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( - ProcessFreeBSD *process, Module *module, const char *argv[], - Environment env, 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::Status &error) - : m_process(static_cast(process)), - m_operation_thread(), m_monitor_thread(), m_pid(LLDB_INVALID_PROCESS_ID), m_terminal_fd(-1), m_operation(0) { - using namespace std::placeholders; - - std::unique_ptr args( - new LaunchArgs(this, module, argv, std::move(env), stdin_file_spec, - stdout_file_spec, stderr_file_spec, working_dir)); - - sem_init(&m_operation_pending, 0, 0); - sem_init(&m_operation_done, 0, 0); - - StartLaunchOpThread(args.get(), error); - if (!error.Success()) - return; - - if (llvm::sys::RetryAfterSignal(-1, sem_wait, &args->m_semaphore) == -1) { - 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. - llvm::Expected monitor_thread = - Host::StartMonitoringChildProcess( - std::bind(&ProcessMonitor::MonitorCallback, this, _1, _2, _3, _4), - GetPID(), true); - if (!monitor_thread || !monitor_thread->IsJoinable()) { - error.SetErrorToGenericError(); - error.SetErrorString("Process launch failed."); - return; - } - m_monitor_thread = *monitor_thread; -} - -ProcessMonitor::ProcessMonitor(ProcessFreeBSD *process, lldb::pid_t pid, - lldb_private::Status &error) - : m_process(static_cast(process)), - m_operation_thread(), m_monitor_thread(), m_pid(pid), m_terminal_fd(-1), m_operation(0) { - using namespace std::placeholders; - - 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; - - if (llvm::sys::RetryAfterSignal(-1, sem_wait, &args->m_semaphore) == -1) { - 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. - llvm::Expected monitor_thread = - Host::StartMonitoringChildProcess( - std::bind(&ProcessMonitor::MonitorCallback, this, _1, _2, _3, _4), - GetPID(), true); - if (!monitor_thread || !monitor_thread->IsJoinable()) { - error.SetErrorToGenericError(); - error.SetErrorString("Process attach failed."); - return; - } - m_monitor_thread = *monitor_thread; -} - -ProcessMonitor::~ProcessMonitor() { StopMonitor(); } - -// Thread setup and tear down. -void ProcessMonitor::StartLaunchOpThread(LaunchArgs *args, Status &error) { - static const char *g_thread_name = "lldb.process.freebsd.operation"; - - if (m_operation_thread && m_operation_thread->IsJoinable()) - return; - - llvm::Expected operation_thread = - ThreadLauncher::LaunchThread(g_thread_name, LaunchOpThread, args); - if (operation_thread) - m_operation_thread = *operation_thread; - else - error = operation_thread.takeError(); -} - -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) { - ProcessMonitor *monitor = args->m_monitor; - ProcessFreeBSD &process = monitor->GetProcess(); - const char **argv = args->m_argv; - 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; - - PseudoTerminal terminal; - - // Propagate the environment if one is not supplied. - Environment::Envp envp = - (args->m_env.empty() ? Host::GetEnvironment() : args->m_env).getEnvp(); - - llvm::Expected pid = terminal.Fork(); - if (!pid) { - args->m_error = pid.takeError(); - 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(PT_TRACE_ME, 0, 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.CloseSecondaryFileDescriptor(); - - // 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); - - // Execute. We should never return. - execve(argv[0], const_cast(argv), envp); - exit(eExecFailed); - } - - // Wait for the child process to to trap on its call to execve. - ::pid_t wpid; - int status; - if ((wpid = waitpid(*pid, &status, 0)) < 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_t)*pid && - "Could not sync with inferior process."); - -#ifdef notyet - // Have the child raise an event on exit. This is used to keep the child in - // limbo until it is destroyed. - if (PTRACE(PTRACE_SETOPTIONS, *pid, NULL, PTRACE_O_TRACEEXIT) < 0) { - args->m_error.SetErrorToErrno(); - goto FINISH; - } -#endif - // Release the master terminal descriptor and pass it off to the - // ProcessMonitor instance. Similarly stash the inferior pid. - monitor->m_terminal_fd = terminal.ReleasePrimaryFileDescriptor(); - monitor->m_pid = *pid; - - // Set the terminal fd to be in non blocking mode (it simplifies the - // implementation of ProcessFreeBSD::GetSTDOUT to have a non-blocking - // descriptor to read from). - if (!EnsureFDFlags(monitor->m_terminal_fd, O_NONBLOCK, args->m_error)) - goto FINISH; - - process.SendMessage(ProcessMessage::Attach(*pid)); - -FINISH: - return args->m_error.Success(); -} - -void ProcessMonitor::StartAttachOpThread(AttachArgs *args, - lldb_private::Status &error) { - static const char *g_thread_name = "lldb.process.freebsd.operation"; - - if (m_operation_thread && m_operation_thread->IsJoinable()) - return; - - llvm::Expected operation_thread = - ThreadLauncher::LaunchThread(g_thread_name, AttachOpThread, args); - if (operation_thread) - m_operation_thread = *operation_thread; - else - error = operation_thread.takeError(); -} - -void *ProcessMonitor::AttachOpThread(void *arg) { - AttachArgs *args = static_cast(arg); - - Attach(args); - - ServeOperation(args); - return NULL; -} - -void ProcessMonitor::Attach(AttachArgs *args) { - lldb::pid_t pid = args->m_pid; - - ProcessMonitor *monitor = args->m_monitor; - ProcessFreeBSD &process = monitor->GetProcess(); - - if (pid <= 1) { - args->m_error.SetErrorToGenericError(); - args->m_error.SetErrorString("Attaching to process 1 is not allowed."); - return; - } - - // Attach to the requested process. - if (PTRACE(PT_ATTACH, pid, NULL, 0) < 0) { - args->m_error.SetErrorToErrno(); - return; - } - - int status; - if ((status = waitpid(pid, NULL, 0)) < 0) { - args->m_error.SetErrorToErrno(); - return; - } - - process.SendMessage(ProcessMessage::Attach(pid)); -} - -size_t -ProcessMonitor::GetCurrentThreadIDs(std::vector &thread_ids) { - lwpid_t *tids; - int tdcnt; - - thread_ids.clear(); - - tdcnt = PTRACE(PT_GETNUMLWPS, m_pid, NULL, 0); - if (tdcnt <= 0) - return 0; - tids = (lwpid_t *)malloc(tdcnt * sizeof(*tids)); - if (tids == NULL) - return 0; - if (PTRACE(PT_GETLWPLIST, m_pid, (void *)tids, tdcnt) < 0) { - free(tids); - return 0; - } - thread_ids = std::vector(tids, tids + tdcnt); - free(tids); - return thread_ids.size(); -} - -bool ProcessMonitor::MonitorCallback(ProcessMonitor *monitor, lldb::pid_t pid, - bool exited, int signal, int status) { - ProcessMessage message; - ProcessFreeBSD *process = monitor->m_process; - assert(process); - bool stop_monitoring; - struct ptrace_lwpinfo plwp; - int ptrace_err; - - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - - if (exited) { - LLDB_LOGF(log, "ProcessMonitor::%s() got exit signal, tid = %" PRIu64, - __FUNCTION__, pid); - message = ProcessMessage::Exit(pid, status); - process->SendMessage(message); - return pid == process->GetID(); - } - - if (!monitor->GetLwpInfo(pid, &plwp, ptrace_err)) - stop_monitoring = true; // pid is gone. Bail. - else { - switch (plwp.pl_siginfo.si_signo) { - case SIGTRAP: - message = MonitorSIGTRAP(monitor, &plwp.pl_siginfo, plwp.pl_lwpid); - break; - - default: - message = MonitorSignal(monitor, &plwp.pl_siginfo, plwp.pl_lwpid); - break; - } - - process->SendMessage(message); - stop_monitoring = message.GetKind() == ProcessMessage::eExitMessage; - } - - return stop_monitoring; -} - -ProcessMessage ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor, - const siginfo_t *info, - lldb::tid_t tid) { - 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; - - case (SIGTRAP /* | (PTRACE_EVENT_EXIT << 8) */): { - // The inferior process is about to exit. Maintain the process in a state - // of "limbo" until we are explicitly commanded to detach, destroy, resume, - // etc. - unsigned long data = 0; - if (!monitor->GetEventMessage(tid, &data)) - data = -1; - LLDB_LOGF(log, - "ProcessMonitor::%s() received exit? event, data = %lx, tid " - "= %" PRIu64, - __FUNCTION__, data, tid); - message = ProcessMessage::Limbo(tid, (data >> 8)); - break; - } - - case 0: - case TRAP_TRACE: -#ifdef TRAP_CAP - // Map TRAP_CAP to a trace trap in the absense of a more specific handler. - case TRAP_CAP: -#endif - LLDB_LOGF(log, - "ProcessMonitor::%s() received trace event, tid = %" PRIu64 - " : si_code = %d", - __FUNCTION__, tid, info->si_code); - message = ProcessMessage::Trace(tid); - break; - - case SI_KERNEL: - case TRAP_BRKPT: - if (monitor->m_process->IsSoftwareStepBreakpoint(tid)) { - LLDB_LOGF(log, - "ProcessMonitor::%s() received sw single step breakpoint " - "event, tid = %" PRIu64, - __FUNCTION__, tid); - message = ProcessMessage::Trace(tid); - } else { - LLDB_LOGF( - log, "ProcessMonitor::%s() received breakpoint event, tid = %" PRIu64, - __FUNCTION__, tid); - message = ProcessMessage::Break(tid); - } - break; - } - - return message; -} - -ProcessMessage ProcessMonitor::MonitorSignal(ProcessMonitor *monitor, - const siginfo_t *info, - lldb::tid_t tid) { - 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 FreeBSD. - // - // 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_USER) { - LLDB_LOGF(log, - "ProcessMonitor::%s() received signal %s with code %s, pid = %d", - __FUNCTION__, - monitor->m_process->GetUnixSignals()->GetSignalAsCString(signo), - "SI_USER", info->si_pid); - if (info->si_pid == getpid()) - return ProcessMessage::SignalDelivered(tid, signo); - else - return ProcessMessage::Signal(tid, signo); - } - - LLDB_LOGF(log, "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); - if (reason != CrashReason::eInvalidCrashReason) { - return ProcessMessage::Crash(tid, reason, signo, fault_addr); - } // else; Use atleast si_signo info for other si_code - } - - // Everything else is "normal" and does not require any special action on our - // part. - return ProcessMessage::Signal(tid, signo); -} - -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 - sem_wait(&monitor->m_operation_pending); - - monitor->m_operation->Execute(monitor); - - // notify calling thread that operation is complete - sem_post(&monitor->m_operation_done); - } -} - -void ProcessMonitor::DoOperation(Operation *op) { - std::lock_guard guard(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 - sem_wait(&m_operation_done); -} - -size_t ProcessMonitor::ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, - Status &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::Status &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, size, value, result); - DoOperation(&op); - return result; -} - -bool ProcessMonitor::WriteRegisterValue(lldb::tid_t tid, unsigned offset, - const char *reg_name, - const RegisterValue &value) { - bool result; - WriteRegOperation op(tid, offset, value, result); - DoOperation(&op); - return result; -} - -bool ProcessMonitor::ReadDebugRegisterValue( - lldb::tid_t tid, unsigned offset, const char *reg_name, unsigned size, - lldb_private::RegisterValue &value) { - bool result; - ReadDebugRegOperation op(tid, offset, size, value, result); - DoOperation(&op); - return result; -} - -bool ProcessMonitor::WriteDebugRegisterValue( - lldb::tid_t tid, unsigned offset, const char *reg_name, - const lldb_private::RegisterValue &value) { - bool result; - WriteDebugRegOperation op(tid, offset, 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, result); - DoOperation(&op); - return result; -} - -bool ProcessMonitor::ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size) { - bool result; - ReadFPROperation op(tid, buf, result); - DoOperation(&op); - return result; -} - -bool ProcessMonitor::ReadRegisterSet(lldb::tid_t tid, void *buf, - size_t buf_size, unsigned int regset) { - return false; -} - -bool ProcessMonitor::WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size) { - bool result; - WriteGPROperation op(tid, buf, result); - DoOperation(&op); - return result; -} - -bool ProcessMonitor::WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size) { - bool result; - WriteFPROperation op(tid, buf, result); - DoOperation(&op); - return result; -} - -bool ProcessMonitor::WriteRegisterSet(lldb::tid_t tid, void *buf, - size_t buf_size, unsigned int regset) { - return false; -} - -bool ProcessMonitor::ReadThreadPointer(lldb::tid_t tid, lldb::addr_t &value) { - return false; -} - -bool ProcessMonitor::Resume(lldb::tid_t unused, uint32_t signo) { - bool result; - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - - if (log) { - const char *signame = - m_process->GetUnixSignals()->GetSignalAsCString(signo); - if (signame == nullptr) - signame = ""; - LLDB_LOGF(log, - "ProcessMonitor::%s() resuming pid %" PRIu64 " with signal %s", - __FUNCTION__, GetPID(), signame); - } - ResumeOperation op(signo, result); - DoOperation(&op); - LLDB_LOGF(log, "ProcessMonitor::%s() resuming result = %s", __FUNCTION__, - result ? "true" : "false"); - return result; -} - -bool ProcessMonitor::SingleStep(lldb::tid_t unused, uint32_t signo) { - bool result; - SingleStepOperation op(signo, result); - DoOperation(&op); - return result; -} - -bool ProcessMonitor::Kill() { - bool result; - KillOperation op(result); - DoOperation(&op); - return result; -} - -bool ProcessMonitor::GetLwpInfo(lldb::tid_t tid, void *lwpinfo, - int &ptrace_err) { - bool result; - LwpInfoOperation op(tid, lwpinfo, result, ptrace_err); - DoOperation(&op); - return result; -} - -bool ProcessMonitor::ThreadSuspend(lldb::tid_t tid, bool suspend) { - bool result; - ThreadSuspendOperation op(tid, suspend, result); - 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::Status ProcessMonitor::Detach(lldb::tid_t tid) { - lldb_private::Status error; - if (tid != LLDB_INVALID_THREAD_ID) { - DetachOperation op(error); - DoOperation(&op); - } - return error; -} - -bool ProcessMonitor::DupDescriptor(const FileSpec &file_spec, int fd, - int flags) { - int target_fd = llvm::sys::RetryAfterSignal(-1, 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 && m_monitor_thread->IsJoinable()) { - m_monitor_thread->Cancel(); - m_monitor_thread->Join(nullptr); - m_monitor_thread->Reset(); - } -} - -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; - } -} - -// FIXME: 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. -// -// Right now, the above logic is in ProcessPOSIX, so we need a definition of -// this function in the FreeBSD ProcessMonitor implementation even if it isn't -// logically needed. -// -// We really should figure out what actually happens on FreeBSD and move the -// Linux-specific logic out of ProcessPOSIX as needed. - -bool ProcessMonitor::WaitForInitialTIDStop(lldb::tid_t tid) { return true; } - -void ProcessMonitor::StopOpThread() { - if (m_operation_thread && m_operation_thread->IsJoinable()) { - m_operation_thread->Cancel(); - m_operation_thread->Join(nullptr); - m_operation_thread->Reset(); - } -} diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h deleted file mode 100644 --- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h +++ /dev/null @@ -1,63 +0,0 @@ -//===-- RegisterContextPOSIX.h --------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_RegisterContextPOSIX_H_ -#define liblldb_RegisterContextPOSIX_H_ - -#include "Plugins/Process/Utility/RegisterInfoInterface.h" -#include "lldb/Target/RegisterContext.h" -#include "lldb/Utility/ArchSpec.h" - -/// \class POSIXBreakpointProtocol -/// -/// Extends RegisterClass with a few virtual operations useful on POSIX. -class POSIXBreakpointProtocol { -public: - POSIXBreakpointProtocol() { m_watchpoints_initialized = false; } - virtual ~POSIXBreakpointProtocol() {} - - /// Updates the register state of the associated thread after hitting a - /// breakpoint (if that make sense for the architecture). Default - /// implementation simply returns true for architectures which do not - /// require any update. - /// - /// \return - /// True if the operation succeeded and false otherwise. - virtual bool UpdateAfterBreakpoint() = 0; - - /// Determines the index in lldb's register file given a kernel byte offset. - virtual unsigned GetRegisterIndexFromOffset(unsigned offset) = 0; - - // Checks to see if a watchpoint specified by hw_index caused the inferior - // to stop. - virtual bool IsWatchpointHit(uint32_t hw_index) = 0; - - // Resets any watchpoints that have been hit. - virtual bool ClearWatchpointHits() = 0; - - // Returns the watchpoint address associated with a watchpoint hardware - // index. - virtual lldb::addr_t GetWatchpointAddress(uint32_t hw_index) = 0; - - virtual bool IsWatchpointVacant(uint32_t hw_index) = 0; - - virtual bool SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, - bool read, bool write, - uint32_t hw_index) = 0; - - // From lldb_private::RegisterContext - virtual uint32_t NumSupportedHardwareWatchpoints() = 0; - - // Force m_watchpoints_initialized to TRUE - void ForceWatchpointsInitialized() { m_watchpoints_initialized = true; } - -protected: - bool m_watchpoints_initialized; -}; - -#endif // #ifndef liblldb_RegisterContextPOSIX_H_ diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.h b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.h deleted file mode 100644 --- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.h +++ /dev/null @@ -1,80 +0,0 @@ -//===-- RegisterContextPOSIXProcessMonitor_arm.h --------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_RegisterContextPOSIXProcessMonitor_arm_H_ -#define liblldb_RegisterContextPOSIXProcessMonitor_arm_H_ - -#include "Plugins/Process/Utility/RegisterContextPOSIX_arm.h" -#include "RegisterContextPOSIX.h" - -class RegisterContextPOSIXProcessMonitor_arm : public RegisterContextPOSIX_arm, - public POSIXBreakpointProtocol { -public: - RegisterContextPOSIXProcessMonitor_arm( - lldb_private::Thread &thread, - std::unique_ptr register_info); - -protected: - bool ReadGPR() override; - - bool ReadFPR() override; - - bool WriteGPR() override; - - bool WriteFPR() override; - - // 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) override; - - bool WriteRegister(const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue &value) override; - - bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; - - bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; - - uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, - bool write) override; - - bool ClearHardwareWatchpoint(uint32_t hw_index) override; - - bool HardwareSingleStep(bool enable) override; - - // POSIXBreakpointProtocol - bool UpdateAfterBreakpoint() override; - - unsigned GetRegisterIndexFromOffset(unsigned offset) override; - - bool IsWatchpointHit(uint32_t hw_index) override; - - bool ClearWatchpointHits() override; - - lldb::addr_t GetWatchpointAddress(uint32_t hw_index) override; - - bool IsWatchpointVacant(uint32_t hw_index) override; - - bool SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read, - bool write, uint32_t hw_index) override; - - uint32_t NumSupportedHardwareWatchpoints() override; - -private: - RegisterInfoPOSIX_arm::GPR m_gpr_arm; - - RegisterInfoPOSIX_arm::FPU m_fpr; - - ProcessMonitor &GetMonitor(); -}; - -#endif diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp deleted file mode 100644 --- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp +++ /dev/null @@ -1,260 +0,0 @@ -//===-- RegisterContextPOSIXProcessMonitor_arm.cpp ------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===---------------------------------------------------------------------===// - -#include "lldb/Target/Thread.h" -#include "lldb/Utility/DataBufferHeap.h" -#include "lldb/Utility/RegisterValue.h" - -#include "ProcessFreeBSD.h" -#include "ProcessMonitor.h" -#include "RegisterContextPOSIXProcessMonitor_arm.h" -#include "Plugins/Process/Utility/RegisterContextPOSIX_arm.h" -#include "Plugins/Process/Utility/lldb-arm-register-enums.h" - -using namespace lldb_private; -using namespace lldb; - -#define REG_CONTEXT_SIZE (GetGPRSize()) - -RegisterContextPOSIXProcessMonitor_arm::RegisterContextPOSIXProcessMonitor_arm( - lldb_private::Thread &thread, - std::unique_ptr register_info) - : RegisterContextPOSIX_arm(thread, std::move(register_info)) {} - -ProcessMonitor &RegisterContextPOSIXProcessMonitor_arm::GetMonitor() { - ProcessSP base = CalculateProcess(); - ProcessFreeBSD *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)) { - Status 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 (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; -} diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.h b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.h deleted file mode 100644 --- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.h +++ /dev/null @@ -1,82 +0,0 @@ -//===-- RegisterContextPOSIXProcessMonitor_arm64.h --------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_RegisterContextPOSIXProcessMonitor_arm64_H_ -#define liblldb_RegisterContextPOSIXProcessMonitor_arm64_H_ - -#include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h" -#include "RegisterContextPOSIX.h" - -class RegisterContextPOSIXProcessMonitor_arm64 - : public RegisterContextPOSIX_arm64, - public POSIXBreakpointProtocol { -public: - RegisterContextPOSIXProcessMonitor_arm64( - lldb_private::Thread &thread, - std::unique_ptr register_info); - -protected: - bool ReadGPR() override; - - bool ReadFPR() override; - - bool WriteGPR() override; - - bool WriteFPR() override; - - // 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) override; - - bool WriteRegister(const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue &value) override; - - bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; - - bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; - - uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, - bool write) override; - - bool ClearHardwareWatchpoint(uint32_t hw_index) override; - - bool HardwareSingleStep(bool enable) override; - - // POSIXBreakpointProtocol - bool UpdateAfterBreakpoint() override; - - unsigned GetRegisterIndexFromOffset(unsigned offset) override; - - bool IsWatchpointHit(uint32_t hw_index) override; - - bool ClearWatchpointHits() override; - - lldb::addr_t GetWatchpointAddress(uint32_t hw_index) override; - - bool IsWatchpointVacant(uint32_t hw_index) override; - - bool SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read, - bool write, uint32_t hw_index) override; - - uint32_t NumSupportedHardwareWatchpoints() override; - -private: - RegisterInfoPOSIX_arm64::GPR m_gpr_arm64; // 64-bit general purpose registers. - - RegisterInfoPOSIX_arm64::FPU - m_fpr; // floating-point registers including extended register sets. - - ProcessMonitor &GetMonitor(); -}; - -#endif diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp deleted file mode 100644 --- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp +++ /dev/null @@ -1,267 +0,0 @@ -//===-- RegisterContextPOSIXProcessMonitor_arm64.cpp ----------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===---------------------------------------------------------------------===// - -#include "lldb/Target/Thread.h" -#include "lldb/Utility/DataBufferHeap.h" -#include "lldb/Utility/RegisterValue.h" - -#include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h" -#include "ProcessFreeBSD.h" -#include "ProcessMonitor.h" -#include "RegisterContextPOSIXProcessMonitor_arm64.h" - -#define REG_CONTEXT_SIZE (GetGPRSize()) - -using namespace lldb; -using namespace lldb_private; - -RegisterContextPOSIXProcessMonitor_arm64:: - RegisterContextPOSIXProcessMonitor_arm64( - lldb_private::Thread &thread, - std::unique_ptr register_info) - : RegisterContextPOSIX_arm64(thread, std::move(register_info)) { - ::memset(&m_gpr_arm64, 0, sizeof m_gpr_arm64); - ::memset(&m_fpr, 0, sizeof m_fpr); -} - -ProcessMonitor &RegisterContextPOSIXProcessMonitor_arm64::GetMonitor() { - lldb::ProcessSP base = CalculateProcess(); - ProcessFreeBSD *process = static_cast(base.get()); - return process->GetMonitor(); -} - -bool RegisterContextPOSIXProcessMonitor_arm64::ReadGPR() { - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadGPR(m_thread.GetID(), &m_gpr_arm64, GetGPRSize()); -} - -bool RegisterContextPOSIXProcessMonitor_arm64::ReadFPR() { - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadFPR(m_thread.GetID(), &m_fpr, sizeof m_fpr); -} - -bool RegisterContextPOSIXProcessMonitor_arm64::WriteGPR() { - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteGPR(m_thread.GetID(), &m_gpr_arm64, GetGPRSize()); -} - -bool RegisterContextPOSIXProcessMonitor_arm64::WriteFPR() { - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteFPR(m_thread.GetID(), &m_fpr, sizeof m_fpr); -} - -bool RegisterContextPOSIXProcessMonitor_arm64::ReadRegister( - const unsigned reg, lldb_private::RegisterValue &value) { - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadRegisterValue(m_thread.GetID(), GetRegisterOffset(reg), - GetRegisterName(reg), GetRegisterSize(reg), - value); -} - -bool RegisterContextPOSIXProcessMonitor_arm64::WriteRegister( - const unsigned reg, const lldb_private::RegisterValue &value) { - unsigned reg_to_write = reg; - lldb_private::RegisterValue value_to_write = value; - - // Check if this is a subregister of a full register. - const lldb_private::RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg); - if (reg_info->invalidate_regs && - (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) { - lldb_private::RegisterValue full_value; - uint32_t full_reg = reg_info->invalidate_regs[0]; - const lldb_private::RegisterInfo *full_reg_info = - GetRegisterInfoAtIndex(full_reg); - - // Read the full register. - if (ReadRegister(full_reg_info, full_value)) { - lldb_private::Status error; - lldb::ByteOrder byte_order = GetByteOrder(); - uint8_t dst[lldb_private::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[lldb_private::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_arm64::ReadRegister( - const lldb_private::RegisterInfo *reg_info, - lldb_private::RegisterValue &value) { - if (!reg_info) - return false; - - const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; - - if (IsFPR(reg)) { - if (!ReadFPR()) - return false; - } else { - uint32_t full_reg = reg; - bool is_subreg = reg_info->invalidate_regs && - (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); - - if (is_subreg) { - // Read the full aligned 64-bit register. - full_reg = reg_info->invalidate_regs[0]; - } - return ReadRegister(full_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_arm64::WriteRegister( - const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue &value) { - const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; - - if (IsGPR(reg)) - return WriteRegister(reg, value); - - return false; -} - -bool RegisterContextPOSIXProcessMonitor_arm64::ReadAllRegisterValues( - lldb::DataBufferSP &data_sp) { - bool success = false; - data_sp.reset(new lldb_private::DataBufferHeap(REG_CONTEXT_SIZE, 0)); - if (ReadGPR() && ReadFPR()) { - uint8_t *dst = data_sp->GetBytes(); - success = dst != 0; - - if (success) { - ::memcpy(dst, &m_gpr_arm64, GetGPRSize()); - dst += GetGPRSize(); - ::memcpy(dst, &m_fpr, sizeof m_fpr); - } - } - return success; -} - -bool RegisterContextPOSIXProcessMonitor_arm64::WriteAllRegisterValues( - const lldb::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_arm64, src, GetGPRSize()); - if (WriteGPR()) { - src += GetGPRSize(); - ::memcpy(&m_fpr, src, sizeof m_fpr); - success = WriteFPR(); - } - } - } - return success; -} - -uint32_t RegisterContextPOSIXProcessMonitor_arm64::SetHardwareWatchpoint( - lldb::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_arm64::ClearHardwareWatchpoint( - uint32_t hw_index) { - return false; -} - -bool RegisterContextPOSIXProcessMonitor_arm64::HardwareSingleStep(bool enable) { - return false; -} - -bool RegisterContextPOSIXProcessMonitor_arm64::UpdateAfterBreakpoint() { - if (GetPC() == LLDB_INVALID_ADDRESS) - return false; - - return true; -} - -unsigned RegisterContextPOSIXProcessMonitor_arm64::GetRegisterIndexFromOffset( - unsigned offset) { - unsigned reg; - for (reg = 0; reg < GetRegisterCount(); reg++) { - if (GetRegisterInfo()[reg].byte_offset == offset) - break; - } - assert(reg < GetRegisterCount() && "Invalid register offset."); - return reg; -} - -bool RegisterContextPOSIXProcessMonitor_arm64::IsWatchpointHit( - uint32_t hw_index) { - return false; -} - -bool RegisterContextPOSIXProcessMonitor_arm64::ClearWatchpointHits() { - return false; -} - -lldb::addr_t RegisterContextPOSIXProcessMonitor_arm64::GetWatchpointAddress( - uint32_t hw_index) { - return LLDB_INVALID_ADDRESS; -} - -bool RegisterContextPOSIXProcessMonitor_arm64::IsWatchpointVacant( - uint32_t hw_index) { - return false; -} - -bool RegisterContextPOSIXProcessMonitor_arm64::SetHardwareWatchpointWithIndex( - lldb::addr_t addr, size_t size, bool read, bool write, uint32_t hw_index) { - return false; -} - -uint32_t -RegisterContextPOSIXProcessMonitor_arm64::NumSupportedHardwareWatchpoints() { - return 0; -} diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.h b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.h deleted file mode 100644 --- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.h +++ /dev/null @@ -1,82 +0,0 @@ -//===-- RegisterContextPOSIXProcessMonitor_mips64.h -------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_RegisterContextPOSIXProcessMonitor_mips64_H_ -#define liblldb_RegisterContextPOSIXProcessMonitor_mips64_H_ - -#include "Plugins/Process/Utility/RegisterContextPOSIX_mips64.h" -#include "Plugins/Process/Utility/lldb-mips-freebsd-register-enums.h" -#include "RegisterContextPOSIX.h" - -class ProcessMonitor; - -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() override; - - bool ReadFPR() override; - - bool WriteGPR() override; - - bool WriteFPR() override; - - // 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) override; - - bool WriteRegister(const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue &value) override; - - bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; - - bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; - - uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, - bool write) override; - - bool ClearHardwareWatchpoint(uint32_t hw_index) override; - - bool HardwareSingleStep(bool enable) override; - - // POSIXBreakpointProtocol - bool UpdateAfterBreakpoint() override; - - unsigned GetRegisterIndexFromOffset(unsigned offset) override; - - bool IsWatchpointHit(uint32_t hw_index) override; - - bool ClearWatchpointHits() override; - - lldb::addr_t GetWatchpointAddress(uint32_t hw_index) override; - - bool IsWatchpointVacant(uint32_t hw_index) override; - - bool SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read, - bool write, uint32_t hw_index) override; - - uint32_t NumSupportedHardwareWatchpoints() override; - -private: - uint64_t - m_gpr_mips64[lldb_private::k_num_gpr_registers_mips64]; // general purpose registers. - ProcessMonitor &GetMonitor(); -}; - -#endif diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp deleted file mode 100644 --- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp +++ /dev/null @@ -1,262 +0,0 @@ -//===-- RegisterContextPOSIXProcessMonitor_mips64.cpp ---------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "lldb/Target/Thread.h" -#include "lldb/Utility/DataBufferHeap.h" -#include "lldb/Utility/RegisterValue.h" - -#include "Plugins/Process/Utility/RegisterContextPOSIX_mips64.h" -#include "ProcessFreeBSD.h" -#include "ProcessMonitor.h" -#include "RegisterContextPOSIXProcessMonitor_mips64.h" - -using namespace lldb_private; -using namespace lldb; - -#define REG_CONTEXT_SIZE (GetGPRSize()) - -RegisterContextPOSIXProcessMonitor_mips64:: - RegisterContextPOSIXProcessMonitor_mips64( - Thread &thread, uint32_t concrete_frame_idx, - lldb_private::RegisterInfoInterface *register_info) - : RegisterContextPOSIX_mips64(thread, concrete_frame_idx, register_info) {} - -ProcessMonitor &RegisterContextPOSIXProcessMonitor_mips64::GetMonitor() { - ProcessSP base = CalculateProcess(); - ProcessFreeBSD *process = static_cast(base.get()); - return process->GetMonitor(); -} - -bool RegisterContextPOSIXProcessMonitor_mips64::ReadGPR() { - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadGPR(m_thread.GetID(), &m_gpr_mips64, GetGPRSize()); -} - -bool RegisterContextPOSIXProcessMonitor_mips64::ReadFPR() { - // XXX not yet implemented - return false; -} - -bool RegisterContextPOSIXProcessMonitor_mips64::WriteGPR() { - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteGPR(m_thread.GetID(), &m_gpr_mips64, GetGPRSize()); -} - -bool RegisterContextPOSIXProcessMonitor_mips64::WriteFPR() { - // XXX not yet implemented - return false; -} - -bool RegisterContextPOSIXProcessMonitor_mips64::ReadRegister( - const unsigned reg, RegisterValue &value) { - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadRegisterValue(m_thread.GetID(), GetRegisterOffset(reg), - GetRegisterName(reg), GetRegisterSize(reg), - value); -} - -bool RegisterContextPOSIXProcessMonitor_mips64::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)) { - Status 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_mips64::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 { - uint32_t full_reg = reg; - bool is_subreg = reg_info->invalidate_regs && - (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); - - if (is_subreg) { - // Read the full aligned 64-bit register. - full_reg = reg_info->invalidate_regs[0]; - } - - bool success = ReadRegister(full_reg, value); - - if (success) { - // If our read was not aligned (for ah,bh,ch,dh), shift our returned - // value one byte to the right. - if (is_subreg && (reg_info->byte_offset & 0x1)) - value.SetUInt64(value.GetAsUInt64() >> 8); - - // 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_mips64::WriteRegister( - const RegisterInfo *reg_info, const RegisterValue &value) { - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - - if (IsGPR(reg)) - return WriteRegister(reg, value); - - return false; -} - -bool RegisterContextPOSIXProcessMonitor_mips64::ReadAllRegisterValues( - DataBufferSP &data_sp) { - bool success = false; - data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); - if (ReadGPR() && ReadFPR()) { - uint8_t *dst = data_sp->GetBytes(); - success = dst != 0; - - if (success) { - ::memcpy(dst, &m_gpr_mips64, GetGPRSize()); - } - } - return success; -} - -bool RegisterContextPOSIXProcessMonitor_mips64::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_mips64, src, GetGPRSize()); - - if (WriteGPR()) { - src += GetGPRSize(); - } - } - } - return success; -} - -uint32_t RegisterContextPOSIXProcessMonitor_mips64::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_mips64::ClearHardwareWatchpoint( - uint32_t hw_index) { - return false; -} - -bool RegisterContextPOSIXProcessMonitor_mips64::HardwareSingleStep( - bool enable) { - return false; -} - -bool RegisterContextPOSIXProcessMonitor_mips64::UpdateAfterBreakpoint() { - // PC points one byte past the int3 responsible for the breakpoint. - lldb::addr_t pc; - - if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) - return false; - - SetPC(pc - 1); - return true; -} - -unsigned RegisterContextPOSIXProcessMonitor_mips64::GetRegisterIndexFromOffset( - unsigned offset) { - unsigned reg; - for (reg = 0; reg < k_num_registers_mips64; reg++) { - if (GetRegisterInfo()[reg].byte_offset == offset) - break; - } - assert(reg < k_num_registers_mips64 && "Invalid register offset."); - return reg; -} - -bool RegisterContextPOSIXProcessMonitor_mips64::IsWatchpointHit( - uint32_t hw_index) { - return false; -} - -bool RegisterContextPOSIXProcessMonitor_mips64::ClearWatchpointHits() { - return false; -} - -addr_t RegisterContextPOSIXProcessMonitor_mips64::GetWatchpointAddress( - uint32_t hw_index) { - return LLDB_INVALID_ADDRESS; -} - -bool RegisterContextPOSIXProcessMonitor_mips64::IsWatchpointVacant( - uint32_t hw_index) { - return false; -} - -bool RegisterContextPOSIXProcessMonitor_mips64::SetHardwareWatchpointWithIndex( - addr_t addr, size_t size, bool read, bool write, uint32_t hw_index) { - return false; -} - -uint32_t -RegisterContextPOSIXProcessMonitor_mips64::NumSupportedHardwareWatchpoints() { - return 0; -} diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.h b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.h deleted file mode 100644 --- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.h +++ /dev/null @@ -1,84 +0,0 @@ -//===-- RegisterContextPOSIXProcessMonitor_powerpc.h -------------*- C++ -//-*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_RegisterContextPOSIXProcessMonitor_powerpc_H_ -#define liblldb_RegisterContextPOSIXProcessMonitor_powerpc_H_ - -#include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h" -#include "RegisterContextPOSIX.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() override; - - bool ReadFPR() override; - - bool ReadVMX() override; - - bool WriteGPR() override; - - bool WriteFPR() override; - - bool WriteVMX() override; - - // 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) override; - - bool WriteRegister(const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue &value) override; - - bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; - - bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; - - uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, - bool write) override; - - bool ClearHardwareWatchpoint(uint32_t hw_index) override; - - bool HardwareSingleStep(bool enable) override; - - // POSIXBreakpointProtocol - bool UpdateAfterBreakpoint() override; - - unsigned GetRegisterIndexFromOffset(unsigned offset) override; - - bool IsWatchpointHit(uint32_t hw_index) override; - - bool ClearWatchpointHits() override; - - lldb::addr_t GetWatchpointAddress(uint32_t hw_index) override; - - bool IsWatchpointVacant(uint32_t hw_index) override; - - bool SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read, - bool write, uint32_t hw_index) override; - - uint32_t NumSupportedHardwareWatchpoints() override; - -private: - ProcessMonitor &GetMonitor(); -}; - -#endif diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp deleted file mode 100644 --- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp +++ /dev/null @@ -1,274 +0,0 @@ -//===-- RegisterContextPOSIXProcessMonitor_powerpc.cpp --------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "lldb/Target/Thread.h" -#include "lldb/Utility/DataBufferHeap.h" -#include "lldb/Utility/RegisterValue.h" - -#include "ProcessFreeBSD.h" -#include "ProcessMonitor.h" -#include "RegisterContextPOSIXProcessMonitor_powerpc.h" -#include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.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(); - ProcessFreeBSD *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)) { - Status 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 (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; -} diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h deleted file mode 100644 --- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h +++ /dev/null @@ -1,81 +0,0 @@ -//===-- RegisterContextPOSIXProcessMonitor_x86.h ----------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_RegisterContextPOSIXProcessMonitor_x86_H_ -#define liblldb_RegisterContextPOSIXProcessMonitor_x86_H_ - -#include "Plugins/Process/Utility/RegisterContextPOSIX_x86.h" -#include "RegisterContextPOSIX.h" -#include - -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() override; - - bool ReadFPR() override; - - bool WriteGPR() override; - - bool WriteFPR() override; - - // 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) override; - - bool WriteRegister(const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue &value) override; - - bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; - - bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; - - uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, - bool write) override; - - bool ClearHardwareWatchpoint(uint32_t hw_index) override; - - bool HardwareSingleStep(bool enable) override; - - // POSIXBreakpointProtocol - bool UpdateAfterBreakpoint() override; - - unsigned GetRegisterIndexFromOffset(unsigned offset) override; - - bool IsWatchpointHit(uint32_t hw_index) override; - - bool ClearWatchpointHits() override; - - lldb::addr_t GetWatchpointAddress(uint32_t hw_index) override; - - bool IsWatchpointVacant(uint32_t hw_index) override; - - bool SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read, - bool write, uint32_t hw_index) override; - - uint32_t NumSupportedHardwareWatchpoints() override; - -private: - ProcessMonitor &GetMonitor(); - uint32_t - m_fctrl_offset_in_userarea; // Offset of 'fctrl' in 'UserArea' Structure - struct iovec m_iovec; -}; - -#endif diff --git a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp b/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp deleted file mode 100644 --- a/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp +++ /dev/null @@ -1,613 +0,0 @@ -//===-- RegisterContextPOSIXProcessMonitor_x86.cpp ------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "lldb/Target/Thread.h" -#include "lldb/Utility/DataBufferHeap.h" -#include "lldb/Utility/RegisterValue.h" - -#include "Plugins/Process/FreeBSD/ProcessFreeBSD.h" -#include "Plugins/Process/FreeBSD/ProcessMonitor.h" -#include "RegisterContextPOSIXProcessMonitor_x86.h" - -using namespace lldb_private; -using namespace lldb; - -// Support ptrace extensions even when compiled without required kernel support -#ifndef NT_X86_XSTATE -#define NT_X86_XSTATE 0x202 -#endif - -#define REG_CONTEXT_SIZE (GetGPRSize() + sizeof(FPR)) - -static uint32_t size_and_rw_bits(size_t size, bool read, bool write) { - uint32_t rw; - - if (read) - rw = 0x3; // READ or READ/WRITE - else if (write) - rw = 0x1; // WRITE - else - assert(0 && "read and write cannot both be false"); - - switch (size) { - case 1: - return rw; - case 2: - return (0x1 << 2) | rw; - case 4: - return (0x3 << 2) | rw; - case 8: - return (0x2 << 2) | rw; - default: - assert(0 && "invalid size, must be one of 1, 2, 4, or 8"); - return 0; // Unreachable. Just to silence compiler. - } -} - -RegisterContextPOSIXProcessMonitor_x86_64:: - RegisterContextPOSIXProcessMonitor_x86_64( - Thread &thread, uint32_t concrete_frame_idx, - lldb_private::RegisterInfoInterface *register_info) - : RegisterContextPOSIX_x86(thread, concrete_frame_idx, register_info) { - // Store byte offset of fctrl (i.e. first register of FPR) wrt 'UserArea' - const RegisterInfo *reg_info_fctrl = GetRegisterInfoByName("fctrl"); - m_fctrl_offset_in_userarea = reg_info_fctrl->byte_offset; - - m_iovec.iov_base = &m_fpr.xsave; - m_iovec.iov_len = sizeof(m_fpr.xsave); -} - -ProcessMonitor &RegisterContextPOSIXProcessMonitor_x86_64::GetMonitor() { - ProcessSP base = CalculateProcess(); - ProcessFreeBSD *process = static_cast(base.get()); - return process->GetMonitor(); -} - -bool RegisterContextPOSIXProcessMonitor_x86_64::ReadGPR() { - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadGPR(m_thread.GetID(), &m_gpr_x86_64, GetGPRSize()); -} - -bool RegisterContextPOSIXProcessMonitor_x86_64::ReadFPR() { - ProcessMonitor &monitor = GetMonitor(); - if (GetFPRType() == eFXSAVE) - return monitor.ReadFPR(m_thread.GetID(), &m_fpr.fxsave, - sizeof(m_fpr.fxsave)); - - if (GetFPRType() == eXSAVE) - return monitor.ReadRegisterSet(m_thread.GetID(), &m_iovec, - sizeof(m_fpr.xsave), NT_X86_XSTATE); - return false; -} - -bool RegisterContextPOSIXProcessMonitor_x86_64::WriteGPR() { - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteGPR(m_thread.GetID(), &m_gpr_x86_64, GetGPRSize()); -} - -bool RegisterContextPOSIXProcessMonitor_x86_64::WriteFPR() { - ProcessMonitor &monitor = GetMonitor(); - if (GetFPRType() == eFXSAVE) - return monitor.WriteFPR(m_thread.GetID(), &m_fpr.fxsave, - sizeof(m_fpr.fxsave)); - - if (GetFPRType() == eXSAVE) - return monitor.WriteRegisterSet(m_thread.GetID(), &m_iovec, - sizeof(m_fpr.xsave), NT_X86_XSTATE); - return false; -} - -bool RegisterContextPOSIXProcessMonitor_x86_64::ReadRegister( - const unsigned reg, RegisterValue &value) { - ProcessMonitor &monitor = GetMonitor(); - -#if defined(__FreeBSD__) - if (reg >= m_reg_info.first_dr) - return monitor.ReadDebugRegisterValue( - m_thread.GetID(), GetRegisterOffset(reg), GetRegisterName(reg), - GetRegisterSize(reg), value); -#endif - return monitor.ReadRegisterValue(m_thread.GetID(), GetRegisterOffset(reg), - GetRegisterName(reg), GetRegisterSize(reg), - value); -} - -bool RegisterContextPOSIXProcessMonitor_x86_64::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)) { - Status 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(); -#if defined(__FreeBSD__) - if (reg >= m_reg_info.first_dr) - return monitor.WriteDebugRegisterValue( - m_thread.GetID(), GetRegisterOffset(reg_to_write), - GetRegisterName(reg_to_write), value_to_write); -#endif - return monitor.WriteRegisterValue( - m_thread.GetID(), GetRegisterOffset(reg_to_write), - GetRegisterName(reg_to_write), value_to_write); -} - -bool RegisterContextPOSIXProcessMonitor_x86_64::ReadRegister( - const RegisterInfo *reg_info, RegisterValue &value) { - if (!reg_info) - return false; - - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - - if (IsFPR(reg, GetFPRType())) { - if (!ReadFPR()) - return false; - } else { - uint32_t full_reg = reg; - bool is_subreg = reg_info->invalidate_regs && - (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); - - if (is_subreg) { - // Read the full aligned 64-bit register. - full_reg = reg_info->invalidate_regs[0]; - } - - bool success = ReadRegister(full_reg, value); - - if (success) { - // If our read was not aligned (for ah,bh,ch,dh), shift our returned - // value one byte to the right. - if (is_subreg && (reg_info->byte_offset & 0x1)) - value.SetUInt64(value.GetAsUInt64() >> 8); - - // 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; - } - - if (reg_info->encoding == eEncodingVector) { - ByteOrder byte_order = GetByteOrder(); - - if (byte_order != ByteOrder::eByteOrderInvalid) { - if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st) - value.SetBytes(m_fpr.fxsave.stmm[reg - m_reg_info.first_st].bytes, - reg_info->byte_size, byte_order); - if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm) - value.SetBytes(m_fpr.fxsave.stmm[reg - m_reg_info.first_mm].bytes, - reg_info->byte_size, byte_order); - if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm) - value.SetBytes(m_fpr.fxsave.xmm[reg - m_reg_info.first_xmm].bytes, - reg_info->byte_size, byte_order); - if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm) { - // Concatenate ymm using the register halves in xmm.bytes and - // ymmh.bytes - if (GetFPRType() == eXSAVE && CopyXSTATEtoYMM(reg, byte_order)) - value.SetBytes(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, - reg_info->byte_size, byte_order); - else - return false; - } - return value.GetType() == RegisterValue::eTypeBytes; - } - return false; - } - - // Get pointer to m_fpr.fxsave variable and set the data from it. Byte - // offsets of all registers are calculated wrt 'UserArea' structure. However, - // ReadFPR() reads fpu registers {using ptrace(PT_GETFPREGS,..)} and stores - // them in 'm_fpr' (of type FPR structure). To extract values of fpu - // registers, m_fpr should be read at byte offsets calculated wrt to FPR - // structure. - - // Since, FPR structure is also one of the member of UserArea structure. - // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) - - // byte_offset(fctrl wrt UserArea) - assert((reg_info->byte_offset - m_fctrl_offset_in_userarea) < sizeof(m_fpr)); - uint8_t *src = - (uint8_t *)&m_fpr + reg_info->byte_offset - m_fctrl_offset_in_userarea; - switch (reg_info->byte_size) { - case 1: - value.SetUInt8(*(uint8_t *)src); - return true; - 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_x86_64::WriteRegister( - const RegisterInfo *reg_info, const RegisterValue &value) { - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - - if (IsGPR(reg)) - return WriteRegister(reg, value); - - if (IsFPR(reg, GetFPRType())) { - if (reg_info->encoding == eEncodingVector) { - if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st) - ::memcpy(m_fpr.fxsave.stmm[reg - m_reg_info.first_st].bytes, - value.GetBytes(), value.GetByteSize()); - - if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm) - ::memcpy(m_fpr.fxsave.stmm[reg - m_reg_info.first_mm].bytes, - value.GetBytes(), value.GetByteSize()); - - if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm) - ::memcpy(m_fpr.fxsave.xmm[reg - m_reg_info.first_xmm].bytes, - value.GetBytes(), value.GetByteSize()); - - if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm) { - if (GetFPRType() != eXSAVE) - return false; // the target processor does not support AVX - - // Store ymm register content, and split into the register halves in - // xmm.bytes and ymmh.bytes - ::memcpy(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, - value.GetBytes(), value.GetByteSize()); - if (false == CopyYMMtoXSTATE(reg, GetByteOrder())) - return false; - } - } else { - // Get pointer to m_fpr.fxsave variable and set the data to it. Byte - // offsets of all registers are calculated wrt 'UserArea' structure. - // However, WriteFPR() takes m_fpr (of type FPR structure) and writes - // only fpu registers using ptrace(PT_SETFPREGS,..) API. Hence fpu - // registers should be written in m_fpr at byte offsets calculated wrt - // FPR structure. - - // Since, FPR structure is also one of the member of UserArea structure. - // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) - - // byte_offset(fctrl wrt UserArea) - assert((reg_info->byte_offset - m_fctrl_offset_in_userarea) < - sizeof(m_fpr)); - uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset - - m_fctrl_offset_in_userarea; - switch (reg_info->byte_size) { - case 1: - *(uint8_t *)dst = value.GetAsUInt8(); - break; - case 2: - *(uint16_t *)dst = value.GetAsUInt16(); - break; - case 4: - *(uint32_t *)dst = value.GetAsUInt32(); - break; - case 8: - *(uint64_t *)dst = value.GetAsUInt64(); - break; - default: - assert(false && "Unhandled data size."); - return false; - } - } - - if (WriteFPR()) { - if (IsAVX(reg)) - return CopyYMMtoXSTATE(reg, GetByteOrder()); - return true; - } - } - return false; -} - -bool RegisterContextPOSIXProcessMonitor_x86_64::ReadAllRegisterValues( - DataBufferSP &data_sp) { - bool success = false; - data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); - if (ReadGPR() && ReadFPR()) { - uint8_t *dst = data_sp->GetBytes(); - success = dst != 0; - - if (success) { - ::memcpy(dst, &m_gpr_x86_64, GetGPRSize()); - dst += GetGPRSize(); - if (GetFPRType() == eFXSAVE) - ::memcpy(dst, &m_fpr.fxsave, sizeof(m_fpr.fxsave)); - } - - if (GetFPRType() == eXSAVE) { - ByteOrder byte_order = GetByteOrder(); - - // Assemble the YMM register content from the register halves. - for (uint32_t reg = m_reg_info.first_ymm; - success && reg <= m_reg_info.last_ymm; ++reg) - success = CopyXSTATEtoYMM(reg, byte_order); - - if (success) { - // Copy the extended register state including the assembled ymm - // registers. - ::memcpy(dst, &m_fpr, sizeof(m_fpr)); - } - } - } - return success; -} - -bool RegisterContextPOSIXProcessMonitor_x86_64::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_x86_64, src, GetGPRSize()); - - if (WriteGPR()) { - src += GetGPRSize(); - if (GetFPRType() == eFXSAVE) - ::memcpy(&m_fpr.fxsave, src, sizeof(m_fpr.fxsave)); - if (GetFPRType() == eXSAVE) - ::memcpy(&m_fpr.xsave, src, sizeof(m_fpr.xsave)); - - success = WriteFPR(); - if (success) { - if (GetFPRType() == eXSAVE) { - ByteOrder byte_order = GetByteOrder(); - - // Parse the YMM register content from the register halves. - for (uint32_t reg = m_reg_info.first_ymm; - success && reg <= m_reg_info.last_ymm; ++reg) - success = CopyYMMtoXSTATE(reg, byte_order); - } - } - } - } - } - return success; -} - -uint32_t RegisterContextPOSIXProcessMonitor_x86_64::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_x86_64::ClearHardwareWatchpoint( - uint32_t hw_index) { - if (hw_index < NumSupportedHardwareWatchpoints()) { - RegisterValue current_dr7_bits; - - if (ReadRegister(m_reg_info.first_dr + 7, current_dr7_bits)) { - uint64_t new_dr7_bits = - current_dr7_bits.GetAsUInt64() & ~(3 << (2 * hw_index)); - - if (WriteRegister(m_reg_info.first_dr + 7, RegisterValue(new_dr7_bits))) - return true; - } - } - - return false; -} - -bool RegisterContextPOSIXProcessMonitor_x86_64::HardwareSingleStep( - bool enable) { - enum { TRACE_BIT = 0x100 }; - uint64_t rflags; - - if ((rflags = ReadRegisterAsUnsigned(m_reg_info.gpr_flags, -1UL)) == -1UL) - return false; - - if (enable) { - if (rflags & TRACE_BIT) - return true; - - rflags |= TRACE_BIT; - } else { - if (!(rflags & TRACE_BIT)) - return false; - - rflags &= ~TRACE_BIT; - } - - return WriteRegisterFromUnsigned(m_reg_info.gpr_flags, rflags); -} - -bool RegisterContextPOSIXProcessMonitor_x86_64::UpdateAfterBreakpoint() { - // PC points one byte past the int3 responsible for the breakpoint. - lldb::addr_t pc; - - if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) - return false; - - SetPC(pc - 1); - return true; -} - -unsigned RegisterContextPOSIXProcessMonitor_x86_64::GetRegisterIndexFromOffset( - unsigned offset) { - unsigned reg; - for (reg = 0; reg < m_reg_info.num_registers; reg++) { - if (GetRegisterInfo()[reg].byte_offset == offset) - break; - } - assert(reg < m_reg_info.num_registers && "Invalid register offset."); - return reg; -} - -bool RegisterContextPOSIXProcessMonitor_x86_64::IsWatchpointHit( - uint32_t hw_index) { - bool is_hit = false; - - if (m_watchpoints_initialized == false) { - // Reset the debug status and debug control registers - RegisterValue zero_bits = RegisterValue(uint64_t(0)); - if (!WriteRegister(m_reg_info.first_dr + 6, zero_bits) || - !WriteRegister(m_reg_info.first_dr + 7, zero_bits)) - assert(false && "Could not initialize watchpoint registers"); - m_watchpoints_initialized = true; - } - - if (hw_index < NumSupportedHardwareWatchpoints()) { - RegisterValue value; - - if (ReadRegister(m_reg_info.first_dr + 6, value)) { - uint64_t val = value.GetAsUInt64(); - is_hit = val & (1 << hw_index); - } - } - - return is_hit; -} - -bool RegisterContextPOSIXProcessMonitor_x86_64::ClearWatchpointHits() { - return WriteRegister(m_reg_info.first_dr + 6, RegisterValue((uint64_t)0)); -} - -addr_t RegisterContextPOSIXProcessMonitor_x86_64::GetWatchpointAddress( - uint32_t hw_index) { - addr_t wp_monitor_addr = LLDB_INVALID_ADDRESS; - - if (hw_index < NumSupportedHardwareWatchpoints()) { - if (!IsWatchpointVacant(hw_index)) { - RegisterValue value; - - if (ReadRegister(m_reg_info.first_dr + hw_index, value)) - wp_monitor_addr = value.GetAsUInt64(); - } - } - - return wp_monitor_addr; -} - -bool RegisterContextPOSIXProcessMonitor_x86_64::IsWatchpointVacant( - uint32_t hw_index) { - bool is_vacant = false; - RegisterValue value; - - assert(hw_index < NumSupportedHardwareWatchpoints()); - - if (m_watchpoints_initialized == false) { - // Reset the debug status and debug control registers - RegisterValue zero_bits = RegisterValue(uint64_t(0)); - if (!WriteRegister(m_reg_info.first_dr + 6, zero_bits) || - !WriteRegister(m_reg_info.first_dr + 7, zero_bits)) - assert(false && "Could not initialize watchpoint registers"); - m_watchpoints_initialized = true; - } - - if (ReadRegister(m_reg_info.first_dr + 7, value)) { - uint64_t val = value.GetAsUInt64(); - is_vacant = (val & (3 << 2 * hw_index)) == 0; - } - - return is_vacant; -} - -bool RegisterContextPOSIXProcessMonitor_x86_64::SetHardwareWatchpointWithIndex( - addr_t addr, size_t size, bool read, bool write, uint32_t hw_index) { - const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); - - if (num_hw_watchpoints == 0 || hw_index >= num_hw_watchpoints) - return false; - - if (!(size == 1 || size == 2 || size == 4 || size == 8)) - return false; - - if (read == false && write == false) - return false; - - if (!IsWatchpointVacant(hw_index)) - return false; - - // Set both dr7 (debug control register) and dri (debug address register). - - // dr7{7-0} encodes the local/global enable bits: - // global enable --. .-- local enable - // | | - // v v - // dr0 -> bits{1-0} - // dr1 -> bits{3-2} - // dr2 -> bits{5-4} - // dr3 -> bits{7-6} - // - // dr7{31-16} encodes the rw/len bits: - // b_x+3, b_x+2, b_x+1, b_x - // where bits{x+1, x} => rw - // 0b00: execute, 0b01: write, 0b11: read-or-write, - // 0b10: io read-or-write (unused) - // and bits{x+3, x+2} => len - // 0b00: 1-byte, 0b01: 2-byte, 0b11: 4-byte, 0b10: 8-byte - // - // dr0 -> bits{19-16} - // dr1 -> bits{23-20} - // dr2 -> bits{27-24} - // dr3 -> bits{31-28} - if (hw_index < num_hw_watchpoints) { - RegisterValue current_dr7_bits; - - if (ReadRegister(m_reg_info.first_dr + 7, current_dr7_bits)) { - uint64_t new_dr7_bits = - current_dr7_bits.GetAsUInt64() | - (1 << (2 * hw_index) | - size_and_rw_bits(size, read, write) << (16 + 4 * hw_index)); - - if (WriteRegister(m_reg_info.first_dr + hw_index, RegisterValue(addr)) && - WriteRegister(m_reg_info.first_dr + 7, RegisterValue(new_dr7_bits))) - return true; - } - } - - return false; -} - -uint32_t -RegisterContextPOSIXProcessMonitor_x86_64::NumSupportedHardwareWatchpoints() { - // Available debug address registers: dr0, dr1, dr2, dr3 - return 4; -} diff --git a/lldb/tools/lldb-server/CMakeLists.txt b/lldb/tools/lldb-server/CMakeLists.txt --- a/lldb/tools/lldb-server/CMakeLists.txt +++ b/lldb/tools/lldb-server/CMakeLists.txt @@ -10,9 +10,7 @@ endif() if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") - list(APPEND LLDB_PLUGINS - lldbPluginProcessFreeBSDRemote - lldbPluginProcessFreeBSD) + list(APPEND LLDB_PLUGINS lldbPluginProcessFreeBSDRemote) endif() if(CMAKE_SYSTEM_NAME MATCHES "NetBSD")