Author: Jonas Devlieghere Date: 2020-01-24T15:07:31-08:00 New Revision: 96f3ea0d21b48ca088355db10d4d1a2e9bc9f884
URL: https://github.com/llvm/llvm-project/commit/96f3ea0d21b48ca088355db10d4d1a2e9bc9f884 DIFF: https://github.com/llvm/llvm-project/commit/96f3ea0d21b48ca088355db10d4d1a2e9bc9f884.diff LOG: [lldb/debugserver] Implement hardware breakpoints for x86_64 and i386 This implements hardware breakpoints for x86_64 and i386 in debugserver. It's based on Pedro's patch sent to lldb-commits [1] although most of it is the same as the existing hardware watchpoint implementation. [1] http://lists.llvm.org/pipermail/lldb-commits/Week-of-Mon-20200113/060327.html Differential revision: https://reviews.llvm.org/D72985 Added: Modified: lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/TestHWBreakMultiThread.py lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h lldb/tools/debugserver/source/RNBRemote.cpp Removed: ################################################################################ diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/TestHWBreakMultiThread.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/TestHWBreakMultiThread.py index 56112b24eb52..16c63b9ced1c 100644 --- a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/TestHWBreakMultiThread.py +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/TestHWBreakMultiThread.py @@ -9,26 +9,47 @@ from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil -# Hardware breakpoints are supported only by platforms mentioned in oslist. -@skipUnlessPlatform(oslist=['linux']) class HardwareBreakpointMultiThreadTestCase(TestBase): NO_DEBUG_INFO_TESTCASE = True mydir = TestBase.compute_mydir(__file__) - # LLDB supports hardware breakpoints for arm and aarch64 architectures. + # LLDB on linux supports hardware breakpoints for arm and aarch64 + # architectures. + @skipUnlessPlatform(oslist=['linux']) @skipIf(archs=no_match(['arm', 'aarch64'])) - def test_hw_break_set_delete_multi_thread(self): + def test_hw_break_set_delete_multi_thread_linux(self): self.build() self.setTearDownCleanup() - self.break_multi_thread('delete') + self.break_multi_thread('delete', 'breakpoint') - # LLDB supports hardware breakpoints for arm and aarch64 architectures. + # LLDB on linux supports hardware breakpoints for arm and aarch64 + # architectures. + @skipUnlessPlatform(oslist=['linux']) @skipIf(archs=no_match(['arm', 'aarch64'])) - def test_hw_break_set_disable_multi_thread(self): + def test_hw_break_set_disable_multi_thread_linux(self): self.build() self.setTearDownCleanup() - self.break_multi_thread('disable') + self.break_multi_thread('disable', 'breakpoint') + + # LLDB on darwin supports hardware breakpoints for arm, aarch64, x86_64 and + # i386 architectures. + @skipUnlessDarwin + @skipIfOutOfTreeDebugserver + def test_hw_break_set_delete_multi_thread_macos(self): + self.build() + self.setTearDownCleanup() + self.break_multi_thread('delete', 'EXC_BREAKPOINT') + + # LLDB on darwin supports hardware breakpoints for arm, aarch64, x86_64 and + # i386 architectures. + @skipUnlessDarwin + @skipIfOutOfTreeDebugserver + def test_hw_break_set_disable_multi_thread_macos(self): + self.build() + self.setTearDownCleanup() + self.break_multi_thread('disable', 'EXC_BREAKPOINT') + def setUp(self): # Call super's setUp(). @@ -39,7 +60,7 @@ def setUp(self): self.first_stop = line_number( self.source, 'Starting thread creation with hardware breakpoint set') - def break_multi_thread(self, removal_type): + def break_multi_thread(self, removal_type, stop_reason): """Test that lldb hardware breakpoints work for multiple threads.""" self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) @@ -54,8 +75,7 @@ def break_multi_thread(self, removal_type): # We should be stopped again due to the breakpoint. # The stop reason of the thread should be breakpoint. self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, - substrs=['stopped', - 'stop reason = breakpoint']) + substrs=['stopped', 'stop reason = breakpoint']) # Now set a hardware breakpoint in thread function. self.expect("breakpoint set -b hw_break_function --hardware", @@ -75,7 +95,7 @@ def break_multi_thread(self, removal_type): # The stop reason of the thread should be breakpoint. self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, substrs=[ - 'stop reason = breakpoint', + 'stop reason = {}'.format(stop_reason), 'hw_break_function']) # Continue the loop and test that we are stopped 4 times. diff --git a/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp b/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp index 45d05d6e0bdd..90cc25650e38 100644 --- a/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp +++ b/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp @@ -980,7 +980,8 @@ uint32_t DNBArchMachARM::NumSupportedHardwareWatchpoints() { } uint32_t DNBArchMachARM::EnableHardwareBreakpoint(nub_addr_t addr, - nub_size_t size) { + nub_size_t size, + bool also_set_on_task) { // Make sure our address isn't bogus if (addr & 1) return INVALID_NUB_HW_INDEX; @@ -1052,7 +1053,8 @@ uint32_t DNBArchMachARM::EnableHardwareBreakpoint(nub_addr_t addr, return INVALID_NUB_HW_INDEX; } -bool DNBArchMachARM::DisableHardwareBreakpoint(uint32_t hw_index) { +bool DNBArchMachARM::DisableHardwareBreakpoint(uint32_t hw_index, + bool also_set_on_task) { kern_return_t kret = GetDBGState(false); const uint32_t num_hw_points = NumSupportedHardwareBreakpoints(); diff --git a/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h b/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h index 4bb899b4503d..4c27a342f9ff 100644 --- a/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h +++ b/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h @@ -70,8 +70,10 @@ class DNBArchMachARM : public DNBArchProtocol { virtual uint32_t NumSupportedHardwareBreakpoints(); virtual uint32_t NumSupportedHardwareWatchpoints(); - virtual uint32_t EnableHardwareBreakpoint(nub_addr_t addr, nub_size_t size); - virtual bool DisableHardwareBreakpoint(uint32_t hw_break_index); + virtual uint32_t EnableHardwareBreakpoint(nub_addr_t addr, nub_size_t size, + bool also_set_on_task); + virtual bool DisableHardwareBreakpoint(uint32_t hw_break_index, + bool also_set_on_task); virtual uint32_t EnableHardwareWatchpoint(nub_addr_t addr, nub_size_t size, bool read, bool write, diff --git a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp index 7d2d0c2ef1b3..27bc75110620 100644 --- a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp +++ b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp @@ -718,6 +718,11 @@ bool DNBArchImplI386::NotifyException(MachException::Data &exc) { return false; } +uint32_t DNBArchImplI386::NumSupportedHardwareBreakpoints() { + // Available debug address registers: dr0, dr1, dr2, dr3. + return 4; +} + uint32_t DNBArchImplI386::NumSupportedHardwareWatchpoints() { // Available debug address registers: dr0, dr1, dr2, dr3. return 4; @@ -797,6 +802,151 @@ void DNBArchImplI386::SetWatchpoint(DBG &debug_state, uint32_t hw_index, return; } +void DNBArchImplI386::SetHardwareBreakpoint(DBG &debug_state, uint32_t hw_index, + nub_addr_t addr, nub_size_t size) { + // Set both dr7 (debug control register) and dri (debug address register). + + // dr7{7-0} encodes the local/gloabl enable bits: + // global enable --. .-- local enable + // | | + // v v + // dr0 -> bits{1-0} + // dr1 -> bits{3-2} + // dr2 -> bits{5-4} + // dr3 -> bits{7-6} + // + // dr7{31-16} encodes the rw/len bits: + // b_x+3, b_x+2, b_x+1, b_x + // where bits{x+1, x} => rw + // 0b00: execute, 0b01: write, 0b11: read-or-write, 0b10: io + // read-or-write (unused) + // and bits{x+3, x+2} => len + // 0b00: 1-byte, 0b01: 2-byte, 0b11: 4-byte, 0b10: 8-byte + // + // dr0 -> bits{19-16} + // dr1 -> bits{23-20} + // dr2 -> bits{27-24} + // dr3 -> bits{31-28} + debug_state.__dr7 |= (1 << (2 * hw_index) | 0 << (16 + 4 * hw_index)); + uint32_t addr_32 = addr & 0xffffffff; + switch (hw_index) { + case 0: + debug_state.__dr0 = addr_32; + break; + case 1: + debug_state.__dr1 = addr_32; + break; + case 2: + debug_state.__dr2 = addr_32; + break; + case 3: + debug_state.__dr3 = addr_32; + break; + default: + assert(0 && + "invalid hardware register index, must be one of 0, 1, 2, or 3"); + } + return; +} + +uint32_t DNBArchImplI386::EnableHardwareBreakpoint(nub_addr_t addr, + nub_size_t size, + bool also_set_on_task) { + DNBLogThreadedIf(LOG_BREAKPOINTS, + "DNBArchImplI386::EnableHardwareBreakpoint( addr = " + "0x%8.8llx, size = %llu )", + (uint64_t)addr, (uint64_t)size); + + const uint32_t num_hw_breakpoints = NumSupportedHardwareBreakpoints(); + // Read the debug state + kern_return_t kret = GetDBGState(false); + + if (kret != KERN_SUCCESS) { + return INVALID_NUB_HW_INDEX; + } + + // Check to make sure we have the needed hardware support + uint32_t i = 0; + + DBG &debug_state = m_state.context.dbg; + for (i = 0; i < num_hw_breakpoints; ++i) { + if (IsWatchpointVacant(debug_state, i)) { + break; + } + } + + // See if we found an available hw breakpoint slot above + if (i < num_hw_breakpoints) { + DNBLogThreadedIf( + LOG_BREAKPOINTS, + "DNBArchImplI386::EnableHardwareBreakpoint( free slot = %u )", i); + + StartTransForHWP(); + + // Modify our local copy of the debug state, first. + SetHardwareBreakpoint(debug_state, i, addr, size); + // Now set the watch point in the inferior. + kret = SetDBGState(also_set_on_task); + + DNBLogThreadedIf(LOG_BREAKPOINTS, + "DNBArchImplI386::" + "EnableHardwareBreakpoint() " + "SetDBGState() => 0x%8.8x.", + kret); + + if (kret == KERN_SUCCESS) { + DNBLogThreadedIf( + LOG_BREAKPOINTS, + "DNBArchImplI386::EnableHardwareBreakpoint( enabled at slot = %u)", + i); + return i; + } + // Revert to the previous debug state voluntarily. The transaction + // coordinator knows that we have failed. + else { + m_state.context.dbg = GetDBGCheckpoint(); + } + } else { + DNBLogThreadedIf(LOG_BREAKPOINTS, + "DNBArchImplI386::EnableHardwareBreakpoint(addr = " + "0x%8.8llx, size = %llu) => all hardware breakpoint " + "resources are being used.", + (uint64_t)addr, (uint64_t)size); + } + + return INVALID_NUB_HW_INDEX; +} + +bool DNBArchImplI386::DisableHardwareBreakpoint(uint32_t hw_index, + bool also_set_on_task) { + kern_return_t kret = GetDBGState(false); + + const uint32_t num_hw_points = NumSupportedHardwareBreakpoints(); + if (kret == KERN_SUCCESS) { + DBG &debug_state = m_state.context.dbg; + if (hw_index < num_hw_points && + !IsWatchpointVacant(debug_state, hw_index)) { + + StartTransForHWP(); + + // Modify our local copy of the debug state, first. + ClearWatchpoint(debug_state, hw_index); + // Now disable the watch point in the inferior. + kret = SetDBGState(true); + DNBLogThreadedIf(LOG_WATCHPOINTS, + "DNBArchImplI386::DisableHardwareBreakpoint( %u )", + hw_index); + + if (kret == KERN_SUCCESS) + return true; + else // Revert to the previous debug state voluntarily. The transaction + // coordinator knows that we have failed. + m_state.context.dbg = GetDBGCheckpoint(); + } + } + return false; +} + void DNBArchImplI386::ClearWatchpoint(DBG &debug_state, uint32_t hw_index) { debug_state.__dr7 &= ~(3 << (2 * hw_index)); switch (hw_index) { diff --git a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h index 12b515a29575..dfd2ef0c8541 100644 --- a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h +++ b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h @@ -51,7 +51,12 @@ class DNBArchImplI386 : public DNBArchProtocol { virtual bool ThreadDidStop(); virtual bool NotifyException(MachException::Data &exc); + virtual uint32_t NumSupportedHardwareBreakpoints(); virtual uint32_t NumSupportedHardwareWatchpoints(); + virtual uint32_t EnableHardwareBreakpoint(nub_addr_t addr, nub_size_t size, + bool also_set_on_task); + virtual bool DisableHardwareBreakpoint(uint32_t hw_index, + bool also_set_on_task); virtual uint32_t EnableHardwareWatchpoint(nub_addr_t addr, nub_size_t size, bool read, bool write, bool also_set_on_task); @@ -210,6 +215,9 @@ class DNBArchImplI386 : public DNBArchProtocol { static uint32_t GetRegisterContextSize(); + static void SetHardwareBreakpoint(DBG &debug_state, uint32_t hw_index, + nub_addr_t addr, nub_size_t size); + // Helper functions for watchpoint manipulations. static void SetWatchpoint(DBG &debug_state, uint32_t hw_index, nub_addr_t addr, nub_size_t size, bool read, diff --git a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp index 319215e8a7f4..519b6277fd06 100644 --- a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp +++ b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp @@ -679,6 +679,12 @@ uint32_t DNBArchImplX86_64::NumSupportedHardwareWatchpoints() { return 4; } +uint32_t DNBArchImplX86_64::NumSupportedHardwareBreakpoints() { + DNBLogThreadedIf(LOG_BREAKPOINTS, + "DNBArchImplX86_64::NumSupportedHardwareBreakpoints"); + return 4; +} + static uint32_t size_and_rw_bits(nub_size_t size, bool read, bool write) { uint32_t rw; if (read) { @@ -853,6 +859,153 @@ DNBArchImplX86_64::DBG DNBArchImplX86_64::GetDBGCheckpoint() { return m_2pc_dbg_checkpoint; } +void DNBArchImplX86_64::SetHardwareBreakpoint(DBG &debug_state, + uint32_t hw_index, + nub_addr_t addr, + nub_size_t size) { + // Set both dr7 (debug control register) and dri (debug address register). + + // dr7{7-0} encodes the local/gloabl enable bits: + // global enable --. .-- local enable + // | | + // v v + // dr0 -> bits{1-0} + // dr1 -> bits{3-2} + // dr2 -> bits{5-4} + // dr3 -> bits{7-6} + // + // dr7{31-16} encodes the rw/len bits: + // b_x+3, b_x+2, b_x+1, b_x + // where bits{x+1, x} => rw + // 0b00: execute, 0b01: write, 0b11: read-or-write, 0b10: io + // read-or-write (unused) + // and bits{x+3, x+2} => len + // 0b00: 1-byte, 0b01: 2-byte, 0b11: 4-byte, 0b10: 8-byte + // + // dr0 -> bits{19-16} + // dr1 -> bits{23-20} + // dr2 -> bits{27-24} + // dr3 -> bits{31-28} + debug_state.__dr7 |= (1 << (2 * hw_index) | 0 << (16 + 4 * hw_index)); + + switch (hw_index) { + case 0: + debug_state.__dr0 = addr; + break; + case 1: + debug_state.__dr1 = addr; + break; + case 2: + debug_state.__dr2 = addr; + break; + case 3: + debug_state.__dr3 = addr; + break; + default: + assert(0 && + "invalid hardware register index, must be one of 0, 1, 2, or 3"); + } + return; +} + +uint32_t DNBArchImplX86_64::EnableHardwareBreakpoint(nub_addr_t addr, + nub_size_t size, + bool also_set_on_task) { + DNBLogThreadedIf(LOG_BREAKPOINTS, + "DNBArchImplX86_64::EnableHardwareBreakpoint( addr = " + "0x%8.8llx, size = %llu )", + (uint64_t)addr, (uint64_t)size); + + const uint32_t num_hw_breakpoints = NumSupportedHardwareBreakpoints(); + // Read the debug state + kern_return_t kret = GetDBGState(false); + + if (kret != KERN_SUCCESS) { + return INVALID_NUB_HW_INDEX; + } + + // Check to make sure we have the needed hardware support + uint32_t i = 0; + + DBG &debug_state = m_state.context.dbg; + for (i = 0; i < num_hw_breakpoints; ++i) { + if (IsWatchpointVacant(debug_state, i)) { + break; + } + } + + // See if we found an available hw breakpoint slot above + if (i < num_hw_breakpoints) { + DNBLogThreadedIf( + LOG_BREAKPOINTS, + "DNBArchImplX86_64::EnableHardwareBreakpoint( free slot = %u )", i); + + StartTransForHWP(); + + // Modify our local copy of the debug state, first. + SetHardwareBreakpoint(debug_state, i, addr, size); + // Now set the watch point in the inferior. + kret = SetDBGState(also_set_on_task); + + DNBLogThreadedIf(LOG_BREAKPOINTS, + "DNBArchImplX86_64::" + "EnableHardwareBreakpoint() " + "SetDBGState() => 0x%8.8x.", + kret); + + if (kret == KERN_SUCCESS) { + DNBLogThreadedIf( + LOG_BREAKPOINTS, + "DNBArchImplX86_64::EnableHardwareBreakpoint( enabled at slot = %u)", + i); + return i; + } + // Revert to the previous debug state voluntarily. The transaction + // coordinator knows that we have failed. + else { + m_state.context.dbg = GetDBGCheckpoint(); + } + } else { + DNBLogThreadedIf(LOG_BREAKPOINTS, + "DNBArchImplX86_64::EnableHardwareBreakpoint(addr = " + "0x%8.8llx, size = %llu) => all hardware breakpoint " + "resources are being used.", + (uint64_t)addr, (uint64_t)size); + } + + return INVALID_NUB_HW_INDEX; +} + +bool DNBArchImplX86_64::DisableHardwareBreakpoint(uint32_t hw_index, + bool also_set_on_task) { + kern_return_t kret = GetDBGState(false); + + const uint32_t num_hw_points = NumSupportedHardwareBreakpoints(); + if (kret == KERN_SUCCESS) { + DBG &debug_state = m_state.context.dbg; + if (hw_index < num_hw_points && + !IsWatchpointVacant(debug_state, hw_index)) { + + StartTransForHWP(); + + // Modify our local copy of the debug state, first. + ClearWatchpoint(debug_state, hw_index); + // Now disable the watch point in the inferior. + kret = SetDBGState(true); + DNBLogThreadedIf(LOG_WATCHPOINTS, + "DNBArchImplX86_64::DisableHardwareBreakpoint( %u )", + hw_index); + + if (kret == KERN_SUCCESS) + return true; + else // Revert to the previous debug state voluntarily. The transaction + // coordinator knows that we have failed. + m_state.context.dbg = GetDBGCheckpoint(); + } + } + return false; +} + uint32_t DNBArchImplX86_64::EnableHardwareWatchpoint(nub_addr_t addr, nub_size_t size, bool read, bool write, diff --git a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h index 62ce37d4c049..94c3969084a8 100644 --- a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h +++ b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h @@ -50,7 +50,13 @@ class DNBArchImplX86_64 : public DNBArchProtocol { virtual bool ThreadDidStop(); virtual bool NotifyException(MachException::Data &exc); + virtual uint32_t NumSupportedHardwareBreakpoints(); virtual uint32_t NumSupportedHardwareWatchpoints(); + + virtual uint32_t EnableHardwareBreakpoint(nub_addr_t addr, nub_size_t size, + bool also_set_on_task); + virtual bool DisableHardwareBreakpoint(uint32_t hw_break_index, + bool also_set_on_task); virtual uint32_t EnableHardwareWatchpoint(nub_addr_t addr, nub_size_t size, bool read, bool write, bool also_set_on_task); @@ -213,6 +219,9 @@ class DNBArchImplX86_64 : public DNBArchProtocol { static uint32_t GetRegisterContextSize(); + static void SetHardwareBreakpoint(DBG &debug_state, uint32_t hw_index, + nub_addr_t addr, nub_size_t size); + // Helper functions for watchpoint manipulations. static void SetWatchpoint(DBG &debug_state, uint32_t hw_index, nub_addr_t addr, nub_size_t size, bool read, diff --git a/lldb/tools/debugserver/source/RNBRemote.cpp b/lldb/tools/debugserver/source/RNBRemote.cpp index 64e3bc49abc8..6f2c7353b723 100644 --- a/lldb/tools/debugserver/source/RNBRemote.cpp +++ b/lldb/tools/debugserver/source/RNBRemote.cpp @@ -279,12 +279,10 @@ void RNBRemote::CreatePacketTable() { "x", "Read data from memory")); t.push_back(Packet(write_data_to_memory, &RNBRemote::HandlePacket_X, NULL, "X", "Write data to memory")); - // t.push_back (Packet (insert_hardware_bp, - // &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "Z1", "Insert hardware - // breakpoint")); - // t.push_back (Packet (remove_hardware_bp, - // &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "z1", "Remove hardware - // breakpoint")); + t.push_back(Packet(insert_hardware_bp, &RNBRemote::HandlePacket_z, NULL, "Z1", + "Insert hardware breakpoint")); + t.push_back(Packet(remove_hardware_bp, &RNBRemote::HandlePacket_z, NULL, "z1", + "Remove hardware breakpoint")); t.push_back(Packet(insert_write_watch_bp, &RNBRemote::HandlePacket_z, NULL, "Z2", "Insert write watchpoint")); t.push_back(Packet(remove_write_watch_bp, &RNBRemote::HandlePacket_z, NULL, _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits