[Lldb-commits] [lldb] f7ec3e3 - [lldb] Skip overlapping hardware and external breakpoints when writing memory

Tatyana Krasnukha via lldb-commits lldb-commits at lists.llvm.org
Wed Jul 29 11:27:40 PDT 2020


Author: Tatyana Krasnukha
Date: 2020-07-29T21:27:23+03:00
New Revision: f7ec3e3be70d10a630ac22c64073a845b168c829

URL: https://github.com/llvm/llvm-project/commit/f7ec3e3be70d10a630ac22c64073a845b168c829
DIFF: https://github.com/llvm/llvm-project/commit/f7ec3e3be70d10a630ac22c64073a845b168c829.diff

LOG: [lldb] Skip overlapping hardware and external breakpoints when writing memory

This fixes the assertion `assert(intersects);` in the Process::WriteMemory function.

Differential Revision: https://reviews.llvm.org/D84254

Added: 
    lldb/test/API/functionalities/breakpoint/hardware_breakpoints/write_memory_with_hw_breakpoint/Makefile
    lldb/test/API/functionalities/breakpoint/hardware_breakpoints/write_memory_with_hw_breakpoint/TestWriteMemoryWithHWBreakpoint.py
    lldb/test/API/functionalities/breakpoint/hardware_breakpoints/write_memory_with_hw_breakpoint/main.cpp

Modified: 
    lldb/source/Breakpoint/BreakpointSite.cpp
    lldb/source/Target/Process.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/source/Breakpoint/BreakpointSite.cpp b/lldb/source/Breakpoint/BreakpointSite.cpp
index a33fd0a1c462..bdcabd7cce5e 100644
--- a/lldb/source/Breakpoint/BreakpointSite.cpp
+++ b/lldb/source/Breakpoint/BreakpointSite.cpp
@@ -167,40 +167,39 @@ bool BreakpointSite::IntersectsRange(lldb::addr_t addr, size_t size,
                                      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<lldb::addr_t>(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<lldb::addr_t>(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<lldb::addr_t>(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<lldb::addr_t>(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
index 3776a90e546a..36a2930f7915 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -2291,6 +2291,9 @@ size_t Process::WriteMemory(addr_t addr, const void *buf, size_t size,
     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
index 000000000000..99998b20bcb0
--- /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
index 000000000000..842519be6f89
--- /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
index 000000000000..bad219082caf
--- /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;
+}


        


More information about the lldb-commits mailing list