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