129 lines · python
1""" Check that registers written to memory for expression evaluation are2 written using the target's endian not the host's.3"""4 5from enum import Enum6from textwrap import dedent7import lldb8from lldbsuite.test.lldbtest import *9from lldbsuite.test.decorators import *10from lldbsuite.test.gdbclientutils import *11from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase12 13 14class Endian(Enum):15 BIG = 016 LITTLE = 117 18 19class Responder(MockGDBServerResponder):20 def __init__(self, doc, endian):21 super().__init__()22 self.target_xml = doc23 self.endian = endian24 25 def qXferRead(self, obj, annex, offset, length):26 if annex == "target.xml":27 return self.target_xml, False28 return (None,)29 30 def readRegister(self, regnum):31 return "E01"32 33 def readRegisters(self):34 # 64 bit pc value.35 data = ["00", "00", "00", "00", "00", "00", "12", "34"]36 if self.endian == Endian.LITTLE:37 data.reverse()38 return "".join(data)39 40 41class TestXMLRegisterFlags(GDBRemoteTestBase):42 def do_endian_test(self, endian):43 architecture, pc_reg_name, yaml_file, data, machine = {44 Endian.BIG: ("s390x", "pswa", "s390x.yaml", "ELFDATA2MSB", "EM_S390"),45 Endian.LITTLE: (46 "aarch64",47 "pc",48 "aarch64.yaml",49 "ELFDATA2LSB",50 "EM_AARCH64",51 ),52 }[endian]53 54 self.server.responder = Responder(55 dedent(56 f"""\57 <?xml version="1.0"?>58 <target version="1.0">59 <architecture>{architecture}</architecture>60 <feature>61 <reg name="{pc_reg_name}" bitsize="64"/>62 </feature>63 </target>"""64 ),65 endian,66 )67 68 # We need to have a program file, so that we have a full type system,69 # so that we can do the casts later.70 obj_path = self.getBuildArtifact("main.o")71 yaml_path = self.getBuildArtifact(yaml_file)72 with open(yaml_path, "w") as f:73 f.write(74 dedent(75 f"""\76 --- !ELF77 FileHeader:78 Class: ELFCLASS6479 Data: {data}80 Type: ET_REL81 Machine: {machine}82 ...83 """84 )85 )86 self.yaml2obj(yaml_path, obj_path)87 target = self.dbg.CreateTarget(obj_path)88 89 process = self.connect(target)90 lldbutil.expect_state_changes(91 self, self.dbg.GetListener(), process, [lldb.eStateStopped]92 )93 94 # If expressions convert register values into target endian, the95 # result of register read, expr and casts should be the same.96 pc_value = "0x0000000000001234"97 self.expect(98 "register read pc",99 substrs=[pc_value],100 )101 self.expect("expr --format hex -- $pc", substrs=[pc_value])102 103 pc = (104 process.thread[0]105 .frame[0]106 .GetRegisters()107 .GetValueAtIndex(0)108 .GetChildMemberWithName("pc")109 )110 ull = target.FindTypes("unsigned long long").GetTypeAtIndex(0)111 pc_ull = pc.Cast(ull)112 113 self.assertEqual(pc.GetValue(), pc_ull.GetValue())114 self.assertEqual(pc.GetValueAsAddress(), pc_ull.GetValueAsAddress())115 self.assertEqual(pc.GetValueAsSigned(), pc_ull.GetValueAsSigned())116 self.assertEqual(pc.GetValueAsUnsigned(), pc_ull.GetValueAsUnsigned())117 118 @skipIfXmlSupportMissing119 @skipIfRemote120 @skipIfLLVMTargetMissing("AArch64")121 def test_little_endian_target(self):122 self.do_endian_test(Endian.LITTLE)123 124 @skipIfXmlSupportMissing125 @skipIfRemote126 @skipIfLLVMTargetMissing("SystemZ")127 def test_big_endian_target(self):128 self.do_endian_test(Endian.BIG)129