self.exe_name = self.testMethodName
self.d = {'CXX_SOURCES': self.source, 'EXE': self.exe_name}
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
# Most of the MIPS boards provide only one H/W watchpoints, and S/W
# watchpoints are not supported yet
@expectedFailureAll(triple=re.compile('^mips'))
self.exe_name = self.getBuildArtifact('a.out')
self.d = {'C_SOURCES': self.source, 'EXE': self.exe_name}
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
@add_test_categories(["basic_process"])
def test_hello_watchpoint_using_watchpoint_set(self):
"""Test a simple sequence of watchpoint creation and watchpoint hit."""
mydir = TestBase.compute_mydir(__file__)
NO_DEBUG_INFO_TESTCASE = True
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
@skipIf(bugnumber="llvm.org/pr30758", oslist=["linux"], archs=["arm", "aarch64", "powerpc64le"])
@skipIfwatchOS
def test(self):
NO_DEBUG_INFO_TESTCASE = True
main_spec = lldb.SBFileSpec("main.cpp", False)
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
@expectedFailureNetBSD
def test_watchpoint_before_thread_start(self):
"""Test that we can hit a watchpoint we set before starting another thread"""
self.do_watchpoint_test("Before running the thread")
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
@expectedFailureNetBSD
def test_watchpoint_after_thread_start(self):
"""Test that we can hit a watchpoint we set after starting another thread"""
self.expect("watchpoint list -v",
substrs=['hit_count = 1'])
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
def test_watchpoint_multiple_threads_wp_set_and_then_delete(self):
"""Test that lldb watchpoint works for multiple threads, and after the watchpoint is deleted, the watchpoint event should no longer fires."""
self.build()
'aarch64',
'arm'],
bugnumber="llvm.org/pr26031")
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
# Read-write watchpoints not supported on SystemZ
@expectedFailureAll(archs=['s390x'])
@expectedFailureAll(oslist=["ios", "watchos", "tvos", "bridgeos"], bugnumber="<rdar://problem/34027183>") # watchpoint tests aren't working on arm64
self.exe_name = self.testMethodName
self.d = {'C_SOURCES': self.source, 'EXE': self.exe_name}
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
# Read-write watchpoints not supported on SystemZ
@expectedFailureAll(archs=['s390x'])
def test_rw_watchpoint(self):
self.expect("watchpoint list -v",
substrs=['hit_count = 2'])
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
# Read-write watchpoints not supported on SystemZ
@expectedFailureAll(archs=['s390x'])
def test_rw_watchpoint_delete(self):
self.expect("process status",
substrs=['exited'])
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
# Read-write watchpoints not supported on SystemZ
@expectedFailureAll(archs=['s390x'])
def test_rw_watchpoint_set_ignore_count(self):
self.expect("watchpoint list -v",
substrs=['hit_count = 2', 'ignore_count = 2'])
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
# Read-write watchpoints not supported on SystemZ
@expectedFailureAll(archs=['s390x'])
def test_rw_disable_after_first_stop(self):
self.expect("watchpoint list -v",
substrs=['hit_count = 1'])
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
# Read-write watchpoints not supported on SystemZ
@expectedFailureAll(archs=['s390x'])
def test_rw_disable_then_enable(self):
archs=["aarch64"],
triple=no_match(".*-android"),
bugnumber="llvm.org/pr27710") # work on android
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
@expectedFailureNetBSD
def test_watchpoint_command(self):
"""Test 'watchpoint command'."""
archs=["aarch64"],
triple=no_match(".*-android"),
bugnumber="llvm.org/pr27710") # work on android
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
def test_watchpoint_command_can_disable_a_watchpoint(self):
"""Test that 'watchpoint command' action can disable a watchpoint after it is triggered."""
self.build(dictionary=self.d)
@skipIfFreeBSD # timing out on buildbot
@expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
- @expectedFailureAll(
oslist=["linux"],
archs=["aarch64"],
triple=no_match(".*-android"),
@skipIfFreeBSD # timing out on buildbot
@expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
- @expectedFailureAll(
oslist=["linux"],
archs=["aarch64"],
triple=no_match(".*-android"),
archs=["aarch64"],
triple=no_match(".*-android"),
bugnumber="llvm.org/pr27710")
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
@expectedFailureNetBSD
def test_watchpoint_cond(self):
"""Test watchpoint condition."""
# Call super's setUp().
TestBase.setUp(self)
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
def test_disable_works (self):
"""Set a watchpoint, disable it, and make sure it doesn't get hit."""
self.build()
self.do_test(False)
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
def test_disable_enable_works (self):
"""Set a watchpoint, disable it, and make sure it doesn't get hit."""
self.build()
archs=["aarch64"],
triple=no_match(".*-android"),
bugnumber="llvm.org/pr27710")
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
def test_with_python_api(self):
"""Test that adding, deleting and modifying watchpoints sends the appropriate events."""
self.build()
mydir = TestBase.compute_mydir(__file__)
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
def test_value_of_vector_variable_using_watchpoint_set(self):
"""Test verify displayed value of vector variable."""
exe = self.getBuildArtifact("a.out")
'aarch64',
'arm'],
bugnumber="llvm.org/pr26031")
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
@expectedFailureNetBSD
def test_watchlocation_using_watchpoint_set(self):
"""Test watching a location with 'watchpoint set expression -w write -s size' option."""
self.exe_name = self.getBuildArtifact("a.out")
self.d = {'C_SOURCES': self.source, 'EXE': self.exe_name}
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
# Read-write watchpoints not supported on SystemZ
@expectedFailureAll(archs=['s390x'])
def test_byte_size_watchpoints_with_byte_selection(self):
"""Test to selectively watch different bytes in a 8-byte array."""
self.run_watchpoint_size_test('byteArray', 8, '1')
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
# Read-write watchpoints not supported on SystemZ
@expectedFailureAll(archs=['s390x'])
def test_two_byte_watchpoints_with_word_selection(self):
"""Test to selectively watch different words in an 8-byte word array."""
self.run_watchpoint_size_test('wordArray', 4, '2')
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
# Read-write watchpoints not supported on SystemZ
@expectedFailureAll(archs=['s390x'])
def test_four_byte_watchpoints_with_dword_selection(self):
self.source, '// Set break point at this line.')
@add_test_categories(['pyapi'])
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
# Read-write watchpoints not supported on SystemZ
@expectedFailureAll(archs=['s390x'])
def test_watch_val(self):
self.source, '// Set break point at this line.')
@add_test_categories(['pyapi'])
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
# Read-write watchpoints not supported on SystemZ
@expectedFailureAll(archs=['s390x'])
def test_set_watch_ignore_count(self):
self.source, '// Set break point at this line.')
@add_test_categories(['pyapi'])
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
def test_watch_iter(self):
"""Exercise SBTarget.watchpoint_iter() API to iterate on the available watchpoints."""
self.build()
archs=["aarch64"],
triple=no_match(".*-android"),
bugnumber="llvm.org/pr27710")
- @skipIfWindows # Watchpoints not supported on Windows, and this test hangs
def test_watchpoint_cond_api(self):
"""Test watchpoint condition API."""
self.build(dictionary=self.d)
self.violating_func = "do_bad_thing_with_location"
@add_test_categories(['pyapi'])
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
@expectedFailureNetBSD
def test_watch_location(self):
"""Exercise SBValue.WatchPointee() API to set a watchpoint."""
self.violating_func = "do_bad_thing_with_location"
@add_test_categories(['pyapi'])
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
@expectedFailureNetBSD
def test_watch_address(self):
"""Exercise SBTarget.WatchAddress() API to set a watchpoint."""
HANDLE m_initial_stop_event = nullptr;
bool m_initial_stop_received = false;
bool m_stop_at_entry;
- std::map<lldb::tid_t, HostThread> m_new_threads;
+ std::map<lldb::tid_t, lldb::ThreadSP> m_new_threads;
std::set<lldb::tid_t> m_exited_threads;
};
#include "lldb/Host/windows/windows.h"
#include <psapi.h>
+#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
ProcessWindows::ProcessWindows(lldb::TargetSP target_sp,
lldb::ListenerSP listener_sp)
- : lldb_private::Process(target_sp, listener_sp) {}
+ : lldb_private::Process(target_sp, listener_sp),
+ m_watchpoint_ids(
+ RegisterContextWindows::GetNumHardwareBreakpointSlots(),
+ LLDB_INVALID_BREAK_ID) {}
ProcessWindows::~ProcessWindows() {}
stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*stop_thread,
site->GetID());
stop_thread->SetStopInfo(stop_info);
- } else {
- LLDB_LOG(log, "single stepping thread {0}", stop_thread->GetID());
- stop_info = StopInfo::CreateStopReasonToTrace(*stop_thread);
+
+ return;
+ }
+
+ auto *reg_ctx = static_cast<RegisterContextWindows *>(
+ stop_thread->GetRegisterContext().get());
+ uint32_t slot_id = reg_ctx->GetTriggeredHardwareBreakpointSlotId();
+ if (slot_id != LLDB_INVALID_INDEX32) {
+ int id = m_watchpoint_ids[slot_id];
+ LLDB_LOG(log,
+ "Single-stepped onto a watchpoint in process {0} at address "
+ "{1:x} with watchpoint {2}",
+ m_session_data->m_debugger->GetProcess().GetProcessId(), pc, id);
+
+ if (lldb::WatchpointSP wp_sp =
+ GetTarget().GetWatchpointList().FindByID(id))
+ wp_sp->SetHardwareIndex(slot_id);
+
+ stop_info = StopInfo::CreateStopReasonWithWatchpointID(
+ *stop_thread, id, m_watchpoints[id].address);
stop_thread->SetStopInfo(stop_info);
+
+ return;
}
+
+ LLDB_LOG(log, "single stepping thread {0}", stop_thread->GetID());
+ stop_info = StopInfo::CreateStopReasonToTrace(*stop_thread);
+ stop_thread->SetStopInfo(stop_info);
+
return;
}
// Also add all the threads that are new since the last time we broke into
// the debugger.
for (const auto &thread_info : m_session_data->m_new_threads) {
- ThreadSP thread(new TargetThreadWindows(*this, thread_info.second));
- thread->SetID(thread_info.first);
- new_thread_list.AddThread(thread);
+ new_thread_list.AddThread(thread_info.second);
++new_size;
++new_threads;
LLDB_LOGV(log, "Thread {0} is new since last update.", thread_info.first);
SetProcessExitStatus(GetID(), true, 0, exit_code);
SetPrivateState(eStateExited);
- // If the process exits before any initial stop then notify the debugger
+ // If the process exits before any initial stop then notify the debugger
// of the error otherwise WaitForDebuggerConnection() will be blocked.
- // An example of this issue is when a process fails to load a dependent DLL.
+ // An example of this issue is when a process fails to load a dependent DLL.
if (m_session_data && !m_session_data->m_initial_stop_received) {
Status error(exit_code, eErrorTypeWin32);
OnDebuggerError(error, 0);
FileSystem::Instance().Resolve(executable_file);
ModuleSpec module_spec(executable_file);
Status error;
- module = GetTarget().GetOrCreateModule(module_spec,
- true /* notify */, &error);
+ module =
+ GetTarget().GetOrCreateModule(module_spec, true /* notify */, &error);
if (!module) {
return;
}
// returned from DoLaunch() / DoAttach() yet so the target may not have set
// the process instance to `this` yet.
llvm::sys::ScopedLock lock(m_mutex);
- const HostThreadWindows &wmain_thread =
- debugger->GetMainThread().GetNativeThread();
- m_session_data->m_new_threads[wmain_thread.GetThreadId()] =
- debugger->GetMainThread();
+
+ const HostThread &host_main_thread = debugger->GetMainThread();
+ ThreadSP main_thread =
+ std::make_shared<TargetThreadWindows>(*this, host_main_thread);
+
+ tid_t id = host_main_thread.GetNativeThread().GetThreadId();
+ main_thread->SetID(id);
+
+ m_session_data->m_new_threads[id] = main_thread;
}
ExceptionResult
void ProcessWindows::OnCreateThread(const HostThread &new_thread) {
llvm::sys::ScopedLock lock(m_mutex);
- const HostThreadWindows &wnew_thread = new_thread.GetNativeThread();
- m_session_data->m_new_threads[wnew_thread.GetThreadId()] = new_thread;
+
+ ThreadSP thread = std::make_shared<TargetThreadWindows>(*this, new_thread);
+
+ const HostNativeThread &native_new_thread = new_thread.GetNativeThread();
+ tid_t id = native_new_thread.GetThreadId();
+ thread->SetID(id);
+
+ m_session_data->m_new_threads[id] = thread;
+
+ for (const std::map<int, WatchpointInfo>::value_type &p : m_watchpoints) {
+ auto *reg_ctx = static_cast<RegisterContextWindows *>(
+ thread->GetRegisterContext().get());
+ reg_ctx->AddHardwareBreakpoint(p.second.slot_id, p.second.address,
+ p.second.size, p.second.read,
+ p.second.write);
+ }
}
void ProcessWindows::OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) {
return;
}
}
+
+Status ProcessWindows::GetWatchpointSupportInfo(uint32_t &num) {
+ num = RegisterContextWindows::GetNumHardwareBreakpointSlots();
+ return {};
+}
+
+Status ProcessWindows::GetWatchpointSupportInfo(uint32_t &num, bool &after) {
+ num = RegisterContextWindows::GetNumHardwareBreakpointSlots();
+ after = RegisterContextWindows::DoHardwareBreakpointsTriggerAfter();
+ return {};
+}
+
+Status ProcessWindows::EnableWatchpoint(Watchpoint *wp, bool notify) {
+ Status error;
+
+ if (wp->IsEnabled()) {
+ wp->SetEnabled(true, notify);
+ return error;
+ }
+
+ WatchpointInfo info;
+ for (info.slot_id = 0;
+ info.slot_id < RegisterContextWindows::GetNumHardwareBreakpointSlots();
+ info.slot_id++)
+ if (m_watchpoint_ids[info.slot_id] == LLDB_INVALID_BREAK_ID)
+ break;
+ if (info.slot_id == RegisterContextWindows::GetNumHardwareBreakpointSlots()) {
+ error.SetErrorStringWithFormat("Can't find free slot for watchpoint %i",
+ wp->GetID());
+ return error;
+ }
+ info.address = wp->GetLoadAddress();
+ info.size = wp->GetByteSize();
+ info.read = wp->WatchpointRead();
+ info.write = wp->WatchpointWrite();
+
+ for (unsigned i = 0U; i < m_thread_list.GetSize(); i++) {
+ Thread *thread = m_thread_list.GetThreadAtIndex(i).get();
+ auto *reg_ctx = static_cast<RegisterContextWindows *>(
+ thread->GetRegisterContext().get());
+ if (!reg_ctx->AddHardwareBreakpoint(info.slot_id, info.address, info.size,
+ info.read, info.write)) {
+ error.SetErrorStringWithFormat(
+ "Can't enable watchpoint %i on thread 0x%llx", wp->GetID(),
+ thread->GetID());
+ break;
+ }
+ }
+ if (error.Fail()) {
+ for (unsigned i = 0U; i < m_thread_list.GetSize(); i++) {
+ Thread *thread = m_thread_list.GetThreadAtIndex(i).get();
+ auto *reg_ctx = static_cast<RegisterContextWindows *>(
+ thread->GetRegisterContext().get());
+ reg_ctx->RemoveHardwareBreakpoint(info.slot_id);
+ }
+ return error;
+ }
+
+ m_watchpoints[wp->GetID()] = info;
+ m_watchpoint_ids[info.slot_id] = wp->GetID();
+
+ wp->SetEnabled(true, notify);
+
+ return error;
+}
+
+Status ProcessWindows::DisableWatchpoint(Watchpoint *wp, bool notify) {
+ Status error;
+
+ if (!wp->IsEnabled()) {
+ wp->SetEnabled(false, notify);
+ return error;
+ }
+
+ auto it = m_watchpoints.find(wp->GetID());
+ if (it == m_watchpoints.end()) {
+ error.SetErrorStringWithFormat("Info about watchpoint %i is not found",
+ wp->GetID());
+ return error;
+ }
+
+ for (unsigned i = 0U; i < m_thread_list.GetSize(); i++) {
+ Thread *thread = m_thread_list.GetThreadAtIndex(i).get();
+ auto *reg_ctx = static_cast<RegisterContextWindows *>(
+ thread->GetRegisterContext().get());
+ if (!reg_ctx->RemoveHardwareBreakpoint(it->second.slot_id)) {
+ error.SetErrorStringWithFormat(
+ "Can't disable watchpoint %i on thread 0x%llx", wp->GetID(),
+ thread->GetID());
+ break;
+ }
+ }
+ if (error.Fail())
+ return error;
+
+ m_watchpoint_ids[it->second.slot_id] = LLDB_INVALID_BREAK_ID;
+ m_watchpoints.erase(it);
+
+ wp->SetEnabled(false, notify);
+
+ return error;
+}
} // namespace lldb_private
void OnUnloadDll(lldb::addr_t module_addr) override;
void OnDebugString(const std::string &string) override;
void OnDebuggerError(const Status &error, uint32_t type) override;
+
+ Status GetWatchpointSupportInfo(uint32_t &num) override;
+ Status GetWatchpointSupportInfo(uint32_t &num, bool &after) override;
+ Status EnableWatchpoint(Watchpoint *wp, bool notify = true) override;
+ Status DisableWatchpoint(Watchpoint *wp, bool notify = true) override;
+
+private:
+ struct WatchpointInfo {
+ uint32_t slot_id;
+ lldb::addr_t address;
+ uint32_t size;
+ bool read;
+ bool write;
+ };
+ std::map<lldb::break_id_t, WatchpointInfo> m_watchpoints;
+ std::vector<lldb::break_id_t> m_watchpoint_ids;
};
} // namespace lldb_private
#include "TargetThreadWindows.h"
#include "llvm/ADT/STLExtras.h"
+#include "lldb/Target/Target.h"
using namespace lldb;
using namespace lldb_private;
assert(data_sp->GetByteSize() >= sizeof(m_context));
memcpy(&m_context, data_sp->GetBytes(), sizeof(m_context));
- TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread);
- if (!::SetThreadContext(
- wthread.GetHostThread().GetNativeThread().GetSystemHandle(),
- &m_context))
- return false;
-
- return true;
+ return ApplyAllRegisterValues();
}
uint32_t RegisterContextWindows::ConvertRegisterKindToRegisterNumber(
return LLDB_INVALID_REGNUM;
}
-// Subclasses can these functions if desired
-uint32_t RegisterContextWindows::NumSupportedHardwareBreakpoints() {
- // Support for hardware breakpoints not yet implemented.
- return 0;
-}
+bool RegisterContextWindows::HardwareSingleStep(bool enable) { return false; }
-uint32_t RegisterContextWindows::SetHardwareBreakpoint(lldb::addr_t addr,
- size_t size) {
- return 0;
-}
+bool RegisterContextWindows::AddHardwareBreakpoint(uint32_t slot,
+ lldb::addr_t address,
+ uint32_t size, bool read,
+ bool write) {
+ if (slot >= NUM_HARDWARE_BREAKPOINT_SLOTS)
+ return false;
-bool RegisterContextWindows::ClearHardwareBreakpoint(uint32_t hw_idx) {
- return false;
-}
+ switch (size) {
+ case 1:
+ case 2:
+ case 4:
+#if defined(_M_AMD64)
+ case 8:
+#endif
+ break;
+ default:
+ return false;
+ }
-uint32_t RegisterContextWindows::NumSupportedHardwareWatchpoints() {
- // Support for hardware watchpoints not yet implemented.
- return 0;
-}
+ if (!CacheAllRegisterValues())
+ return false;
+
+ unsigned shift = 2 * slot;
+ m_context.Dr7 |= 1ULL << shift;
+
+ (&m_context.Dr0)[slot] = address;
-uint32_t RegisterContextWindows::SetHardwareWatchpoint(lldb::addr_t addr,
- size_t size, bool read,
- bool write) {
- return 0;
+ shift = 18 + 4 * slot;
+ m_context.Dr7 &= ~(3ULL << shift);
+ m_context.Dr7 |= (size == 8 ? 2ULL : size - 1) << shift;
+
+ shift = 16 + 4 * slot;
+ m_context.Dr7 &= ~(3ULL << shift);
+ m_context.Dr7 |= (read ? 3ULL : (write ? 1ULL : 0)) << shift;
+
+ return ApplyAllRegisterValues();
}
-bool RegisterContextWindows::ClearHardwareWatchpoint(uint32_t hw_index) {
- return false;
+bool RegisterContextWindows::RemoveHardwareBreakpoint(uint32_t slot) {
+ if (slot >= NUM_HARDWARE_BREAKPOINT_SLOTS)
+ return false;
+
+ if (!CacheAllRegisterValues())
+ return false;
+
+ unsigned shift = 2 * slot;
+ m_context.Dr7 &= ~(1ULL << shift);
+
+ return ApplyAllRegisterValues();
}
-bool RegisterContextWindows::HardwareSingleStep(bool enable) { return false; }
+uint32_t RegisterContextWindows::GetTriggeredHardwareBreakpointSlotId() {
+ if (!CacheAllRegisterValues())
+ return LLDB_INVALID_INDEX32;
+
+ for (unsigned i = 0UL; i < NUM_HARDWARE_BREAKPOINT_SLOTS; i++)
+ if (m_context.Dr6 & (1ULL << i))
+ return i;
+
+ return LLDB_INVALID_INDEX32;
+}
bool RegisterContextWindows::CacheAllRegisterValues() {
Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_REGISTERS);
m_context_stale = false;
return true;
}
+
+bool RegisterContextWindows::ApplyAllRegisterValues() {
+ TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread);
+ return ::SetThreadContext(
+ wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context);
+}
uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,
uint32_t num) override;
- // Subclasses can override these functions if desired
- uint32_t NumSupportedHardwareBreakpoints() override;
-
- uint32_t SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override;
-
- bool ClearHardwareBreakpoint(uint32_t hw_idx) override;
-
- uint32_t NumSupportedHardwareWatchpoints() override;
+ bool HardwareSingleStep(bool enable) override;
- uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read,
- bool write) override;
+ static constexpr uint32_t GetNumHardwareBreakpointSlots() {
+ return NUM_HARDWARE_BREAKPOINT_SLOTS;
+ }
+ static constexpr bool DoHardwareBreakpointsTriggerAfter() { return true; }
- bool ClearHardwareWatchpoint(uint32_t hw_index) override;
+ bool AddHardwareBreakpoint(uint32_t slot, lldb::addr_t address, uint32_t size,
+ bool read, bool write);
+ bool RemoveHardwareBreakpoint(uint32_t slot);
- bool HardwareSingleStep(bool enable) override;
+ uint32_t GetTriggeredHardwareBreakpointSlotId();
protected:
+ static constexpr unsigned NUM_HARDWARE_BREAKPOINT_SLOTS = 4;
+
virtual bool CacheAllRegisterValues();
+ virtual bool ApplyAllRegisterValues();
CONTEXT m_context;
bool m_context_stale;
};
-}
+} // namespace lldb_private
#endif // #ifndef liblldb_RegisterContextWindows_H_
}
// Physically update the registers in the target process.
- TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread);
- return ::SetThreadContext(
- wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context);
+ return ApplyAllRegisterValues();
}
#endif // defined(__x86_64__) || defined(_M_X64)
}
// Physically update the registers in the target process.
- TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread);
- return ::SetThreadContext(
- wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context);
+ return ApplyAllRegisterValues();
}
bool RegisterContextWindows_x86::ReadRegisterHelper(