|
| 1 | +""" Check that when a debug server provides XML that only defines SVE Z registers, |
| 2 | + and does not include Neon V registers, lldb creates sub-registers to represent |
| 3 | + the V registers as the bottom 128 bits of the Z registers. |
| 4 | +
|
| 5 | + qemu-aarch64 is one such debug server. |
| 6 | +
|
| 7 | + This also doubles as a test that lldb has a fallback path for registers of |
| 8 | + unknown type that are > 128 bits, as the SVE registers are here. |
| 9 | +""" |
| 10 | + |
| 11 | +from textwrap import dedent |
| 12 | +import lldb |
| 13 | +from lldbsuite.test.lldbtest import * |
| 14 | +from lldbsuite.test.decorators import * |
| 15 | +from lldbsuite.test.gdbclientutils import * |
| 16 | +from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase |
| 17 | + |
| 18 | + |
| 19 | +class Responder(MockGDBServerResponder): |
| 20 | + def __init__(self): |
| 21 | + super().__init__() |
| 22 | + self.vg = 4 |
| 23 | + self.pc = 0xA0A0A0A0A0A0A0A0 |
| 24 | + |
| 25 | + def qXferRead(self, obj, annex, offset, length): |
| 26 | + if annex == "target.xml": |
| 27 | + # Note that QEMU sends the current SVE size in XML and the debugger |
| 28 | + # then reads vg to know the latest size. |
| 29 | + return ( |
| 30 | + dedent( |
| 31 | + """\ |
| 32 | + <?xml version="1.0"?> |
| 33 | + <target version="1.0"> |
| 34 | + <architecture>aarch64</architecture> |
| 35 | + <feature name="org.gnu.gdb.aarch64.core"> |
| 36 | + <reg name="pc" regnum="0" bitsize="64"/> |
| 37 | + <reg name="vg" regnum="1" bitsize="64"/> |
| 38 | + <reg name="z0" regnum="2" bitsize="2048" type="not_a_type"/> |
| 39 | + </feature> |
| 40 | + </target>""" |
| 41 | + ), |
| 42 | + False, |
| 43 | + ) |
| 44 | + |
| 45 | + return (None,) |
| 46 | + |
| 47 | + def readRegister(self, regnum): |
| 48 | + return "E01" |
| 49 | + |
| 50 | + def readRegisters(self): |
| 51 | + return "".join( |
| 52 | + [ |
| 53 | + # 64 bit PC. |
| 54 | + f"{self.pc:x}", |
| 55 | + # 64 bit vg |
| 56 | + f"0{self.vg}00000000000000", |
| 57 | + # Enough data for 256 and 512 bit SVE. |
| 58 | + "".join([f"{n:02x}" * 4 for n in range(1, 17)]), |
| 59 | + ] |
| 60 | + ) |
| 61 | + |
| 62 | + def cont(self): |
| 63 | + # vg is expedited so that lldb can resize the SVE registers. |
| 64 | + return f"T02thread:1ff0d;threads:1ff0d;thread-pcs:{self.pc};01:0{self.vg}00000000000000;" |
| 65 | + |
| 66 | + def writeRegisters(self, registers_hex): |
| 67 | + # We get a block of data containing values in regnum order. |
| 68 | + self.vg = int(registers_hex[16:18]) |
| 69 | + return "OK" |
| 70 | + |
| 71 | + |
| 72 | +class TestXMLRegisterFlags(GDBRemoteTestBase): |
| 73 | + def check_regs(self, vg): |
| 74 | + # Each 32 bit chunk repeats n. |
| 75 | + z0_value = " ".join( |
| 76 | + [" ".join([f"0x{n:02x}"] * 4) for n in range(1, (vg * 2) + 1)] |
| 77 | + ) |
| 78 | + |
| 79 | + self.expect( |
| 80 | + "register read vg z0 v0 s0 d0", |
| 81 | + substrs=[ |
| 82 | + f" vg = 0x000000000000000{vg}\n" |
| 83 | + " z0 = {" + z0_value + "}\n" |
| 84 | + " v0 = {0x01 0x01 0x01 0x01 0x02 0x02 0x02 0x02 0x03 0x03 0x03 0x03 0x04 0x04 0x04 0x04}\n" |
| 85 | + " s0 = 2.36942783E-38\n" |
| 86 | + " d0 = 5.3779407333977203E-299\n" |
| 87 | + ], |
| 88 | + ) |
| 89 | + |
| 90 | + self.expect("register read s0 --format uint32", substrs=["s0 = {0x01010101}"]) |
| 91 | + self.expect( |
| 92 | + "register read d0 --format uint64", |
| 93 | + substrs=["d0 = {0x0202020201010101}"], |
| 94 | + ) |
| 95 | + |
| 96 | + @skipIfXmlSupportMissing |
| 97 | + @skipIfRemote |
| 98 | + @skipIfLLVMTargetMissing("AArch64") |
| 99 | + def test_v_sub_registers(self): |
| 100 | + self.server.responder = Responder() |
| 101 | + target = self.dbg.CreateTarget("") |
| 102 | + |
| 103 | + if self.TraceOn(): |
| 104 | + self.runCmd("log enable gdb-remote packets") |
| 105 | + self.addTearDownHook(lambda: self.runCmd("log disable gdb-remote packets")) |
| 106 | + |
| 107 | + process = self.connect(target) |
| 108 | + lldbutil.expect_state_changes( |
| 109 | + self, self.dbg.GetListener(), process, [lldb.eStateStopped] |
| 110 | + ) |
| 111 | + |
| 112 | + self.check_regs(4) |
| 113 | + |
| 114 | + # Now increase the SVE length and continue. The mock will respond with a new |
| 115 | + # vg and lldb will reconfigure the register defs. This should not break the |
| 116 | + # sub-registers. |
| 117 | + |
| 118 | + self.runCmd("register write vg 8") |
| 119 | + self.expect("continue", substrs=["stop reason = signal SIGINT"]) |
| 120 | + |
| 121 | + self.check_regs(8) |
0 commit comments