[lldb-dev] [Bug 51673] New: AArch64 debug problems on Windows

via lldb-dev lldb-dev at lists.llvm.org
Mon Aug 30 06:44:39 PDT 2021


https://bugs.llvm.org/show_bug.cgi?id=51673

            Bug ID: 51673
           Summary: AArch64 debug problems on Windows
           Product: lldb
           Version: 10.0
          Hardware: Other
                OS: Windows NT
            Status: NEW
          Severity: normal
          Priority: P
         Component: All Bugs
          Assignee: lldb-dev at lists.llvm.org
          Reporter: eric at andante.org
                CC: jdevlieghere at apple.com, llvm-bugs at lists.llvm.org

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.

-- 
You are receiving this mail because:
You are the assignee for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20210830/5d2b3612/attachment.html>


More information about the lldb-dev mailing list