File: TestGdbClientModuleLoad.py

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (153 lines) | stat: -rw-r--r-- 5,755 bytes parent folder | download | duplicates (8)
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import lldb
from lldbsuite.test.lldbtest import *
from lldbsuite.test.decorators import *
from lldbsuite.test.gdbclientutils import *
from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase


class MyResponder(MockGDBServerResponder):
    """
    A responder which simulates a process with a single shared library loaded.
    Its parameters allow configuration of various properties of the library.
    """

    def __init__(self, testcase, triple, library_name, auxv_entry, region_info):
        MockGDBServerResponder.__init__(self)
        self.testcase = testcase
        self._triple = triple
        self._library_name = library_name
        self._auxv_entry = auxv_entry
        self._region_info = region_info

    def qSupported(self, client_supported):
        return (
            super().qSupported(client_supported)
            + ";qXfer:auxv:read+;qXfer:libraries-svr4:read+"
        )

    def qXferRead(self, obj, annex, offset, length):
        if obj == "features" and annex == "target.xml":
            return (
                """<?xml version="1.0"?>
                <target version="1.0">
                  <architecture>i386:x86-64</architecture>
                  <feature name="org.gnu.gdb.i386.core">
                    <reg name="rip" bitsize="64" regnum="0" type="code_ptr" group="general"/>
                  </feature>
                </target>""",
                False,
            )
        elif obj == "auxv":
            # 0x09 = AT_ENTRY, which lldb uses to compute the load bias of the
            # main binary.
            return (
                hex_decode_bytes(
                    self._auxv_entry
                    + "09000000000000000000ee000000000000000000000000000000000000000000"
                ),
                False,
            )
        elif obj == "libraries-svr4":
            return (
                """<?xml version="1.0"?>
                <library-list-svr4 version="1.0">
                  <library name="%s" lm="0xdeadbeef" l_addr="0xef0000" l_ld="0xdeadbeef"/>
                </library-list-svr4>"""
                % self._library_name,
                False,
            )
        else:
            return None, False

    def qfThreadInfo(self):
        return "m47"

    def qsThreadInfo(self):
        return "l"

    def qProcessInfo(self):
        return "pid:47;ptrsize:8;endian:little;triple:%s;" % hex_encode_bytes(
            self._triple
        )

    def setBreakpoint(self, packet):
        return "OK"

    def readMemory(self, addr, length):
        if addr == 0xEE1000:
            return "00" * 0x30 + "0020ee0000000000"
        elif addr == 0xEE2000:
            return "01000000000000000030ee0000000000dead00000000000000000000000000000000000000000000"
        elif addr == 0xEF0000:
            with open(self.testcase.getBuildArtifact("libmodule_load.so"), "rb") as f:
                contents = f.read(-1)
            return hex_encode_bytes(seven.bitcast_to_string(contents))
        return ("baadf00d00" * 1000)[0 : length * 2]

    def qMemoryRegionInfo(self, addr):
        if addr < 0xEE0000:
            return "start:0;size:ee0000;"
        elif addr < 0xEF0000:
            return "start:ee0000;size:10000;"
        elif addr < 0xF00000:
            return "start:ef0000;size:1000;permissions:rx;" + self._region_info
        else:
            return "start:ef1000;size:ffffffffff10f000"


class TestGdbClientModuleLoad(GDBRemoteTestBase):
    @skipIfXmlSupportMissing
    def test_android_app_process(self):
        """
        This test simulates the scenario where the (android) dynamic linker
        reports incorrect file name of the main executable. Lldb uses
        qMemoryRegionInfo to get the correct value.
        """
        region_info = "name:%s;" % (
            hex_encode_bytes(self.getBuildArtifact("libmodule_load.so"))
        )
        self.server.responder = MyResponder(
            self, "x86_64-pc-linux-android", "bogus-name", "", region_info
        )
        self.yaml2obj("module_load.yaml", self.getBuildArtifact("libmodule_load.so"))
        target = self.createTarget("module_load.yaml")

        process = self.connect(target)
        self.assertTrue(process.IsValid(), "Process is valid")

        lldbutil.expect_state_changes(
            self, self.dbg.GetListener(), process, [lldb.eStateStopped]
        )

        self.filecheck("image list", __file__, "-check-prefix=ANDROID")

    # ANDROID: [  0] {{.*}} 0x0000000000ee0000 {{.*}}module_load
    # ANDROID: [  1] {{.*}} 0x0000000000ef0000 {{.*}}libmodule_load.so

    @skipIfXmlSupportMissing
    def test_vdso(self):
        """
        This test checks vdso loading in the situation where the process does
        not have memory region information about the vdso address. This can
        happen in core files, as they don't store this data.
        We want to check that the vdso is loaded exactly once.
        """
        # vdso address
        AT_SYSINFO_EHDR = "21000000000000000000ef0000000000"
        self.server.responder = MyResponder(
            self, "x86_64-pc-linux", "linux-vdso.so.1", AT_SYSINFO_EHDR, ""
        )
        self.yaml2obj("module_load.yaml", self.getBuildArtifact("libmodule_load.so"))
        target = self.createTarget("module_load.yaml")

        process = self.connect(target)
        self.assertTrue(process.IsValid(), "Process is valid")

        lldbutil.expect_state_changes(
            self, self.dbg.GetListener(), process, [lldb.eStateStopped]
        )

        self.filecheck("image list", __file__, "-check-prefix=VDSO")
        # VDSO: [  0] {{.*}} 0x0000000000ee0000 {{.*}}module_load
        # VDSO: [  1] {{.*}} 0x0000000000ef0000 {{.*}}[vdso]
        self.assertEqual(self.target().GetNumModules(), 2)