Skip to content

Commit 244a67e

Browse files
committed
[lldb][RISCV] fix LR/SC handling in lldb-server
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.
1 parent 4d7192a commit 244a67e

File tree

1 file changed

+11
-6
lines changed

1 file changed

+11
-6
lines changed

lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -349,34 +349,39 @@ bool AtomicSequence(EmulateInstructionRISCV &emulator) {
349349
if (!inst || (!std::holds_alternative<LR_W>(inst->decoded) &&
350350
!std::holds_alternative<LR_D>(inst->decoded)))
351351
return false;
352+
current_pc += 4;
352353

353-
// The second instruction should be BNE to exit address
354-
inst = emulator.ReadInstructionAt(current_pc += 4);
354+
// The second instruction should be BNE or C.BNEZ to exit address
355+
inst = emulator.ReadInstructionAt(current_pc);
355356
if (!inst || !std::holds_alternative<B>(inst->decoded))
356357
return false;
357358
auto bne_exit = std::get<B>(inst->decoded);
358359
if (bne_exit.funct3 != BNE)
359360
return false;
360361
// save the exit address to check later
361362
const auto exit_pc = current_pc + SextW(bne_exit.imm);
363+
// Can be C.BNEZ (2 bytes) or BNE (4 bytes)
364+
current_pc += inst->is_rvc ? 2 : 4;
362365

363366
// The third instruction should be SC.W or SC.D
364-
inst = emulator.ReadInstructionAt(current_pc += 4);
367+
inst = emulator.ReadInstructionAt(current_pc);
365368
if (!inst || (!std::holds_alternative<SC_W>(inst->decoded) &&
366369
!std::holds_alternative<SC_D>(inst->decoded)))
367370
return false;
371+
current_pc += 4;
368372

369-
// The fourth instruction should be BNE to entry address
370-
inst = emulator.ReadInstructionAt(current_pc += 4);
373+
// The fourth instruction should be BNE or C.BNEZ to entry address
374+
inst = emulator.ReadInstructionAt(current_pc);
371375
if (!inst || !std::holds_alternative<B>(inst->decoded))
372376
return false;
373377
auto bne_start = std::get<B>(inst->decoded);
374378
if (bne_start.funct3 != BNE)
375379
return false;
376380
if (entry_pc != current_pc + SextW(bne_start.imm))
377381
return false;
382+
// Can be C.BNEZ (2 bytes) or BNE (4 bytes)
383+
current_pc += inst->is_rvc ? 2 : 4;
378384

379-
current_pc += 4;
380385
// check the exit address and jump to it
381386
return exit_pc == current_pc && emulator.WritePC(current_pc);
382387
}

0 commit comments

Comments
 (0)