]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gdb: LoongArch: Improve the handling of atomic sequence
authorHui Li <lihui@loongson.cn>
Thu, 6 Feb 2025 12:29:56 +0000 (20:29 +0800)
committerTiezhu Yang <yangtiezhu@loongson.cn>
Mon, 10 Feb 2025 11:31:48 +0000 (19:31 +0800)
In the current code, when using software single-step to debug atomic
instruction sequence, the execution of the atomic instruction sequence
may not be completed normally.

Here is a test with setting a software watchpoint to execute in software
single-step mode:

$ cat test.c
int a = 0;
int main()
  {
    a = 1;
    return 0;
  }
$ gcc -g test.c -o test
$ gdb test
..
(gdb) start
..
Temporary breakpoint 1, main () at test.c:4
4     a = 1;
(gdb) set can-use-hw-watchpoints 0
(gdb) n
5     return 0;
(gdb) watch a
Watchpoint 2: a
(gdb) c
Continuing.

At this point, the program continues to execute and can not exit
normally because it incorrectly handled the following ll/sc atomic
sequence in __run_exit_handlers () from /lib64/libc.so.6 during
software single-step execution.

   0x00007ffff7df7a48 <+408>: ld.d         $t1, $s2, 1776
   0x00007ffff7df7a4c <+412>: ll.w         $t0, $t1, 0
=> 0x00007ffff7df7a50 <+416>: bne          $t0, $zero, 20 # 0x7ffff7df7a64 <__run_exit_handlers+436>
   0x00007ffff7df7a54 <+420>: or           $t3, $zero, $s4
   0x00007ffff7df7a58 <+424>: sc.w         $t3, $t1, 0
   0x00007ffff7df7a5c <+428>: beq          $zero, $t3, -16 # 0x7ffff7df7a4c <__run_exit_handlers+412>
   0x00007ffff7df7a60 <+432>: b            8 # 0x7ffff7df7a68 <__run_exit_handlers+440>
   0x00007ffff7df7a64 <+436>: dbar         0x700
   0x00007ffff7df7a68 <+440>: slli.w       $t0, $t0, 0x0

The root cause of this problem is that a breakpoint was inserted in the
middle of ll/sc atomic sequence during software single-step execution.
The execution result of the atomic instruction sequence is disrupted,
causing the program unable to complete the execution of the atomic
instruction sequence normally.

Further explanation, if the current pc is 0x00007ffff7df7a50, it is a
conditional branch instruction, breakpoint should only be set at the
jump destination address (0x00007ffff7df7a64, which is outside of the
ll/sc atomic instruction sequence) and should not set at the address
of pc + 4 (0x00007ffff7df7a54, which is in the middle of ll/sc atomic
sequence).

Modify a judgment condition in loongarch_deal_with_atomic_sequence()
to ensure that breakpoints can not be inserted in the middle of ll/sc
atomic sequence to address such issues.

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

index 1cab29bbecbe9b519160de522aee624d599244cd..00c72d1155001b89746f721a08f22d9717d61f1d 100644 (file)
@@ -351,11 +351,13 @@ loongarch_deal_with_atomic_sequence (struct regcache *regcache, CORE_ADDR cur_pc
        {
          return {};
        }
-      /* Look for a conditional branch instruction, put a breakpoint in its destination address.  */
+      /* Look for a conditional branch instruction, put a breakpoint in its destination address
+        which is outside of the ll/sc atomic instruction sequence.  */
       else if (loongarch_insn_is_cond_branch (insn))
        {
          next_pc = loongarch_next_pc (regcache, cur_pc);
-         next_pcs.push_back (next_pc);
+         if (next_pc != cur_pc + insn_len)
+           next_pcs.push_back (next_pc);
        }
       /* Look for a Store Conditional instruction which closes the atomic sequence.  */
       else if (loongarch_insn_is_sc (insn))