1 /* 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 17 #if !ADB_HOST 18 19 #if !defined(__ANDROID_RECOVERY__) 20 #define TRACE_TAG JDWP 21 22 #include "sysdeps.h" 23 24 #include <errno.h> 25 #include <inttypes.h> 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <string.h> 29 #include <sys/socket.h> 30 #include <sys/un.h> 31 #include <unistd.h> 32 33 #include <list> 34 #include <memory> 35 #include <thread> 36 #include <vector> 37 38 #include <adbconnection/process_info.h> 39 #include <adbconnection/server.h> 40 #include <android-base/cmsg.h> 41 #include <android-base/unique_fd.h> 42 43 #include "adb.h" 44 #include "adb_io.h" 45 #include "adb_unique_fd.h" 46 #include "adb_utils.h" 47 #include "app_processes.pb.h" 48 49 using android::base::borrowed_fd; 50 using android::base::unique_fd; 51 52 /* here's how these things work. 53 54 when adbd starts, it creates a unix server socket 55 named @jdwp-control (@ is a shortcut for "first byte is zero" 56 to use the private namespace instead of the file system) 57 58 when a new JDWP daemon thread starts in a new VM process, it creates 59 a connection to @jdwp-control to announce its availability. 60 61 62 JDWP thread @jdwp-control 63 | | 64 |-------------------------------> | 65 | hello I'm in process <pid> | 66 | | 67 | | 68 69 the connection is kept alive. it will be closed automatically if 70 the JDWP process terminates (this allows adbd to detect dead 71 processes). 72 73 adbd thus maintains a list of "active" JDWP processes. it can send 74 its content to clients through the "device:debug-ports" service, 75 or even updates through the "device:track-debug-ports" service. 76 77 when a debugger wants to connect, it simply runs the command 78 equivalent to "adb forward tcp:<hostport> jdwp:<pid>" 79 80 "jdwp:<pid>" is a new forward destination format used to target 81 a given JDWP process on the device. when sutch a request arrives, 82 adbd does the following: 83 84 - first, it calls socketpair() to create a pair of equivalent 85 sockets. 86 87 - it attaches the first socket in the pair to a local socket 88 which is itself attached to the transport's remote socket: 89 90 91 - it sends the file descriptor of the second socket directly 92 to the JDWP process with the help of sendmsg() 93 94 95 JDWP thread @jdwp-control 96 | | 97 | <----------------------| 98 | OK, try this file descriptor | 99 | | 100 | | 101 102 then, the JDWP thread uses this new socket descriptor as its 103 pass-through connection to the debugger (and receives the 104 JDWP-Handshake message, answers to it, etc...) 105 106 this gives the following graphics: 107 ____________________________________ 108 | | 109 | ADB Server (host) | 110 | | 111 Debugger <---> LocalSocket <----> RemoteSocket | 112 | ^^ | 113 |___________________________||_______| 114 || 115 Transport || 116 (TCP for emulator - USB for device) || 117 || 118 ___________________________||_______ 119 | || | 120 | ADBD (device) || | 121 | VV | 122 JDWP <======> LocalSocket <----> RemoteSocket | 123 | | 124 |____________________________________| 125 126 due to the way adb works, this doesn't need a special socket 127 type or fancy handling of socket termination if either the debugger 128 or the JDWP process closes the connection. 129 130 THIS IS THE SIMPLEST IMPLEMENTATION I COULD FIND, IF YOU HAPPEN 131 TO HAVE A BETTER IDEA, LET ME KNOW - Digit 132 133 **********************************************************************/ 134 135 /** JDWP PID List Support Code 136 ** for each JDWP process, we record its pid and its connected socket 137 **/ 138 139 enum class TrackerKind { 140 kJdwp, 141 kApp, 142 }; 143 144 static void jdwp_process_event(int socket, unsigned events, void* _proc); 145 static void jdwp_process_list_updated(void); 146 static void app_process_list_updated(void); 147 148 struct JdwpProcess; 149 static auto& _jdwp_list = *new std::list<std::unique_ptr<JdwpProcess>>(); 150 151 struct JdwpProcess { 152 JdwpProcess(unique_fd socket, ProcessInfo process) { 153 CHECK(process.pid != 0); 154 155 this->socket = socket; 156 this->process = process; 157 this->fde = fdevent_create(socket.release(), jdwp_process_event, this); 158 159 if (!this->fde) { 160 LOG(FATAL) << "could not create fdevent for new JDWP process"; 161 } 162 } 163 164 ~JdwpProcess() { 165 if (this->socket >= 0) { 166 adb_shutdown(this->socket); 167 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() { 179 auto pred = [this](const auto& proc) { return proc.get() == this; }; 180 _jdwp_list.remove_if(pred); 181 } 182 183 borrowed_fd socket = -1; 184 ProcessInfo process; 185 fdevent* fde = nullptr; 186 187 std::vector<unique_fd> out_fds; 188 }; 189 190 // Populate the list of processes for "track-jdwp" service. 191 static size_t jdwp_process_list(char* buffer, size_t bufferlen) { 192 std::string temp; 193 194 for (auto& proc : _jdwp_list) { 195 if (!proc->process.debuggable) continue; 196 std::string next = std::to_string(proc->process.pid) + "\n"; 197 if (temp.length() + next.length() > bufferlen) { 198 D("truncating JDWP process list (max len = %zu)", bufferlen); 199 break; 200 } 201 temp.append(next); 202 } 203 204 memcpy(buffer, temp.data(), temp.length()); 205 return temp.length(); 206 } 207 208 // Populate the list of processes for "track-app" service. 209 // The list is a protobuf message in the binary format for efficiency. 210 static size_t app_process_list(char* buffer, size_t bufferlen) { 211 adb::proto::AppProcesses output; // result that's guaranteed to fit in the given buffer 212 adb::proto::AppProcesses temp; // temporary result that may be longer than the given buffer 213 std::string serialized_message; 214 215 for (auto& proc : _jdwp_list) { 216 if (!proc->process.debuggable && !proc->process.profileable) continue; 217 auto* entry = temp.add_process(); 218 entry->set_pid(proc->process.pid); 219 entry->set_debuggable(proc->process.debuggable); 220 entry->set_profileable(proc->process.profileable); 221 entry->set_architecture(proc->process.arch_name, proc->process.arch_name_length); 222 temp.SerializeToString(&serialized_message); 223 if (serialized_message.size() > bufferlen) { 224 D("truncating app process list (max len = %zu)", bufferlen); 225 break; 226 } 227 output = temp; 228 } 229 output.SerializeToString(&serialized_message); 230 memcpy(buffer, serialized_message.data(), serialized_message.length()); 231 return serialized_message.length(); 232 } 233 234 // Populate the list of processes for either "track-jdwp" or "track-app" services, 235 // depending on the given kind. 236 static size_t process_list(TrackerKind kind, char* buffer, size_t bufferlen) { 237 switch (kind) { 238 case TrackerKind::kJdwp: 239 return jdwp_process_list(buffer, bufferlen); 240 case TrackerKind::kApp: 241 return app_process_list(buffer, bufferlen); 242 } 243 } 244 245 static size_t process_list_msg(TrackerKind kind, char* buffer, size_t bufferlen) { 246 // Message is length-prefixed with 4 hex digits in ASCII. 247 static constexpr size_t header_len = 4; 248 if (bufferlen < header_len) { 249 LOG(FATAL) << "invalid JDWP process list buffer size: " << bufferlen; 250 } 251 252 char head[header_len + 1]; 253 size_t len = process_list(kind, buffer + header_len, bufferlen - header_len); 254 snprintf(head, sizeof head, "%04zx", len); 255 memcpy(buffer, head, header_len); 256 return len + header_len; 257 } 258 259 static void jdwp_process_event(int socket, unsigned events, void* _proc) { 260 JdwpProcess* proc = reinterpret_cast<JdwpProcess*>(_proc); 261 CHECK_EQ(socket, proc->socket.get()); 262 263 if (events & FDE_READ) { 264 // We already have the PID, if we can read from the socket, we've probably hit EOF. 265 D("terminating JDWP connection %" PRId64, proc->process.pid); 266 goto CloseProcess; 267 } 268 269 if (events & FDE_WRITE) { 270 D("trying to send fd to JDWP process (count = %zu)", proc->out_fds.size()); 271 CHECK(!proc->out_fds.empty()); 272 273 int fd = proc->out_fds.back().get(); 274 if (android::base::SendFileDescriptors(socket, "", 1, fd) != 1) { 275 D("sending new file descriptor to JDWP %" PRId64 " failed: %s", proc->process.pid, 276 strerror(errno)); 277 goto CloseProcess; 278 } 279 280 D("sent file descriptor %d to JDWP process %" PRId64, fd, proc->process.pid); 281 282 proc->out_fds.pop_back(); 283 if (proc->out_fds.empty()) { 284 fdevent_del(proc->fde, FDE_WRITE); 285 } 286 } 287 288 return; 289 290 CloseProcess: 291 bool debuggable = proc->process.debuggable; 292 bool profileable = proc->process.profileable; 293 proc->RemoveFromList(); 294 if (debuggable) jdwp_process_list_updated(); 295 if (debuggable || profileable) app_process_list_updated(); 296 } 297 298 unique_fd create_jdwp_connection_fd(int pid) { 299 D("looking for pid %d in JDWP process list", pid); 300 301 for (auto& proc : _jdwp_list) { 302 // Don't allow JDWP connection to a non-debuggable process. 303 if (!proc->process.debuggable) continue; 304 if (proc->process.pid == static_cast<uint64_t>(pid)) { 305 int fds[2]; 306 307 if (adb_socketpair(fds) < 0) { 308 D("%s: socket pair creation failed: %s", __FUNCTION__, strerror(errno)); 309 return unique_fd{}; 310 } 311 D("socketpair: (%d,%d)", fds[0], fds[1]); 312 313 proc->out_fds.emplace_back(fds[1]); 314 if (proc->out_fds.size() == 1) { 315 fdevent_add(proc->fde, FDE_WRITE); 316 } 317 318 return unique_fd{fds[0]}; 319 } 320 } 321 D("search failed !!"); 322 return unique_fd{}; 323 } 324 325 /** "jdwp" local service implementation 326 ** this simply returns the list of known JDWP process pids 327 **/ 328 329 struct JdwpSocket : public asocket { 330 bool pass = false; 331 }; 332 333 static void jdwp_socket_close(asocket* s) { 334 D("LS(%d): closing jdwp socket", s->id); 335 336 if (s->peer) { 337 D("LS(%d) peer->close()ing peer->id=%d peer->fd=%d", s->id, s->peer->id, s->peer->fd); 338 s->peer->peer = nullptr; 339 s->peer->close(s->peer); 340 s->peer = nullptr; 341 } 342 343 remove_socket(s); 344 delete s; 345 } 346 347 static int jdwp_socket_enqueue(asocket* s, apacket::payload_type) { 348 /* you can't write to this asocket */ 349 D("LS(%d): JDWP socket received data?", s->id); 350 s->peer->close(s->peer); 351 return -1; 352 } 353 354 static void jdwp_socket_ready(asocket* s) { 355 JdwpSocket* jdwp = (JdwpSocket*)s; 356 asocket* peer = jdwp->peer; 357 358 /* on the first call, send the list of pids, 359 * on the second one, close the connection 360 */ 361 if (!jdwp->pass) { 362 apacket::payload_type data; 363 data.resize(s->get_max_payload()); 364 size_t len = jdwp_process_list(&data[0], data.size()); 365 data.resize(len); 366 peer->enqueue(peer, std::move(data)); 367 jdwp->pass = true; 368 } else { 369 peer->close(peer); 370 } 371 } 372 373 asocket* create_jdwp_service_socket(void) { 374 JdwpSocket* s = new JdwpSocket(); 375 376 if (!s) { 377 LOG(FATAL) << "failed to allocate JdwpSocket"; 378 } 379 380 install_local_socket(s); 381 382 s->ready = jdwp_socket_ready; 383 s->enqueue = jdwp_socket_enqueue; 384 s->close = jdwp_socket_close; 385 s->pass = false; 386 387 return s; 388 } 389 390 /** "track-jdwp" local service implementation 391 ** this periodically sends the list of known JDWP process pids 392 ** to the client... 393 **/ 394 395 struct JdwpTracker : public asocket { 396 TrackerKind kind; 397 bool need_initial; 398 399 explicit JdwpTracker(TrackerKind k, bool initial) : kind(k), need_initial(initial) {} 400 }; 401 402 static auto& _jdwp_trackers = *new std::vector<std::unique_ptr<JdwpTracker>>(); 403 404 static void process_list_updated(TrackerKind kind) { 405 std::string data; 406 const int kMaxLength = kind == TrackerKind::kJdwp ? 1024 : 2048; 407 data.resize(kMaxLength); 408 data.resize(process_list_msg(kind, &data[0], data.size())); 409 410 for (auto& t : _jdwp_trackers) { 411 if (t->kind == kind && t->peer) { 412 // The tracker might not have been connected yet. 413 apacket::payload_type payload(data.begin(), data.end()); 414 t->peer->enqueue(t->peer, std::move(payload)); 415 } 416 } 417 } 418 419 static void jdwp_process_list_updated(void) { 420 process_list_updated(TrackerKind::kJdwp); 421 } 422 423 static void app_process_list_updated(void) { 424 process_list_updated(TrackerKind::kApp); 425 } 426 427 static void jdwp_tracker_close(asocket* s) { 428 D("LS(%d): destroying jdwp tracker service", s->id); 429 430 if (s->peer) { 431 D("LS(%d) peer->close()ing peer->id=%d peer->fd=%d", s->id, s->peer->id, s->peer->fd); 432 s->peer->peer = nullptr; 433 s->peer->close(s->peer); 434 s->peer = nullptr; 435 } 436 437 remove_socket(s); 438 439 auto pred = [s](const auto& tracker) { return tracker.get() == s; }; 440 _jdwp_trackers.erase(std::remove_if(_jdwp_trackers.begin(), _jdwp_trackers.end(), pred), 441 _jdwp_trackers.end()); 442 } 443 444 static void jdwp_tracker_ready(asocket* s) { 445 JdwpTracker* t = (JdwpTracker*)s; 446 447 if (t->need_initial) { 448 apacket::payload_type data; 449 data.resize(s->get_max_payload()); 450 data.resize(process_list_msg(t->kind, &data[0], data.size())); 451 t->need_initial = false; 452 s->peer->enqueue(s->peer, std::move(data)); 453 } 454 } 455 456 static int jdwp_tracker_enqueue(asocket* s, apacket::payload_type) { 457 /* you can't write to this socket */ 458 D("LS(%d): JDWP tracker received data?", s->id); 459 s->peer->close(s->peer); 460 return -1; 461 } 462 463 static asocket* create_process_tracker_service_socket(TrackerKind kind) { 464 auto t = std::make_unique<JdwpTracker>(kind, true); 465 if (!t) { 466 LOG(FATAL) << "failed to allocate JdwpTracker"; 467 } 468 469 memset(t.get(), 0, sizeof(asocket)); 470 471 install_local_socket(t.get()); 472 D("LS(%d): created new jdwp tracker service", t->id); 473 474 t->ready = jdwp_tracker_ready; 475 t->enqueue = jdwp_tracker_enqueue; 476 t->close = jdwp_tracker_close; 477 478 asocket* result = t.get(); 479 480 _jdwp_trackers.emplace_back(std::move(t)); 481 482 return result; 483 } 484 485 asocket* create_jdwp_tracker_service_socket() { 486 return create_process_tracker_service_socket(TrackerKind::kJdwp); 487 } 488 489 asocket* create_app_tracker_service_socket() { 490 return create_process_tracker_service_socket(TrackerKind::kApp); 491 } 492 493 int init_jdwp(void) { 494 std::thread([]() { 495 adb_thread_setname("jdwp control"); 496 adbconnection_listen([](int fd, ProcessInfo process) { 497 LOG(INFO) << "jdwp connection from " << process.pid; 498 fdevent_run_on_main_thread([fd, process] { 499 unique_fd ufd(fd); 500 auto proc = std::make_unique<JdwpProcess>(std::move(ufd), process); 501 if (!proc) { 502 LOG(FATAL) << "failed to allocate JdwpProcess"; 503 } 504 _jdwp_list.emplace_back(std::move(proc)); 505 if (process.debuggable) jdwp_process_list_updated(); 506 if (process.debuggable || process.profileable) app_process_list_updated(); 507 }); 508 }); 509 }).detach(); 510 return 0; 511 } 512 513 #else // !defined(__ANDROID_RECOVERY) 514 #include "adb.h" 515 516 asocket* create_jdwp_service_socket(void) { 517 return nullptr; 518 } 519 520 unique_fd create_jdwp_connection_fd(int pid) { 521 return {}; 522 } 523 524 asocket* create_app_tracker_service_socket() { 525 return nullptr; 526 } 527 528 asocket* create_jdwp_tracker_service_socket() { 529 return nullptr; 530 } 531 532 int init_jdwp() { 533 return 0; 534 } 535 536 #endif /* defined(__ANDROID_RECOVERY__) */ 537 #endif /* !ADB_HOST */ 538