23 using namespace platform_android;
30 llvm::StringRef remote_socket_name,
31 const std::optional<AdbClient::UnixSocketNamespace> &socket_namespace,
36 auto error = AdbClient::CreateByDeviceID(device_id, adb);
41 LLDB_LOGF(log,
"Connected to Android device \"%s\"", device_id.c_str());
43 if (remote_port != 0) {
44 LLDB_LOGF(log,
"Forwarding remote TCP port %d to local TCP port %d",
45 remote_port, local_port);
49 LLDB_LOGF(log,
"Forwarding remote socket \"%s\" to local TCP port %d",
50 remote_socket_name.str().c_str(), local_port);
52 if (!socket_namespace)
53 return Status(
"Invalid socket namespace");
67 std::unique_ptr<TCPSocket> tcp_socket(
new TCPSocket(
true,
false));
71 error = tcp_socket->Listen(
"127.0.0.1:0", 1);
73 port = tcp_socket->GetLocalPortNumber();
78 PlatformAndroidRemoteGDBServer::~PlatformAndroidRemoteGDBServer() {
79 for (
const auto &it : m_port_forwards)
83 bool PlatformAndroidRemoteGDBServer::LaunchGDBServer(
lldb::pid_t &pid,
85 assert(IsConnected());
88 if (!m_gdb_client_up->LaunchGDBServer(
"127.0.0.1", pid, remote_port,
95 const char *gdbstub_port = std::getenv(
"ANDROID_PLATFORM_LOCAL_GDB_PORT");
97 local_port = std::stoi(gdbstub_port);
99 auto error = MakeConnectURL(pid, local_port, remote_port, socket_name.c_str(),
101 if (
error.Success() && log)
102 LLDB_LOGF(log,
"gdbserver connect URL: %s", connect_url.c_str());
104 return error.Success();
107 bool PlatformAndroidRemoteGDBServer::KillSpawnedProcess(
lldb::pid_t pid) {
108 assert(IsConnected());
109 DeleteForwardPort(pid);
110 return m_gdb_client_up->KillSpawnedProcess(pid);
113 Status PlatformAndroidRemoteGDBServer::ConnectRemote(
Args &args) {
118 "\"platform connect\" takes a single argument: <connect-url>");
122 return Status(
"URL is null.");
123 std::optional<URI> parsed_url = URI::Parse(url);
125 return Status(
"Invalid URL: %s", url);
126 if (parsed_url->hostname !=
"localhost")
127 m_device_id = parsed_url->hostname.str();
129 m_socket_namespace.reset();
130 if (parsed_url->scheme ==
"unix-connect")
131 m_socket_namespace = AdbClient::UnixSocketNamespaceFileSystem;
132 else if (parsed_url->scheme ==
"unix-abstract-connect")
133 m_socket_namespace = AdbClient::UnixSocketNamespaceAbstract;
136 const char *platform_local_port = std::getenv(
"ANDROID_PLATFORM_LOCAL_PORT");
137 if (platform_local_port)
138 local_port = std::stoi(platform_local_port);
142 parsed_url->port.value_or(0), parsed_url->path,
151 LLDB_LOGF(log,
"Rewritten platform connect URL: %s", connect_url.c_str());
153 error = PlatformRemoteGDBServer::ConnectRemote(args);
160 Status PlatformAndroidRemoteGDBServer::DisconnectRemote() {
162 return PlatformRemoteGDBServer::DisconnectRemote();
165 void PlatformAndroidRemoteGDBServer::DeleteForwardPort(
lldb::pid_t pid) {
168 auto it = m_port_forwards.find(pid);
169 if (it == m_port_forwards.end())
172 const auto port = it->second;
176 "Failed to delete port forwarding (pid=%" PRIu64
177 ", port=%d, device=%s): %s",
178 pid, port, m_device_id.c_str(),
error.AsCString());
180 m_port_forwards.erase(it);
183 Status PlatformAndroidRemoteGDBServer::MakeConnectURL(
185 const uint16_t remote_port, llvm::StringRef remote_socket_name,
187 static const int kAttempsNum = 5;
193 m_socket_namespace, m_device_id);
194 if (
error.Success()) {
195 m_port_forwards[pid] = local;
196 std::ostringstream url_str;
197 url_str <<
"connect://127.0.0.1:" << local;
198 connect_url = url_str.str();
204 return forward(local_port, remote_port);
209 for (
auto i = 0; i < kAttempsNum; ++i) {
215 if (forward(local_port, remote_port).
Success())
222 lldb::ProcessSP PlatformAndroidRemoteGDBServer::ConnectProcess(
223 llvm::StringRef connect_url, llvm::StringRef plugin_name,
230 static lldb::pid_t s_remote_gdbserver_fake_pid = 0xffffffffffffffffULL;
232 std::optional<URI> parsed_url = URI::Parse(connect_url);
234 error.SetErrorStringWithFormat(
"Invalid URL: %s",
235 connect_url.str().c_str());
240 error = MakeConnectURL(s_remote_gdbserver_fake_pid--, 0,
241 parsed_url->port.value_or(0), parsed_url->path,
246 return PlatformRemoteGDBServer::ConnectProcess(new_connect_url, plugin_name,
247 debugger, target,
error);