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