[Lldb-commits] [lldb] [lldb][test] Fix TestWriteOverSoftwareBreakpoint (PR #231850)

David Spickett via lldb-commits lldb-commits at lists.llvm.org
Wed Oct 14 03:18:10 PDT 2026


https://github.com/DavidSpickett created https://github.com/llvm/llvm-project/pull/231850

After the changes made in #230518. They are correct, but broke an assumption that I had made that there would be no live code between the set of nops
and the breakpoint location.

Before:
 730:   d503201f        nop
 734:   14000001        b       738 <place_break_here>
0000000000000738 <place_break_here>:

That "b" is dead code, but -

After:
 73c:   d503201f        nop
 740:   14000001        b       744 <foo+0x30>
 744:   b9400fe0        ldr     w0, [sp, #12]
0000000000000748 <place_break_here>:
 748:   d503201f        nop

That "ldr" is not.

To fix this, use a single inline asm block so we
can control the layout. The only drawback to that
is we have to spell out the branch over the
dead code.

Turns out most architectures are just "b" though.
Only tested on AArch64 but I did check that the
instructions assembled for the other targets.

>From a451c0bea926def6439efc017ab9f770f271f2dd Mon Sep 17 00:00:00 2001
From: David Spickett <david.spickett at arm.com>
Date: Wed, 14 Oct 2026 10:08:34 +0000
Subject: [PATCH] [lldb][test] Fix TestWriteOverSoftwareBreakpoint

After the changes made in #230518. They are correct,
but broke an assumption that I had made that there
would be no live code between the set of nops
and the breakpoint location.

Before:
 730:   d503201f        nop
 734:   14000001        b       738 <place_break_here>
0000000000000738 <place_break_here>:

That "b" is dead code, but -

After:
 73c:   d503201f        nop
 740:   14000001        b       744 <foo+0x30>
 744:   b9400fe0        ldr     w0, [sp, #12]
0000000000000748 <place_break_here>:
 748:   d503201f        nop

That "ldr" is not.

To fix this, use a single inline asm block so we
can control the layout. The only drawback to that
is we have to spell out the branch over the
dead code.

Turns out most architectures are just "b" though.
Only tested on AArch64 but I did check that the
instructions assembled for the other targets.
---
 .../write_over_software_breakpoint/main.c     | 39 +++++++++++--------
 1 file changed, 23 insertions(+), 16 deletions(-)

diff --git a/lldb/test/API/functionalities/breakpoint/write_over_software_breakpoint/main.c b/lldb/test/API/functionalities/breakpoint/write_over_software_breakpoint/main.c
index 4c9100dda604a..ca3e28f2bb762 100644
--- a/lldb/test/API/functionalities/breakpoint/write_over_software_breakpoint/main.c
+++ b/lldb/test/API/functionalities/breakpoint/write_over_software_breakpoint/main.c
@@ -1,22 +1,29 @@
+#if defined(__x86_64__) || defined(__i386__)
+#define BRANCH_FWD "jmp 1f\n"
+#elif defined(__aarch64__) || defined(__arm__) || defined(__powerpc64__) ||    \
+    defined(__powerpc__) || defined(__s390x__) || defined(__loongarch__)
+#define BRANCH_FWD "b 1f\n"
+#elif defined(__riscv)
+#define BRANCH_FWD "j 1f\n"
+#else
+#error Do not know unconditional branch mnemonic for this architecture.
+#endif
+
 volatile int always_false;
 
 int foo() {
-  // This nop is deliberately dead code so that we have an instruction
-  // immediately prior to the breakpoint that we are allowed to corrupt.
-  if (always_false) {
-    // This dead code must be at least 4 bytes even on an architecture where
-    // nop is 1 byte.
-    asm volatile("nop\n"
-                 "nop\n"
-                 "nop\n"
-                 "nop\n");
-  }
-  // We are assuming that there are no instructions placed between the dead code
-  // above and the assembly below. This is not guaranteed but it's safer than
-  // assuming that this function will have no prologue instructions or breaking
-  // in the very first instruction of foo and hoping whatever comes before is
-  // not important.
-  asm volatile(".globl place_break_here\n"
+  asm volatile(BRANCH_FWD
+               // This is dead code that we are allowed to corrupt.
+               // There are 4 so that even if nop is 1 byte, we have 4 bytes
+               // we can overwrite safely.
+               "nop\n"
+               "nop\n"
+               "nop\n"
+               "nop\n"
+               // No live code should be between the dead code above
+               // and the breakpoint location below.
+               "1:\n"
+               ".globl place_break_here\n"
                "place_break_here:\n"
                // The test will repeatedly add and remove a breakpoint here.
                "nop");



More information about the lldb-commits mailing list