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