blob: 8ff07480fa9cc6177cba445b930d65ad71e03d24 [file] [log] [blame]
Dan Albertdb6fe642015-03-19 15:21:08 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Josh Gaofa3605a2020-03-16 11:30:09 -070017#if !defined(__ANDROID_RECOVERY__)
Yabin Cui19bec5b2015-09-22 15:52:57 -070018#define TRACE_TAG JDWP
Dan Albertdb6fe642015-03-19 15:21:08 -070019
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080020#include "sysdeps.h"
Dan Albertdb6fe642015-03-19 15:21:08 -070021
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080022#include <errno.h>
Shukang Zhou420ad552020-02-13 17:01:39 -080023#include <inttypes.h>
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080024#include <stdio.h>
Elliott Hughes43df1092015-07-23 17:12:58 -070025#include <stdlib.h>
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080026#include <string.h>
Josh Gao9eaf33c2016-05-13 15:28:34 -070027#include <sys/socket.h>
28#include <sys/un.h>
Teddie Stenvif56e7f52010-02-15 12:20:44 +010029#include <unistd.h>
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080030
Josh Gao9eaf33c2016-05-13 15:28:34 -070031#include <list>
32#include <memory>
Josh Gaoeb5e6052019-06-19 14:14:57 -070033#include <thread>
Josh Gao9eaf33c2016-05-13 15:28:34 -070034#include <vector>
35
Josh Gaoeb5e6052019-06-19 14:14:57 -070036#include <adbconnection/server.h>
Josh Gao2d83b542019-01-10 14:29:29 -080037#include <android-base/cmsg.h>
Fabien Sanglard5d4eaef2024-12-18 14:56:14 -080038#include <android-base/file.h>
Josh Gaoeb5e6052019-06-19 14:14:57 -070039#include <android-base/unique_fd.h>
Fabien Sanglard5d4eaef2024-12-18 14:56:14 -080040#include <processgroup/processgroup.h>
Josh Gao2d83b542019-01-10 14:29:29 -080041
Dan Albertdb6fe642015-03-19 15:21:08 -070042#include "adb.h"
Josh Gao9eaf33c2016-05-13 15:28:34 -070043#include "adb_io.h"
Josh Gaoea7457b2016-08-30 15:39:25 -070044#include "adb_unique_fd.h"
Yabin Cui5fc22312015-10-06 15:10:05 -070045#include "adb_utils.h"
Shukang Zhou420ad552020-02-13 17:01:39 -080046#include "app_processes.pb.h"
Dan Albertdb6fe642015-03-19 15:21:08 -070047
Josh Gaoeb5e6052019-06-19 14:14:57 -070048using android::base::borrowed_fd;
49using android::base::unique_fd;
50
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080051/* here's how these things work.
52
53 when adbd starts, it creates a unix server socket
Josh Gao9eaf33c2016-05-13 15:28:34 -070054 named @jdwp-control (@ is a shortcut for "first byte is zero"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080055 to use the private namespace instead of the file system)
56
57 when a new JDWP daemon thread starts in a new VM process, it creates
Josh Gao9eaf33c2016-05-13 15:28:34 -070058 a connection to @jdwp-control to announce its availability.
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080059
60
Josh Gao9eaf33c2016-05-13 15:28:34 -070061 JDWP thread @jdwp-control
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080062 | |
63 |-------------------------------> |
64 | hello I'm in process <pid> |
65 | |
66 | |
67
68 the connection is kept alive. it will be closed automatically if
69 the JDWP process terminates (this allows adbd to detect dead
70 processes).
71
72 adbd thus maintains a list of "active" JDWP processes. it can send
73 its content to clients through the "device:debug-ports" service,
74 or even updates through the "device:track-debug-ports" service.
75
76 when a debugger wants to connect, it simply runs the command
77 equivalent to "adb forward tcp:<hostport> jdwp:<pid>"
78
79 "jdwp:<pid>" is a new forward destination format used to target
80 a given JDWP process on the device. when sutch a request arrives,
81 adbd does the following:
82
83 - first, it calls socketpair() to create a pair of equivalent
84 sockets.
85
86 - it attaches the first socket in the pair to a local socket
87 which is itself attached to the transport's remote socket:
88
89
90 - it sends the file descriptor of the second socket directly
91 to the JDWP process with the help of sendmsg()
92
93
Josh Gao9eaf33c2016-05-13 15:28:34 -070094 JDWP thread @jdwp-control
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080095 | |
96 | <----------------------|
97 | OK, try this file descriptor |
98 | |
99 | |
100
101 then, the JDWP thread uses this new socket descriptor as its
102 pass-through connection to the debugger (and receives the
103 JDWP-Handshake message, answers to it, etc...)
104
105 this gives the following graphics:
106 ____________________________________
107 | |
108 | ADB Server (host) |
109 | |
110 Debugger <---> LocalSocket <----> RemoteSocket |
111 | ^^ |
112 |___________________________||_______|
113 ||
114 Transport ||
115 (TCP for emulator - USB for device) ||
116 ||
117 ___________________________||_______
118 | || |
119 | ADBD (device) || |
120 | VV |
121 JDWP <======> LocalSocket <----> RemoteSocket |
122 | |
123 |____________________________________|
124
125 due to the way adb works, this doesn't need a special socket
126 type or fancy handling of socket termination if either the debugger
127 or the JDWP process closes the connection.
128
129 THIS IS THE SIMPLEST IMPLEMENTATION I COULD FIND, IF YOU HAPPEN
130 TO HAVE A BETTER IDEA, LET ME KNOW - Digit
131
132**********************************************************************/
133
134/** JDWP PID List Support Code
135 ** for each JDWP process, we record its pid and its connected socket
136 **/
137
Shukang Zhou420ad552020-02-13 17:01:39 -0800138enum class TrackerKind {
139 kJdwp,
140 kApp,
141};
142
Josh Gao9eaf33c2016-05-13 15:28:34 -0700143static void jdwp_process_event(int socket, unsigned events, void* _proc);
Elliott Hughesa8ab5ce2024-06-28 12:10:09 +0000144static void jdwp_process_list_updated();
145static void app_process_list_updated();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800146
Josh Gao9eaf33c2016-05-13 15:28:34 -0700147struct JdwpProcess;
Josh Gao361148b2018-01-02 12:01:43 -0800148static auto& _jdwp_list = *new std::list<std::unique_ptr<JdwpProcess>>();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800149
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800150struct JdwpProcess {
Shukang Zhou420ad552020-02-13 17:01:39 -0800151 JdwpProcess(unique_fd socket, ProcessInfo process) {
152 CHECK(process.pid != 0);
Josh Gaoeb5e6052019-06-19 14:14:57 -0700153
Josh Gao9eaf33c2016-05-13 15:28:34 -0700154 this->socket = socket;
Shukang Zhou420ad552020-02-13 17:01:39 -0800155 this->process = process;
Josh Gaoeb5e6052019-06-19 14:14:57 -0700156 this->fde = fdevent_create(socket.release(), jdwp_process_event, this);
Fabien Sanglard15335e02024-03-05 21:33:44 +0000157 fdevent_set(this->fde, FDE_READ);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800158
Josh Gao9eaf33c2016-05-13 15:28:34 -0700159 if (!this->fde) {
Elliott Hughese64126b2018-10-19 13:59:44 -0700160 LOG(FATAL) << "could not create fdevent for new JDWP process";
Josh Gao9eaf33c2016-05-13 15:28:34 -0700161 }
Josh Gao9eaf33c2016-05-13 15:28:34 -0700162 }
163
164 ~JdwpProcess() {
165 if (this->socket >= 0) {
166 adb_shutdown(this->socket);
Josh Gao9eaf33c2016-05-13 15:28:34 -0700167 this->socket = -1;
168 }
169
170 if (this->fde) {
171 fdevent_destroy(this->fde);
172 this->fde = nullptr;
173 }
174
175 out_fds.clear();
176 }
177
178 void RemoveFromList() {
Josh Gao9eaf33c2016-05-13 15:28:34 -0700179 auto pred = [this](const auto& proc) { return proc.get() == this; };
180 _jdwp_list.remove_if(pred);
181 }
182
Josh Gaoeb5e6052019-06-19 14:14:57 -0700183 borrowed_fd socket = -1;
Shukang Zhou420ad552020-02-13 17:01:39 -0800184 ProcessInfo process;
Josh Gao9eaf33c2016-05-13 15:28:34 -0700185 fdevent* fde = nullptr;
186
Fabien Sanglardb7452ff2023-11-02 15:08:50 -0700187 // When a jdwp:<PID> request arrives, we create a socketpair and immediately
188 // return one end to the requester. The other end is "staged" in this queue.
189 // The next time @jdwp-control becomes FDE_WRITE, we send the back() fd (it is
190 // received on the other end of @jdwp-control by ART) and pop it. This queue
191 // should almost always be empty if ART reads() from @jdwp-control properly.
Josh Gao9eaf33c2016-05-13 15:28:34 -0700192 std::vector<unique_fd> out_fds;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800193};
194
Shukang Zhou420ad552020-02-13 17:01:39 -0800195// Populate the list of processes for "track-jdwp" service.
Josh Gao9eaf33c2016-05-13 15:28:34 -0700196static size_t jdwp_process_list(char* buffer, size_t bufferlen) {
197 std::string temp;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800198
Josh Gao9eaf33c2016-05-13 15:28:34 -0700199 for (auto& proc : _jdwp_list) {
Shukang Zhou420ad552020-02-13 17:01:39 -0800200 if (!proc->process.debuggable) continue;
201 std::string next = std::to_string(proc->process.pid) + "\n";
Josh Gao9eaf33c2016-05-13 15:28:34 -0700202 if (temp.length() + next.length() > bufferlen) {
203 D("truncating JDWP process list (max len = %zu)", bufferlen);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800204 break;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800205 }
Josh Gao9eaf33c2016-05-13 15:28:34 -0700206 temp.append(next);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800207 }
Josh Gao9eaf33c2016-05-13 15:28:34 -0700208
209 memcpy(buffer, temp.data(), temp.length());
210 return temp.length();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800211}
212
Shukang Zhou420ad552020-02-13 17:01:39 -0800213// Populate the list of processes for "track-app" service.
214// The list is a protobuf message in the binary format for efficiency.
215static size_t app_process_list(char* buffer, size_t bufferlen) {
216 adb::proto::AppProcesses output; // result that's guaranteed to fit in the given buffer
217 adb::proto::AppProcesses temp; // temporary result that may be longer than the given buffer
218 std::string serialized_message;
219
220 for (auto& proc : _jdwp_list) {
221 if (!proc->process.debuggable && !proc->process.profileable) continue;
222 auto* entry = temp.add_process();
Yi Kongaa8bdb12024-08-12 18:10:54 +0800223 *entry = proc->process.toProtobuf();
Shukang Zhou420ad552020-02-13 17:01:39 -0800224 temp.SerializeToString(&serialized_message);
225 if (serialized_message.size() > bufferlen) {
226 D("truncating app process list (max len = %zu)", bufferlen);
227 break;
228 }
229 output = temp;
230 }
231 output.SerializeToString(&serialized_message);
232 memcpy(buffer, serialized_message.data(), serialized_message.length());
233 return serialized_message.length();
234}
235
236// Populate the list of processes for either "track-jdwp" or "track-app" services,
237// depending on the given kind.
238static size_t process_list(TrackerKind kind, char* buffer, size_t bufferlen) {
239 switch (kind) {
240 case TrackerKind::kJdwp:
241 return jdwp_process_list(buffer, bufferlen);
242 case TrackerKind::kApp:
243 return app_process_list(buffer, bufferlen);
244 }
245}
246
247static size_t process_list_msg(TrackerKind kind, char* buffer, size_t bufferlen) {
Josh Gao9eaf33c2016-05-13 15:28:34 -0700248 // Message is length-prefixed with 4 hex digits in ASCII.
249 static constexpr size_t header_len = 4;
250 if (bufferlen < header_len) {
Elliott Hughese64126b2018-10-19 13:59:44 -0700251 LOG(FATAL) << "invalid JDWP process list buffer size: " << bufferlen;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800252 }
253
Josh Gao9eaf33c2016-05-13 15:28:34 -0700254 char head[header_len + 1];
Shukang Zhou420ad552020-02-13 17:01:39 -0800255 size_t len = process_list(kind, buffer + header_len, bufferlen - header_len);
Josh Gao9eaf33c2016-05-13 15:28:34 -0700256 snprintf(head, sizeof head, "%04zx", len);
257 memcpy(buffer, head, header_len);
258 return len + header_len;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800259}
260
Josh Gao9eaf33c2016-05-13 15:28:34 -0700261static void jdwp_process_event(int socket, unsigned events, void* _proc) {
262 JdwpProcess* proc = reinterpret_cast<JdwpProcess*>(_proc);
Josh Gaoeb5e6052019-06-19 14:14:57 -0700263 CHECK_EQ(socket, proc->socket.get());
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800264
265 if (events & FDE_READ) {
Fabien Sanglard15335e02024-03-05 21:33:44 +0000266 auto process_info = readProcessInfoFromSocket(socket);
267
268 // Unable to get a process info, the remote app process either died or errored
269 if (!process_info) {
270 goto CloseProcess;
271 }
272
Fabien Sanglardbef3d192024-12-12 17:47:35 -0800273 VLOG(JDWP) << "Received JDWP Process info for pid=" << process_info->pid;
Fabien Sanglard15335e02024-03-05 21:33:44 +0000274 proc->process = std::move(*process_info);
275 jdwp_process_list_updated();
276 app_process_list_updated();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800277 }
278
279 if (events & FDE_WRITE) {
Josh Gao9eaf33c2016-05-13 15:28:34 -0700280 D("trying to send fd to JDWP process (count = %zu)", proc->out_fds.size());
Josh Gaocc1dcc82018-10-05 17:09:41 -0700281 CHECK(!proc->out_fds.empty());
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800282
Josh Gaocc1dcc82018-10-05 17:09:41 -0700283 int fd = proc->out_fds.back().get();
Josh Gao2d83b542019-01-10 14:29:29 -0800284 if (android::base::SendFileDescriptors(socket, "", 1, fd) != 1) {
Shukang Zhou420ad552020-02-13 17:01:39 -0800285 D("sending new file descriptor to JDWP %" PRId64 " failed: %s", proc->process.pid,
286 strerror(errno));
Josh Gaocc1dcc82018-10-05 17:09:41 -0700287 goto CloseProcess;
288 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800289
Shukang Zhou420ad552020-02-13 17:01:39 -0800290 D("sent file descriptor %d to JDWP process %" PRId64, fd, proc->process.pid);
Josh Gao9eaf33c2016-05-13 15:28:34 -0700291
Josh Gaocc1dcc82018-10-05 17:09:41 -0700292 proc->out_fds.pop_back();
293 if (proc->out_fds.empty()) {
Fabien Sanglardbef3d192024-12-12 17:47:35 -0800294 VLOG(JDWP) << "Removing FDE_WRITE";
Josh Gaocc1dcc82018-10-05 17:09:41 -0700295 fdevent_del(proc->fde, FDE_WRITE);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800296 }
297 }
Josh Gao9eaf33c2016-05-13 15:28:34 -0700298
299 return;
300
301CloseProcess:
Fabien Sanglardbef3d192024-12-12 17:47:35 -0800302 VLOG(JDWP) << "Process " << proc->process.pid << " has disconnected";
Shukang Zhou420ad552020-02-13 17:01:39 -0800303 bool debuggable = proc->process.debuggable;
304 bool profileable = proc->process.profileable;
Josh Gao9eaf33c2016-05-13 15:28:34 -0700305 proc->RemoveFromList();
Shukang Zhou420ad552020-02-13 17:01:39 -0800306 if (debuggable) jdwp_process_list_updated();
307 if (debuggable || profileable) app_process_list_updated();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800308}
309
Fabien Sanglard5d4eaef2024-12-18 14:56:14 -0800310static bool is_process_in_freezer(const ProcessInfo& info) {
311 // Check "/sys/fs/cgroup/apps/uid_{}/pid_{}/cgroup.freeze". Since "apps" is configurable,
312 // use libprocessgroup to make sure we always have the right path.
313 std::string path;
314 if (!CgroupGetAttributePathForProcess("FreezerState", info.uid, info.pid, path)) {
315 VLOG(JDWP) << std::format("Failed to build frozen path of '{}' (got '{}')", info.pid, path);
316 return false;
317 }
318
319 std::string content;
320 if (!android::base::ReadFileToString(path, &content)) {
321 VLOG(JDWP) << std::format("Failed to read ({})", path);
322 return false;
323 }
324
325 bool is_frozen = content == "1\n";
326 VLOG(JDWP) << std::format("Checking if pid {} is frozen at '{}' = '{}'", info.pid, path,
327 content);
328
329 if (is_frozen) {
330 LOG(WARNING) << std::format("According to '{}'(='{}'), pid {} is frozen", path, content,
331 info.pid);
332 }
333 return is_frozen;
334}
335
336static unique_fd send_socket_to_process(JdwpProcess& proc) {
337 // Process in the cached apps freezer don't get scheduled.
338 // Returning a socket will hang the debugger and leak a fd until the app is taken
339 // out of the freezer. Fail instead.
340 if (is_process_in_freezer(proc.process)) {
341 ProcessInfo& info = proc.process;
342 LOG(WARNING) << std::format("Process {} ({}) is frozen. Denying JDWP connection", info.pid,
343 info.process_name);
344 return unique_fd{};
345 }
346
347 int fds[2];
348 if (adb_socketpair(fds) < 0) {
349 LOG(WARNING) << std::format("{}: socket pair creation failed: {}", __FUNCTION__,
350 strerror(errno));
351 return unique_fd{};
352 }
353
354 VLOG(JDWP) << std::format("socketpair: ({},{})", fds[0], fds[1]);
355 proc.out_fds.emplace_back(fds[1]);
356 if (proc.out_fds.size() == 1) {
357 fdevent_add(proc.fde, FDE_WRITE);
358 }
359
360 return unique_fd{fds[0]};
361}
362
Fabien Sanglard5f42cc72025-01-21 14:48:35 -0800363unique_fd create_jdwp_connection_fd(pid_t pid) {
Fabien Sanglard5d4eaef2024-12-18 14:56:14 -0800364 VLOG(JDWP) << std::format("looking for pid {} in JDWP process list", pid);
Josh Gao9eaf33c2016-05-13 15:28:34 -0700365
366 for (auto& proc : _jdwp_list) {
Shukang Zhou420ad552020-02-13 17:01:39 -0800367 // Don't allow JDWP connection to a non-debuggable process.
Fabien Sanglard5d4eaef2024-12-18 14:56:14 -0800368 if (!proc->process.debuggable) {
369 continue;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800370 }
Fabien Sanglard5d4eaef2024-12-18 14:56:14 -0800371
Fabien Sanglard5f42cc72025-01-21 14:48:35 -0800372 if (static_cast<pid_t>(proc->process.pid) != pid) {
Fabien Sanglard5d4eaef2024-12-18 14:56:14 -0800373 continue;
374 }
375
376 return send_socket_to_process(*proc);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800377 }
Fabien Sanglard5d4eaef2024-12-18 14:56:14 -0800378 LOG(WARNING) << std::format("search for pid {} failed !!", pid);
Josh Gao5607e922018-07-25 18:15:52 -0700379 return unique_fd{};
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800380}
381
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800382/** "jdwp" local service implementation
383 ** this simply returns the list of known JDWP process pids
384 **/
385
Josh Gao9eaf33c2016-05-13 15:28:34 -0700386struct JdwpSocket : public asocket {
Josh Gao5cb76ce2018-02-12 17:24:00 -0800387 bool pass = false;
Elliott Hughesfe7ff812015-04-17 09:47:42 -0700388};
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800389
Josh Gao9eaf33c2016-05-13 15:28:34 -0700390static void jdwp_socket_close(asocket* s) {
391 D("LS(%d): closing jdwp socket", s->id);
392
393 if (s->peer) {
394 D("LS(%d) peer->close()ing peer->id=%d peer->fd=%d", s->id, s->peer->id, s->peer->fd);
395 s->peer->peer = nullptr;
396 s->peer->close(s->peer);
397 s->peer = nullptr;
398 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800399
400 remove_socket(s);
Josh Gao5cb76ce2018-02-12 17:24:00 -0800401 delete s;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800402}
403
Josh Gaocd2a5292018-03-07 16:52:28 -0800404static int jdwp_socket_enqueue(asocket* s, apacket::payload_type) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800405 /* you can't write to this asocket */
Josh Gao9eaf33c2016-05-13 15:28:34 -0700406 D("LS(%d): JDWP socket received data?", s->id);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800407 s->peer->close(s->peer);
408 return -1;
409}
410
Josh Gao9eaf33c2016-05-13 15:28:34 -0700411static void jdwp_socket_ready(asocket* s) {
412 JdwpSocket* jdwp = (JdwpSocket*)s;
413 asocket* peer = jdwp->peer;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800414
Josh Gao9eaf33c2016-05-13 15:28:34 -0700415 /* on the first call, send the list of pids,
416 * on the second one, close the connection
417 */
418 if (!jdwp->pass) {
Josh Gaocd2a5292018-03-07 16:52:28 -0800419 apacket::payload_type data;
Josh Gaoa7d9d712018-02-01 13:17:50 -0800420 data.resize(s->get_max_payload());
421 size_t len = jdwp_process_list(&data[0], data.size());
422 data.resize(len);
423 peer->enqueue(peer, std::move(data));
Josh Gao9eaf33c2016-05-13 15:28:34 -0700424 jdwp->pass = true;
425 } else {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800426 peer->close(peer);
427 }
428}
429
Elliott Hughesa8ab5ce2024-06-28 12:10:09 +0000430asocket* create_jdwp_service_socket() {
Josh Gao5cb76ce2018-02-12 17:24:00 -0800431 JdwpSocket* s = new JdwpSocket();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800432
Josh Gao9eaf33c2016-05-13 15:28:34 -0700433 if (!s) {
Elliott Hughese64126b2018-10-19 13:59:44 -0700434 LOG(FATAL) << "failed to allocate JdwpSocket";
Josh Gao9eaf33c2016-05-13 15:28:34 -0700435 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800436
Josh Gao9eaf33c2016-05-13 15:28:34 -0700437 install_local_socket(s);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800438
Josh Gao9eaf33c2016-05-13 15:28:34 -0700439 s->ready = jdwp_socket_ready;
440 s->enqueue = jdwp_socket_enqueue;
441 s->close = jdwp_socket_close;
442 s->pass = false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800443
Josh Gao9eaf33c2016-05-13 15:28:34 -0700444 return s;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800445}
446
447/** "track-jdwp" local service implementation
448 ** this periodically sends the list of known JDWP process pids
449 ** to the client...
450 **/
451
Josh Gao9eaf33c2016-05-13 15:28:34 -0700452struct JdwpTracker : public asocket {
Shukang Zhou420ad552020-02-13 17:01:39 -0800453 TrackerKind kind;
Josh Gao9eaf33c2016-05-13 15:28:34 -0700454 bool need_initial;
Shukang Zhou420ad552020-02-13 17:01:39 -0800455
456 explicit JdwpTracker(TrackerKind k, bool initial) : kind(k), need_initial(initial) {}
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800457};
458
Josh Gao361148b2018-01-02 12:01:43 -0800459static auto& _jdwp_trackers = *new std::vector<std::unique_ptr<JdwpTracker>>();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800460
Shukang Zhou420ad552020-02-13 17:01:39 -0800461static void process_list_updated(TrackerKind kind) {
Fabien Sanglard2e9756a2024-03-28 23:22:59 +0000462 // Find out the max payload we can output.
463 // We start with the max the protocol can handle (hex4).
464 size_t maxPayload = UINT16_MAX;
465 for (auto& t : _jdwp_trackers) {
466 maxPayload = std::min(maxPayload, t->get_max_payload());
467 }
468
Josh Gaoa7d9d712018-02-01 13:17:50 -0800469 std::string data;
Fabien Sanglard2e9756a2024-03-28 23:22:59 +0000470 data.resize(maxPayload);
Shukang Zhou420ad552020-02-13 17:01:39 -0800471 data.resize(process_list_msg(kind, &data[0], data.size()));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800472
Josh Gao9eaf33c2016-05-13 15:28:34 -0700473 for (auto& t : _jdwp_trackers) {
Shukang Zhou420ad552020-02-13 17:01:39 -0800474 if (t->kind == kind && t->peer) {
Josh Gao9eaf33c2016-05-13 15:28:34 -0700475 // The tracker might not have been connected yet.
Josh Gaocd2a5292018-03-07 16:52:28 -0800476 apacket::payload_type payload(data.begin(), data.end());
477 t->peer->enqueue(t->peer, std::move(payload));
Josh Gao9eaf33c2016-05-13 15:28:34 -0700478 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800479 }
480}
481
Elliott Hughesa8ab5ce2024-06-28 12:10:09 +0000482static void jdwp_process_list_updated() {
Shukang Zhou420ad552020-02-13 17:01:39 -0800483 process_list_updated(TrackerKind::kJdwp);
484}
485
Elliott Hughesa8ab5ce2024-06-28 12:10:09 +0000486static void app_process_list_updated() {
Shukang Zhou420ad552020-02-13 17:01:39 -0800487 process_list_updated(TrackerKind::kApp);
488}
489
Josh Gao9eaf33c2016-05-13 15:28:34 -0700490static void jdwp_tracker_close(asocket* s) {
491 D("LS(%d): destroying jdwp tracker service", s->id);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800492
Josh Gao9eaf33c2016-05-13 15:28:34 -0700493 if (s->peer) {
494 D("LS(%d) peer->close()ing peer->id=%d peer->fd=%d", s->id, s->peer->id, s->peer->fd);
495 s->peer->peer = nullptr;
496 s->peer->close(s->peer);
497 s->peer = nullptr;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800498 }
499
500 remove_socket(s);
501
Josh Gao9eaf33c2016-05-13 15:28:34 -0700502 auto pred = [s](const auto& tracker) { return tracker.get() == s; };
Josh Gaoeea5fea2017-03-10 11:19:48 -0800503 _jdwp_trackers.erase(std::remove_if(_jdwp_trackers.begin(), _jdwp_trackers.end(), pred),
504 _jdwp_trackers.end());
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800505}
506
Josh Gao9eaf33c2016-05-13 15:28:34 -0700507static void jdwp_tracker_ready(asocket* s) {
508 JdwpTracker* t = (JdwpTracker*)s;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800509
Josh Gao9eaf33c2016-05-13 15:28:34 -0700510 if (t->need_initial) {
Josh Gaocd2a5292018-03-07 16:52:28 -0800511 apacket::payload_type data;
Josh Gaoa7d9d712018-02-01 13:17:50 -0800512 data.resize(s->get_max_payload());
Shukang Zhou420ad552020-02-13 17:01:39 -0800513 data.resize(process_list_msg(t->kind, &data[0], data.size()));
Josh Gao9eaf33c2016-05-13 15:28:34 -0700514 t->need_initial = false;
Josh Gaoa7d9d712018-02-01 13:17:50 -0800515 s->peer->enqueue(s->peer, std::move(data));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800516 }
517}
518
Josh Gaocd2a5292018-03-07 16:52:28 -0800519static int jdwp_tracker_enqueue(asocket* s, apacket::payload_type) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800520 /* you can't write to this socket */
Josh Gao9eaf33c2016-05-13 15:28:34 -0700521 D("LS(%d): JDWP tracker received data?", s->id);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800522 s->peer->close(s->peer);
523 return -1;
524}
525
Josh Gaofa3605a2020-03-16 11:30:09 -0700526static asocket* create_process_tracker_service_socket(TrackerKind kind) {
Shaju Mathew237944f2023-06-01 18:03:03 -0700527 std::unique_ptr<JdwpTracker> t = std::make_unique<JdwpTracker>(kind, true);
Josh Gao9eaf33c2016-05-13 15:28:34 -0700528 if (!t) {
Elliott Hughese64126b2018-10-19 13:59:44 -0700529 LOG(FATAL) << "failed to allocate JdwpTracker";
Josh Gao9eaf33c2016-05-13 15:28:34 -0700530 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800531
Shaju Mathew237944f2023-06-01 18:03:03 -0700532 /* Object layout (with an inheritance hierarchy) varies across arch (e.g
533 * armv7a/Android TV vs aarch64), so no assumptions can be made about
534 * accessing fields based on offsets (e.g memset(t.get(), 0, sizeof(asocket))
535 * might clobber an unintended memory location).
536 */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800537
Josh Gao9eaf33c2016-05-13 15:28:34 -0700538 install_local_socket(t.get());
539 D("LS(%d): created new jdwp tracker service", t->id);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800540
Josh Gao9eaf33c2016-05-13 15:28:34 -0700541 t->ready = jdwp_tracker_ready;
542 t->enqueue = jdwp_tracker_enqueue;
543 t->close = jdwp_tracker_close;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800544
Josh Gao9eaf33c2016-05-13 15:28:34 -0700545 asocket* result = t.get();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800546
Josh Gao9eaf33c2016-05-13 15:28:34 -0700547 _jdwp_trackers.emplace_back(std::move(t));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800548
Josh Gao9eaf33c2016-05-13 15:28:34 -0700549 return result;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800550}
551
Shukang Zhou420ad552020-02-13 17:01:39 -0800552asocket* create_jdwp_tracker_service_socket() {
553 return create_process_tracker_service_socket(TrackerKind::kJdwp);
554}
555
556asocket* create_app_tracker_service_socket() {
557 return create_process_tracker_service_socket(TrackerKind::kApp);
558}
559
Elliott Hughesa8ab5ce2024-06-28 12:10:09 +0000560int init_jdwp() {
Josh Gaoeb5e6052019-06-19 14:14:57 -0700561 std::thread([]() {
562 adb_thread_setname("jdwp control");
Shukang Zhou420ad552020-02-13 17:01:39 -0800563 adbconnection_listen([](int fd, ProcessInfo process) {
564 LOG(INFO) << "jdwp connection from " << process.pid;
Shaju Mathew705fa1c2022-12-31 19:36:54 -0800565 fdevent_run_on_looper([fd, process] {
Josh Gaoeb5e6052019-06-19 14:14:57 -0700566 unique_fd ufd(fd);
Shukang Zhou420ad552020-02-13 17:01:39 -0800567 auto proc = std::make_unique<JdwpProcess>(std::move(ufd), process);
Josh Gaoeb5e6052019-06-19 14:14:57 -0700568 if (!proc) {
569 LOG(FATAL) << "failed to allocate JdwpProcess";
570 }
571 _jdwp_list.emplace_back(std::move(proc));
Shukang Zhou420ad552020-02-13 17:01:39 -0800572 if (process.debuggable) jdwp_process_list_updated();
573 if (process.debuggable || process.profileable) app_process_list_updated();
Josh Gaoeb5e6052019-06-19 14:14:57 -0700574 });
575 });
576 }).detach();
577 return 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800578}
579
Josh Gaofa3605a2020-03-16 11:30:09 -0700580#else // !defined(__ANDROID_RECOVERY)
581#include "adb.h"
582
Elliott Hughesa8ab5ce2024-06-28 12:10:09 +0000583asocket* create_jdwp_service_socket() {
Josh Gaofa3605a2020-03-16 11:30:09 -0700584 return nullptr;
585}
586
Fabien Sanglard5f42cc72025-01-21 14:48:35 -0800587unique_fd create_jdwp_connection_fd(pid_t pid) {
Josh Gaofa3605a2020-03-16 11:30:09 -0700588 return {};
589}
590
591asocket* create_app_tracker_service_socket() {
592 return nullptr;
593}
594
595asocket* create_jdwp_tracker_service_socket() {
596 return nullptr;
597}
598
599int init_jdwp() {
600 return 0;
601}
602
603#endif /* defined(__ANDROID_RECOVERY__) */