xref: /llvm-project/lldb/test/API/functionalities/gdb_remote_client/TestGdbClientModuleLoad.py (revision 80fcecb13c388ff087a27a4b0e7ca3dd8c98eaa4)
1import lldb
2from lldbsuite.test.lldbtest import *
3from lldbsuite.test.decorators import *
4from lldbsuite.test.gdbclientutils import *
5from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase
6
7
8class MyResponder(MockGDBServerResponder):
9    """
10    A responder which simulates a process with a single shared library loaded.
11    Its parameters allow configuration of various properties of the library.
12    """
13
14    def __init__(self, testcase, triple, library_name, auxv_entry, region_info):
15        MockGDBServerResponder.__init__(self)
16        self.testcase = testcase
17        self._triple = triple
18        self._library_name = library_name
19        self._auxv_entry = auxv_entry
20        self._region_info = region_info
21
22    def qSupported(self, client_supported):
23        return (
24            super().qSupported(client_supported)
25            + ";qXfer:auxv:read+;qXfer:libraries-svr4:read+"
26        )
27
28    def qXferRead(self, obj, annex, offset, length):
29        if obj == "features" and annex == "target.xml":
30            return (
31                """<?xml version="1.0"?>
32                <target version="1.0">
33                  <architecture>i386:x86-64</architecture>
34                  <feature name="org.gnu.gdb.i386.core">
35                    <reg name="rip" bitsize="64" regnum="0" type="code_ptr" group="general"/>
36                  </feature>
37                </target>""",
38                False,
39            )
40        elif obj == "auxv":
41            # 0x09 = AT_ENTRY, which lldb uses to compute the load bias of the
42            # main binary.
43            return (
44                hex_decode_bytes(
45                    self._auxv_entry
46                    + "09000000000000000000ee000000000000000000000000000000000000000000"
47                ),
48                False,
49            )
50        elif obj == "libraries-svr4":
51            return (
52                """<?xml version="1.0"?>
53                <library-list-svr4 version="1.0">
54                  <library name="%s" lm="0xdeadbeef" l_addr="0xef0000" l_ld="0xdeadbeef"/>
55                </library-list-svr4>"""
56                % self._library_name,
57                False,
58            )
59        else:
60            return None, False
61
62    def qfThreadInfo(self):
63        return "m47"
64
65    def qsThreadInfo(self):
66        return "l"
67
68    def qProcessInfo(self):
69        return "pid:47;ptrsize:8;endian:little;triple:%s;" % hex_encode_bytes(
70            self._triple
71        )
72
73    def setBreakpoint(self, packet):
74        return "OK"
75
76    def readMemory(self, addr, length):
77        if addr == 0xEE1000:
78            return "00" * 0x30 + "0020ee0000000000"
79        elif addr == 0xEE2000:
80            return "01000000000000000030ee0000000000dead00000000000000000000000000000000000000000000"
81        elif addr == 0xEF0000:
82            with open(self.testcase.getBuildArtifact("libmodule_load.so"), "rb") as f:
83                contents = f.read(-1)
84            return hex_encode_bytes(seven.bitcast_to_string(contents))
85        return ("baadf00d00" * 1000)[0 : length * 2]
86
87    def qMemoryRegionInfo(self, addr):
88        if addr < 0xEE0000:
89            return "start:0;size:ee0000;"
90        elif addr < 0xEF0000:
91            return "start:ee0000;size:10000;"
92        elif addr < 0xF00000:
93            return "start:ef0000;size:1000;permissions:rx;" + self._region_info
94        else:
95            return "start:ef1000;size:ffffffffff10f000"
96
97
98class TestGdbClientModuleLoad(GDBRemoteTestBase):
99    @skipIfXmlSupportMissing
100    def test_android_app_process(self):
101        """
102        This test simulates the scenario where the (android) dynamic linker
103        reports incorrect file name of the main executable. Lldb uses
104        qMemoryRegionInfo to get the correct value.
105        """
106        region_info = "name:%s;" % (
107            hex_encode_bytes(self.getBuildArtifact("libmodule_load.so"))
108        )
109        self.server.responder = MyResponder(
110            self, "x86_64-pc-linux-android", "bogus-name", "", region_info
111        )
112        self.yaml2obj("module_load.yaml", self.getBuildArtifact("libmodule_load.so"))
113        target = self.createTarget("module_load.yaml")
114
115        process = self.connect(target)
116        self.assertTrue(process.IsValid(), "Process is valid")
117
118        lldbutil.expect_state_changes(
119            self, self.dbg.GetListener(), process, [lldb.eStateStopped]
120        )
121
122        self.filecheck("image list", __file__, "-check-prefix=ANDROID")
123
124    # ANDROID: [  0] {{.*}} 0x0000000000ee0000 {{.*}}module_load
125    # ANDROID: [  1] {{.*}} 0x0000000000ef0000 {{.*}}libmodule_load.so
126
127    @skipIfXmlSupportMissing
128    def test_vdso(self):
129        """
130        This test checks vdso loading in the situation where the process does
131        not have memory region information about the vdso address. This can
132        happen in core files, as they don't store this data.
133        We want to check that the vdso is loaded exactly once.
134        """
135        # vdso address
136        AT_SYSINFO_EHDR = "21000000000000000000ef0000000000"
137        self.server.responder = MyResponder(
138            self, "x86_64-pc-linux", "linux-vdso.so.1", AT_SYSINFO_EHDR, ""
139        )
140        self.yaml2obj("module_load.yaml", self.getBuildArtifact("libmodule_load.so"))
141        target = self.createTarget("module_load.yaml")
142
143        process = self.connect(target)
144        self.assertTrue(process.IsValid(), "Process is valid")
145
146        lldbutil.expect_state_changes(
147            self, self.dbg.GetListener(), process, [lldb.eStateStopped]
148        )
149
150        self.filecheck("image list", __file__, "-check-prefix=VDSO")
151        # VDSO: [  0] {{.*}} 0x0000000000ee0000 {{.*}}module_load
152        # VDSO: [  1] {{.*}} 0x0000000000ef0000 {{.*}}[vdso]
153        self.assertEqual(self.target().GetNumModules(), 2)
154