I posted this question on Stack Overflow, but I’m afraid SO might not be the right forum. Please forgive me for cross posting.
I’m working on a JIT compiler on the ARM64 platform. In order to debug the machine code it emits, sometimes I will have the compiler emit a brk
instruction so that I can inspect the state of things using lldb.
Unlike the x86_64 platform, the PC register is at the instruction (not after it):
Process 61859 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BREAKPOINT (code=1, subcode=0x1008e8020)
frame #0: 0x00000001008e8020
-> 0x1008e8020: brk #0x1
0x1008e8024: ldur x9, [x9]
0x1008e8028: mov x10, #0x4000
0x1008e802c: movk x10, #0x8e, lsl #16
Target 0: (ruby) stopped.
(lldb) p/x $pc
(unsigned long) $3 = 0x00000001008e8020
(lldb)
This means I cannot use si
in lldb to step over the brk
instruction because the brk
instruction will just be evaluated over and over:
Process 61859 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BREAKPOINT (code=1, subcode=0x1008e8020)
frame #0: 0x00000001008e8020
-> 0x1008e8020: brk #0x1
0x1008e8024: ldur x9, [x9]
0x1008e8028: mov x10, #0x4000
0x1008e802c: movk x10, #0x8e, lsl #16
Target 0: (ruby) stopped.
(lldb) p/x $pc
(unsigned long) $3 = 0x00000001008e8020
(lldb) si
Process 61859 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BREAKPOINT (code=1, subcode=0x1008e8020)
frame #0: 0x00000001008e8020
-> 0x1008e8020: brk #0x1
0x1008e8024: ldur x9, [x9]
0x1008e8028: mov x10, #0x4000
0x1008e802c: movk x10, #0x8e, lsl #16
Target 0: (ruby) stopped.
(lldb) si
Process 61859 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BREAKPOINT (code=1, subcode=0x1008e8020)
frame #0: 0x00000001008e8020
-> 0x1008e8020: brk #0x1
0x1008e8024: ldur x9, [x9]
0x1008e8028: mov x10, #0x4000
0x1008e802c: movk x10, #0x8e, lsl #16
Target 0: (ruby) stopped.
(lldb)
I know that I can directly write to the $pc
register to step over the instruction, but I don’t want to copy / paste the next address every time. I used to use this command:
register write $pc `$pc + 4`
But something changed on macOS such that the above command doesn’t work anymore. I get the following error:
error: Failed to write register 'pc' with value '$pc + 4': '$pc + 4' is not a valid unsigned integer string value
Is there a better or more supported way to step over brk
instructions on ARM64? I’m currently using this version of lldb:
$ lldb -v
lldb-1403.0.17.64
Apple Swift version 5.8 (swiftlang-5.8.0.124.2 clang-1403.0.22.11.100)
Thanks, and again I’m really sorry for cross posting. I am not sure where to ask this question.