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