1 /* Remote utility routines for the remote server for GDB.
2    Copyright (C) 2008
3    Free Software Foundation, Inc.
4 
5    This file is part of GDB.
6 
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program; If not, see <http://www.gnu.org/licenses/>.  */
19 /*
20  * Copyright (C) 2009, Mukesh Rathor, Oracle Corp.  All rights reserved.
21  *
22  * This program is free software; you can redistribute it and/or
23  * modify it under the terms of the GNU General Public
24  * License v2 as published by the Free Software Foundation.
25  *
26  * This program is distributed in the hope that it will be useful,
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
29  * General Public License for more details.
30  *
31  * You should have received a copy of the GNU General Public
32  * License along with this program; If not, see <http://www.gnu.org/licenses/>.
33  */
34 
35 /* This module handles communication with remote gdb.  courtesy
36  * of gdbserver remote-utils.c */
37 
38 
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <sys/ioctl.h>
43 #include <sys/file.h>
44 #include <netinet/in.h>
45 #include <sys/socket.h>
46 #include <netdb.h>
47 #include <netinet/tcp.h>
48 #include <arpa/inet.h>
49 #include <unistd.h>
50 #include <fcntl.h>
51 #include <signal.h>
52 #include <errno.h>
53 
54 #include "gx.h"
55 
56 
57 extern int gx_remote_dbg;
58 
59 static int remote_fd;
60 
61 
62 /* Returns: 0 success. -1 failure */
63 static int
do_tcp(char * port_str)64 do_tcp(char *port_str)
65 {
66     int port;
67     struct sockaddr_in sockaddr;
68     socklen_t tmp;
69     int sock_fd;
70 
71     port = atoi(port_str);
72 
73     sock_fd = socket(PF_INET, SOCK_STREAM, 0);
74     if (sock_fd < 0) {
75         gxprt("ERROR: failed socket open. errno:%d\n", errno);
76         return -1;
77     }
78 
79     /* Allow rapid reuse of this port. */
80     tmp = 1;
81     setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&tmp,sizeof(tmp));
82 
83     memset(&sockaddr, 0, sizeof(sockaddr));
84     sockaddr.sin_family = PF_INET;
85     sockaddr.sin_port = htons (port);
86     sockaddr.sin_addr.s_addr = INADDR_ANY;
87 
88     if (bind(sock_fd, (struct sockaddr *) &sockaddr, sizeof (sockaddr))
89         || listen (sock_fd, 1)) {
90         gxprt("ERROR: can't bind address. errno:%d\n", errno);
91         close(sock_fd);
92         return -1;
93     }
94     printf("Listening on port %d\n", port);
95 
96     tmp = sizeof(sockaddr);
97     remote_fd = accept(sock_fd, (struct sockaddr *) &sockaddr, &tmp);
98     if (remote_fd == -1) {
99         gxprt("ERROR: accept failed. errno:%d\n", errno);
100         close(sock_fd);
101         return -1;
102     }
103 
104     /* Enable TCP keep alive process. */
105     tmp = 1;
106     setsockopt(sock_fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&tmp,sizeof(tmp));
107 
108     /* Tell TCP not to delay small packets.  This greatly speeds up
109      * interactive response. */
110     tmp = 1;
111     setsockopt(remote_fd, IPPROTO_TCP, TCP_NODELAY,
112                (char *)&tmp, sizeof(tmp));
113 
114     close(sock_fd);           /* No longer need this */
115 
116     signal(SIGPIPE, SIG_IGN); /* If we don't do this, then gdbserver simply
117                                * exits when the remote side dies.  */
118 
119     /* Convert IP address to string */
120     printf("Remote debugging from host %s\n", inet_ntoa(sockaddr.sin_addr));
121 
122     return 0;
123 }
124 
125 /*
126  * Open a connection for remote gdb on the given port number
127  * Returns: 0 for success. -1 for failure
128  */
129 int
gx_remote_open(char * portnum_str)130 gx_remote_open(char *portnum_str)
131 {
132     int save_fcntl_flags;
133 
134     if (do_tcp(portnum_str) == -1) {
135         close(remote_fd);
136         return -1;
137     }
138 
139 #if defined(F_SETFL) && defined (FASYNC)
140     save_fcntl_flags = fcntl(remote_fd, F_GETFL, 0);
141     fcntl(remote_fd, F_SETFL, save_fcntl_flags | FASYNC);
142 #if defined (F_SETOWN)
143     fcntl (remote_fd, F_SETOWN, getpid ());
144 #endif
145 #endif
146     return 0;
147 }
148 
149 void
gx_remote_close(void)150 gx_remote_close(void)
151 {
152     close(remote_fd);
153 }
154 
155 
156 /* Returns next char from remote gdb.  -1 if error.  */
157 static int
readchar(void)158 readchar(void)
159 {
160     static char buf[BUFSIZ];
161     static int bufcnt = 0;
162     static char *bufp;
163     uint64_t ll;
164 
165     if (bufcnt-- > 0)
166         return *bufp++ & 0x7f;
167 
168     bufcnt = read(remote_fd, buf, sizeof (buf));
169     ll = *(uint64_t *)buf;
170     if (bufcnt <= 0) {
171         if (bufcnt == 0)
172             gxprt("readchar: Got EOF\n");
173         else
174             perror ("readchar");
175         return -1;
176     }
177     bufp = buf;
178     bufcnt--;
179     return *bufp++ & 0x7f;
180 }
181 
182 /* Read a packet from the remote machine, with error checking,
183  * and store it in buf.
184  * Returns:  length of packet, or negative int if error.
185  */
186 int
gx_getpkt(char * buf)187 gx_getpkt (char *buf)
188 {
189     char *bp;
190     unsigned char csum, c1, c2;
191     int c;
192 
193     while (1) {
194         csum = 0;
195 
196         while (1) {
197             c = readchar();
198             if (c == '$')
199                 break;
200 
201             if (gx_remote_dbg)
202                 gxprt("[getpkt: discarding char '%c']\n", c);
203             if (c < 0)
204                 return -1;
205         }
206 
207         bp = buf;
208         while (1) {
209             c = readchar ();
210             if (c < 0)
211                 return -1;
212             if (c == '#')
213                 break;
214             *bp++ = c;
215             csum += c;
216         }
217         *bp = 0;
218 
219         c1 = gx_fromhex(readchar());
220         c2 = gx_fromhex(readchar());
221 
222         if (csum == (c1 << 4) + c2)
223             break;
224 
225         gxprt("Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n",
226               (c1 << 4) + c2, csum, buf);
227         if (write(remote_fd, "-", 1) != 1) {
228             perror("write");
229             return -1;
230         }
231     }
232     if (gx_remote_dbg) {
233         gxprt("getpkt (\"%s\");  [sending ack] \n", buf);
234     }
235 
236     if (write(remote_fd, "+", 1) != 1) {
237         perror("write");
238         return -1;
239     }
240 
241     if (gx_remote_dbg) {
242         gxprt("[sent ack]\n");
243     }
244     return bp - buf;
245 }
246 
247 void
gx_reply_ok(char * buf)248 gx_reply_ok(char *buf)
249 {
250     buf[0] = 'O';
251     buf[1] = 'K';
252     buf[2] = '\0';
253 }
254 
255 /* ENN error */
256 void
gx_reply_error(char * buf)257 gx_reply_error(char *buf)
258 {
259     buf[0] = 'E';
260     buf[1] = '0';
261     buf[2] = '1';
262     buf[3] = '\0';
263 }
264 
265 /*
266  * Send a packet to the remote machine, with error checking.
267  * The data of the packet is in buf.
268  * Returns: >= 0 on success, -1 otherwise.
269  */
270 int
gx_putpkt(char * buf)271 gx_putpkt (char *buf)
272 {
273     int i;
274     unsigned char csum = 0;
275     char *buf2;
276     char buf3[1];
277     int cnt = strlen (buf);
278     char *p;
279 
280     buf2 = malloc(8192);
281 
282     /* Copy the packet into buffer buf2, encapsulating it
283      * and giving it a checksum.  */
284 
285     p = buf2;
286     *p++ = '$';
287 
288     for (i = 0; i < cnt; i++) {
289         csum += buf[i];
290         *p++ = buf[i];
291     }
292     *p++ = '#';
293     *p++ = gx_tohex((csum >> 4) & 0xf);
294     *p++ = gx_tohex(csum & 0xf);
295 
296     *p = '\0';
297 
298     /* Send it over and over until we get a positive ack.  */
299 
300     do {
301         int cc;
302 
303         if (write(remote_fd, buf2, p - buf2) != p - buf2) {
304             perror("putpkt(write)");
305             free(buf2);
306             return -1;
307         }
308         if (gx_remote_dbg)
309             gxprt("putpkt (\"%s\"); [looking for ack]\n", buf2);
310 
311         cc = read(remote_fd, buf3, 1);
312         if (gx_remote_dbg)
313             gxprt("[received '%c' (0x%x)]\n", buf3[0], buf3[0]);
314 
315         if (cc <= 0) {
316             if (cc == 0)
317                 gxprt("putpkt(read): Got EOF\n");
318             else
319                 gxprt("putpkt(read)");
320             free(buf2);
321             return -1;
322         }
323         /* Check for an input interrupt while we're here.  */
324         if (buf3[0] == '\003')
325             gxprt("WARN: need to send SIGINT in putpkt\n");
326 
327     } while (buf3[0] != '+');
328 
329     free(buf2);
330     return 1;                       /* Success! */
331 }
332 
333