diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-04-16 16:04:10 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-04-16 16:04:10 +0000 |
commit | 74a628f776edb588bff8f8f5cc16eac947c9d631 (patch) | |
tree | dc32e010ac4902621e5a279bfeb48628f7f0e166 /source/Host/common/NativeProcessProtocol.cpp | |
parent | afed7be32164a598f8172282c249af7266c48b46 (diff) |
Notes
Diffstat (limited to 'source/Host/common/NativeProcessProtocol.cpp')
-rw-r--r-- | source/Host/common/NativeProcessProtocol.cpp | 118 |
1 files changed, 106 insertions, 12 deletions
diff --git a/source/Host/common/NativeProcessProtocol.cpp b/source/Host/common/NativeProcessProtocol.cpp index d77b8b2e97466..9d4149d700ba1 100644 --- a/source/Host/common/NativeProcessProtocol.cpp +++ b/source/Host/common/NativeProcessProtocol.cpp @@ -10,7 +10,6 @@ #include "lldb/Host/common/NativeProcessProtocol.h" #include "lldb/Core/ArchSpec.h" -#include "lldb/Core/Log.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/State.h" #include "lldb/Host/Host.h" @@ -20,6 +19,7 @@ #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/Process.h" #include "lldb/Utility/LLDBAssert.h" +#include "lldb/Utility/Log.h" #include "lldb/lldb-enumerations.h" using namespace lldb; @@ -46,6 +46,12 @@ lldb_private::Error NativeProcessProtocol::Interrupt() { #endif } +Error NativeProcessProtocol::IgnoreSignals(llvm::ArrayRef<int> signals) { + m_signals_to_ignore.clear(); + m_signals_to_ignore.insert(signals.begin(), signals.end()); + return Error(); +} + lldb_private::Error NativeProcessProtocol::GetMemoryRegionInfo(lldb::addr_t load_addr, MemoryRegionInfo &range_info) { @@ -139,11 +145,8 @@ NativeProcessProtocol::GetWatchpointMap() const { return m_watchpoint_list.GetWatchpointMap(); } -uint32_t NativeProcessProtocol::GetMaxWatchpoints() const { - // This default implementation will return the number of - // *hardware* breakpoints available. MacOSX and other OS - // implementations that support software breakpoints will want to - // override this correctly for their implementation. +llvm::Optional<std::pair<uint32_t, uint32_t>> +NativeProcessProtocol::GetHardwareDebugSupportInfo() const { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); // get any thread @@ -154,7 +157,7 @@ uint32_t NativeProcessProtocol::GetMaxWatchpoints() const { log->Warning("NativeProcessProtocol::%s (): failed to find a thread to " "grab a NativeRegisterContext!", __FUNCTION__); - return 0; + return llvm::None; } NativeRegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext()); @@ -163,10 +166,11 @@ uint32_t NativeProcessProtocol::GetMaxWatchpoints() const { log->Warning("NativeProcessProtocol::%s (): failed to get a " "RegisterContextNativeProcess from the first thread!", __FUNCTION__); - return 0; + return llvm::None; } - return reg_ctx_sp->NumSupportedHardwareWatchpoints(); + return std::make_pair(reg_ctx_sp->NumSupportedHardwareBreakpoints(), + reg_ctx_sp->NumSupportedHardwareWatchpoints()); } Error NativeProcessProtocol::SetWatchpoint(lldb::addr_t addr, size_t size, @@ -263,6 +267,92 @@ Error NativeProcessProtocol::RemoveWatchpoint(lldb::addr_t addr) { return overall_error.Fail() ? overall_error : error; } +const HardwareBreakpointMap & +NativeProcessProtocol::GetHardwareBreakpointMap() const { + return m_hw_breakpoints_map; +} + +Error NativeProcessProtocol::SetHardwareBreakpoint(lldb::addr_t addr, + size_t size) { + // This default implementation assumes setting a hardware breakpoint for + // this process will require setting same hardware breakpoint for each + // of its existing threads. New thread will do the same once created. + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + + // Update the thread list + UpdateThreads(); + + // Exit here if target does not have required hardware breakpoint capability. + auto hw_debug_cap = GetHardwareDebugSupportInfo(); + + if (hw_debug_cap == llvm::None || hw_debug_cap->first == 0 || + hw_debug_cap->first <= m_hw_breakpoints_map.size()) + return Error("Target does not have required no of hardware breakpoints"); + + // Vector below stores all thread pointer for which we have we successfully + // set this hardware breakpoint. If any of the current process threads fails + // to set this hardware breakpoint then roll back and remove this breakpoint + // for all the threads that had already set it successfully. + std::vector<NativeThreadProtocolSP> breakpoint_established_threads; + + // Request to set a hardware breakpoint for each of current process threads. + std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); + for (auto thread_sp : m_threads) { + assert(thread_sp && "thread list should not have a NULL thread!"); + if (!thread_sp) + continue; + + Error thread_error = thread_sp->SetHardwareBreakpoint(addr, size); + if (thread_error.Success()) { + // Remember that we set this breakpoint successfully in + // case we need to clear it later. + breakpoint_established_threads.push_back(thread_sp); + } else { + // Unset the breakpoint for each thread we successfully + // set so that we get back to a consistent state of "not + // set" for this hardware breakpoint. + for (auto rollback_thread_sp : breakpoint_established_threads) { + Error remove_error = rollback_thread_sp->RemoveHardwareBreakpoint(addr); + if (remove_error.Fail() && log) { + log->Warning("NativeProcessProtocol::%s (): RemoveHardwareBreakpoint" + " failed for pid=%" PRIu64 ", tid=%" PRIu64 ": %s", + __FUNCTION__, GetID(), rollback_thread_sp->GetID(), + remove_error.AsCString()); + } + } + + return thread_error; + } + } + + // Register new hardware breakpoint into hardware breakpoints map of current + // process. + m_hw_breakpoints_map[addr] = {addr, size}; + + return Error(); +} + +Error NativeProcessProtocol::RemoveHardwareBreakpoint(lldb::addr_t addr) { + // Update the thread list + UpdateThreads(); + + Error error; + + std::lock_guard<std::recursive_mutex> guard(m_threads_mutex); + for (auto thread_sp : m_threads) { + assert(thread_sp && "thread list should not have a NULL thread!"); + if (!thread_sp) + continue; + + error = thread_sp->RemoveHardwareBreakpoint(addr); + } + + // Also remove from hardware breakpoint map of current process. + m_hw_breakpoints_map.erase(addr); + + return error; +} + bool NativeProcessProtocol::RegisterNativeDelegate( NativeDelegate &native_delegate) { std::lock_guard<std::recursive_mutex> guard(m_delegates_mutex); @@ -339,8 +429,12 @@ Error NativeProcessProtocol::SetSoftwareBreakpoint(lldb::addr_t addr, }); } -Error NativeProcessProtocol::RemoveBreakpoint(lldb::addr_t addr) { - return m_breakpoint_list.DecRef(addr); +Error NativeProcessProtocol::RemoveBreakpoint(lldb::addr_t addr, + bool hardware) { + if (hardware) + return RemoveHardwareBreakpoint(addr); + else + return m_breakpoint_list.DecRef(addr); } Error NativeProcessProtocol::EnableBreakpoint(lldb::addr_t addr) { @@ -410,7 +504,7 @@ Error NativeProcessProtocol::ResolveProcessArchitecture(lldb::pid_t pid, return Error("failed to retrieve a valid architecture from the exe module"); } -#ifndef __linux__ +#if !defined(__linux__) && !defined(__NetBSD__) // These need to be implemented to support lldb-gdb-server on a given platform. // Stubs are // provided to make the rest of the code link on non-supported platforms. |