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