~ubuntu-branches/ubuntu/utopic/xen/utopic

« back to all changes in this revision

Viewing changes to tools/debugger/gdbsx/gx/gx_comm.c

  • Committer: Bazaar Package Importer
  • Author(s): Bastian Blank
  • Date: 2010-05-06 15:47:38 UTC
  • mto: (1.3.1) (15.1.1 sid) (4.1.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20100506154738-agoz0rlafrh1fnq7
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

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