1 //===-- PlatformAndroidRemoteGDBServer.cpp ----------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 // Other libraries and framework includes 11 #include "lldb/Core/Error.h" 12 #include "lldb/Host/ConnectionFileDescriptor.h" 13 #include "llvm/ADT/StringRef.h" 14 15 // Project includes 16 #include "PlatformAndroidRemoteGDBServer.h" 17 #include "Utility/UriParser.h" 18 19 using namespace lldb; 20 using namespace lldb_private; 21 22 static const lldb::pid_t g_remote_platform_pid = 0; // Alias for the process id of lldb-platform 23 static const uint32_t g_adb_timeout = 10000; // 10 ms 24 25 static void 26 SendMessageToAdb (Connection& conn, const std::string& packet, Error& error) 27 { 28 ConnectionStatus status; 29 30 char length_buffer[5]; 31 snprintf (length_buffer, sizeof (length_buffer), "%04zx", packet.size()); 32 33 conn.Write (length_buffer, 4, status, &error); 34 if (error.Fail ()) 35 return; 36 37 conn.Write (packet.c_str(), packet.size(), status, &error); 38 } 39 40 static std::string 41 ReadMessageFromAdb (Connection& conn, bool has_okay, Error& error) 42 { 43 ConnectionStatus status; 44 45 char buffer[5]; 46 buffer[4] = 0; 47 48 if (has_okay) 49 { 50 conn.Read (buffer, 4, g_adb_timeout, status, &error); 51 if (error.Fail ()) 52 return ""; 53 54 if (strncmp (buffer, "OKAY", 4) != 0) 55 { 56 error.SetErrorStringWithFormat ("\"OKAY\" expected from adb, received: \"%s\"", buffer); 57 return ""; 58 } 59 } 60 61 conn.Read (buffer, 4, g_adb_timeout, status, &error); 62 if (error.Fail()) 63 return ""; 64 65 size_t packet_len = 0; 66 sscanf(buffer, "%zx", &packet_len); 67 std::string result(packet_len, 0); 68 conn.Read (&result[0], packet_len, g_adb_timeout, status, &error); 69 if (error.Fail ()) 70 return ""; 71 72 return result; 73 } 74 75 static Error 76 ForwardPortWithAdb (uint16_t port, std::string& device_id) 77 { 78 Error error; 79 80 { 81 // Fetch the device list from ADB and if only 1 device found then use that device 82 // TODO: Handle the case when more device is available 83 std::unique_ptr<ConnectionFileDescriptor> conn (new ConnectionFileDescriptor ()); 84 if (conn->Connect ("connect://localhost:5037", &error) != eConnectionStatusSuccess) 85 return error; 86 87 SendMessageToAdb (*conn, "host:devices", error); 88 if (error.Fail ()) 89 return error; 90 std::string in_buffer = ReadMessageFromAdb (*conn, true, error); 91 92 llvm::StringRef deviceList(in_buffer); 93 std::pair<llvm::StringRef, llvm::StringRef> devices = deviceList.split ('\n'); 94 if (devices.first.size () == 0 || devices.second.size () > 0) 95 { 96 error.SetErrorString ("Wrong number of devices returned from ADB"); 97 return error; 98 } 99 100 device_id = devices.first.split ('\t').first; 101 } 102 103 { 104 // Forward the port to the (only) connected device 105 std::unique_ptr<ConnectionFileDescriptor> conn (new ConnectionFileDescriptor ()); 106 if (conn->Connect ("connect://localhost:5037", &error) != eConnectionStatusSuccess) 107 return error; 108 109 char port_buffer[32]; 110 snprintf (port_buffer, sizeof (port_buffer), "tcp:%d;tcp:%d", port, port); 111 112 std::string out_buffer = "host-serial:" + device_id + ":forward:" + port_buffer; 113 SendMessageToAdb (*conn, out_buffer, error); 114 if (error.Fail ()) 115 return error; 116 117 std::string in_buffer = ReadMessageFromAdb (*conn, false, error); 118 if (in_buffer != "OKAY") 119 error.SetErrorString (in_buffer.c_str ()); 120 } 121 122 return error; 123 } 124 125 static Error 126 DeleteForwardPortWithAdb (uint16_t port, const std::string& device_id) 127 { 128 Error error; 129 130 std::unique_ptr<ConnectionFileDescriptor> conn (new ConnectionFileDescriptor ()); 131 if (conn->Connect ("connect://localhost:5037", &error) != eConnectionStatusSuccess) 132 return error; 133 134 char port_buffer[16]; 135 snprintf (port_buffer, sizeof (port_buffer), "tcp:%d", port); 136 137 std::string out_buffer = "host-serial:" + device_id + ":killforward:" + port_buffer; 138 SendMessageToAdb (*conn, out_buffer, error); 139 if (error.Fail ()) 140 return error; 141 142 std::string in_buffer = ReadMessageFromAdb (*conn, true, error); 143 if (in_buffer != "OKAY") 144 error.SetErrorString (in_buffer.c_str ()); 145 146 return error; 147 } 148 149 PlatformAndroidRemoteGDBServer::PlatformAndroidRemoteGDBServer () 150 { 151 } 152 153 PlatformAndroidRemoteGDBServer::~PlatformAndroidRemoteGDBServer () 154 { 155 for (const auto& it : m_port_forwards) 156 { 157 DeleteForwardPortWithAdb (it.second.first, it.second.second); 158 } 159 } 160 161 uint16_t 162 PlatformAndroidRemoteGDBServer::LaunchGDBserverAndGetPort (lldb::pid_t &pid) 163 { 164 uint16_t port = m_gdb_client.LaunchGDBserverAndGetPort (pid, "127.0.0.1"); 165 if (port == 0) 166 return port; 167 168 std::string device_id; 169 Error error = ForwardPortWithAdb (port, device_id); 170 if (error.Fail ()) 171 return 0; 172 173 m_port_forwards[pid] = std::make_pair (port, device_id); 174 175 return port; 176 } 177 178 bool 179 PlatformAndroidRemoteGDBServer::KillSpawnedProcess (lldb::pid_t pid) 180 { 181 auto it = m_port_forwards.find (pid); 182 if (it != m_port_forwards.end ()) 183 { 184 DeleteForwardPortWithAdb (it->second.first, it->second.second); 185 m_port_forwards.erase (it); 186 } 187 188 return m_gdb_client.KillSpawnedProcess (pid); 189 } 190 191 Error 192 PlatformAndroidRemoteGDBServer::ConnectRemote (Args& args) 193 { 194 if (args.GetArgumentCount () != 1) 195 return Error ("\"platform connect\" takes a single argument: <connect-url>"); 196 197 int port; 198 std::string scheme, host, path; 199 const char *url = args.GetArgumentAtIndex (0); 200 if (!UriParser::Parse (url, scheme, host, port, path)) 201 return Error ("invalid uri"); 202 203 std::string device_id; 204 Error error = ForwardPortWithAdb (port, device_id); 205 if (error.Fail ()) 206 return error; 207 208 m_port_forwards[g_remote_platform_pid] = std::make_pair (port, device_id); 209 210 return PlatformRemoteGDBServer::ConnectRemote (args); 211 } 212 213 Error 214 PlatformAndroidRemoteGDBServer::DisconnectRemote () 215 { 216 auto it = m_port_forwards.find (g_remote_platform_pid); 217 if (it != m_port_forwards.end ()) 218 { 219 DeleteForwardPortWithAdb (it->second.first, it->second.second); 220 m_port_forwards.erase (it); 221 } 222 223 return PlatformRemoteGDBServer::DisconnectRemote (); 224 } 225