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/Core/Log.h"
13 
14 // Project includes
15 #include "AdbClient.h"
16 #include "PlatformAndroidRemoteGDBServer.h"
17 #include "Utility/UriParser.h"
18 
19 using namespace lldb;
20 using namespace lldb_private;
21 using namespace platform_android;
22 
23 static const lldb::pid_t g_remote_platform_pid = 0; // Alias for the process id of lldb-platform
24 
25 static Error
26 ForwardPortWithAdb (uint16_t port, std::string& device_id)
27 {
28     Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM));
29 
30     // Fetch the device list from ADB and if only 1 device found then use that device
31     // TODO: Handle the case when more device is available
32     AdbClient adb;
33     auto error = AdbClient::CreateByDeviceID (nullptr, adb);
34     if (error.Fail ())
35         return error;
36 
37     device_id = adb.GetDeviceID ();
38     if (log)
39         log->Printf("Connected to Android device \"%s\"", device_id.c_str ());
40 
41     return adb.SetPortForwarding (port);
42 }
43 
44 static Error
45 DeleteForwardPortWithAdb (uint16_t port, const std::string& device_id)
46 {
47     AdbClient adb (device_id);
48     return adb.DeletePortForwarding (port);
49 }
50 
51 PlatformAndroidRemoteGDBServer::PlatformAndroidRemoteGDBServer ()
52 {
53 }
54 
55 PlatformAndroidRemoteGDBServer::~PlatformAndroidRemoteGDBServer ()
56 {
57     for (const auto& it : m_port_forwards)
58     {
59         DeleteForwardPortWithAdb (it.second.first, it.second.second);
60     }
61 }
62 
63 uint16_t
64 PlatformAndroidRemoteGDBServer::LaunchGDBserverAndGetPort (lldb::pid_t &pid)
65 {
66     uint16_t port = m_gdb_client.LaunchGDBserverAndGetPort (pid, "127.0.0.1");
67     if (port == 0)
68         return port;
69 
70     std::string device_id;
71     Error error = ForwardPortWithAdb (port, device_id);
72     if (error.Fail ())
73         return 0;
74 
75     m_port_forwards[pid] = std::make_pair (port, device_id);
76 
77     return port;
78 }
79 
80 bool
81 PlatformAndroidRemoteGDBServer::KillSpawnedProcess (lldb::pid_t pid)
82 {
83     auto it = m_port_forwards.find (pid);
84     if (it != m_port_forwards.end ())
85     {
86         DeleteForwardPortWithAdb (it->second.first, it->second.second);
87         m_port_forwards.erase (it);
88     }
89 
90     return m_gdb_client.KillSpawnedProcess (pid);
91 }
92 
93 Error
94 PlatformAndroidRemoteGDBServer::ConnectRemote (Args& args)
95 {
96     if (args.GetArgumentCount () != 1)
97         return Error ("\"platform connect\" takes a single argument: <connect-url>");
98 
99     int port;
100     std::string scheme, host, path;
101     const char *url = args.GetArgumentAtIndex (0);
102     if (!UriParser::Parse (url, scheme, host, port, path))
103         return Error ("invalid uri");
104 
105     std::string device_id;
106     Error error = ForwardPortWithAdb (port, device_id);
107     if (error.Fail ())
108         return error;
109 
110     m_port_forwards[g_remote_platform_pid] = std::make_pair (port, device_id);
111 
112     return PlatformRemoteGDBServer::ConnectRemote (args);
113 }
114 
115 Error
116 PlatformAndroidRemoteGDBServer::DisconnectRemote ()
117 {
118     auto it = m_port_forwards.find (g_remote_platform_pid);
119     if (it != m_port_forwards.end ())
120     {
121         DeleteForwardPortWithAdb (it->second.first, it->second.second);
122         m_port_forwards.erase (it);
123     }
124 
125     return PlatformRemoteGDBServer::DisconnectRemote ();
126 }
127