• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* implement the "debug-ports" and "track-debug-ports" device services */
2 #include "sysdeps.h"
3 #define  TRACE_TAG   TRACE_JDWP
4 #include "adb.h"
5 #include <errno.h>
6 #include <stdio.h>
7 #include <string.h>
8 
9 /* here's how these things work.
10 
11    when adbd starts, it creates a unix server socket
12    named @vm-debug-control (@ is a shortcut for "first byte is zero"
13    to use the private namespace instead of the file system)
14 
15    when a new JDWP daemon thread starts in a new VM process, it creates
16    a connection to @vm-debug-control to announce its availability.
17 
18 
19      JDWP thread                             @vm-debug-control
20          |                                         |
21          |------------------------------->         |
22          | hello I'm in process <pid>              |
23          |                                         |
24          |                                         |
25 
26     the connection is kept alive. it will be closed automatically if
27     the JDWP process terminates (this allows adbd to detect dead
28     processes).
29 
30     adbd thus maintains a list of "active" JDWP processes. it can send
31     its content to clients through the "device:debug-ports" service,
32     or even updates through the "device:track-debug-ports" service.
33 
34     when a debugger wants to connect, it simply runs the command
35     equivalent to  "adb forward tcp:<hostport> jdwp:<pid>"
36 
37     "jdwp:<pid>" is a new forward destination format used to target
38     a given JDWP process on the device. when sutch a request arrives,
39     adbd does the following:
40 
41       - first, it calls socketpair() to create a pair of equivalent
42         sockets.
43 
44       - it attaches the first socket in the pair to a local socket
45         which is itself attached to the transport's remote socket:
46 
47 
48       - it sends the file descriptor of the second socket directly
49         to the JDWP process with the help of sendmsg()
50 
51 
52      JDWP thread                             @vm-debug-control
53          |                                         |
54          |                  <----------------------|
55          |           OK, try this file descriptor  |
56          |                                         |
57          |                                         |
58 
59    then, the JDWP thread uses this new socket descriptor as its
60    pass-through connection to the debugger (and receives the
61    JDWP-Handshake message, answers to it, etc...)
62 
63    this gives the following graphics:
64                     ____________________________________
65                    |                                    |
66                    |          ADB Server (host)         |
67                    |                                    |
68         Debugger <---> LocalSocket <----> RemoteSocket  |
69                    |                           ^^       |
70                    |___________________________||_______|
71                                                ||
72                                      Transport ||
73            (TCP for emulator - USB for device) ||
74                                                ||
75                     ___________________________||_______
76                    |                           ||       |
77                    |          ADBD  (device)   ||       |
78                    |                           VV       |
79          JDWP <======> LocalSocket <----> RemoteSocket  |
80                    |                                    |
81                    |____________________________________|
82 
83     due to the way adb works, this doesn't need a special socket
84     type or fancy handling of socket termination if either the debugger
85     or the JDWP process closes the connection.
86 
87     THIS IS THE SIMPLEST IMPLEMENTATION I COULD FIND, IF YOU HAPPEN
88     TO HAVE A BETTER IDEA, LET ME KNOW - Digit
89 
90 **********************************************************************/
91 
92 /** JDWP PID List Support Code
93  ** for each JDWP process, we record its pid and its connected socket
94  **/
95 
96 #define  MAX_OUT_FDS   4
97 
98 #if !ADB_HOST
99 
100 #include <sys/socket.h>
101 #include <sys/un.h>
102 
103 typedef struct JdwpProcess  JdwpProcess;
104 struct JdwpProcess {
105     JdwpProcess*  next;
106     JdwpProcess*  prev;
107     int           pid;
108     int           socket;
109     fdevent*      fde;
110 
111     char          in_buff[4];  /* input character to read PID */
112     int           in_len;      /* number from JDWP process    */
113 
114     int           out_fds[MAX_OUT_FDS]; /* output array of file descriptors */
115     int           out_count;            /* to send to the JDWP process      */
116 };
117 
118 static JdwpProcess  _jdwp_list;
119 
120 static int
jdwp_process_list(char * buffer,int bufferlen)121 jdwp_process_list( char*  buffer, int  bufferlen )
122 {
123     char*         end  = buffer + bufferlen;
124     char*         p    = buffer;
125     JdwpProcess*  proc = _jdwp_list.next;
126 
127     for ( ; proc != &_jdwp_list; proc = proc->next ) {
128         int  len;
129 
130         /* skip transient connections */
131         if (proc->pid < 0)
132             continue;
133 
134         len = snprintf(p, end-p, "%d\n", proc->pid);
135         if (p + len >= end)
136             break;
137         p += len;
138     }
139     p[0] = 0;
140     return (p - buffer);
141 }
142 
143 
144 static int
jdwp_process_list_msg(char * buffer,int bufferlen)145 jdwp_process_list_msg( char*  buffer, int  bufferlen )
146 {
147     char  head[5];
148     int   len = jdwp_process_list( buffer+4, bufferlen-4 );
149     snprintf(head, sizeof head, "%04x", len);
150     memcpy(buffer, head, 4);
151     return len + 4;
152 }
153 
154 
155 static void  jdwp_process_list_updated(void);
156 
157 static void
jdwp_process_free(JdwpProcess * proc)158 jdwp_process_free( JdwpProcess*  proc )
159 {
160     if (proc) {
161         int  n;
162 
163         proc->prev->next = proc->next;
164         proc->next->prev = proc->prev;
165 
166         if (proc->socket >= 0) {
167             adb_shutdown(proc->socket);
168             adb_close(proc->socket);
169             proc->socket = -1;
170         }
171 
172         if (proc->fde != NULL) {
173             fdevent_destroy(proc->fde);
174             proc->fde = NULL;
175         }
176         proc->pid = -1;
177 
178         for (n = 0; n < proc->out_count; n++) {
179             adb_close(proc->out_fds[n]);
180         }
181         proc->out_count = 0;
182 
183         free(proc);
184 
185         jdwp_process_list_updated();
186     }
187 }
188 
189 
190 static void  jdwp_process_event(int, unsigned, void*);  /* forward */
191 
192 
193 static JdwpProcess*
jdwp_process_alloc(int socket)194 jdwp_process_alloc( int  socket )
195 {
196     JdwpProcess*  proc = calloc(1,sizeof(*proc));
197 
198     if (proc == NULL) {
199         D("not enough memory to create new JDWP process\n");
200         return NULL;
201     }
202 
203     proc->socket = socket;
204     proc->pid    = -1;
205     proc->next   = proc;
206     proc->prev   = proc;
207 
208     proc->fde = fdevent_create( socket, jdwp_process_event, proc );
209     if (proc->fde == NULL) {
210         D("could not create fdevent for new JDWP process\n" );
211         free(proc);
212         return NULL;
213     }
214 
215     proc->fde->state |= FDE_DONT_CLOSE;
216     proc->in_len      = 0;
217     proc->out_count   = 0;
218 
219     /* append to list */
220     proc->next = &_jdwp_list;
221     proc->prev = proc->next->prev;
222 
223     proc->prev->next = proc;
224     proc->next->prev = proc;
225 
226     /* start by waiting for the PID */
227     fdevent_add(proc->fde, FDE_READ);
228 
229     return proc;
230 }
231 
232 
233 static void
jdwp_process_event(int socket,unsigned events,void * _proc)234 jdwp_process_event( int  socket, unsigned  events, void*  _proc )
235 {
236     JdwpProcess*  proc = _proc;
237 
238     if (events & FDE_READ) {
239         if (proc->pid < 0) {
240             /* read the PID as a 4-hexchar string */
241             char*  p    = proc->in_buff + proc->in_len;
242             int    size = 4 - proc->in_len;
243             char   temp[5];
244             while (size > 0) {
245                 int  len = recv( socket, p, size, 0 );
246                 if (len < 0) {
247                     if (errno == EINTR)
248                         continue;
249                     if (errno == EAGAIN)
250                         return;
251                     /* this can fail here if the JDWP process crashes very fast */
252                     D("weird unknown JDWP process failure: %s\n",
253                       strerror(errno));
254 
255                     goto CloseProcess;
256                 }
257                 if (len == 0) {  /* end of stream ? */
258                     D("weird end-of-stream from unknown JDWP process\n");
259                     goto CloseProcess;
260                 }
261                 p            += len;
262                 proc->in_len += len;
263                 size         -= len;
264             }
265             /* we have read 4 characters, now decode the pid */
266             memcpy(temp, proc->in_buff, 4);
267             temp[4] = 0;
268 
269             if (sscanf( temp, "%04x", &proc->pid ) != 1) {
270                 D("could not decode JDWP %p PID number: '%s'\n", proc, temp);
271                 goto CloseProcess;
272             }
273 
274             /* all is well, keep reading to detect connection closure */
275             D("Adding pid %d to jdwp process list\n", proc->pid);
276             jdwp_process_list_updated();
277         }
278         else
279         {
280             /* the pid was read, if we get there it's probably because the connection
281              * was closed (e.g. the JDWP process exited or crashed) */
282             char  buf[32];
283 
284             for (;;) {
285                 int  len = recv(socket, buf, sizeof(buf), 0);
286 
287                 if (len <= 0) {
288                     if (len < 0 && errno == EINTR)
289                         continue;
290                     if (len < 0 && errno == EAGAIN)
291                         return;
292                     else {
293                         D("terminating JDWP %d connection: %s\n", proc->pid,
294                           strerror(errno));
295                         break;
296                     }
297                 }
298                 else {
299                     D( "ignoring unexpected JDWP %d control socket activity (%d bytes)\n",
300                        proc->pid, len );
301                 }
302             }
303 
304         CloseProcess:
305             if (proc->pid >= 0)
306                 D( "remove pid %d to jdwp process list\n", proc->pid );
307             jdwp_process_free(proc);
308             return;
309         }
310     }
311 
312     if (events & FDE_WRITE) {
313         D("trying to write to JDWP pid controli (count=%d first=%d) %d\n",
314           proc->pid, proc->out_count, proc->out_fds[0]);
315         if (proc->out_count > 0) {
316             int  fd = proc->out_fds[0];
317             int  n, ret;
318             struct cmsghdr*  cmsg;
319             struct msghdr    msg;
320             struct iovec     iov;
321             char             dummy = '!';
322             char             buffer[sizeof(struct cmsghdr) + sizeof(int)];
323 
324             iov.iov_base       = &dummy;
325             iov.iov_len        = 1;
326             msg.msg_name       = NULL;
327             msg.msg_namelen    = 0;
328             msg.msg_iov        = &iov;
329             msg.msg_iovlen     = 1;
330             msg.msg_flags      = 0;
331             msg.msg_control    = buffer;
332             msg.msg_controllen = sizeof(buffer);
333 
334             cmsg = CMSG_FIRSTHDR(&msg);
335             cmsg->cmsg_len   = msg.msg_controllen;
336             cmsg->cmsg_level = SOL_SOCKET;
337             cmsg->cmsg_type  = SCM_RIGHTS;
338             ((int*)CMSG_DATA(cmsg))[0] = fd;
339 
340             for (;;) {
341                 ret = sendmsg(proc->socket, &msg, 0);
342                 if (ret >= 0)
343                     break;
344                 if (errno == EINTR)
345                     continue;
346                 D("sending new file descriptor to JDWP %d failed: %s\n",
347                   proc->pid, strerror(errno));
348                 goto CloseProcess;
349             }
350 
351             D("sent file descriptor %d to JDWP process %d\n",
352               fd, proc->pid);
353 
354             for (n = 1; n < proc->out_count; n++)
355                 proc->out_fds[n-1] = proc->out_fds[n];
356 
357             if (--proc->out_count == 0)
358                 fdevent_del( proc->fde, FDE_WRITE );
359         }
360     }
361 }
362 
363 
364 int
create_jdwp_connection_fd(int pid)365 create_jdwp_connection_fd(int  pid)
366 {
367     JdwpProcess*  proc = _jdwp_list.next;
368 
369     D("looking for pid %d in JDWP process list\n", pid);
370     for ( ; proc != &_jdwp_list; proc = proc->next ) {
371         if (proc->pid == pid) {
372             goto FoundIt;
373         }
374     }
375     D("search failed !!\n");
376     return -1;
377 
378 FoundIt:
379     {
380         int  fds[2];
381 
382         if (proc->out_count >= MAX_OUT_FDS) {
383             D("%s: too many pending JDWP connection for pid %d\n",
384               __FUNCTION__, pid);
385             return -1;
386         }
387 
388         if (adb_socketpair(fds) < 0) {
389             D("%s: socket pair creation failed: %s\n",
390               __FUNCTION__, strerror(errno));
391             return -1;
392         }
393 
394         proc->out_fds[ proc->out_count ] = fds[1];
395         if (++proc->out_count == 1)
396             fdevent_add( proc->fde, FDE_WRITE );
397 
398         return fds[0];
399     }
400 }
401 
402 /**  VM DEBUG CONTROL SOCKET
403  **
404  **  we do implement a custom asocket to receive the data
405  **/
406 
407 /* name of the debug control Unix socket */
408 #define  JDWP_CONTROL_NAME      "\0jdwp-control"
409 #define  JDWP_CONTROL_NAME_LEN  (sizeof(JDWP_CONTROL_NAME)-1)
410 
411 typedef struct {
412     int       listen_socket;
413     fdevent*  fde;
414 
415 } JdwpControl;
416 
417 
418 static void
419 jdwp_control_event(int  s, unsigned events, void*  user);
420 
421 
422 static int
jdwp_control_init(JdwpControl * control,const char * sockname,int socknamelen)423 jdwp_control_init( JdwpControl*  control,
424                    const char*   sockname,
425                    int           socknamelen )
426 {
427     struct sockaddr_un   addr;
428     socklen_t            addrlen;
429     int                  s;
430     int                  maxpath = sizeof(addr.sun_path);
431     int                  pathlen = socknamelen;
432 
433     if (pathlen >= maxpath) {
434         D( "vm debug control socket name too long (%d extra chars)\n",
435            pathlen+1-maxpath );
436         return -1;
437     }
438 
439     memset(&addr, 0, sizeof(addr));
440     addr.sun_family = AF_UNIX;
441     memcpy(addr.sun_path, sockname, socknamelen);
442 
443     s = socket( AF_UNIX, SOCK_STREAM, 0 );
444     if (s < 0) {
445         D( "could not create vm debug control socket. %d: %s\n",
446            errno, strerror(errno));
447         return -1;
448     }
449 
450     addrlen = (pathlen + sizeof(addr.sun_family));
451 
452     if (bind(s, (struct sockaddr*)&addr, addrlen) < 0) {
453         D( "could not bind vm debug control socket: %d: %s\n",
454            errno, strerror(errno) );
455         adb_close(s);
456         return -1;
457     }
458 
459     if ( listen(s, 4) < 0 ) {
460         D("listen failed in jdwp control socket: %d: %s\n",
461           errno, strerror(errno));
462         adb_close(s);
463         return -1;
464     }
465 
466     control->listen_socket = s;
467 
468     control->fde = fdevent_create(s, jdwp_control_event, control);
469     if (control->fde == NULL) {
470         D( "could not create fdevent for jdwp control socket\n" );
471         adb_close(s);
472         return -1;
473     }
474 
475     /* only wait for incoming connections */
476     fdevent_add(control->fde, FDE_READ);
477 
478     D("jdwp control socket started (%d)\n", control->listen_socket);
479     return 0;
480 }
481 
482 
483 static void
jdwp_control_event(int s,unsigned events,void * _control)484 jdwp_control_event( int  s, unsigned  events, void*  _control )
485 {
486     JdwpControl*  control = (JdwpControl*) _control;
487 
488     if (events & FDE_READ) {
489         struct sockaddr   addr;
490         socklen_t         addrlen = sizeof(addr);
491         int               s = -1;
492         JdwpProcess*      proc;
493 
494         do {
495             s = adb_socket_accept( control->listen_socket, &addr, &addrlen );
496             if (s < 0) {
497                 if (errno == EINTR)
498                     continue;
499                 if (errno == ECONNABORTED) {
500                     /* oops, the JDWP process died really quick */
501                     D("oops, the JDWP process died really quick\n");
502                     return;
503                 }
504                 /* the socket is probably closed ? */
505                 D( "weird accept() failed on jdwp control socket: %s\n",
506                    strerror(errno) );
507                 return;
508             }
509         }
510         while (s < 0);
511 
512         proc = jdwp_process_alloc( s );
513         if (proc == NULL)
514             return;
515     }
516 }
517 
518 
519 static JdwpControl   _jdwp_control;
520 
521 /** "jdwp" local service implementation
522  ** this simply returns the list of known JDWP process pids
523  **/
524 
525 typedef struct {
526     asocket  socket;
527     int      pass;
528 } JdwpSocket;
529 
530 static void
jdwp_socket_close(asocket * s)531 jdwp_socket_close( asocket*  s )
532 {
533     asocket*  peer = s->peer;
534 
535     remove_socket(s);
536 
537     if (peer) {
538         peer->peer = NULL;
539         peer->close(peer);
540     }
541     free(s);
542 }
543 
544 static int
jdwp_socket_enqueue(asocket * s,apacket * p)545 jdwp_socket_enqueue( asocket*  s, apacket*  p )
546 {
547     /* you can't write to this asocket */
548     put_apacket(p);
549     s->peer->close(s->peer);
550     return -1;
551 }
552 
553 
554 static void
jdwp_socket_ready(asocket * s)555 jdwp_socket_ready( asocket*  s )
556 {
557     JdwpSocket*  jdwp = (JdwpSocket*)s;
558     asocket*     peer = jdwp->socket.peer;
559 
560    /* on the first call, send the list of pids,
561     * on the second one, close the connection
562     */
563     if (jdwp->pass == 0) {
564         apacket*  p = get_apacket();
565         p->len = jdwp_process_list((char*)p->data, MAX_PAYLOAD);
566         peer->enqueue(peer, p);
567         jdwp->pass = 1;
568     }
569     else {
570         peer->close(peer);
571     }
572 }
573 
574 asocket*
create_jdwp_service_socket(void)575 create_jdwp_service_socket( void )
576 {
577     JdwpSocket*  s = calloc(sizeof(*s),1);
578 
579     if (s == NULL)
580         return NULL;
581 
582     install_local_socket(&s->socket);
583 
584     s->socket.ready   = jdwp_socket_ready;
585     s->socket.enqueue = jdwp_socket_enqueue;
586     s->socket.close   = jdwp_socket_close;
587     s->pass           = 0;
588 
589     return &s->socket;
590 }
591 
592 /** "track-jdwp" local service implementation
593  ** this periodically sends the list of known JDWP process pids
594  ** to the client...
595  **/
596 
597 typedef struct JdwpTracker  JdwpTracker;
598 
599 struct JdwpTracker {
600     asocket       socket;
601     JdwpTracker*  next;
602     JdwpTracker*  prev;
603     int           need_update;
604 };
605 
606 static JdwpTracker   _jdwp_trackers_list;
607 
608 
609 static void
jdwp_process_list_updated(void)610 jdwp_process_list_updated(void)
611 {
612     char             buffer[1024];
613     int              len;
614     JdwpTracker*  t = _jdwp_trackers_list.next;
615 
616     len = jdwp_process_list_msg(buffer, sizeof(buffer));
617 
618     for ( ; t != &_jdwp_trackers_list; t = t->next ) {
619         apacket*  p    = get_apacket();
620         asocket*  peer = t->socket.peer;
621         memcpy(p->data, buffer, len);
622         p->len = len;
623         peer->enqueue( peer, p );
624     }
625 }
626 
627 static void
jdwp_tracker_close(asocket * s)628 jdwp_tracker_close( asocket*  s )
629 {
630     JdwpTracker*  tracker = (JdwpTracker*) s;
631     asocket*      peer    = s->peer;
632 
633     if (peer) {
634         peer->peer = NULL;
635         peer->close(peer);
636     }
637 
638     remove_socket(s);
639 
640     tracker->prev->next = tracker->next;
641     tracker->next->prev = tracker->prev;
642 
643     free(s);
644 }
645 
646 static void
jdwp_tracker_ready(asocket * s)647 jdwp_tracker_ready( asocket*  s )
648 {
649     JdwpTracker*  t = (JdwpTracker*) s;
650 
651     if (t->need_update) {
652         apacket*  p = get_apacket();
653         t->need_update = 0;
654         p->len = jdwp_process_list_msg((char*)p->data, sizeof(p->data));
655         s->peer->enqueue(s->peer, p);
656     }
657 }
658 
659 static int
jdwp_tracker_enqueue(asocket * s,apacket * p)660 jdwp_tracker_enqueue( asocket*  s, apacket*  p )
661 {
662     /* you can't write to this socket */
663     put_apacket(p);
664     s->peer->close(s->peer);
665     return -1;
666 }
667 
668 
669 asocket*
create_jdwp_tracker_service_socket(void)670 create_jdwp_tracker_service_socket( void )
671 {
672     JdwpTracker*  t = calloc(sizeof(*t),1);
673 
674     if (t == NULL)
675         return NULL;
676 
677     t->next = &_jdwp_trackers_list;
678     t->prev = t->next->prev;
679 
680     t->next->prev = t;
681     t->prev->next = t;
682 
683     install_local_socket(&t->socket);
684 
685     t->socket.ready   = jdwp_tracker_ready;
686     t->socket.enqueue = jdwp_tracker_enqueue;
687     t->socket.close   = jdwp_tracker_close;
688     t->need_update    = 1;
689 
690     return &t->socket;
691 }
692 
693 
694 int
init_jdwp(void)695 init_jdwp(void)
696 {
697     _jdwp_list.next = &_jdwp_list;
698     _jdwp_list.prev = &_jdwp_list;
699 
700     _jdwp_trackers_list.next = &_jdwp_trackers_list;
701     _jdwp_trackers_list.prev = &_jdwp_trackers_list;
702 
703     return jdwp_control_init( &_jdwp_control,
704                               JDWP_CONTROL_NAME,
705                               JDWP_CONTROL_NAME_LEN );
706 }
707 
708 #endif /* !ADB_HOST */
709 
710