aboutsummaryrefslogtreecommitdiff
path: root/lldb/test/API/commands/expression/TestRegisterExpressionEndian.py
blob: d6de8731385b6d886cace5811fb02b560f2ace91 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
""" 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)