blob: 3303d57d4504a806926f596b183d53d2fc6b5c6d [file] [edit]
"""Test unions from GDB remote target description XML."""
from textwrap import dedent
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.gdbclientutils import *
from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase
from lldbsuite.test.lldbtest import *
class TestXMLRegisterUnion(GDBRemoteTestBase):
def setup_multidoc_test(self, docs, register_data):
self.server.responder = MockGDBServerXMLResponder(docs, register_data)
target = self.dbg.CreateTarget("")
process = self.connect(target)
lldbutil.expect_state_changes(
self, self.dbg.GetListener(), process, [lldb.eStateStopped]
)
return process
def setup_register_test(self, definitions, register_data):
return self.setup_multidoc_test(
{
"target.xml": dedent(
"""\
<?xml version="1.0"?>
<target version="1.0">
<architecture>aarch64</architecture>
<feature name="test.register.unions">
{}
</feature>
</target>"""
).format(definitions)
},
register_data,
)
def assert_union_info(self, name, byte_size, members):
self.expect(
"register info {}".format(name),
substrs=["Size: {} bytes".format(byte_size), "Union members:"] + members,
)
def assert_no_union_info(self, name):
self.expect("register info {}".format(name), substrs=["Name: {}".format(name)])
self.expect(
"register info {}".format(name),
matching=False,
substrs=["Union members:"],
)
@skipIfXmlSupportMissing
@skipIfRemote
def test_direct_and_nested_union_metadata(self):
self.setup_register_test(
"""\
<vector id="v2f" type="ieee_single" count="2"/>
<union id="views">
<field name="f32" type="ieee_single"/>
<field name="f64" type="ieee_double"/>
<field name="lanes" type="v2f"/>
</union>
<union id="nested">
<field name="view" type="views"/>
<field name="raw" type="uint64"/>
</union>
<reg name="direct" regnum="0" bitsize="64" type="views"/>
<reg name="nested" regnum="1" bitsize="64" type="nested"/>
<reg name="larger" regnum="2" bitsize="128" type="views"/>
<reg name="pc" bitsize="64"/>""",
"00" * 40,
)
self.assert_union_info(
"direct",
8,
[
"f32 (ieee_single, 4 bytes)",
"f64 (ieee_double, 8 bytes)",
"lanes (v2f, 8 bytes)",
],
)
self.assert_union_info(
"nested", 8, ["view (views, 8 bytes)", "raw (uint64, 8 bytes)"]
)
self.assert_union_info(
"larger",
16,
[
"f32 (ieee_single, 4 bytes)",
"f64 (ieee_double, 8 bytes)",
"lanes (v2f, 8 bytes)",
],
)
@skipIfXmlSupportMissing
@skipIfRemote
def test_vector_of_union_metadata(self):
self.setup_register_test(
"""\
<union id="scalar32_views">
<field name="f32" type="ieee_single"/>
<field name="u32" type="uint32"/>
</union>
<vector id="v4views" type="scalar32_views" count="4"/>
<union id="pointer_view">
<field name="pointer" type="data_ptr"/>
</union>
<vector id="v2p" type="pointer_view" count="2"/>
<reg name="u0" regnum="0" bitsize="32" type="scalar32_views"/>
<reg name="v0" regnum="1" bitsize="128" type="v4views"/>
<reg name="p0" regnum="2" bitsize="128" type="v2p"/>
<reg name="pc" bitsize="64"/>""",
"00" * 44,
)
self.assert_union_info(
"u0", 4, ["f32 (ieee_single, 4 bytes)", "u32 (uint32, 4 bytes)"]
)
self.expect(
"register info v0",
substrs=["Size: 16 bytes", "Vector elements: 4"],
)
self.expect(
"register info p0",
substrs=["Size: 16 bytes", "Vector elements: 2"],
)
@skipIfXmlSupportMissing
@skipIfRemote
def test_invalid_unions_are_ignored(self):
self.setup_register_test(
"""\
<enum id="enumeration" size="4">
<evalue name="zero" value="0"/>
</enum>
<flags id="flags" size="4">
<field name="bit" start="0" end="0"/>
</flags>
<union>
<field name="value" type="uint64"/>
</union>
<union id="empty"/>
<union id="missing_field_name">
<field type="uint64"/>
</union>
<union id="missing_field_type">
<field name="value"/>
</union>
<union id="unknown_field_type">
<field name="value" type="not_defined"/>
</union>
<union id="partial_invalid_field">
<field name="valid" type="uint64"/>
<field name="invalid" type="not_defined"/>
</union>
<union id="forward_field_type">
<field name="value" type="later"/>
</union>
<union id="enum_field_type">
<field name="value" type="enumeration"/>
</union>
<union id="flags_field_type">
<field name="value" type="flags"/>
</union>
<union id="later">
<field name="value" type="uint64"/>
</union>
<union id="wide">
<field name="value" type="uint64"/>
</union>
<reg name="empty" regnum="0" bitsize="64" type="empty"/>
<reg name="missing_field_name" regnum="1" bitsize="64"
type="missing_field_name"/>
<reg name="missing_field_type" regnum="2" bitsize="64"
type="missing_field_type"/>
<reg name="unknown_field_type" regnum="3" bitsize="64"
type="unknown_field_type"/>
<reg name="forward_field_type" regnum="4" bitsize="64"
type="forward_field_type"/>
<reg name="enum_field_type" regnum="5" bitsize="32"
type="enum_field_type"/>
<reg name="flags_field_type" regnum="6" bitsize="32"
type="flags_field_type"/>
<reg name="later" regnum="7" bitsize="64" type="later"/>
<reg name="wrong_size" regnum="8" bitsize="32" type="wide"/>
<reg name="partial_invalid_field" regnum="9" bitsize="64"
type="partial_invalid_field"/>
<reg name="pc" bitsize="64"/>""",
"00" * 76,
)
for name in [
"empty",
"missing_field_name",
"missing_field_type",
"unknown_field_type",
"partial_invalid_field",
"forward_field_type",
"enum_field_type",
"flags_field_type",
"wrong_size",
]:
self.assert_no_union_info(name)
self.assert_union_info("later", 8, ["value (uint64, 8 bytes)"])
@skipIfXmlSupportMissing
@skipIfRemote
def test_duplicate_union_id_uses_first_definition(self):
self.setup_register_test(
"""\
<union id="shared">
<field name="first" type="uint64"/>
</union>
<union id="shared">
<field name="second" type="ieee_double"/>
</union>
<reg name="u0" regnum="0" bitsize="64" type="shared"/>
<reg name="pc" bitsize="64"/>""",
"00" * 16,
)
self.assert_union_info("u0", 8, ["first (uint64, 8 bytes)"])
self.expect("register info u0", matching=False, substrs=["second"])
@skipIfXmlSupportMissing
@skipIfRemote
def test_union_ids_are_scoped_to_included_feature(self):
self.setup_multidoc_test(
{
"target.xml": dedent(
"""\
<?xml version="1.0"?>
<target version="1.0">
<architecture>aarch64</architecture>
<xi:include href="first.xml"/>
<xi:include href="second.xml"/>
<xi:include href="third.xml"/>
</target>"""
),
"first.xml": dedent(
"""\
<?xml version="1.0"?>
<feature name="feature.first">
<union id="shared">
<field name="first" type="uint64"/>
</union>
<reg name="first" regnum="0" bitsize="64" type="shared"/>
</feature>"""
),
"second.xml": dedent(
"""\
<?xml version="1.0"?>
<feature name="feature.second">
<union id="shared">
<field name="second" type="uint32"/>
</union>
<reg name="second" regnum="1" bitsize="32" type="shared"/>
</feature>"""
),
"third.xml": dedent(
"""\
<?xml version="1.0"?>
<feature name="feature.third">
<reg name="unresolved" regnum="2" bitsize="64" type="shared"/>
<reg name="pc" bitsize="64"/>
</feature>"""
),
},
"00" * 28,
)
self.assert_union_info("first", 8, ["first (uint64, 8 bytes)"])
self.assert_union_info("second", 4, ["second (uint32, 4 bytes)"])
self.assert_no_union_info("unresolved")