1import lldb 2import binascii 3import os 4import time 5from lldbsuite.test.lldbtest import * 6from lldbsuite.test.decorators import * 7from lldbsuite.test.gdbclientutils import * 8from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase 9 10 11def hexlify(string): 12 return binascii.hexlify(string.encode()).decode() 13 14 15class TestPlatformClient(GDBRemoteTestBase): 16 def test_process_list_with_all_users(self): 17 """Test connecting to a remote linux platform""" 18 19 class MyResponder(MockGDBServerResponder): 20 def __init__(self): 21 MockGDBServerResponder.__init__(self) 22 self.currentQsProc = 0 23 self.all_users = False 24 25 def qfProcessInfo(self, packet): 26 if "all_users:1" in packet: 27 self.all_users = True 28 name = hexlify("/a/test_process") 29 args = "-".join( 30 map( 31 hexlify, 32 ["/system/bin/sh", "-c", "/data/local/tmp/lldb-server"], 33 ) 34 ) 35 return ( 36 "pid:10;ppid:1;uid:2;gid:3;euid:4;egid:5;name:" 37 + name 38 + ";args:" 39 + args 40 + ";" 41 ) 42 else: 43 self.all_users = False 44 return "E04" 45 46 def qsProcessInfo(self): 47 if self.all_users: 48 if self.currentQsProc == 0: 49 self.currentQsProc = 1 50 name = hexlify("/b/another_test_process") 51 # This intentionally has a badly encoded argument 52 args = "X".join(map(hexlify, ["/system/bin/ls", "--help"])) 53 return ( 54 "pid:11;ppid:2;uid:3;gid:4;euid:5;egid:6;name:" 55 + name 56 + ";args:" 57 + args 58 + ";" 59 ) 60 elif self.currentQsProc == 1: 61 self.currentQsProc = 0 62 return "E04" 63 else: 64 return "E04" 65 66 self.server.responder = MyResponder() 67 68 try: 69 self.runCmd("platform select remote-linux") 70 self.runCmd("platform connect " + self.server.get_connect_url()) 71 self.assertTrue(self.dbg.GetSelectedPlatform().IsConnected()) 72 self.expect( 73 "platform process list -x", 74 substrs=[ 75 "2 matching processes were found", 76 "test_process", 77 "another_test_process", 78 ], 79 ) 80 self.expect( 81 "platform process list -xv", 82 substrs=[ 83 "PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE ARGUMENTS", 84 "10 1 2 3 4 5 /system/bin/sh -c /data/local/tmp/lldb-server", 85 "11 2 3 4 5 6", 86 ], 87 ) 88 self.expect( 89 "platform process list -xv", substrs=["/system/bin/ls"], matching=False 90 ) 91 self.expect( 92 "platform process list", 93 error=True, 94 substrs=[ 95 'error: no processes were found on the "remote-linux" platform' 96 ], 97 ) 98 finally: 99 self.dbg.GetSelectedPlatform().DisconnectRemote() 100 101 class TimeoutResponder(MockGDBServerResponder): 102 """A mock server, which takes a very long time to compute the working 103 directory.""" 104 105 def __init__(self): 106 MockGDBServerResponder.__init__(self) 107 108 def qGetWorkingDir(self): 109 time.sleep(10) 110 return hexlify("/foo/bar") 111 112 def test_no_timeout(self): 113 """Test that we honor the timeout setting. With a large enough timeout, 114 we should get the CWD successfully.""" 115 116 self.server.responder = TestPlatformClient.TimeoutResponder() 117 self.runCmd("settings set plugin.process.gdb-remote.packet-timeout 30") 118 plat = lldb.SBPlatform("remote-linux") 119 try: 120 self.assertSuccess( 121 plat.ConnectRemote( 122 lldb.SBPlatformConnectOptions(self.server.get_connect_url()) 123 ) 124 ) 125 self.assertEqual(plat.GetWorkingDirectory(), "/foo/bar") 126 finally: 127 plat.DisconnectRemote() 128 129 def test_timeout(self): 130 """Test that we honor the timeout setting. With a small timeout, CWD 131 retrieval should fail.""" 132 133 self.server.responder = TestPlatformClient.TimeoutResponder() 134 self.runCmd("settings set plugin.process.gdb-remote.packet-timeout 3") 135 plat = lldb.SBPlatform("remote-linux") 136 try: 137 self.assertSuccess( 138 plat.ConnectRemote( 139 lldb.SBPlatformConnectOptions(self.server.get_connect_url()) 140 ) 141 ) 142 self.assertIsNone(plat.GetWorkingDirectory()) 143 finally: 144 plat.DisconnectRemote() 145