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 ( """ i386:x86-64 """, 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 ( """ """ % 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)