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