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 @skipIfXmlSupportMissing 84 def test_android_app_process(self): 85 """ 86 This test simulates the scenario where the (android) dynamic linker 87 reports incorrect file name of the main executable. Lldb uses 88 qMemoryRegionInfo to get the correct value. 89 """ 90 region_info = "name:%s;" % ( 91 hex_encode_bytes(self.getBuildArtifact("libmodule_load.so"))) 92 self.server.responder = MyResponder(self, "x86_64-pc-linux-android", 93 "bogus-name", "", region_info) 94 self.yaml2obj("module_load.yaml", self.getBuildArtifact("libmodule_load.so")) 95 target = self.createTarget("module_load.yaml") 96 97 process = self.connect(target) 98 self.assertTrue(process.IsValid(), "Process is valid") 99 100 lldbutil.expect_state_changes(self, self.dbg.GetListener(), process, 101 [lldb.eStateStopped]) 102 103 self.filecheck("image list", __file__, "-check-prefix=ANDROID") 104# ANDROID: [ 0] {{.*}} 0x0000000000ee0000 {{.*}}module_load 105# ANDROID: [ 1] {{.*}} 0x0000000000ef0000 {{.*}}libmodule_load.so 106 107 @skipIfXmlSupportMissing 108 def test_vdso(self): 109 """ 110 This test checks vdso loading in the situation where the process does 111 not have memory region information about the vdso address. This can 112 happen in core files, as they don't store this data. 113 We want to check that the vdso is loaded exactly once. 114 """ 115 # vdso address 116 AT_SYSINFO_EHDR = "21000000000000000000ef0000000000" 117 self.server.responder = MyResponder(self, "x86_64-pc-linux", 118 "linux-vdso.so.1", AT_SYSINFO_EHDR, "") 119 self.yaml2obj("module_load.yaml", self.getBuildArtifact("libmodule_load.so")) 120 target = self.createTarget("module_load.yaml") 121 122 process = self.connect(target) 123 self.assertTrue(process.IsValid(), "Process is valid") 124 125 lldbutil.expect_state_changes(self, self.dbg.GetListener(), process, 126 [lldb.eStateStopped]) 127 128 self.filecheck("image list", __file__, "-check-prefix=VDSO") 129# VDSO: [ 0] {{.*}} 0x0000000000ee0000 {{.*}}module_load 130# VDSO: [ 1] {{.*}} 0x0000000000ef0000 {{.*}}[vdso] 131 self.assertEquals(self.target().GetNumModules(), 2) 132