diff --git a/lldb/source/Breakpoint/BreakpointSite.cpp b/lldb/source/Breakpoint/BreakpointSite.cpp --- a/lldb/source/Breakpoint/BreakpointSite.cpp +++ b/lldb/source/Breakpoint/BreakpointSite.cpp @@ -167,40 +167,39 @@ lldb::addr_t *intersect_addr, size_t *intersect_size, size_t *opcode_offset) const { - // We only use software traps for software breakpoints - if (!IsHardware()) { - if (m_byte_size > 0) { - const lldb::addr_t bp_end_addr = m_addr + m_byte_size; - const lldb::addr_t end_addr = addr + size; - // Is the breakpoint end address before the passed in start address? - if (bp_end_addr <= addr) - return false; - // Is the breakpoint start address after passed in end address? - if (end_addr <= m_addr) - return false; - if (intersect_addr || intersect_size || opcode_offset) { - if (m_addr < addr) { - if (intersect_addr) - *intersect_addr = addr; - if (intersect_size) - *intersect_size = - std::min(bp_end_addr, end_addr) - addr; - if (opcode_offset) - *opcode_offset = addr - m_addr; - } else { - if (intersect_addr) - *intersect_addr = m_addr; - if (intersect_size) - *intersect_size = - std::min(bp_end_addr, end_addr) - m_addr; - if (opcode_offset) - *opcode_offset = 0; - } + // The function should be called only for software breakpoints. + lldbassert(GetType() == Type::eSoftware); + + if (m_byte_size > 0) { + const lldb::addr_t bp_end_addr = m_addr + m_byte_size; + const lldb::addr_t end_addr = addr + size; + // Is the breakpoint end address before the passed in start address? + if (bp_end_addr <= addr) + return false; + // Is the breakpoint start address after passed in end address? + if (end_addr <= m_addr) + return false; + if (intersect_addr || intersect_size || opcode_offset) { + if (m_addr < addr) { + if (intersect_addr) + *intersect_addr = addr; + if (intersect_size) + *intersect_size = + std::min(bp_end_addr, end_addr) - addr; + if (opcode_offset) + *opcode_offset = addr - m_addr; + } else { + if (intersect_addr) + *intersect_addr = m_addr; + if (intersect_size) + *intersect_size = + std::min(bp_end_addr, end_addr) - m_addr; + if (opcode_offset) + *opcode_offset = 0; } - return true; } + return true; } - return false; } size_t diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -2291,6 +2291,9 @@ if (error.Fail()) return; + if (bp->GetType() != BreakpointSite::eSoftware) + return; + addr_t intersect_addr; size_t intersect_size; size_t opcode_offset; diff --git a/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/write_memory_with_hw_breakpoint/Makefile b/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/write_memory_with_hw_breakpoint/Makefile new file mode 100644 --- /dev/null +++ b/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/write_memory_with_hw_breakpoint/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/write_memory_with_hw_breakpoint/TestWriteMemoryWithHWBreakpoint.py b/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/write_memory_with_hw_breakpoint/TestWriteMemoryWithHWBreakpoint.py new file mode 100644 --- /dev/null +++ b/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/write_memory_with_hw_breakpoint/TestWriteMemoryWithHWBreakpoint.py @@ -0,0 +1,51 @@ +""" +Test that writing memory does't affect hardware breakpoints. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +from functionalities.breakpoint.hardware_breakpoints.base import * + +class WriteMemoryWithHWBreakpoint(HardwareBreakpointTestBase): + mydir = TestBase.compute_mydir(__file__) + + def does_not_support_hw_breakpoints(self): + return not super().supports_hw_breakpoints() + + @skipTestIfFn(does_not_support_hw_breakpoints) + def test_copy_memory_with_hw_break(self): + self.build() + exe = self.getBuildArtifact("a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Run the program and stop at entry. + self.expect("process launch --stop-at-entry", + patterns=["Process .* launched: .*a.out"]) + + process = target.GetProcess() + self.assertTrue(process, PROCESS_IS_VALID) + + # Set a hardware breakpoint. + bp_id = lldbutil.run_break_set_by_symbol(self, "hw_break_function", + extra_options="--hardware") + + # Get breakpoint location from the breakpoint. + location = target.FindBreakpointByID(bp_id).GetLocationAtIndex(0) + self.assertTrue(location and location.IsResolved(), + VALID_BREAKPOINT_LOCATION) + + # Check that writing overlapping memory doesn't crash. + address = location.GetLoadAddress() + data = str("\x01\x02\x03\x04") + error = lldb.SBError() + + result = process.WriteMemory(address, data, error) + self.assertTrue(error.Success() and result == len(bytes)) diff --git a/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/write_memory_with_hw_breakpoint/main.cpp b/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/write_memory_with_hw_breakpoint/main.cpp new file mode 100644 --- /dev/null +++ b/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/write_memory_with_hw_breakpoint/main.cpp @@ -0,0 +1,9 @@ +static volatile int num = 1; + +bool hw_break_function (int i) { + return num == i; +} + +int main (int argc, char const *argv[]) { + return hw_break_function(argc) ? 0 : 1; +}