122 lines · python
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 represent3 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 of8 unknown type that are > 128 bits, as the SVE registers are here.9"""10 11from textwrap import dedent12import lldb13from lldbsuite.test.lldbtest import *14from lldbsuite.test.decorators import *15from lldbsuite.test.gdbclientutils import *16from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase17 18 19class Responder(MockGDBServerResponder):20 def __init__(self):21 super().__init__()22 self.vg = 423 self.pc = 0xA0A0A0A0A0A0A0A024 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 debugger28 # 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 vg56 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 72class 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 @skipIfXmlSupportMissing97 @skipIfRemote98 @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 new115 # vg and lldb will reconfigure the register defs. This should not break the116 # 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)122