]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gdb: LoongArch: Restrict breakpoint outside of atomic sequence
authorTiezhu Yang <yangtiezhu@loongson.cn>
Mon, 1 Sep 2025 01:29:56 +0000 (09:29 +0800)
committerTiezhu Yang <yangtiezhu@loongson.cn>
Wed, 3 Sep 2025 12:56:51 +0000 (20:56 +0800)
We can't put a breakpoint in the middle of a ll/sc atomic sequence,
so look for the end of the sequence and put the breakpoint there,
it has been handled in the commit 208b57e53ed9 ("gdb: LoongArch:
Deal with atomic sequence").

Especially, maybe there is a conditional branch instruction in the
middle of a ll/sc atomic sequence, its destination address may be
current pc + 4 which is inside the atomic sequence, it should not
put a breakpoint in its destination address in this case, this has
been handled in the commit a4242dc3f5fa ("gdb: LoongArch: Improve
the handling of atomic sequence").

Additionally, if there is a conditional branch instruction in the
middle of a ll/sc atomic sequence, its destination address may be
not current pc + 4 but still inside the atomic sequence, it should
not put a breakpoint in its destination address in this case.

So in order to avoid putting a breakpoint in the middle of a ll/sc
atomic sequence in any case, just look for the start and end of the
sequence, and restrict the breakpoint outside of the atomic sequence.

Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
gdb/loongarch-tdep.c

index 0bd8b36db0b0df0ffda4e9f072fc24d4ad95712b..f88fb5f0b09ef9439e039560041c5693f4f83815 100644 (file)
@@ -461,12 +461,16 @@ cond_branch_destination_address (CORE_ADDR cur_pc, insn_t insn)
 }
 
 /* We can't put a breakpoint in the middle of a ll/sc atomic sequence,
-   so look for the end of the sequence and put the breakpoint there.  */
+   so a breakpoint should be outside of atomic sequence in any case,
+   just look for the start and end of the sequence, and then restrict
+   the breakpoint outside of the atomic sequence.  */
 
 static std::vector<CORE_ADDR>
 loongarch_deal_with_atomic_sequence (struct regcache *regcache, CORE_ADDR cur_pc)
 {
   CORE_ADDR next_pc;
+  CORE_ADDR ll_insn_addr;
+  CORE_ADDR sc_insn_addr;
   std::vector<CORE_ADDR> next_pcs;
   insn_t insn = loongarch_fetch_instruction (cur_pc);
   size_t insn_len = loongarch_insn_length (insn);
@@ -477,6 +481,30 @@ loongarch_deal_with_atomic_sequence (struct regcache *regcache, CORE_ADDR cur_pc
   if (!loongarch_insn_is_ll (insn))
     return {};
 
+  /* Record the address of a Load Linked instruction  */
+  ll_insn_addr = cur_pc;
+
+  for (int insn_count = 0; insn_count < atomic_sequence_length; ++insn_count)
+    {
+      cur_pc += insn_len;
+      insn = loongarch_fetch_instruction (cur_pc);
+
+      if (loongarch_insn_is_sc (insn))
+       {
+         /* Record the address of a Store Conditional instruction  */
+         sc_insn_addr = cur_pc;
+         found_atomic_sequence_endpoint = true;
+         break;
+       }
+    }
+
+  /* We didn't find a closing Store Conditional instruction, fallback to the standard code.  */
+  if (!found_atomic_sequence_endpoint)
+    return {};
+
+  /* Restore current PC with the address of a Load Linked instruction  */
+  cur_pc = ll_insn_addr;
+
   /* Assume that no atomic sequence is longer than "atomic_sequence_length" instructions.  */
   for (int insn_count = 0; insn_count < atomic_sequence_length; ++insn_count)
     {
@@ -493,23 +521,19 @@ loongarch_deal_with_atomic_sequence (struct regcache *regcache, CORE_ADDR cur_pc
       else if (loongarch_insn_is_cond_branch (insn))
        {
          next_pc = cond_branch_destination_address (cur_pc, insn);
-         if (next_pc != cur_pc + insn_len)
+         /* Restrict the breakpoint outside of the atomic sequence.  */
+         if (next_pc < ll_insn_addr || next_pc > sc_insn_addr)
            next_pcs.push_back (next_pc);
        }
       /* Look for a Store Conditional instruction which closes the atomic sequence.  */
       else if (loongarch_insn_is_sc (insn))
        {
-         found_atomic_sequence_endpoint = true;
          next_pc = cur_pc + insn_len;
          next_pcs.push_back (next_pc);
          break;
        }
     }
 
-  /* We didn't find a closing Store Conditional instruction, fallback to the standard code.  */
-  if (!found_atomic_sequence_endpoint)
-    return {};
-
   return next_pcs;
 }