-
Notifications
You must be signed in to change notification settings - Fork 15.4k
Description
| Bugzilla Link | 51673 |
| Resolution | FIXED |
| Resolved on | Sep 22, 2021 04:14 |
| Version | 10.0 |
| OS | Windows NT |
| Reporter | LLVM Bugzilla Contributor |
| CC | @JDevlieghere,@mstorsjo |
| Fixed by commit(s) | 9f34f75 |
Extended Description
I was using lldb on Windows (Raspberry Pi 4 - ARM Cortex-A72 processor), and there were a couple of x86-isms that persist that make it impossible to set and use breakpoints.
Platform::GetSoftwareBreakpointTrapOpcode()
NativeProcessProtocol::GetSoftwareBreakpointTrapOpcode()
Uses "0xd4 0x20 0x00 0x00" for breakpoint on aarch64, but this does not work on Windows as it fails with a STATUS_ILLEGAL_INSTRUCTION exception being thrown.
case llvm::Triple::aarch64: {
static const uint8_t g_aarch64_opcode[] = {0x00, 0x00, 0x20, 0xd4};
The compiler intrinsic __debug_break() generates "{0x00, 0x00, 0x3e, 0xd4}". If I instead use this, then the program stops at the requested breakpoint, as expected.
TargetThreadWindows::DoResume()
NativeThreadWindows::DoResume()
Sets flag 0x100 for single step, but that's only valid for x86/x64.
if (resume_state == eStateStepping) {
uint32_t flags_index =
GetRegisterContext()->ConvertRegisterKindToRegisterNumber(
eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
uint64_t flags_value =
GetRegisterContext()->ReadRegisterAsUnsigned(flags_index, 0);
flags_value |= 0x100; // Set the trap flag on the CPU /* only correct for x86/x64 */
GetRegisterContext()->WriteRegisterFromUnsigned(flags_index, flags_value);
}
For AArch64, it should instead be 0x200000, as this is the location of the 'SS' bit of the PState register. Using this value, then single stepping works as expected.
Without a fix in this area, single stepping simply doesn't work.
ProcessWindows::RefreshStateAfterStop()
When handling EXCEPTION_BREAKPOINT, it assumes that the breakpoint instruction is 1 byte, which is only correct for x86/x64.
// The current EIP is AFTER the BP opcode, which is one byte.
uint64_t pc = register_context->GetPC() - 1;
The basic theory here is that after a breakpoint exception, that the program counter points to the instruction after the breakpoint, so we need to back up one instruction to get to the real breakpoint. On x86, a breakpoint is a single byte 0xCC. For AArch64 it needs to be 4 bytes (as noted above). Other architectures are going to be different of course. One can temporarily tweak this so that it works, of course, but on the surface it seems like the breakpoint information is already encapsulated in Platform.cpp, I suppose it would be best to simply leverage that.
Note that I am currently working in a LLVM 10.0 source tree, but I looked ahead to version 12 and I see no changes in this area.
I should add that with fixes/tweaks in all 3 of these places, the AArch64 lldb actually behaves pretty normally. I am still having a little trouble with PDB files, but I can address that separately.