""" 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"""\ {architecture} """ ), 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)