Skip to content

[lldb][RISCV] fix LR/SC atomic sequence handling in lldb-server #127505

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 24, 2025

Conversation

dlav-sc
Copy link
Contributor

@dlav-sc dlav-sc commented Feb 17, 2025

lldb-server had limited support for single-stepping through the lr/sc atomic sequence. This patch enhances that support for all possible atomic sequences.

@llvmbot
Copy link
Member

llvmbot commented Feb 17, 2025

@llvm/pr-subscribers-lldb

Author: None (dlav-sc)

Changes

lldb-server didn't consider that LR instruction may be followed not only by BNE instruction (takes 4 bytes), but by BNEZ too, which is a compressed instruction (takes 2 bytes). As a result, after BNEZ lldb-server reseived an incorrect PC value and couldn't parse the next instruction opcode.


Full diff: https://github.com/llvm/llvm-project/pull/127505.diff

1 Files Affected:

  • (modified) lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp (+11-6)
diff --git a/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp b/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp
index badc7ba36f011..e4de28d97d1ff 100644
--- a/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp
+++ b/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp
@@ -349,9 +349,10 @@ bool AtomicSequence(EmulateInstructionRISCV &emulator) {
   if (!inst || (!std::holds_alternative<LR_W>(inst->decoded) &&
                 !std::holds_alternative<LR_D>(inst->decoded)))
     return false;
+  current_pc += 4;
 
-  // The second instruction should be BNE to exit address
-  inst = emulator.ReadInstructionAt(current_pc += 4);
+      // The second instruction should be BNE or C.BNEZ to exit address
+      inst = emulator.ReadInstructionAt(current_pc);
   if (!inst || !std::holds_alternative<B>(inst->decoded))
     return false;
   auto bne_exit = std::get<B>(inst->decoded);
@@ -359,15 +360,18 @@ bool AtomicSequence(EmulateInstructionRISCV &emulator) {
     return false;
   // save the exit address to check later
   const auto exit_pc = current_pc + SextW(bne_exit.imm);
+  // Can be C.BNEZ (2 bytes) or BNE (4 bytes)
+  current_pc += inst->is_rvc ? 2 : 4;
 
   // The third instruction should be SC.W or SC.D
-  inst = emulator.ReadInstructionAt(current_pc += 4);
+  inst = emulator.ReadInstructionAt(current_pc);
   if (!inst || (!std::holds_alternative<SC_W>(inst->decoded) &&
                 !std::holds_alternative<SC_D>(inst->decoded)))
     return false;
+  current_pc += 4;
 
-  // The fourth instruction should be BNE to entry address
-  inst = emulator.ReadInstructionAt(current_pc += 4);
+      // The fourth instruction should be BNE or C.BNEZ to entry address
+      inst = emulator.ReadInstructionAt(current_pc);
   if (!inst || !std::holds_alternative<B>(inst->decoded))
     return false;
   auto bne_start = std::get<B>(inst->decoded);
@@ -375,8 +379,9 @@ bool AtomicSequence(EmulateInstructionRISCV &emulator) {
     return false;
   if (entry_pc != current_pc + SextW(bne_start.imm))
     return false;
+  // Can be C.BNEZ (2 bytes) or BNE (4 bytes)
+  current_pc += inst->is_rvc ? 2 : 4;
 
-  current_pc += 4;
   // check the exit address and jump to it
   return exit_pc == current_pc && emulator.WritePC(current_pc);
 }

Copy link

github-actions bot commented Feb 17, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@dlav-sc dlav-sc force-pushed the dlav-sc/lldb-fix-lrsc-inst branch from 2ab6cea to 8691dc9 Compare February 17, 2025 15:34
@dlav-sc dlav-sc added the bug Indicates an unexpected problem or unintended behavior label Feb 17, 2025
@dlav-sc dlav-sc force-pushed the dlav-sc/lldb-fix-lrsc-inst branch from 8691dc9 to 244a67e Compare February 17, 2025 15:35
@dlav-sc dlav-sc changed the title [lldb] fix LR/SC handling in lldb-server [lldb][RISCV] fix LR/SC handling in lldb-server Feb 17, 2025
@JDevlieghere
Copy link
Member

CC @SEmmmer

@DavidSpickett
Copy link
Collaborator

Please update the title/description to mention that this is within atomic sequences. I thought this was some kind of fused instruction pair/delay slot type deal but it's not that.

Looks fine at a high level, but I always like to get an architecture expert in just in case. @asb you or someone else you know of? Confirming the claims about the format of the sequence would be enough I think.

@dlav-sc dlav-sc changed the title [lldb][RISCV] fix LR/SC handling in lldb-server [lldb][RISCV] fix LR/SC atomic sequence handling in lldb-server Mar 28, 2025
@dlav-sc
Copy link
Contributor Author

dlav-sc commented Mar 31, 2025

I'm going to land this by the end of the week. If you have any concerns, please let me know.

@asb
Copy link
Contributor

asb commented Mar 31, 2025

My apologies for missing this before. It is indeed completely valid to have a compressed branch immediately after the lr.w or sc.w and remain compliant with the forward progress guarantee. I feel I'm lacking a bit of higher level understanding of what this code is trying to do it, because:

  • It matches only one of many possible lr.[wd]/sc.[wd] sequences. For instance we'll have sequences of other integer instructions between the lr and sc for things like narrower than 32-bit cmpxchg (see llvm/test/CodeGen/RISCV/atomic-cmpxchg.ll)
  • Why isn't there a a call to m_emu.WriteMem in the implementation?

@dlav-sc
Copy link
Contributor Author

dlav-sc commented Apr 3, 2025

It matches only one of many possible lr.[wd]/sc.[wd] sequences.

I was confused too when I saw this for the first time. I expected to see a processing a sequence of integer instructions between lr and sc. This patch was enough to fix my issue, so I decided to bring it here as is. However, I'm now thinking I could try to do something more comprehensive and support any possible sequence of instructions.

Why isn't there a a call to m_emu.WriteMem in the implementation?

From what I understand, it's not a real simulator. This is used in lldb for software stepping to determine where to set a breakpoint. lldb needs to emulate the instruction to obtain next PC.

lldb-server had limited support for single-stepping through the
lr/sc atomic sequence. This patch enhances that support for all
possible atomic sequences.
@dlav-sc dlav-sc force-pushed the dlav-sc/lldb-fix-lrsc-inst branch from 244a67e to 626f439 Compare May 29, 2025 16:50
Copy link

github-actions bot commented May 29, 2025

✅ With the latest revision this PR passed the Python code formatter.

@dlav-sc dlav-sc force-pushed the dlav-sc/lldb-fix-lrsc-inst branch from 626f439 to b25477e Compare May 29, 2025 16:59
@dlav-sc
Copy link
Contributor Author

dlav-sc commented May 29, 2025

@DavidSpickett, @asb could you take another look at this patch, please?

I've added support for instruction step for any possible riscv atomic sequence (or at least I believe so). Additionally, I've made some minor refactoring to the software single-step logic.

Copy link
Collaborator

@DavidSpickett DavidSpickett left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I'm someone looking to find out if a particular atomic sequence is valid, where do I look, what's the ABI / ISA doc that tells us that?

I don't literally want to do that now, but someone in future might, so if there is one, please add links to it in the PR message and the top of the test file.

(if there is no stable link, the doc's name is enough)

@dlav-sc dlav-sc force-pushed the dlav-sc/lldb-fix-lrsc-inst branch from 262b3b0 to f93c15d Compare June 23, 2025 23:17
@dlav-sc dlav-sc force-pushed the dlav-sc/lldb-fix-lrsc-inst branch from f93c15d to 576298d Compare June 23, 2025 23:24
Copy link
Collaborator

@DavidSpickett DavidSpickett left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@dlav-sc
Copy link
Contributor Author

dlav-sc commented Jun 24, 2025

LGTM

Thank you for the review! I'm going to land it by the end of the day.

@dlav-sc dlav-sc merged commit 3bc1fc6 into llvm:main Jun 24, 2025
7 checks passed
@slydiman
Copy link
Contributor

slydiman commented Jun 24, 2025

lldb-remote-linux-ubuntu is broken after this patch.
Please update the test conditions to skip riscv tests on non-riscv platforms.
Note r matches in aarch64 for rv* regex. https://regex101.com/r/qDLwI2/1
Update rv* with ^rv.* must be enough.

DrSergei pushed a commit to DrSergei/llvm-project that referenced this pull request Jun 24, 2025
…#127505)

lldb-server had limited support for single-stepping through the lr/sc
atomic sequence. This patch enhances that support for all possible
atomic sequences.
@JDevlieghere
Copy link
Member

JDevlieghere added a commit that referenced this pull request Jun 24, 2025
…er" (#145597)

Reverts #127505 because
`riscv/step/TestSoftwareStep.py` is failing on the bots.
llvm-sync bot pushed a commit to arm/arm-toolchain that referenced this pull request Jun 24, 2025
…n lldb-server" (#145597)

Reverts llvm/llvm-project#127505 because
`riscv/step/TestSoftwareStep.py` is failing on the bots.
@DavidSpickett
Copy link
Collaborator

Yeah to my surprise it's re.search not re.match. Makes sense in hindsight though.

anthonyhatran pushed a commit to anthonyhatran/llvm-project that referenced this pull request Jun 26, 2025
…#127505)

lldb-server had limited support for single-stepping through the lr/sc
atomic sequence. This patch enhances that support for all possible
atomic sequences.
anthonyhatran pushed a commit to anthonyhatran/llvm-project that referenced this pull request Jun 26, 2025
…er" (llvm#145597)

Reverts llvm#127505 because
`riscv/step/TestSoftwareStep.py` is failing on the bots.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Indicates an unexpected problem or unintended behavior lldb
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants