| import lldb | |
| import binascii | |
| import os | |
| import time | |
| from lldbsuite.test.lldbtest import * | |
| from lldbsuite.test.decorators import * | |
| from lldbsuite.test.gdbclientutils import * | |
| from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase | |
| def hexlify(string): | |
| return binascii.hexlify(string.encode()).decode() | |
| class TestPlatformClient(GDBRemoteTestBase): | |
| def test_process_list_with_all_users(self): | |
| """Test connecting to a remote linux platform""" | |
| class MyResponder(MockGDBServerResponder): | |
| def __init__(self): | |
| MockGDBServerResponder.__init__(self) | |
| self.currentQsProc = 0 | |
| self.all_users = False | |
| def qfProcessInfo(self, packet): | |
| if "all_users:1" in packet: | |
| self.all_users = True | |
| name = hexlify("/a/test_process") | |
| args = "-".join( | |
| map( | |
| hexlify, | |
| ["/system/bin/sh", "-c", "/data/local/tmp/lldb-server"], | |
| ) | |
| ) | |
| return ( | |
| "pid:10;ppid:1;uid:2;gid:3;euid:4;egid:5;name:" | |
| + name | |
| + ";args:" | |
| + args | |
| + ";" | |
| ) | |
| else: | |
| self.all_users = False | |
| return "E04" | |
| def qsProcessInfo(self): | |
| if self.all_users: | |
| if self.currentQsProc == 0: | |
| self.currentQsProc = 1 | |
| name = hexlify("/b/another_test_process") | |
| # This intentionally has a badly encoded argument | |
| args = "X".join(map(hexlify, ["/system/bin/ls", "--help"])) | |
| return ( | |
| "pid:11;ppid:2;uid:3;gid:4;euid:5;egid:6;name:" | |
| + name | |
| + ";args:" | |
| + args | |
| + ";" | |
| ) | |
| elif self.currentQsProc == 1: | |
| self.currentQsProc = 0 | |
| return "E04" | |
| else: | |
| return "E04" | |
| self.server.responder = MyResponder() | |
| try: | |
| self.runCmd("platform select remote-linux") | |
| self.runCmd("platform connect " + self.server.get_connect_url()) | |
| self.assertTrue(self.dbg.GetSelectedPlatform().IsConnected()) | |
| self.expect( | |
| "platform process list -x", | |
| substrs=[ | |
| "2 matching processes were found", | |
| "test_process", | |
| "another_test_process", | |
| ], | |
| ) | |
| self.expect( | |
| "platform process list -xv", | |
| substrs=[ | |
| "PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE ARGUMENTS", | |
| "10 1 2 3 4 5 /system/bin/sh -c /data/local/tmp/lldb-server", | |
| "11 2 3 4 5 6", | |
| ], | |
| ) | |
| self.expect( | |
| "platform process list -xv", substrs=["/system/bin/ls"], matching=False | |
| ) | |
| self.expect( | |
| "platform process list", | |
| error=True, | |
| substrs=[ | |
| 'error: no processes were found on the "remote-linux" platform' | |
| ], | |
| ) | |
| finally: | |
| self.dbg.GetSelectedPlatform().DisconnectRemote() | |
| class TimeoutResponder(MockGDBServerResponder): | |
| """A mock server, which takes a very long time to compute the working | |
| directory.""" | |
| def __init__(self): | |
| MockGDBServerResponder.__init__(self) | |
| def qGetWorkingDir(self): | |
| time.sleep(10) | |
| return hexlify("/foo/bar") | |
| def test_no_timeout(self): | |
| """Test that we honor the timeout setting. With a large enough timeout, | |
| we should get the CWD successfully.""" | |
| self.server.responder = TestPlatformClient.TimeoutResponder() | |
| self.runCmd("settings set plugin.process.gdb-remote.packet-timeout 30") | |
| plat = lldb.SBPlatform("remote-linux") | |
| try: | |
| self.assertSuccess( | |
| plat.ConnectRemote( | |
| lldb.SBPlatformConnectOptions(self.server.get_connect_url()) | |
| ) | |
| ) | |
| self.assertEqual(plat.GetWorkingDirectory(), "/foo/bar") | |
| finally: | |
| plat.DisconnectRemote() | |
| def test_timeout(self): | |
| """Test that we honor the timeout setting. With a small timeout, CWD | |
| retrieval should fail.""" | |
| self.server.responder = TestPlatformClient.TimeoutResponder() | |
| self.runCmd("settings set plugin.process.gdb-remote.packet-timeout 3") | |
| plat = lldb.SBPlatform("remote-linux") | |
| try: | |
| self.assertSuccess( | |
| plat.ConnectRemote( | |
| lldb.SBPlatformConnectOptions(self.server.get_connect_url()) | |
| ) | |
| ) | |
| self.assertIsNone(plat.GetWorkingDirectory()) | |
| finally: | |
| plat.DisconnectRemote() |