18ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis/* implement the "debug-ports" and "track-debug-ports" device services */ 28ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include "sysdeps.h" 38ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#define TRACE_TAG TRACE_JDWP 48ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include "adb.h" 58ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <errno.h> 68ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <stdio.h> 78ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <string.h> 88ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis#include <unistd.h> 98ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis 108ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis/* here's how these things work. 118ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis 128ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis when adbd starts, it creates a unix server socket 138ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis named @vm-debug-control (@ is a shortcut for "first byte is zero" 148ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis to use the private namespace instead of the file system) 158ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis 168ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis when a new JDWP daemon thread starts in a new VM process, it creates 178ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis a connection to @vm-debug-control to announce its availability. 188ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis 198ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis 208ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis JDWP thread @vm-debug-control 218ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis | | 228ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis |-------------------------------> | 238ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis | hello I'm in process <pid> | 248ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis | | 258ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis | | 268ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis 278ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis the connection is kept alive. it will be closed automatically if 282adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden the JDWP process terminates (this allows adbd to detect dead 298ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis processes). 308ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis 318ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis adbd thus maintains a list of "active" JDWP processes. it can send 328ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis its content to clients through the "device:debug-ports" service, 338ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis or even updates through the "device:track-debug-ports" service. 348ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis 358ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis when a debugger wants to connect, it simply runs the command 368ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis equivalent to "adb forward tcp:<hostport> jdwp:<pid>" 378ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis 388ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis "jdwp:<pid>" is a new forward destination format used to target 39eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian a given JDWP process on the device. when sutch a request arrives, 408072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian adbd does the following: 41fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis 42fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis - first, it calls socketpair() to create a pair of equivalent 438ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis sockets. 448ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis 458ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis - it attaches the first socket in the pair to a local socket 462adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden which is itself attached to the transport's remote socket: 478ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis 488ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis 492adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden - it sends the file descriptor of the second socket directly 502adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden to the JDWP process with the help of sendmsg() 518ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis 528ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis 538ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis JDWP thread @vm-debug-control 547b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis | | 558ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis | <----------------------| 562adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden | OK, try this file descriptor | 578ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis | | 588a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis | | 598a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis 608a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis then, the JDWP thread uses this new socket descriptor as its 618a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis pass-through connection to the debugger (and receives the 628ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis JDWP-Handshake message, answers to it, etc...) 638ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis 647b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis this gives the following graphics: 657b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis ____________________________________ 668ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis | | 678a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis | ADB Server (host) | 687b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis | | 698ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis Debugger <---> LocalSocket <----> RemoteSocket | 708ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis | ^^ | 718ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis |___________________________||_______| 728ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis || 738ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis Transport || 742adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden (TCP for emulator - USB for device) || 758ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis || 768a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis ___________________________||_______ 778a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis | || | 788a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis | ADBD (device) || | 798a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis | VV | 808a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis JDWP <======> LocalSocket <----> RemoteSocket | 818a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis | | 828ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis |____________________________________| 838ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis 844c00cc11141da7d159eb2323b186ed344115c0f1Jesse Hall due to the way adb works, this doesn't need a special socket 85f78575400977f644cf0b12beb2fa5fc278b6ed4cJesse Hall type or fancy handling of socket termination if either the debugger 868ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis or the JDWP process closes the connection. 872adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden 88c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian THIS IS THE SIMPLEST IMPLEMENTATION I COULD FIND, IF YOU HAPPEN 89c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian TO HAVE A BETTER IDEA, LET ME KNOW - Digit 90c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian 91c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian**********************************************************************/ 928a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis 938a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis/** JDWP PID List Support Code 948a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis ** for each JDWP process, we record its pid and its connected socket 958a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis **/ 968ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis 971df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis#define MAX_OUT_FDS 4 981df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis 991df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis#if !ADB_HOST 1001df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis 1011df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis#include <sys/socket.h> 1024c00cc11141da7d159eb2323b186ed344115c0f1Jesse Hall#include <sys/un.h> 1034c00cc11141da7d159eb2323b186ed344115c0f1Jesse Hall 104f78575400977f644cf0b12beb2fa5fc278b6ed4cJesse Halltypedef struct JdwpProcess JdwpProcess; 1058a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennisstruct JdwpProcess { 1068ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis JdwpProcess* next; 1078ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis JdwpProcess* prev; 1088ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis int pid; 109f0bc2f1d8d37977bd3aef3d3326a70e9e69d4246Mathias Agopian int socket; 110f0bc2f1d8d37977bd3aef3d3326a70e9e69d4246Mathias Agopian fdevent* fde; 1118ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis 1122adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden char in_buff[4]; /* input character to read PID */ 1138ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis int in_len; /* number from JDWP process */ 114c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall 1158a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis int out_fds[MAX_OUT_FDS]; /* output array of file descriptors */ 1168a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis int out_count; /* to send to the JDWP process */ 1178a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis}; 1188a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis 119f0bc2f1d8d37977bd3aef3d3326a70e9e69d4246Mathias Agopianstatic JdwpProcess _jdwp_list; 1208a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis 1218ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennisstatic int 1228ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennisjdwp_process_list( char* buffer, int bufferlen ) 1238ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis{ 1244c00cc11141da7d159eb2323b186ed344115c0f1Jesse Hall char* end = buffer + bufferlen; 1258ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis char* p = buffer; 1262adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden JdwpProcess* proc = _jdwp_list.next; 1278ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis 1281df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis for ( ; proc != &_jdwp_list; proc = proc->next ) { 1298ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis int len; 1308ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis 1318ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis /* skip transient connections */ 132eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian if (proc->pid < 0) 133eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian continue; 1342adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden 135eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian len = snprintf(p, end-p, "%d\n", proc->pid); 1368a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis if (p + len >= end) 1378a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis break; 1388a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis p += len; 1398a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis } 140eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian p[0] = 0; 1418a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis return (p - buffer); 142eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian} 143eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian 144eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian 1458072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopianstatic int 1468072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopianjdwp_process_list_msg( char* buffer, int bufferlen ) 1472adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden{ 1488072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian char head[5]; 1498a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis int len = jdwp_process_list( buffer+4, bufferlen-4 ); 1508a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis snprintf(head, sizeof head, "%04x", len); 1518a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis memcpy(buffer, head, 4); 1528a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis return len + 4; 1538a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis} 1548072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian 1558072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian 1568072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopianstatic void jdwp_process_list_updated(void); 15724202f5676c32edeef6544cf36e06b9fc970dbdeMathias Agopian 158fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennisstatic void 1592adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFaddenjdwp_process_free( JdwpProcess* proc ) 160fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis{ 1618a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis if (proc) { 1628a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis int n; 1638a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis 1648a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis proc->prev->next = proc->next; 16524202f5676c32edeef6544cf36e06b9fc970dbdeMathias Agopian proc->next->prev = proc->prev; 1668a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis 167fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis if (proc->socket >= 0) { 168fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis adb_shutdown(proc->socket); 1698072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian adb_close(proc->socket); 170fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis proc->socket = -1; 171fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis } 1722adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden 173fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis if (proc->fde != NULL) { 1748a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis fdevent_destroy(proc->fde); 1758a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis proc->fde = NULL; 1768a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis } 1778a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis proc->pid = -1; 1788a29ff2a356816694c695db70460f93c7fb4ae6fJamie Gennis 179fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis for (n = 0; n < proc->out_count; n++) { 180fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis adb_close(proc->out_fds[n]); 1818ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis } 1828ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis proc->out_count = 0; 183466a192d2088f9238d34597d1aa28da41367c1caAndy McFadden 1848ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis free(proc); 1858ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis 1868ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis jdwp_process_list_updated(); 1872adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden } 1888ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis} 1898ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis 1908ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis 1918ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennisstatic void jdwp_process_event(int, unsigned, void*); /* forward */ 1922adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden 1938ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis 1947b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennisstatic JdwpProcess* 1957b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennisjdwp_process_alloc( int socket ) 1968ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis{ 1978ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis JdwpProcess* proc = calloc(1,sizeof(*proc)); 1988ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis 1998ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis if (proc == NULL) { 2007b305fffc39d0fe0926e7fd2d7f6a524fbce62b7Jamie Gennis D("not enough memory to create new JDWP process\n"); 2018ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis return NULL; 2028ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis } 2038ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis 2042adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden proc->socket = socket; 2058ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis proc->pid = -1; 2068ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis proc->next = proc; 2078ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis proc->prev = proc; 2088ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis 2098ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis proc->fde = fdevent_create( socket, jdwp_process_event, proc ); 2108ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis if (proc->fde == NULL) { 2112adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden D("could not create fdevent for new JDWP process\n" ); 212c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian free(proc); 213c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian return NULL; 214c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian } 215c04f153353cdb0d291297d10452239f791d3fd2bMathias Agopian 2168ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis proc->fde->state |= FDE_DONT_CLOSE; 217f78575400977f644cf0b12beb2fa5fc278b6ed4cJesse Hall proc->in_len = 0; 2184c00cc11141da7d159eb2323b186ed344115c0f1Jesse Hall proc->out_count = 0; 2198ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis 2201df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis /* append to list */ 2211df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis proc->next = &_jdwp_list; 222f78575400977f644cf0b12beb2fa5fc278b6ed4cJesse Hall proc->prev = proc->next->prev; 223f78575400977f644cf0b12beb2fa5fc278b6ed4cJesse Hall 2248ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis proc->prev->next = proc; 2258ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis proc->next->prev = proc; 2268ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis 2278ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis /* start by waiting for the PID */ 2282adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden fdevent_add(proc->fde, FDE_READ); 2298ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis 230c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall return proc; 231f0bc2f1d8d37977bd3aef3d3326a70e9e69d4246Mathias Agopian} 232f0bc2f1d8d37977bd3aef3d3326a70e9e69d4246Mathias Agopian 233f0bc2f1d8d37977bd3aef3d3326a70e9e69d4246Mathias Agopian 234c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hallstatic void 2358ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennisjdwp_process_event( int socket, unsigned events, void* _proc ) 2368ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis{ 2378ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis JdwpProcess* proc = _proc; 2388ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis 2392adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden if (events & FDE_READ) { 2408ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis if (proc->pid < 0) { 2411df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis /* read the PID as a 4-hexchar string */ 2421df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis char* p = proc->in_buff + proc->in_len; 243c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall int size = 4 - proc->in_len; 2448ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis char temp[5]; 2458ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis while (size > 0) { 246eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian int len = recv( socket, p, size, 0 ); 2472adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden if (len < 0) { 248eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian if (errno == EINTR) 249eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian continue; 250eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian if (errno == EAGAIN) 251eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian return; 252eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian /* this can fail here if the JDWP process crashes very fast */ 253eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian D("weird unknown JDWP process failure: %s\n", 254eafabcdc1639fb96062d9e3c39b0ae27b0238ae1Mathias Agopian strerror(errno)); 2558072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian 2562adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden goto CloseProcess; 2578072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian } 2588072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian if (len == 0) { /* end of stream ? */ 2598072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian D("weird end-of-stream from unknown JDWP process\n"); 2608072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian goto CloseProcess; 2618072711307aa98ee5ee6f7369860ae38c3e19656Mathias Agopian } 262fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis p += len; 2632adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden proc->in_len += len; 264fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis size -= len; 26524202f5676c32edeef6544cf36e06b9fc970dbdeMathias Agopian } 26624202f5676c32edeef6544cf36e06b9fc970dbdeMathias Agopian /* we have read 4 characters, now decode the pid */ 26724202f5676c32edeef6544cf36e06b9fc970dbdeMathias Agopian memcpy(temp, proc->in_buff, 4); 26824202f5676c32edeef6544cf36e06b9fc970dbdeMathias Agopian temp[4] = 0; 269fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis 270fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis if (sscanf( temp, "%04x", &proc->pid ) != 1) { 271fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis D("could not decode JDWP %p PID number: '%s'\n", proc, temp); 272fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis goto CloseProcess; 2732adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden } 274fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis 2752773004a83624ed41cf3f94f2b11878cd8521812Mathias Agopian /* all is well, keep reading to detect connection closure */ 276fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis D("Adding pid %d to jdwp process list\n", proc->pid); 277fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis jdwp_process_list_updated(); 278fe0a87b54654a1392650e7f1862df473287d8332Jamie Gennis } 2798ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis else 2808ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis { 2818ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis /* the pid was read, if we get there it's probably because the connection 2828ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis * was closed (e.g. the JDWP process exited or crashed) */ 2838ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis char buf[32]; 2848ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis 2852adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden for (;;) { 286c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall int len = recv(socket, buf, sizeof(buf), 0); 287c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall 288c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall if (len <= 0) { 2892adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden if (len < 0 && errno == EINTR) 290c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall continue; 291c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall if (len < 0 && errno == EAGAIN) 292c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall return; 293c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall else { 294c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall D("terminating JDWP %d connection: %s\n", proc->pid, 2951df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis strerror(errno)); 296c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall break; 297c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall } 2982adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden } 299c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall else { 3001df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis D( "ignoring unexpected JDWP %d control socket activity (%d bytes)\n", 301c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall proc->pid, len ); 302c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall } 3032adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden } 304c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall 305c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall CloseProcess: 306c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall if (proc->pid >= 0) 307c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall D( "remove pid %d to jdwp process list\n", proc->pid ); 308c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall jdwp_process_free(proc); 309c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall return; 310c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall } 311c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall } 3121df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis 313c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall if (events & FDE_WRITE) { 314c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall D("trying to write to JDWP pid controli (count=%d first=%d) %d\n", 315c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall proc->pid, proc->out_count, proc->out_fds[0]); 3162adaf04fab35cf47c824d74d901b54094e01ccd3Andy McFadden if (proc->out_count > 0) { 317c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall int fd = proc->out_fds[0]; 318c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall int n, ret; 319c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall struct cmsghdr* cmsg; 320c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall struct msghdr msg; 321c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall struct iovec iov; 322c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall char dummy = '!'; 323c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall char buffer[sizeof(struct cmsghdr) + sizeof(int)]; 324c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall int flags; 3251df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis 3261df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis iov.iov_base = &dummy; 327c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall iov.iov_len = 1; 328c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall msg.msg_name = NULL; 329c777b0b3b9b0ea5d8e378fccde6935765e28e329Jesse Hall msg.msg_namelen = 0; 3308ba32fade11abb73f3fd47ea0953c9528eb5b91fJamie Gennis 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