Index: lldb/trunk/source/Plugins/Process/FreeBSD/CMakeLists.txt =================================================================== --- lldb/trunk/source/Plugins/Process/FreeBSD/CMakeLists.txt +++ lldb/trunk/source/Plugins/Process/FreeBSD/CMakeLists.txt @@ -9,8 +9,6 @@ FreeBSDThread.cpp ProcessMonitor.cpp - ProcessPOSIX.cpp - POSIXThread.cpp POSIXStopInfo.cpp RegisterContextPOSIXProcessMonitor_arm.cpp RegisterContextPOSIXProcessMonitor_arm64.cpp Index: lldb/trunk/source/Plugins/Process/FreeBSD/FreeBSDThread.h =================================================================== --- lldb/trunk/source/Plugins/Process/FreeBSD/FreeBSDThread.h +++ lldb/trunk/source/Plugins/Process/FreeBSD/FreeBSDThread.h @@ -10,14 +10,23 @@ #ifndef liblldb_FreeBSDThread_H_ #define liblldb_FreeBSDThread_H_ +// C++ Includes +#include +#include + // Other libraries and framework includes -#include "POSIXThread.h" +#include "lldb/Target/Thread.h" +#include "Plugins/Process/Utility/RegisterContextPOSIX.h" + +class ProcessMessage; +class ProcessMonitor; +class POSIXBreakpointProtocol; //------------------------------------------------------------------------------ // @class FreeBSDThread // @brief Abstraction of a FreeBSD thread. class FreeBSDThread - : public POSIXThread + : public lldb_private::Thread { public: @@ -28,6 +37,101 @@ 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_ap; + + 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 ThreadNotify(const ProcessMessage &message); + void ExitNotify(const ProcessMessage &message); + void ExecNotify(const ProcessMessage &message); + + lldb_private::Unwind * + GetUnwinder() override; + //-------------------------------------------------------------------------- // FreeBSDThread internal API. Index: lldb/trunk/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp +++ lldb/trunk/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp @@ -8,33 +8,293 @@ //===----------------------------------------------------------------------===// // C Includes +#include + // C++ Includes // Other libraries and framework includes #include "lldb/Core/State.h" #include "lldb/Target/UnixSignals.h" // Project includes +#include "lldb/Breakpoint/Watchpoint.h" +#include "lldb/Breakpoint/BreakpointLocation.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/State.h" +#include "lldb/Host/Host.h" +#include "lldb/Host/HostNativeThread.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/StopInfo.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/ThreadSpec.h" +#include "llvm/ADT/SmallString.h" +#include "POSIXStopInfo.h" #include "FreeBSDThread.h" #include "ProcessFreeBSD.h" #include "ProcessPOSIXLog.h" +#include "ProcessMonitor.h" +#include "RegisterContextPOSIXProcessMonitor_arm.h" +#include "RegisterContextPOSIXProcessMonitor_arm64.h" +#include "RegisterContextPOSIXProcessMonitor_mips64.h" +#include "RegisterContextPOSIXProcessMonitor_powerpc.h" +#include "RegisterContextPOSIXProcessMonitor_x86.h" +#include "Plugins/Process/Utility/RegisterContextFreeBSD_arm.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/UnwindLLDB.h" using namespace lldb; using namespace lldb_private; -//------------------------------------------------------------------------------ -// Constructors and destructors. - FreeBSDThread::FreeBSDThread(Process &process, lldb::tid_t tid) - : POSIXThread(process, tid) + : Thread(process, tid), + m_frame_ap (), + m_breakpoint (), + m_thread_name_valid (false), + m_thread_name (), + m_posix_thread(NULL) { + Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) + log->Printf ("FreeBSDThread::%s (tid = %" PRIi64 ")", __FUNCTION__, 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(); } -//------------------------------------------------------------------------------ -// ProcessInterface protocol. +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 NULL; +} + +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) + { + llvm::SmallString<32> thread_name; + HostNativeThread::GetName(GetID(), thread_name); + m_thread_name = thread_name.c_str(); + m_thread_name_valid = true; + } + + if (m_thread_name.empty()) + return NULL; + return m_thread_name.c_str(); +} + +lldb::RegisterContextSP +FreeBSDThread::GetRegisterContext() +{ + if (!m_reg_context_sp) + { + m_posix_thread = NULL; + + RegisterInfoInterface *reg_interface = NULL; + const ArchSpec &target_arch = GetProcess()->GetTarget().GetArchitecture(); + + switch (target_arch.GetTriple().getOS()) + { + case llvm::Triple::FreeBSD: + switch (target_arch.GetMachine()) + { + case llvm::Triple::arm: + reg_interface = new RegisterContextFreeBSD_arm(target_arch); + 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: + break; + } + break; + + default: + break; + } + + assert(reg_interface && "OS or CPU not supported!"); + + switch (target_arch.GetMachine()) + { + case llvm::Triple::aarch64: + { + RegisterContextPOSIXProcessMonitor_arm64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_arm64(*this, 0, reg_interface); + 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, 0, reg_interface); + 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)); + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) + log->Printf ("FreeBSDThread::%s ()", __FUNCTION__); + + if (frame) + concrete_frame_idx = frame->GetConcreteFrameIndex(); + + if (concrete_frame_idx == 0) + reg_ctx_sp = GetRegisterContext(); + else + { + assert(GetUnwinder()); + 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; +} + +Unwind * +FreeBSDThread::GetUnwinder() +{ + if (m_unwinder_ap.get() == NULL) + m_unwinder_ap.reset(new UnwindLLDB(*this)); + + return m_unwinder_ap.get(); +} + +void +FreeBSDThread::DidStop() +{ + // Don't set the thread state to stopped unless we really stopped. +} void FreeBSDThread::WillResume(lldb::StateType resume_state) @@ -68,3 +328,369 @@ break; } } + +bool +FreeBSDThread::Resume() +{ + lldb::StateType resume_state = GetResumeState(); + ProcessMonitor &monitor = GetMonitor(); + bool status; + + Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); + if (log) + log->Printf ("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)); + if (log) + log->Printf ("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::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::eCrashMessage: + CrashNotify(message); + break; + + case ProcessMessage::eNewThreadMessage: + ThreadNotify(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(); + if (log) + log->Printf ("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 () != NULL) + 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(); + if (log) + log->Printf ("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) +{ + 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(); + SetStopInfo (StopInfo::CreateStopReasonWithSignal(*this, signo)); +} + +void +FreeBSDThread::SignalDeliveredNotify(const ProcessMessage &message) +{ + int signo = message.GetSignal(); + SetStopInfo (StopInfo::CreateStopReasonWithSignal(*this, signo)); +} + +void +FreeBSDThread::CrashNotify(const ProcessMessage &message) +{ + // FIXME: Update stop reason as per bugzilla 14598 + int signo = message.GetSignal(); + + assert(message.GetKind() == ProcessMessage::eCrashMessage); + + Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); + if (log) + log->Printf ("FreeBSDThread::%s () signo = %i, reason = '%s'", + __FUNCTION__, signo, message.PrintCrashReason()); + + SetStopInfo (lldb::StopInfoSP(new POSIXCrashStopInfo(*this, signo, + message.GetCrashReason(), + message.GetFaultAddress()))); +} + +void +FreeBSDThread::ThreadNotify(const ProcessMessage &message) +{ + SetStopInfo (lldb::StopInfoSP(new POSIXNewThreadStopInfo(*this))); +} + +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)); +} + Index: lldb/trunk/source/Plugins/Process/FreeBSD/POSIXStopInfo.h =================================================================== --- lldb/trunk/source/Plugins/Process/FreeBSD/POSIXStopInfo.h +++ lldb/trunk/source/Plugins/Process/FreeBSD/POSIXStopInfo.h @@ -17,7 +17,7 @@ #include "lldb/Target/StopInfo.h" #include "CrashReason.h" -#include "POSIXThread.h" +#include "FreeBSDThread.h" #include @@ -42,7 +42,7 @@ : public POSIXStopInfo { public: - POSIXLimboStopInfo(POSIXThread &thread) + POSIXLimboStopInfo(FreeBSDThread &thread) : POSIXStopInfo(thread, 0) { } @@ -70,7 +70,7 @@ : public POSIXStopInfo { public: - POSIXCrashStopInfo(POSIXThread &thread, uint32_t status, + POSIXCrashStopInfo(FreeBSDThread &thread, uint32_t status, CrashReason reason, lldb::addr_t fault_addr); ~POSIXCrashStopInfo(); @@ -88,7 +88,7 @@ : public POSIXStopInfo { public: - POSIXNewThreadStopInfo (POSIXThread &thread) + POSIXNewThreadStopInfo (FreeBSDThread &thread) : POSIXStopInfo (thread, 0) { } Index: lldb/trunk/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp +++ lldb/trunk/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp @@ -45,7 +45,7 @@ //===----------------------------------------------------------------------===// // POSIXCrashStopInfo -POSIXCrashStopInfo::POSIXCrashStopInfo(POSIXThread &thread, +POSIXCrashStopInfo::POSIXCrashStopInfo(FreeBSDThread &thread, uint32_t status, CrashReason reason, lldb::addr_t fault_addr) Index: lldb/trunk/source/Plugins/Process/FreeBSD/POSIXThread.h =================================================================== --- lldb/trunk/source/Plugins/Process/FreeBSD/POSIXThread.h +++ lldb/trunk/source/Plugins/Process/FreeBSD/POSIXThread.h @@ -1,132 +0,0 @@ -//===-- POSIXThread.h -------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_POSIXThread_H_ -#define liblldb_POSIXThread_H_ - -// C Includes -// C++ Includes -#include -#include - -// Other libraries and framework includes -#include "lldb/Target/Thread.h" -#include "Plugins/Process/Utility/RegisterContextPOSIX.h" - -class ProcessMessage; -class ProcessMonitor; -class POSIXBreakpointProtocol; - -//------------------------------------------------------------------------------ -// @class POSIXThread -// @brief Abstraction of a POSIX thread. -class POSIXThread - : public lldb_private::Thread -{ -public: - POSIXThread(lldb_private::Process &process, lldb::tid_t tid); - - virtual ~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_ap; - - 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 ThreadNotify(const ProcessMessage &message); - void ExitNotify(const ProcessMessage &message); - void ExecNotify(const ProcessMessage &message); - - lldb_private::Unwind * - GetUnwinder() override; -}; - -#endif // #ifndef liblldb_POSIXThread_H_ Index: lldb/trunk/source/Plugins/Process/FreeBSD/POSIXThread.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/FreeBSD/POSIXThread.cpp +++ lldb/trunk/source/Plugins/Process/FreeBSD/POSIXThread.cpp @@ -1,661 +0,0 @@ -//===-- POSIXThread.cpp -----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// C Includes -#include - -// C++ Includes -// Other libraries and framework includes -// Project includes -#include "lldb/Breakpoint/Watchpoint.h" -#include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Core/Debugger.h" -#include "lldb/Core/State.h" -#include "lldb/Host/Host.h" -#include "lldb/Host/HostNativeThread.h" -#include "lldb/Host/HostInfo.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/StopInfo.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/ThreadSpec.h" -#include "llvm/ADT/SmallString.h" -#include "POSIXStopInfo.h" -#include "POSIXThread.h" -#include "ProcessPOSIX.h" -#include "ProcessPOSIXLog.h" -#include "ProcessMonitor.h" -#include "RegisterContextPOSIXProcessMonitor_arm.h" -#include "RegisterContextPOSIXProcessMonitor_arm64.h" -#include "RegisterContextPOSIXProcessMonitor_mips64.h" -#include "RegisterContextPOSIXProcessMonitor_powerpc.h" -#include "RegisterContextPOSIXProcessMonitor_x86.h" -#include "Plugins/Process/Utility/RegisterContextFreeBSD_arm.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/UnwindLLDB.h" - -using namespace lldb; -using namespace lldb_private; - - -POSIXThread::POSIXThread(Process &process, lldb::tid_t tid) - : Thread(process, tid), - m_frame_ap (), - m_breakpoint (), - m_thread_name_valid (false), - m_thread_name (), - m_posix_thread(NULL) -{ - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); - if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) - log->Printf ("POSIXThread::%s (tid = %" PRIi64 ")", __FUNCTION__, 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(); - } - } -} - -POSIXThread::~POSIXThread() -{ - DestroyThread(); -} - -ProcessMonitor & -POSIXThread::GetMonitor() -{ - ProcessSP base = GetProcess(); - ProcessPOSIX &process = static_cast(*base); - return process.GetMonitor(); -} - -void -POSIXThread::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 * -POSIXThread::GetInfo() -{ - return NULL; -} - -void -POSIXThread::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 * -POSIXThread::GetName () -{ - if (!m_thread_name_valid) - { - llvm::SmallString<32> thread_name; - HostNativeThread::GetName(GetID(), thread_name); - m_thread_name = thread_name.c_str(); - m_thread_name_valid = true; - } - - if (m_thread_name.empty()) - return NULL; - return m_thread_name.c_str(); -} - -lldb::RegisterContextSP -POSIXThread::GetRegisterContext() -{ - if (!m_reg_context_sp) - { - m_posix_thread = NULL; - - RegisterInfoInterface *reg_interface = NULL; - const ArchSpec &target_arch = GetProcess()->GetTarget().GetArchitecture(); - - switch (target_arch.GetTriple().getOS()) - { - case llvm::Triple::FreeBSD: - switch (target_arch.GetMachine()) - { - case llvm::Triple::arm: - reg_interface = new RegisterContextFreeBSD_arm(target_arch); - 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: - break; - } - break; - - default: - break; - } - - assert(reg_interface && "OS or CPU not supported!"); - - switch (target_arch.GetMachine()) - { - case llvm::Triple::aarch64: - { - RegisterContextPOSIXProcessMonitor_arm64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_arm64(*this, 0, reg_interface); - 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, 0, reg_interface); - 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 -POSIXThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame) -{ - lldb::RegisterContextSP reg_ctx_sp; - uint32_t concrete_frame_idx = 0; - - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); - if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) - log->Printf ("POSIXThread::%s ()", __FUNCTION__); - - if (frame) - concrete_frame_idx = frame->GetConcreteFrameIndex(); - - if (concrete_frame_idx == 0) - reg_ctx_sp = GetRegisterContext(); - else - { - assert(GetUnwinder()); - reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame); - } - - return reg_ctx_sp; -} - -lldb::addr_t -POSIXThread::GetThreadPointer () -{ - ProcessMonitor &monitor = GetMonitor(); - addr_t addr; - if (monitor.ReadThreadPointer (GetID(), addr)) - return addr; - else - return LLDB_INVALID_ADDRESS; -} - -bool -POSIXThread::CalculateStopInfo() -{ - SetStopInfo (m_stop_info_sp); - return true; -} - -Unwind * -POSIXThread::GetUnwinder() -{ - if (m_unwinder_ap.get() == NULL) - m_unwinder_ap.reset(new UnwindLLDB(*this)); - - return m_unwinder_ap.get(); -} - -void -POSIXThread::DidStop() -{ - // Don't set the thread state to stopped unless we really stopped. -} - -bool -POSIXThread::Resume() -{ - lldb::StateType resume_state = GetResumeState(); - ProcessMonitor &monitor = GetMonitor(); - bool status; - - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); - if (log) - log->Printf ("POSIXThread::%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 -POSIXThread::Notify(const ProcessMessage &message) -{ - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); - if (log) - log->Printf ("POSIXThread::%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::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::eCrashMessage: - CrashNotify(message); - break; - - case ProcessMessage::eNewThreadMessage: - ThreadNotify(message); - break; - - case ProcessMessage::eExecMessage: - ExecNotify(message); - break; - } -} - -bool -POSIXThread::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 -POSIXThread::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 -POSIXThread::NumSupportedHardwareWatchpoints() -{ - lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext(); - if (reg_ctx_sp.get()) - return reg_ctx_sp->NumSupportedHardwareWatchpoints(); - return 0; -} - -uint32_t -POSIXThread::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 -POSIXThread::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(); - if (log) - log->Printf ("POSIXThread::%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 () != NULL) - SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id)); - else - { - const bool should_stop = false; - SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id, should_stop)); - } - } - else - SetStopInfo(StopInfoSP()); -} - -void -POSIXThread::WatchNotify(const ProcessMessage &message) -{ - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); - - lldb::addr_t halt_addr = message.GetHWAddress(); - if (log) - log->Printf ("POSIXThread::%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 -POSIXThread::TraceNotify(const ProcessMessage &message) -{ - 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 -POSIXThread::LimboNotify(const ProcessMessage &message) -{ - SetStopInfo (lldb::StopInfoSP(new POSIXLimboStopInfo(*this))); -} - -void -POSIXThread::SignalNotify(const ProcessMessage &message) -{ - int signo = message.GetSignal(); - SetStopInfo (StopInfo::CreateStopReasonWithSignal(*this, signo)); -} - -void -POSIXThread::SignalDeliveredNotify(const ProcessMessage &message) -{ - int signo = message.GetSignal(); - SetStopInfo (StopInfo::CreateStopReasonWithSignal(*this, signo)); -} - -void -POSIXThread::CrashNotify(const ProcessMessage &message) -{ - // FIXME: Update stop reason as per bugzilla 14598 - int signo = message.GetSignal(); - - assert(message.GetKind() == ProcessMessage::eCrashMessage); - - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); - if (log) - log->Printf ("POSIXThread::%s () signo = %i, reason = '%s'", - __FUNCTION__, signo, message.PrintCrashReason()); - - SetStopInfo (lldb::StopInfoSP(new POSIXCrashStopInfo(*this, signo, - message.GetCrashReason(), - message.GetFaultAddress()))); -} - -void -POSIXThread::ThreadNotify(const ProcessMessage &message) -{ - SetStopInfo (lldb::StopInfoSP(new POSIXNewThreadStopInfo(*this))); -} - -unsigned -POSIXThread::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 -POSIXThread::ExecNotify(const ProcessMessage &message) -{ - SetStopInfo (StopInfo::CreateStopReasonWithExec(*this)); -} - -const char * -POSIXThread::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 * -POSIXThread::GetRegisterNameFromOffset(unsigned offset) -{ - return GetRegisterName(GetRegisterIndexFromOffset(offset)); -} - Index: lldb/trunk/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h =================================================================== --- lldb/trunk/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h +++ lldb/trunk/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h @@ -13,18 +13,20 @@ // C Includes // C++ Includes +#include #include // Other libraries and framework includes #include "lldb/Target/Process.h" #include "lldb/Target/ThreadList.h" #include "ProcessMessage.h" -#include "ProcessPOSIX.h" +#include "ProcessFreeBSD.h" class ProcessMonitor; +class FreeBSDThread; class ProcessFreeBSD : - public ProcessPOSIX + public lldb_private::Process { public: @@ -52,23 +54,14 @@ // Constructors and destructors //------------------------------------------------------------------ ProcessFreeBSD(lldb_private::Target& target, - lldb_private::Listener &listener); - - virtual lldb_private::Error - DoDetach(bool keep_stopped); - - virtual bool - UpdateThreadList(lldb_private::ThreadList &old_thread_list, lldb_private::ThreadList &new_thread_list); + lldb_private::Listener &listener, + lldb::UnixSignalsSP &unix_signals_sp); - virtual lldb_private::Error - DoResume(); + ~ProcessFreeBSD(); virtual lldb_private::Error WillResume(); - virtual void - SendMessage(const ProcessMessage &message); - //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ @@ -89,7 +82,170 @@ EnablePluginLogging(lldb_private::Stream *strm, lldb_private::Args &command); +public: + //------------------------------------------------------------------ + // Process protocol. + //------------------------------------------------------------------ + void + Finalize() override; + + bool + CanDebug(lldb_private::Target &target, bool plugin_specified_by_name) override; + + lldb_private::Error + WillLaunch(lldb_private::Module *module) override; + + lldb_private::Error + DoAttachToProcessWithID (lldb::pid_t pid, const lldb_private::ProcessAttachInfo &attach_info) override; + + lldb_private::Error + DoLaunch (lldb_private::Module *exe_module, + lldb_private::ProcessLaunchInfo &launch_info) override; + + void + DidLaunch() override; + + lldb_private::Error + DoResume() override; + + lldb_private::Error + DoHalt(bool &caused_stop) override; + + lldb_private::Error + DoDetach(bool keep_stopped) override; + + lldb_private::Error + DoSignal(int signal) override; + + lldb_private::Error + DoDestroy() override; + + void + DoDidExec() override; + + void + RefreshStateAfterStop() override; + + bool + IsAlive() override; + + size_t + DoReadMemory(lldb::addr_t vm_addr, + void *buf, + size_t size, + lldb_private::Error &error) override; + + size_t + DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, + lldb_private::Error &error) override; + + lldb::addr_t + DoAllocateMemory(size_t size, uint32_t permissions, + lldb_private::Error &error) override; + + lldb_private::Error + DoDeallocateMemory(lldb::addr_t ptr) override; + + virtual size_t + GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite* bp_site); + + lldb_private::Error + EnableBreakpointSite(lldb_private::BreakpointSite *bp_site) override; + + lldb_private::Error + DisableBreakpointSite(lldb_private::BreakpointSite *bp_site) override; + + lldb_private::Error + EnableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true) override; + + lldb_private::Error + DisableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true) override; + + lldb_private::Error + GetWatchpointSupportInfo(uint32_t &num) override; + + lldb_private::Error + GetWatchpointSupportInfo(uint32_t &num, bool &after) override; + + virtual uint32_t + UpdateThreadListIfNeeded(); + + bool + UpdateThreadList(lldb_private::ThreadList &old_thread_list, + lldb_private::ThreadList &new_thread_list) override; + + virtual lldb::ByteOrder + GetByteOrder() const; + + lldb::addr_t + GetImageInfoAddress() override; + + size_t + PutSTDIN(const char *buf, size_t len, lldb_private::Error &error) override; + + const lldb::DataBufferSP + GetAuxvData () override; + + //-------------------------------------------------------------------------- + // 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); + protected: + /// Target byte order. + lldb::ByteOrder m_byte_order; + + /// Process monitor; + ProcessMonitor *m_monitor; + + /// The module we are executing. + lldb_private::Module *m_module; + + /// Message queue notifying this instance of inferior process state changes. + lldb_private::Mutex m_message_mutex; + std::queue m_message_queue; + + /// Drive any exit events to completion. + bool m_exit_now; + + /// Returns true if the process has exited. + bool HasExited(); + + /// Returns true if the process is stopped. + bool IsStopped(); + + /// Returns true if at least one running is currently running + bool IsAThreadRunning(); + + typedef std::map MMapMap; + MMapMap m_addr_to_mmap_size; + + typedef std::set ThreadStopSet; + /// Every thread begins with a stop signal. This keeps track + /// of the threads for which we have received the stop signal. + ThreadStopSet m_seen_initial_stop; + friend class FreeBSDThread; typedef std::vector tid_collection; Index: lldb/trunk/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp +++ lldb/trunk/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp @@ -28,6 +28,23 @@ #include "ProcessMonitor.h" #include "FreeBSDThread.h" +// Other libraries and framework includes +#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/Core/State.h" +#include "lldb/Host/FileSpec.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/Host/posix/Fcntl.h" + + using namespace lldb; using namespace lldb_private; @@ -51,7 +68,7 @@ { lldb::ProcessSP process_sp; if (crash_file_path == NULL) - process_sp.reset(new ProcessFreeBSD (target, listener)); + process_sp.reset(new ProcessFreeBSD (target, listener, GetFreeBSDSignals())); return process_sp; } @@ -113,15 +130,6 @@ return NULL; } -//------------------------------------------------------------------------------ -// Constructors and destructors. - -ProcessFreeBSD::ProcessFreeBSD(Target& target, Listener &listener) - : ProcessPOSIX(target, listener, GetFreeBSDSignals ()), - m_resume_signo(0) -{ -} - void ProcessFreeBSD::Terminate() { @@ -232,7 +240,7 @@ m_suspend_tids.clear(); m_run_tids.clear(); m_step_tids.clear(); - return ProcessPOSIX::WillResume(); + return Process::WillResume(); } void @@ -274,3 +282,780 @@ m_message_queue.push(message); } + +//------------------------------------------------------------------------------ +// Constructors and destructors. + +ProcessFreeBSD::ProcessFreeBSD(Target& target, Listener &listener, UnixSignalsSP &unix_signals_sp) + : Process(target, listener, unix_signals_sp), + m_byte_order(lldb::endian::InlHostByteOrder()), + m_monitor(NULL), + m_module(NULL), + m_message_mutex (Mutex::eMutexTypeRecursive), + 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(Target &target, bool plugin_specified_by_name) +{ + // For now we are just making sure the file exists for a given module + ModuleSP exe_module_sp(target.GetExecutableModule()); + if (exe_module_sp.get()) + return exe_module_sp->GetFileSpec().Exists(); + // If there is no executable module, we return true since we might be preparing to attach. + return true; +} + +Error +ProcessFreeBSD::DoAttachToProcessWithID (lldb::pid_t pid, const ProcessAttachInfo &attach_info) +{ + Error error; + assert(m_monitor == NULL); + + Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) + log->Printf ("ProcessFreeBSD::%s(pid = %" PRIi64 ")", __FUNCTION__, GetID()); + + m_monitor = new ProcessMonitor(this, pid, error); + + if (!error.Success()) + return error; + + PlatformSP platform_sp (m_target.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(), m_target.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() && !m_target.GetArchitecture().IsExactMatch(module_arch)) + m_target.SetArchitecture(module_arch); + + // Initialize the target module list + m_target.SetExecutableModule (exe_module_sp, true); + + SetSTDIOFileDescriptor(m_monitor->GetTerminalFD()); + + SetID(pid); + + return error; +} + +Error +ProcessFreeBSD::WillLaunch(Module* module) +{ + Error 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; +} + +Error +ProcessFreeBSD::DoLaunch (Module *module, + ProcessLaunchInfo &launch_info) +{ + Error error; + assert(m_monitor == NULL); + + FileSpec working_dir = launch_info.GetWorkingDirectory(); + if (working_dir && + (!working_dir.ResolvePath() || + working_dir.GetFileType() != FileSpec::eFileTypeDirectory)) + { + 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().GetSlaveName(NULL,0), false}; + + 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.GetEnvironmentEntries().GetConstArgumentVector(), + 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. + int stdio = fcntl(terminal, F_DUPFD_CLOEXEC, 0); + if (stdio == -1) { + error.SetErrorToErrno(); + return error; + } + 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; +} + +Error +ProcessFreeBSD::DoHalt(bool &caused_stop) +{ + Error error; + + if (IsStopped()) + { + caused_stop = false; + } + else if (kill(GetID(), SIGSTOP)) + { + caused_stop = false; + error.SetErrorToErrno(); + } + else + { + caused_stop = true; + } + return error; +} + +Error +ProcessFreeBSD::DoSignal(int signal) +{ + Error error; + + if (kill(GetID(), signal)) + error.SetErrorToErrno(); + + return error; +} + +Error +ProcessFreeBSD::DoDestroy() +{ + Error 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()); + Error 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, true); + } + } +} + +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)); + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) + log->Printf ("ProcessFreeBSD::%s(), message_queue size = %d", __FUNCTION__, (int)m_message_queue.size()); + + Mutex::Locker lock(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(); + if (log) + log->Printf ("ProcessFreeBSD::%s(), message_queue size = %d, pid = %" PRIi64, __FUNCTION__, (int)m_message_queue.size(), tid); + + if (message.GetKind() == ProcessMessage::eNewThreadMessage) + { + if (log) + log->Printf ("ProcessFreeBSD::%s() adding thread, tid = %" PRIi64, __FUNCTION__, message.GetChildTID()); + lldb::tid_t child_tid = message.GetChildTID(); + ThreadSP thread_sp; + thread_sp.reset(CreateNewFreeBSDThread(*this, child_tid)); + + Mutex::Locker lock(m_thread_list.GetMutex()); + + m_thread_list.AddThread(thread_sp); + } + + 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. + if (log) + log->Printf ("ProcessFreeBSD::%s() removing thread, tid = %" PRIi64, __FUNCTION__, tid); + + Mutex::Locker lock(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, Error &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, + Error &error) +{ + assert(m_monitor); + return m_monitor->WriteMemory(vm_addr, buf, size, error); +} + +addr_t +ProcessFreeBSD::DoAllocateMemory(size_t size, uint32_t permissions, + Error &error) +{ + addr_t allocated_addr = LLDB_INVALID_ADDRESS; + + unsigned prot = 0; + if (permissions & lldb::ePermissionsReadable) + prot |= eMmapProtRead; + if (permissions & lldb::ePermissionsWritable) + prot |= eMmapProtWrite; + if (permissions & lldb::ePermissionsExecutable) + prot |= eMmapProtExec; + + if (InferiorCallMmap(this, allocated_addr, 0, size, prot, + eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) { + m_addr_to_mmap_size[allocated_addr] = size; + error.Clear(); + } else { + allocated_addr = LLDB_INVALID_ADDRESS; + error.SetErrorStringWithFormat("unable to allocate %zu bytes of memory with permissions %s", size, GetPermissionsAsCString (permissions)); + } + + return allocated_addr; +} + +Error +ProcessFreeBSD::DoDeallocateMemory(lldb::addr_t addr) +{ + Error error; + MMapMap::iterator pos = m_addr_to_mmap_size.find(addr); + if (pos != m_addr_to_mmap_size.end() && + InferiorCallMunmap(this, addr, pos->second)) + m_addr_to_mmap_size.erase (pos); + else + error.SetErrorStringWithFormat("unable to deallocate memory at 0x%" 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 = eAddressClassUnknown; + + if (bp_loc_sp) + addr_class = bp_loc_sp->GetAddress ().GetAddressClass (); + + if (addr_class == eAddressClassCodeAlternateISA + || (addr_class == eAddressClassUnknown + && 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; +} + +Error +ProcessFreeBSD::EnableBreakpointSite(BreakpointSite *bp_site) +{ + return EnableSoftwareBreakpoint(bp_site); +} + +Error +ProcessFreeBSD::DisableBreakpointSite(BreakpointSite *bp_site) +{ + return DisableSoftwareBreakpoint(bp_site); +} + +Error +ProcessFreeBSD::EnableWatchpoint(Watchpoint *wp, bool notify) +{ + Error error; + if (wp) + { + user_id_t watchID = wp->GetID(); + addr_t addr = wp->GetLoadAddress(); + Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); + if (log) + log->Printf ("ProcessFreeBSD::EnableWatchpoint(watchID = %" PRIu64 ")", + watchID); + if (wp->IsEnabled()) + { + if (log) + log->Printf("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; + Mutex::Locker lock(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; +} + +Error +ProcessFreeBSD::DisableWatchpoint(Watchpoint *wp, bool notify) +{ + Error error; + if (wp) + { + user_id_t watchID = wp->GetID(); + addr_t addr = wp->GetLoadAddress(); + Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); + if (log) + log->Printf("ProcessFreeBSD::DisableWatchpoint(watchID = %" PRIu64 ")", + watchID); + if (!wp->IsEnabled()) + { + if (log) + log->Printf("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; + Mutex::Locker lock(m_thread_list.GetMutex()); + uint32_t thread_count = m_thread_list.GetSize(false); + for (uint32_t i = 0; i < thread_count; ++i) + { + 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; +} + +Error +ProcessFreeBSD::GetWatchpointSupportInfo(uint32_t &num) +{ + Error error; + Mutex::Locker lock(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; +} + +Error +ProcessFreeBSD::GetWatchpointSupportInfo(uint32_t &num, bool &after) +{ + Error error = GetWatchpointSupportInfo(num); + // Watchpoints trigger and halt the inferior after + // the corresponding instruction has been executed. + after = true; + return error; +} + +uint32_t +ProcessFreeBSD::UpdateThreadListIfNeeded() +{ + Mutex::Locker lock(m_thread_list.GetMutex()); + // Do not allow recursive updates. + return m_thread_list.GetSize(false); +} + +#if 0 +bool +ProcessFreeBSD::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) +{ + Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) + log->Printf ("ProcessFreeBSD::%s() (pid = %" PRIi64 ")", __FUNCTION__, GetID()); + + bool has_updated = false; + // Update the process thread list with this new thread. + // FIXME: We should be using tid, not pid. + assert(m_monitor); + ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false)); + if (!thread_sp) { + thread_sp.reset(CreateNewFreeBSDThread(*this, GetID())); + has_updated = true; + } + + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) + log->Printf ("ProcessFreeBSD::%s() updated pid = %" PRIi64, __FUNCTION__, GetID()); + new_thread_list.AddThread(thread_sp); + + return has_updated; // the list has been updated +} +#endif + +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, Error &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; + Mutex::Locker lock(m_thread_list.GetMutex()); + uint32_t thread_count = m_thread_list.GetSize(false); + for (uint32_t i = 0; i < thread_count; ++i) + { + 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; +} + +const DataBufferSP +ProcessFreeBSD::GetAuxvData () +{ + // If we're the local platform, we can ask the host for auxv data. + PlatformSP platform_sp = m_target.GetPlatform (); + if (platform_sp && platform_sp->IsHost ()) + return lldb_private::Host::GetAuxvData(this); + + // Somewhat unexpected - the process is not running locally or we don't have a platform. + assert (false && "no platform or not the host - how did we get here with ProcessFreeBSD?"); + return DataBufferSP (); +} Index: lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.h =================================================================== --- lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.h +++ lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.h @@ -49,7 +49,7 @@ /// Launches an inferior process ready for debugging. Forms the /// implementation of Process::DoLaunch. - ProcessMonitor(ProcessPOSIX *process, + ProcessMonitor(ProcessFreeBSD *process, lldb_private::Module *module, char const *argv[], char const *envp[], @@ -60,7 +60,7 @@ const lldb_private::ProcessLaunchInfo &launch_info, lldb_private::Error &error); - ProcessMonitor(ProcessPOSIX *process, + ProcessMonitor(ProcessFreeBSD *process, lldb::pid_t pid, lldb_private::Error &error); Index: lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp +++ lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp @@ -32,7 +32,7 @@ #include "lldb/Utility/PseudoTerminal.h" #include "Plugins/Process/POSIX/CrashReason.h" -#include "POSIXThread.h" +#include "FreeBSDThread.h" #include "ProcessFreeBSD.h" #include "ProcessPOSIXLog.h" #include "ProcessMonitor.h" @@ -804,7 +804,7 @@ /// launching or attaching to the inferior process, and then 2) servicing /// operations such as register reads/writes, stepping, etc. See the comments /// on the Operation class for more info as to why this is needed. -ProcessMonitor::ProcessMonitor(ProcessPOSIX *process, +ProcessMonitor::ProcessMonitor(ProcessFreeBSD *process, Module *module, const char *argv[], const char *envp[], @@ -865,7 +865,7 @@ } } -ProcessMonitor::ProcessMonitor(ProcessPOSIX *process, +ProcessMonitor::ProcessMonitor(ProcessFreeBSD *process, lldb::pid_t pid, lldb_private::Error &error) : m_process(static_cast(process)), Index: lldb/trunk/source/Plugins/Process/FreeBSD/ProcessPOSIX.h =================================================================== --- lldb/trunk/source/Plugins/Process/FreeBSD/ProcessPOSIX.h +++ lldb/trunk/source/Plugins/Process/FreeBSD/ProcessPOSIX.h @@ -1,205 +0,0 @@ -//===-- ProcessPOSIX.h ------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_ProcessPOSIX_H_ -#define liblldb_ProcessPOSIX_H_ - -// C Includes - -// C++ Includes -#include -#include - -// Other libraries and framework includes -#include "lldb/Target/Process.h" -#include "ProcessMessage.h" - -class ProcessMonitor; -class POSIXThread; - -class ProcessPOSIX : - public lldb_private::Process -{ -public: - - //------------------------------------------------------------------ - // Constructors and destructors - //------------------------------------------------------------------ - ProcessPOSIX(lldb_private::Target& target, - lldb_private::Listener &listener, - lldb::UnixSignalsSP &unix_signals_sp); - - virtual - ~ProcessPOSIX(); - - //------------------------------------------------------------------ - // Process protocol. - //------------------------------------------------------------------ - void - Finalize() override; - - bool - CanDebug(lldb_private::Target &target, bool plugin_specified_by_name) override; - - lldb_private::Error - WillLaunch(lldb_private::Module *module) override; - - lldb_private::Error - DoAttachToProcessWithID (lldb::pid_t pid, const lldb_private::ProcessAttachInfo &attach_info) override; - - lldb_private::Error - DoLaunch (lldb_private::Module *exe_module, - lldb_private::ProcessLaunchInfo &launch_info) override; - - void - DidLaunch() override; - - lldb_private::Error - DoResume() override; - - lldb_private::Error - DoHalt(bool &caused_stop) override; - - lldb_private::Error - DoDetach(bool keep_stopped) override = 0; - - lldb_private::Error - DoSignal(int signal) override; - - lldb_private::Error - DoDestroy() override; - - void - DoDidExec() override; - - void - RefreshStateAfterStop() override; - - bool - IsAlive() override; - - size_t - DoReadMemory(lldb::addr_t vm_addr, - void *buf, - size_t size, - lldb_private::Error &error) override; - - size_t - DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, - lldb_private::Error &error) override; - - lldb::addr_t - DoAllocateMemory(size_t size, uint32_t permissions, - lldb_private::Error &error) override; - - lldb_private::Error - DoDeallocateMemory(lldb::addr_t ptr) override; - - virtual size_t - GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite* bp_site); - - lldb_private::Error - EnableBreakpointSite(lldb_private::BreakpointSite *bp_site) override; - - lldb_private::Error - DisableBreakpointSite(lldb_private::BreakpointSite *bp_site) override; - - lldb_private::Error - EnableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true) override; - - lldb_private::Error - DisableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true) override; - - lldb_private::Error - GetWatchpointSupportInfo(uint32_t &num) override; - - lldb_private::Error - GetWatchpointSupportInfo(uint32_t &num, bool &after) override; - - virtual uint32_t - UpdateThreadListIfNeeded(); - - bool - UpdateThreadList(lldb_private::ThreadList &old_thread_list, - lldb_private::ThreadList &new_thread_list) override = 0; - - virtual lldb::ByteOrder - GetByteOrder() const; - - lldb::addr_t - GetImageInfoAddress() override; - - size_t - PutSTDIN(const char *buf, size_t len, lldb_private::Error &error) override; - - const lldb::DataBufferSP - GetAuxvData () override; - - //-------------------------------------------------------------------------- - // ProcessPOSIX internal API. - - /// Registers the given message with this process. - virtual void - SendMessage(const ProcessMessage &message); - - ProcessMonitor & - GetMonitor() { assert(m_monitor); return *m_monitor; } - - lldb_private::FileSpec - GetFileSpec(const lldb_private::FileAction *file_action, - const lldb_private::FileSpec &default_file_spec, - const lldb_private::FileSpec &dbg_pts_file_spec); - - /// Adds the thread to the list of threads for which we have received the initial stopping signal. - /// The \p stop_tid parameter indicates the thread which the stop happened for. - bool - AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid); - - bool - WaitingForInitialStop(lldb::tid_t stop_tid); - - virtual POSIXThread * - CreateNewPOSIXThread(lldb_private::Process &process, lldb::tid_t tid); - -protected: - /// Target byte order. - lldb::ByteOrder m_byte_order; - - /// Process monitor; - ProcessMonitor *m_monitor; - - /// The module we are executing. - lldb_private::Module *m_module; - - /// Message queue notifying this instance of inferior process state changes. - lldb_private::Mutex m_message_mutex; - std::queue m_message_queue; - - /// Drive any exit events to completion. - bool m_exit_now; - - /// Returns true if the process has exited. - bool HasExited(); - - /// Returns true if the process is stopped. - bool IsStopped(); - - /// Returns true if at least one running is currently running - bool IsAThreadRunning(); - - typedef std::map MMapMap; - MMapMap m_addr_to_mmap_size; - - typedef std::set ThreadStopSet; - /// Every thread begins with a stop signal. This keeps track - /// of the threads for which we have received the stop signal. - ThreadStopSet m_seen_initial_stop; -}; - -#endif // liblldb_MacOSXProcess_H_ Index: lldb/trunk/source/Plugins/Process/FreeBSD/ProcessPOSIX.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/FreeBSD/ProcessPOSIX.cpp +++ lldb/trunk/source/Plugins/Process/FreeBSD/ProcessPOSIX.cpp @@ -1,939 +0,0 @@ -//===-- ProcessPOSIX.cpp ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// C Includes -#include - -// C++ Includes -// Other libraries and framework includes -#include "lldb/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/Core/State.h" -#include "lldb/Host/FileSpec.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 "ProcessPOSIX.h" -#include "ProcessPOSIXLog.h" -#include "Plugins/Process/Utility/InferiorCallPOSIX.h" -#include "POSIXThread.h" -#include "ProcessMonitor.h" - -#include "lldb/Host/posix/Fcntl.h" - -using namespace lldb; -using namespace lldb_private; - -//------------------------------------------------------------------------------ -// Constructors and destructors. - -ProcessPOSIX::ProcessPOSIX(Target& target, Listener &listener, UnixSignalsSP &unix_signals_sp) - : Process(target, listener, unix_signals_sp), - m_byte_order(lldb::endian::InlHostByteOrder()), - m_monitor(NULL), - m_module(NULL), - m_message_mutex (Mutex::eMutexTypeRecursive), - m_exit_now(false), - m_seen_initial_stop() -{ - // 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(); -} - -ProcessPOSIX::~ProcessPOSIX() -{ - delete m_monitor; -} - -//------------------------------------------------------------------------------ -// Process protocol. -void -ProcessPOSIX::Finalize() -{ - Process::Finalize(); - - if (m_monitor) - m_monitor->StopMonitor(); -} - -bool -ProcessPOSIX::CanDebug(Target &target, bool plugin_specified_by_name) -{ - // For now we are just making sure the file exists for a given module - ModuleSP exe_module_sp(target.GetExecutableModule()); - if (exe_module_sp.get()) - return exe_module_sp->GetFileSpec().Exists(); - // If there is no executable module, we return true since we might be preparing to attach. - return true; -} - -Error -ProcessPOSIX::DoAttachToProcessWithID (lldb::pid_t pid, const ProcessAttachInfo &attach_info) -{ - Error error; - assert(m_monitor == NULL); - - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); - if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) - log->Printf ("ProcessPOSIX::%s(pid = %" PRIi64 ")", __FUNCTION__, GetID()); - - m_monitor = new ProcessMonitor(this, pid, error); - - if (!error.Success()) - return error; - - PlatformSP platform_sp (m_target.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(), m_target.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() && !m_target.GetArchitecture().IsExactMatch(module_arch)) - m_target.SetArchitecture(module_arch); - - // Initialize the target module list - m_target.SetExecutableModule (exe_module_sp, true); - - SetSTDIOFileDescriptor(m_monitor->GetTerminalFD()); - - SetID(pid); - - return error; -} - -Error -ProcessPOSIX::WillLaunch(Module* module) -{ - Error error; - return error; -} - -FileSpec -ProcessPOSIX::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; -} - -Error -ProcessPOSIX::DoLaunch (Module *module, - ProcessLaunchInfo &launch_info) -{ - Error error; - assert(m_monitor == NULL); - - FileSpec working_dir = launch_info.GetWorkingDirectory(); - if (working_dir && - (!working_dir.ResolvePath() || - working_dir.GetFileType() != FileSpec::eFileTypeDirectory)) - { - 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().GetSlaveName(NULL,0), false}; - - 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.GetEnvironmentEntries().GetConstArgumentVector(), - 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. - int stdio = fcntl(terminal, F_DUPFD_CLOEXEC, 0); - if (stdio == -1) { - error.SetErrorToErrno(); - return error; - } - SetSTDIOFileDescriptor(stdio); - } - - SetID(m_monitor->GetPID()); - return error; -} - -void -ProcessPOSIX::DidLaunch() -{ -} - -Error -ProcessPOSIX::DoResume() -{ - StateType state = GetPrivateState(); - - assert(state == eStateStopped); - - SetPrivateState(eStateRunning); - - bool did_resume = false; - - Mutex::Locker lock(m_thread_list.GetMutex()); - - uint32_t thread_count = m_thread_list.GetSize(false); - for (uint32_t i = 0; i < thread_count; ++i) - { - POSIXThread *thread = static_cast( - m_thread_list.GetThreadAtIndex(i, false).get()); - did_resume = thread->Resume() || did_resume; - } - assert(did_resume && "Process resume failed!"); - - return Error(); -} - -addr_t -ProcessPOSIX::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; -} - -Error -ProcessPOSIX::DoHalt(bool &caused_stop) -{ - Error error; - - if (IsStopped()) - { - caused_stop = false; - } - else if (kill(GetID(), SIGSTOP)) - { - caused_stop = false; - error.SetErrorToErrno(); - } - else - { - caused_stop = true; - } - return error; -} - -Error -ProcessPOSIX::DoSignal(int signal) -{ - Error error; - - if (kill(GetID(), signal)) - error.SetErrorToErrno(); - - return error; -} - -Error -ProcessPOSIX::DoDestroy() -{ - Error 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 -ProcessPOSIX::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()); - Error 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, true); - } - } -} - -void -ProcessPOSIX::SendMessage(const ProcessMessage &message) -{ - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); - - Mutex::Locker lock(m_message_mutex); - - Mutex::Locker thread_lock(m_thread_list.GetMutex()); - - POSIXThread *thread = static_cast( - m_thread_list.FindThreadByID(message.GetTID(), false).get()); - - switch (message.GetKind()) - { - case ProcessMessage::eInvalidMessage: - return; - - case ProcessMessage::eAttachMessage: - SetPrivateState(eStateStopped); - return; - - case ProcessMessage::eLimboMessage: - assert(thread); - thread->SetState(eStateStopped); - if (message.GetTID() == GetID()) - { - m_exit_status = message.GetExitStatus(); - if (m_exit_now) - { - SetPrivateState(eStateExited); - m_monitor->Detach(GetID()); - } - else - { - SetPrivateState(eStateStopped); - } - } - else - { - SetPrivateState(eStateStopped); - } - break; - - case ProcessMessage::eExitMessage: - if (thread != nullptr) - thread->SetState(eStateExited); - else - { - if (log) - log->Warning ("ProcessPOSIX::%s eExitMessage for TID %" PRIu64 " failed to find a thread to mark as eStateExited, ignoring", __FUNCTION__, message.GetTID ()); - } - - // FIXME: I'm not sure we need to do this. - if (message.GetTID() == GetID()) - { - SetExitStatus(message.GetExitStatus(), NULL); - } - else if (!IsAThreadRunning()) - SetPrivateState(eStateStopped); - break; - - case ProcessMessage::eSignalMessage: - case ProcessMessage::eSignalDeliveredMessage: - if (message.GetSignal() == SIGSTOP && - AddThreadForInitialStopIfNeeded(message.GetTID())) - return; - // Intentional fall-through - - case ProcessMessage::eBreakpointMessage: - case ProcessMessage::eTraceMessage: - case ProcessMessage::eWatchpointMessage: - case ProcessMessage::eCrashMessage: - assert(thread); - thread->SetState(eStateStopped); - SetPrivateState(eStateStopped); - break; - - case ProcessMessage::eNewThreadMessage: - { - lldb::tid_t new_tid = message.GetChildTID(); - if (WaitingForInitialStop(new_tid)) - { - m_monitor->WaitForInitialTIDStop(new_tid); - } - assert(thread); - thread->SetState(eStateStopped); - SetPrivateState(eStateStopped); - break; - } - - case ProcessMessage::eExecMessage: - { - assert(thread); - thread->SetState(eStateStopped); - SetPrivateState(eStateStopped); - break; - } - } - - - m_message_queue.push(message); -} - -bool -ProcessPOSIX::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 -ProcessPOSIX::WaitingForInitialStop(lldb::tid_t stop_tid) -{ - return (m_seen_initial_stop.find(stop_tid) == m_seen_initial_stop.end()); -} - -POSIXThread * -ProcessPOSIX::CreateNewPOSIXThread(lldb_private::Process &process, lldb::tid_t tid) -{ - return new POSIXThread(process, tid); -} - -void -ProcessPOSIX::RefreshStateAfterStop() -{ - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); - if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) - log->Printf ("ProcessPOSIX::%s(), message_queue size = %d", __FUNCTION__, (int)m_message_queue.size()); - - Mutex::Locker lock(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(); - if (log) - log->Printf ("ProcessPOSIX::%s(), message_queue size = %d, pid = %" PRIi64, __FUNCTION__, (int)m_message_queue.size(), tid); - - if (message.GetKind() == ProcessMessage::eNewThreadMessage) - { - if (log) - log->Printf ("ProcessPOSIX::%s() adding thread, tid = %" PRIi64, __FUNCTION__, message.GetChildTID()); - lldb::tid_t child_tid = message.GetChildTID(); - ThreadSP thread_sp; - thread_sp.reset(CreateNewPOSIXThread(*this, child_tid)); - - Mutex::Locker lock(m_thread_list.GetMutex()); - - m_thread_list.AddThread(thread_sp); - } - - m_thread_list.RefreshStateAfterStop(); - - POSIXThread *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. - if (log) - log->Printf ("ProcessPOSIX::%s() removing thread, tid = %" PRIi64, __FUNCTION__, tid); - - Mutex::Locker lock(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 -ProcessPOSIX::IsAlive() -{ - StateType state = GetPrivateState(); - return state != eStateDetached - && state != eStateExited - && state != eStateInvalid - && state != eStateUnloaded; -} - -size_t -ProcessPOSIX::DoReadMemory(addr_t vm_addr, - void *buf, size_t size, Error &error) -{ - assert(m_monitor); - return m_monitor->ReadMemory(vm_addr, buf, size, error); -} - -size_t -ProcessPOSIX::DoWriteMemory(addr_t vm_addr, const void *buf, size_t size, - Error &error) -{ - assert(m_monitor); - return m_monitor->WriteMemory(vm_addr, buf, size, error); -} - -addr_t -ProcessPOSIX::DoAllocateMemory(size_t size, uint32_t permissions, - Error &error) -{ - addr_t allocated_addr = LLDB_INVALID_ADDRESS; - - unsigned prot = 0; - if (permissions & lldb::ePermissionsReadable) - prot |= eMmapProtRead; - if (permissions & lldb::ePermissionsWritable) - prot |= eMmapProtWrite; - if (permissions & lldb::ePermissionsExecutable) - prot |= eMmapProtExec; - - if (InferiorCallMmap(this, allocated_addr, 0, size, prot, - eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) { - m_addr_to_mmap_size[allocated_addr] = size; - error.Clear(); - } else { - allocated_addr = LLDB_INVALID_ADDRESS; - error.SetErrorStringWithFormat("unable to allocate %zu bytes of memory with permissions %s", size, GetPermissionsAsCString (permissions)); - } - - return allocated_addr; -} - -Error -ProcessPOSIX::DoDeallocateMemory(lldb::addr_t addr) -{ - Error error; - MMapMap::iterator pos = m_addr_to_mmap_size.find(addr); - if (pos != m_addr_to_mmap_size.end() && - InferiorCallMunmap(this, addr, pos->second)) - m_addr_to_mmap_size.erase (pos); - else - error.SetErrorStringWithFormat("unable to deallocate memory at 0x%" PRIx64, addr); - - return error; -} - -size_t -ProcessPOSIX::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 = eAddressClassUnknown; - - if (bp_loc_sp) - addr_class = bp_loc_sp->GetAddress ().GetAddressClass (); - - if (addr_class == eAddressClassCodeAlternateISA - || (addr_class == eAddressClassUnknown - && 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; -} - -Error -ProcessPOSIX::EnableBreakpointSite(BreakpointSite *bp_site) -{ - return EnableSoftwareBreakpoint(bp_site); -} - -Error -ProcessPOSIX::DisableBreakpointSite(BreakpointSite *bp_site) -{ - return DisableSoftwareBreakpoint(bp_site); -} - -Error -ProcessPOSIX::EnableWatchpoint(Watchpoint *wp, bool notify) -{ - Error error; - if (wp) - { - user_id_t watchID = wp->GetID(); - addr_t addr = wp->GetLoadAddress(); - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - if (log) - log->Printf ("ProcessPOSIX::EnableWatchpoint(watchID = %" PRIu64 ")", - watchID); - if (wp->IsEnabled()) - { - if (log) - log->Printf("ProcessPOSIX::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; - Mutex::Locker lock(m_thread_list.GetMutex()); - POSIXThread *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; -} - -Error -ProcessPOSIX::DisableWatchpoint(Watchpoint *wp, bool notify) -{ - Error error; - if (wp) - { - user_id_t watchID = wp->GetID(); - addr_t addr = wp->GetLoadAddress(); - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - if (log) - log->Printf("ProcessPOSIX::DisableWatchpoint(watchID = %" PRIu64 ")", - watchID); - if (!wp->IsEnabled()) - { - if (log) - log->Printf("ProcessPOSIX::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; - Mutex::Locker lock(m_thread_list.GetMutex()); - uint32_t thread_count = m_thread_list.GetSize(false); - for (uint32_t i = 0; i < thread_count; ++i) - { - POSIXThread *thread = static_cast( - m_thread_list.GetThreadAtIndex(i, false).get()); - 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; -} - -Error -ProcessPOSIX::GetWatchpointSupportInfo(uint32_t &num) -{ - Error error; - Mutex::Locker lock(m_thread_list.GetMutex()); - POSIXThread *thread = static_cast( - m_thread_list.GetThreadAtIndex(0, false).get()); - if (thread) - num = thread->NumSupportedHardwareWatchpoints(); - else - error.SetErrorString("Process does not exist."); - return error; -} - -Error -ProcessPOSIX::GetWatchpointSupportInfo(uint32_t &num, bool &after) -{ - Error error = GetWatchpointSupportInfo(num); - // Watchpoints trigger and halt the inferior after - // the corresponding instruction has been executed. - after = true; - return error; -} - -uint32_t -ProcessPOSIX::UpdateThreadListIfNeeded() -{ - Mutex::Locker lock(m_thread_list.GetMutex()); - // Do not allow recursive updates. - return m_thread_list.GetSize(false); -} - -bool -ProcessPOSIX::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) -{ - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); - if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) - log->Printf ("ProcessPOSIX::%s() (pid = %" PRIi64 ")", __FUNCTION__, GetID()); - - bool has_updated = false; - // Update the process thread list with this new thread. - // FIXME: We should be using tid, not pid. - assert(m_monitor); - ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false)); - if (!thread_sp) { - thread_sp.reset(CreateNewPOSIXThread(*this, GetID())); - has_updated = true; - } - - if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) - log->Printf ("ProcessPOSIX::%s() updated pid = %" PRIi64, __FUNCTION__, GetID()); - new_thread_list.AddThread(thread_sp); - - return has_updated; // the list has been updated -} - -ByteOrder -ProcessPOSIX::GetByteOrder() const -{ - // FIXME: We should be able to extract this value directly. See comment in - // ProcessPOSIX(). - return m_byte_order; -} - -size_t -ProcessPOSIX::PutSTDIN(const char *buf, size_t len, Error &error) -{ - ssize_t status; - if ((status = write(m_monitor->GetTerminalFD(), buf, len)) < 0) - { - error.SetErrorToErrno(); - return 0; - } - return status; -} - -//------------------------------------------------------------------------------ -// Utility functions. - -bool -ProcessPOSIX::HasExited() -{ - switch (GetPrivateState()) - { - default: - break; - - case eStateDetached: - case eStateExited: - return true; - } - - return false; -} - -bool -ProcessPOSIX::IsStopped() -{ - switch (GetPrivateState()) - { - default: - break; - - case eStateStopped: - case eStateCrashed: - case eStateSuspended: - return true; - } - - return false; -} - -bool -ProcessPOSIX::IsAThreadRunning() -{ - bool is_running = false; - Mutex::Locker lock(m_thread_list.GetMutex()); - uint32_t thread_count = m_thread_list.GetSize(false); - for (uint32_t i = 0; i < thread_count; ++i) - { - POSIXThread *thread = static_cast( - m_thread_list.GetThreadAtIndex(i, false).get()); - StateType thread_state = thread->GetState(); - if (thread_state == eStateRunning || thread_state == eStateStepping) - { - is_running = true; - break; - } - } - return is_running; -} - -const DataBufferSP -ProcessPOSIX::GetAuxvData () -{ - // If we're the local platform, we can ask the host for auxv data. - PlatformSP platform_sp = m_target.GetPlatform (); - if (platform_sp && platform_sp->IsHost ()) - return lldb_private::Host::GetAuxvData(this); - - // Somewhat unexpected - the process is not running locally or we don't have a platform. - assert (false && "no platform or not the host - how did we get here with ProcessPOSIX?"); - return DataBufferSP (); -} Index: lldb/trunk/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp +++ lldb/trunk/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp @@ -12,7 +12,7 @@ #include "lldb/Target/Thread.h" #include "RegisterContextPOSIX_arm.h" -#include "ProcessPOSIX.h" +#include "ProcessFreeBSD.h" #include "RegisterContextPOSIXProcessMonitor_arm.h" #include "ProcessMonitor.h" @@ -32,7 +32,7 @@ RegisterContextPOSIXProcessMonitor_arm::GetMonitor() { ProcessSP base = CalculateProcess(); - ProcessPOSIX *process = static_cast(base.get()); + ProcessFreeBSD *process = static_cast(base.get()); return process->GetMonitor(); } Index: lldb/trunk/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp +++ lldb/trunk/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp @@ -12,7 +12,7 @@ #include "lldb/Target/Thread.h" #include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h" -#include "ProcessPOSIX.h" +#include "ProcessFreeBSD.h" #include "ProcessMonitor.h" #include "RegisterContextPOSIXProcessMonitor_arm64.h" @@ -32,7 +32,7 @@ RegisterContextPOSIXProcessMonitor_arm64::GetMonitor() { lldb::ProcessSP base = CalculateProcess(); - ProcessPOSIX *process = static_cast(base.get()); + ProcessFreeBSD *process = static_cast(base.get()); return process->GetMonitor(); } Index: lldb/trunk/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp +++ lldb/trunk/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp @@ -12,7 +12,7 @@ #include "lldb/Target/Thread.h" #include "Plugins/Process/Utility/RegisterContextPOSIX_mips64.h" -#include "ProcessPOSIX.h" +#include "ProcessFreeBSD.h" #include "ProcessMonitor.h" #include "RegisterContextPOSIXProcessMonitor_mips64.h" @@ -32,7 +32,7 @@ RegisterContextPOSIXProcessMonitor_mips64::GetMonitor() { ProcessSP base = CalculateProcess(); - ProcessPOSIX *process = static_cast(base.get()); + ProcessFreeBSD *process = static_cast(base.get()); return process->GetMonitor(); } Index: lldb/trunk/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp +++ lldb/trunk/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp @@ -12,7 +12,7 @@ #include "lldb/Target/Thread.h" #include "RegisterContextPOSIX_powerpc.h" -#include "ProcessPOSIX.h" +#include "ProcessFreeBSD.h" #include "RegisterContextPOSIXProcessMonitor_powerpc.h" #include "ProcessMonitor.h" @@ -32,7 +32,7 @@ RegisterContextPOSIXProcessMonitor_powerpc::GetMonitor() { ProcessSP base = CalculateProcess(); - ProcessPOSIX *process = static_cast(base.get()); + ProcessFreeBSD *process = static_cast(base.get()); return process->GetMonitor(); } Index: lldb/trunk/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp +++ lldb/trunk/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp @@ -11,7 +11,7 @@ #include "lldb/Core/RegisterValue.h" #include "lldb/Target/Thread.h" -#include "Plugins/Process/FreeBSD/ProcessPOSIX.h" +#include "Plugins/Process/FreeBSD/ProcessFreeBSD.h" #include "RegisterContextPOSIXProcessMonitor_x86.h" #include "Plugins/Process/FreeBSD/ProcessMonitor.h" @@ -64,7 +64,7 @@ RegisterContextPOSIXProcessMonitor_x86_64::GetMonitor() { ProcessSP base = CalculateProcess(); - ProcessPOSIX *process = static_cast(base.get()); + ProcessFreeBSD *process = static_cast(base.get()); return process->GetMonitor(); }