100e305d2STamas Berghammer //===-- PlatformAndroidRemoteGDBServer.cpp ----------------------*- C++ -*-===//
200e305d2STamas Berghammer //
300e305d2STamas Berghammer //                     The LLVM Compiler Infrastructure
400e305d2STamas Berghammer //
500e305d2STamas Berghammer // This file is distributed under the University of Illinois Open Source
600e305d2STamas Berghammer // License. See LICENSE.TXT for details.
700e305d2STamas Berghammer //
800e305d2STamas Berghammer //===----------------------------------------------------------------------===//
900e305d2STamas Berghammer 
1000e305d2STamas Berghammer // Other libraries and framework includes
1100e305d2STamas Berghammer #include "lldb/Core/Error.h"
12*05a55de3SOleksiy Vyalov #include "lldb/Core/Log.h"
1300e305d2STamas Berghammer #include "lldb/Host/ConnectionFileDescriptor.h"
1400e305d2STamas Berghammer #include "llvm/ADT/StringRef.h"
1500e305d2STamas Berghammer 
1600e305d2STamas Berghammer // Project includes
17*05a55de3SOleksiy Vyalov #include "AdbClient.h"
1800e305d2STamas Berghammer #include "PlatformAndroidRemoteGDBServer.h"
1900e305d2STamas Berghammer #include "Utility/UriParser.h"
2000e305d2STamas Berghammer 
2100e305d2STamas Berghammer using namespace lldb;
2200e305d2STamas Berghammer using namespace lldb_private;
2300e305d2STamas Berghammer 
2400e305d2STamas Berghammer static const lldb::pid_t g_remote_platform_pid = 0; // Alias for the process id of lldb-platform
2500e305d2STamas Berghammer 
2600e305d2STamas Berghammer static Error
2700e305d2STamas Berghammer ForwardPortWithAdb (uint16_t port, std::string& device_id)
2800e305d2STamas Berghammer {
29*05a55de3SOleksiy Vyalov     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM));
3000e305d2STamas Berghammer 
3100e305d2STamas Berghammer     // Fetch the device list from ADB and if only 1 device found then use that device
3200e305d2STamas Berghammer     // TODO: Handle the case when more device is available
33*05a55de3SOleksiy Vyalov     AdbClient adb;
3400e305d2STamas Berghammer 
35*05a55de3SOleksiy Vyalov     AdbClient::DeviceIDList connect_devices;
36*05a55de3SOleksiy Vyalov     auto error = adb.GetDevices (connect_devices);
3700e305d2STamas Berghammer     if (error.Fail ())
3800e305d2STamas Berghammer         return error;
3900e305d2STamas Berghammer 
40*05a55de3SOleksiy Vyalov     if (connect_devices.size () != 1)
41*05a55de3SOleksiy Vyalov         return Error ("Expected a single connected device, got instead %" PRIu64, connect_devices.size ());
4200e305d2STamas Berghammer 
43*05a55de3SOleksiy Vyalov     device_id = connect_devices.front ();
44*05a55de3SOleksiy Vyalov     if (log)
45*05a55de3SOleksiy Vyalov         log->Printf("Connected to Android device \"%s\"", device_id.c_str ());
46*05a55de3SOleksiy Vyalov 
47*05a55de3SOleksiy Vyalov     adb.SetDeviceID (device_id);
48*05a55de3SOleksiy Vyalov     return adb.SetPortForwarding (port);
4900e305d2STamas Berghammer }
5000e305d2STamas Berghammer 
5100e305d2STamas Berghammer static Error
5200e305d2STamas Berghammer DeleteForwardPortWithAdb (uint16_t port, const std::string& device_id)
5300e305d2STamas Berghammer {
54*05a55de3SOleksiy Vyalov     AdbClient adb (device_id);
55*05a55de3SOleksiy Vyalov     return adb.DeletePortForwarding (port);
5600e305d2STamas Berghammer }
5700e305d2STamas Berghammer 
5800e305d2STamas Berghammer PlatformAndroidRemoteGDBServer::PlatformAndroidRemoteGDBServer ()
5900e305d2STamas Berghammer {
6000e305d2STamas Berghammer }
6100e305d2STamas Berghammer 
6200e305d2STamas Berghammer PlatformAndroidRemoteGDBServer::~PlatformAndroidRemoteGDBServer ()
6300e305d2STamas Berghammer {
6400e305d2STamas Berghammer     for (const auto& it : m_port_forwards)
6500e305d2STamas Berghammer     {
6600e305d2STamas Berghammer         DeleteForwardPortWithAdb (it.second.first, it.second.second);
6700e305d2STamas Berghammer     }
6800e305d2STamas Berghammer }
6900e305d2STamas Berghammer 
7000e305d2STamas Berghammer uint16_t
7100e305d2STamas Berghammer PlatformAndroidRemoteGDBServer::LaunchGDBserverAndGetPort (lldb::pid_t &pid)
7200e305d2STamas Berghammer {
7300e305d2STamas Berghammer     uint16_t port = m_gdb_client.LaunchGDBserverAndGetPort (pid, "127.0.0.1");
7400e305d2STamas Berghammer     if (port == 0)
7500e305d2STamas Berghammer         return port;
7600e305d2STamas Berghammer 
7700e305d2STamas Berghammer     std::string device_id;
7800e305d2STamas Berghammer     Error error = ForwardPortWithAdb (port, device_id);
7900e305d2STamas Berghammer     if (error.Fail ())
8000e305d2STamas Berghammer         return 0;
8100e305d2STamas Berghammer 
8200e305d2STamas Berghammer     m_port_forwards[pid] = std::make_pair (port, device_id);
8300e305d2STamas Berghammer 
8400e305d2STamas Berghammer     return port;
8500e305d2STamas Berghammer }
8600e305d2STamas Berghammer 
8700e305d2STamas Berghammer bool
8800e305d2STamas Berghammer PlatformAndroidRemoteGDBServer::KillSpawnedProcess (lldb::pid_t pid)
8900e305d2STamas Berghammer {
9000e305d2STamas Berghammer     auto it = m_port_forwards.find (pid);
9100e305d2STamas Berghammer     if (it != m_port_forwards.end ())
9200e305d2STamas Berghammer     {
9300e305d2STamas Berghammer         DeleteForwardPortWithAdb (it->second.first, it->second.second);
9400e305d2STamas Berghammer         m_port_forwards.erase (it);
9500e305d2STamas Berghammer     }
9600e305d2STamas Berghammer 
9700e305d2STamas Berghammer     return m_gdb_client.KillSpawnedProcess (pid);
9800e305d2STamas Berghammer }
9900e305d2STamas Berghammer 
10000e305d2STamas Berghammer Error
10100e305d2STamas Berghammer PlatformAndroidRemoteGDBServer::ConnectRemote (Args& args)
10200e305d2STamas Berghammer {
10300e305d2STamas Berghammer     if (args.GetArgumentCount () != 1)
10400e305d2STamas Berghammer         return Error ("\"platform connect\" takes a single argument: <connect-url>");
10500e305d2STamas Berghammer 
10600e305d2STamas Berghammer     int port;
10700e305d2STamas Berghammer     std::string scheme, host, path;
10800e305d2STamas Berghammer     const char *url = args.GetArgumentAtIndex (0);
10900e305d2STamas Berghammer     if (!UriParser::Parse (url, scheme, host, port, path))
11000e305d2STamas Berghammer         return Error ("invalid uri");
11100e305d2STamas Berghammer 
11200e305d2STamas Berghammer     std::string device_id;
11300e305d2STamas Berghammer     Error error = ForwardPortWithAdb (port, device_id);
11400e305d2STamas Berghammer     if (error.Fail ())
11500e305d2STamas Berghammer         return error;
11600e305d2STamas Berghammer 
11700e305d2STamas Berghammer     m_port_forwards[g_remote_platform_pid] = std::make_pair (port, device_id);
11800e305d2STamas Berghammer 
11900e305d2STamas Berghammer     return PlatformRemoteGDBServer::ConnectRemote (args);
12000e305d2STamas Berghammer }
12100e305d2STamas Berghammer 
12200e305d2STamas Berghammer Error
12300e305d2STamas Berghammer PlatformAndroidRemoteGDBServer::DisconnectRemote ()
12400e305d2STamas Berghammer {
12500e305d2STamas Berghammer     auto it = m_port_forwards.find (g_remote_platform_pid);
12600e305d2STamas Berghammer     if (it != m_port_forwards.end ())
12700e305d2STamas Berghammer     {
12800e305d2STamas Berghammer         DeleteForwardPortWithAdb (it->second.first, it->second.second);
12900e305d2STamas Berghammer         m_port_forwards.erase (it);
13000e305d2STamas Berghammer     }
13100e305d2STamas Berghammer 
13200e305d2STamas Berghammer     return PlatformRemoteGDBServer::DisconnectRemote ();
13300e305d2STamas Berghammer }
134