""" Check that when a debug server provides XML that only defines SVE Z registers, and does not include Neon V registers, lldb creates sub-registers to represent the V registers as the bottom 128 bits of the Z registers. qemu-aarch64 is one such debug server. This also doubles as a test that lldb has a fallback path for registers of unknown type that are > 128 bits, as the SVE registers are here. """ from textwrap import dedent import lldb from lldbsuite.test.lldbtest import * from lldbsuite.test.decorators import * from lldbsuite.test.gdbclientutils import * from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase class Responder(MockGDBServerResponder): def __init__(self): super().__init__() self.vg = 4 self.pc = 0xA0A0A0A0A0A0A0A0 def qXferRead(self, obj, annex, offset, length): if annex == "target.xml": # Note that QEMU sends the current SVE size in XML and the debugger # then reads vg to know the latest size. return ( dedent( """\ aarch64 """ ), False, ) return (None,) def readRegister(self, regnum): return "E01" def readRegisters(self): return "".join( [ # 64 bit PC. f"{self.pc:x}", # 64 bit vg f"0{self.vg}00000000000000", # Enough data for 256 and 512 bit SVE. "".join([f"{n:02x}" * 4 for n in range(1, 17)]), ] ) def cont(self): # vg is expedited so that lldb can resize the SVE registers. return f"T02thread:1ff0d;threads:1ff0d;thread-pcs:{self.pc};01:0{self.vg}00000000000000;" def writeRegisters(self, registers_hex): # We get a block of data containing values in regnum order. self.vg = int(registers_hex[16:18]) return "OK" class TestXMLRegisterFlags(GDBRemoteTestBase): def check_regs(self, vg): # Each 32 bit chunk repeats n. z0_value = " ".join( [" ".join([f"0x{n:02x}"] * 4) for n in range(1, (vg * 2) + 1)] ) self.expect( "register read vg z0 v0 s0 d0", substrs=[ f" vg = 0x000000000000000{vg}\n" " z0 = {" + z0_value + "}\n" " v0 = {0x01 0x01 0x01 0x01 0x02 0x02 0x02 0x02 0x03 0x03 0x03 0x03 0x04 0x04 0x04 0x04}\n" " s0 = 2.36942783E-38\n" " d0 = 5.3779407333977203E-299\n" ], ) self.expect("register read s0 --format uint32", substrs=["s0 = {0x01010101}"]) self.expect( "register read d0 --format uint64", substrs=["d0 = {0x0202020201010101}"], ) @skipIfXmlSupportMissing @skipIfRemote @skipIfLLVMTargetMissing("AArch64") def test_v_sub_registers(self): self.server.responder = Responder() target = self.dbg.CreateTarget("") if self.TraceOn(): self.runCmd("log enable gdb-remote packets") self.addTearDownHook(lambda: self.runCmd("log disable gdb-remote packets")) process = self.connect(target) lldbutil.expect_state_changes( self, self.dbg.GetListener(), process, [lldb.eStateStopped] ) self.check_regs(4) # Now increase the SVE length and continue. The mock will respond with a new # vg and lldb will reconfigure the register defs. This should not break the # sub-registers. self.runCmd("register write vg 8") self.expect("continue", substrs=["stop reason = signal SIGINT"]) self.check_regs(8)