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