summaryrefslogtreecommitdiff
path: root/source/Host/common/NativeProcessProtocol.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-04-16 16:04:10 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-04-16 16:04:10 +0000
commit74a628f776edb588bff8f8f5cc16eac947c9d631 (patch)
treedc32e010ac4902621e5a279bfeb48628f7f0e166 /source/Host/common/NativeProcessProtocol.cpp
parentafed7be32164a598f8172282c249af7266c48b46 (diff)
Notes
Diffstat (limited to 'source/Host/common/NativeProcessProtocol.cpp')
-rw-r--r--source/Host/common/NativeProcessProtocol.cpp118
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.