154 lines · python
1import lldb2from lldbsuite.test.lldbtest import *3from lldbsuite.test.decorators import *4from lldbsuite.test.gdbclientutils import *5from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase6 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 = testcase17 self._triple = triple18 self._library_name = library_name19 self._auxv_entry = auxv_entry20 self._region_info = region_info21 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 the42 # main binary.43 return (44 hex_decode_bytes(45 self._auxv_entry46 + "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, False61 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._triple71 )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_info94 else:95 return "start:ef1000;size:ffffffffff10f000"96 97 98class TestGdbClientModuleLoad(GDBRemoteTestBase):99 @skipIfXmlSupportMissing100 def test_android_app_process(self):101 """102 This test simulates the scenario where the (android) dynamic linker103 reports incorrect file name of the main executable. Lldb uses104 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_info111 )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_load125 # ANDROID: [ 1] {{.*}} 0x0000000000ef0000 {{.*}}libmodule_load.so126 127 @skipIfXmlSupportMissing128 def test_vdso(self):129 """130 This test checks vdso loading in the situation where the process does131 not have memory region information about the vdso address. This can132 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 address136 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_load152 # VDSO: [ 1] {{.*}} 0x0000000000ef0000 {{.*}}[vdso]153 self.assertEqual(self.target().GetNumModules(), 2)154