blob: d6de8731385b6d886cace5811fb02b560f2ace91 [file] [log] [blame] [edit]
""" Check that registers written to memory for expression evaluation are
written using the target's endian not the host's.
"""
from enum import Enum
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 Endian(Enum):
BIG = 0
LITTLE = 1
class Responder(MockGDBServerResponder):
def __init__(self, doc, endian):
super().__init__()
self.target_xml = doc
self.endian = endian
def qXferRead(self, obj, annex, offset, length):
if annex == "target.xml":
return self.target_xml, False
return (None,)
def readRegister(self, regnum):
return "E01"
def readRegisters(self):
# 64 bit pc value.
data = ["00", "00", "00", "00", "00", "00", "12", "34"]
if self.endian == Endian.LITTLE:
data.reverse()
return "".join(data)
class TestXMLRegisterFlags(GDBRemoteTestBase):
def do_endian_test(self, endian):
architecture, pc_reg_name, yaml_file, data, machine = {
Endian.BIG: ("s390x", "pswa", "s390x.yaml", "ELFDATA2MSB", "EM_S390"),
Endian.LITTLE: (
"aarch64",
"pc",
"aarch64.yaml",
"ELFDATA2LSB",
"EM_AARCH64",
),
}[endian]
self.server.responder = Responder(
dedent(
f"""\
<?xml version="1.0"?>
<target version="1.0">
<architecture>{architecture}</architecture>
<feature>
<reg name="{pc_reg_name}" bitsize="64"/>
</feature>
</target>"""
),
endian,
)
# We need to have a program file, so that we have a full type system,
# so that we can do the casts later.
obj_path = self.getBuildArtifact("main.o")
yaml_path = self.getBuildArtifact(yaml_file)
with open(yaml_path, "w") as f:
f.write(
dedent(
f"""\
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: {data}
Type: ET_REL
Machine: {machine}
...
"""
)
)
self.yaml2obj(yaml_path, obj_path)
target = self.dbg.CreateTarget(obj_path)
process = self.connect(target)
lldbutil.expect_state_changes(
self, self.dbg.GetListener(), process, [lldb.eStateStopped]
)
# If expressions convert register values into target endian, the
# result of register read, expr and casts should be the same.
pc_value = "0x0000000000001234"
self.expect(
"register read pc",
substrs=[pc_value],
)
self.expect("expr --format hex -- $pc", substrs=[pc_value])
pc = (
process.thread[0]
.frame[0]
.GetRegisters()
.GetValueAtIndex(0)
.GetChildMemberWithName("pc")
)
ull = target.FindTypes("unsigned long long").GetTypeAtIndex(0)
pc_ull = pc.Cast(ull)
self.assertEqual(pc.GetValue(), pc_ull.GetValue())
self.assertEqual(pc.GetValueAsAddress(), pc_ull.GetValueAsAddress())
self.assertEqual(pc.GetValueAsSigned(), pc_ull.GetValueAsSigned())
self.assertEqual(pc.GetValueAsUnsigned(), pc_ull.GetValueAsUnsigned())
@skipIfXmlSupportMissing
@skipIfRemote
@skipIfLLVMTargetMissing("AArch64")
def test_little_endian_target(self):
self.do_endian_test(Endian.LITTLE)
@skipIfXmlSupportMissing
@skipIfRemote
@skipIfLLVMTargetMissing("SystemZ")
def test_big_endian_target(self):
self.do_endian_test(Endian.BIG)