This patch handles atomic sequences during single step.
LLDB should treat all instructions in the atomic sequence as if they are a single instruction i.e as a "single instruction block".
So while single stepping, LLDB should detect and skip such sequence by placing breakpoints only outside of such sequence i.e at the end of the sequence.
In MIPS, atomic sequence starts with LL (linked load) instruction and end with SC (store conditional) instruction.
Example of atomic sequence in MIPS:
0x400c08 <+372>: ll $4, 0($2) ----> Start of sequence 0x400c0c <+376>: bne $4, $5, 28 ---> Atomic sequence can contain branches that jump outside sequence range. 0x400c10 <+380>: addiu $3, $zero, 0 0x400c14 <+384>: move $1, $6 0x400c18 <+388>: sc $1, 0($2) -----> End of sequence 0x400c1c <+392>: beqz $1, -20 0x400c20 <+396>: addiu $3, $zero, 1 0x400c24 <+400>: sync 0x400c28 <+404>: bnez $3, 16 ---> Target of branch from sequence
Considering above example, while single stepping from LL instruction, LLDB should stop at instruction
after the end of sequence (instead of stopping at instruction next to LL).
There can be multiple exit/end points to atomic sequence.
- SC instruction
- Branch instructions in atomic sequence that jump outside sequence.
So to handle this, LLDB should place breakpoints at multiple locations:
- Breakpoint at instruction after SC instruction (i.e at 0x400c1c in above ex)
- Breakpoints at target addresses of branch instructions (if the branch target address is outside the sequence) i.e at 0x400c28, target of "bne $4, $5, 28" instruction.
These breakpoint addresses are determined by EmulateInstruction.
This patch makes few assumptions:
- Assumes that no atomic sequence for mips is longer than 16 instructions. i.e scan upto maximum 16 instructions from LL to find end of sequence.
- Assumes that the atomic sequence ends with a sc/scd instruction. So if we dont find "sc/scd" instruction then do not put any breakpoint. i.e fallback to the standard single-step code.
Testcase:
This patch also adds a testcase "TestStepInAtomicSequence.py" to test this change (currently enabled for MIPS only).
The test finds starting instruction of atomic sequence, runs till that instruction then does a single step and
finally verifies that we have stopped after end of sequence.
If you don't find the instructions you are looking for (perhaps due to a compiler change), the test will end up being a no-op. You might want to assert that you actually find the instructions you are looking for.