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