blob: e36013a11491b3c21029205a126fa6a57de0a518 [file] [log] [blame] [edit]
""" 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(
"""\
<?xml version="1.0"?>
<target version="1.0">
<architecture>aarch64</architecture>
<feature name="org.gnu.gdb.aarch64.core">
<reg name="pc" regnum="0" bitsize="64"/>
<reg name="vg" regnum="1" bitsize="64"/>
<reg name="z0" regnum="2" bitsize="2048" type="not_a_type"/>
</feature>
</target>"""
),
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)