]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/cris/rvdummy.c
Update years in copyright notice for the GDB files.
[thirdparty/binutils-gdb.git] / sim / cris / rvdummy.c
CommitLineData
aad3b3cb
HPN
1/* Test-driver for the remote-virtual-component simulator framework
2 for GDB, the GNU Debugger.
3
8acc9f48 4 Copyright 2006-2013 Free Software Foundation, Inc.
aad3b3cb
HPN
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
4744ac1b 10 the Free Software Foundation; either version 3 of the License, or
aad3b3cb
HPN
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
4744ac1b 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
aad3b3cb
HPN
20
21/* Avoid any problems whatsoever building this program if we're not
22 also building hardware support. */
23
24#if !WITH_HW
25int
26main (int argc, char *argv[])
27{
28 return 2;
29}
30#else
31
32#ifdef HAVE_CONFIG_H
33#include "cconfig.h"
34#include "tconfig.h"
35#endif
36
37#include "getopt.h"
38#include "libiberty.h"
39
40#define _GNU_SOURCE
41#include <stdio.h>
42
43#ifdef HAVE_UNISTD_H
44#include <unistd.h>
45#endif
46#ifdef HAVE_STDLIB_H
47#include <stdlib.h>
48#endif
49#ifdef HAVE_STRING_H
50#include <string.h>
51#endif
52
53#ifdef HAVE_SYS_TYPES_H
54#include <sys/types.h>
55#endif
56
57#ifdef HAVE_SYS_TIME_H
58#include <sys/time.h>
59#endif
60
61#ifdef HAVE_SYS_SELECT_H
62#include <sys/select.h>
63#endif
64
65#ifdef HAVE_ERRNO_H
66#include <errno.h>
67#endif
68
69/* Not guarded in dv-sockser.c, so why here. */
70#include <netinet/in.h>
71#include <arpa/inet.h>
72#include <netdb.h>
73#include <sys/socket.h>
74
75enum rv_command {
76 RV_READ_CMD = 0,
77 RV_WRITE_CMD = 1,
78 RV_IRQ_CMD = 2,
79 RV_MEM_RD_CMD = 3,
80 RV_MEM_WR_CMD = 4,
81 RV_MBOX_HANDLE_CMD = 5,
82 RV_MBOX_PUT_CMD = 6,
83 RV_WATCHDOG_CMD = 7
84};
85
86enum opts { OPT_PORT = 1, OPT_TIMEOUT, OPT_VERBOSE };
87
88struct option longopts[] =
89 {
90 {"port", required_argument, NULL, OPT_PORT},
91 {"timeout", required_argument, NULL, OPT_TIMEOUT},
92 {"verbose", no_argument, NULL, OPT_VERBOSE},
93 {NULL, 0, NULL, 0}
94 };
95
96int port = 10000;
97time_t timeout = 30000;
98char *progname = "(unknown)";
99int verbose = 0;
100
101/* Required forward-declarations. */
102static void handle_input_file (int, char *);
103
104/* Set up a "server" listening to the port in PORT for a raw TCP
105 connection. Return a file descriptor for the connection or -1 on
106 error. */
107
108int setupsocket (void)
109{
110 int s;
111 socklen_t len;
112 int reuse = 1;
113 struct sockaddr_in sa_in;
114 struct sockaddr_in from;
115
116 len = sizeof (from);
117 memset (&from, 0, len);
118 memset (&sa_in, 0, sizeof (sa_in));
119
120 s = socket (AF_INET, SOCK_STREAM, 0);
363a6e9f 121 if (s == -1)
aad3b3cb
HPN
122 return -1;
123
124 if (setsockopt (s, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof reuse) != 0)
125 return -1;
126
127 sa_in.sin_port = htons (port);
128 sa_in.sin_family = AF_INET;
129
130 if (bind (s, (struct sockaddr *) & sa_in, sizeof sa_in) < 0)
131 return -1;
132
133 if (listen (s, 1) < 0)
134 return -1;
135
136 return accept (s, (struct sockaddr *) &from, &len);
137}
138
139/* Basic host-to-little-endian 32-bit value. Could use the BFD
140 machinery, but let's avoid it for this only dependency. */
141
142static void
143h2le32 (unsigned char *dest, unsigned int val)
144{
145 dest[0] = val & 255;
146 dest[1] = (val >> 8) & 255;
147 dest[2] = (val >> 16) & 255;
148 dest[3] = (val >> 24) & 255;
149}
150
151/* Send a blob of data. */
152
153static void
154send_output (int fd, unsigned char *buf, int nbytes)
155{
156 while (nbytes > 0)
157 {
158 ssize_t written = write (fd, buf, nbytes);
159 if (written < 0)
160 {
161 fprintf (stderr, "%s: write to socket failed: %s\n",
162 progname, strerror (errno));
163 exit (2);
164 }
165 nbytes -= written;
166 }
167}
168
169/* Receive a blob of data, NBYTES large. Compare to the first NCOMP
170 bytes of BUF; if not a match, write error message to stderr and
171 exit (2). Else put it in buf. */
172
173static void
174expect_input (int fd, unsigned char *buf, int nbytes, int ncomp)
175{
176 unsigned char byt;
177 int i;
178
179 for (i = 0; i < nbytes; i++)
180 {
181 int r;
182
183 do
184 {
185 errno = 0;
186 r = read (fd, &byt, 1);
187 }
188 while (r <= 0 && (r == 0 || errno == EAGAIN));
189
190 if (r != 1)
191 {
192 fprintf (stderr, "%s: read from socket failed: %s",
193 progname, strerror (errno));
194 exit (2);
195 }
196
197 if (i < ncomp && byt != buf[i])
198 {
199 int j;
200 fprintf (stderr, "%s: unexpected input,\n ", progname);
201 if (i == 0)
202 fprintf (stderr, "nothing,");
203 else
204 for (j = 0; j < i; j++)
205 fprintf (stderr, "%02x", buf[j]);
206 fprintf (stderr, "\nthen %02x instead of %02x\n", byt, buf[i]);
207 exit (2);
208 }
209 else
210 buf[i] = byt;
211 }
212}
213
214/* Handle everything about a nil-terminated line of input.
215 Call exit (2) on error with error text on stderr. */
216
217static void
218handle_input (int fd, char *buf, char *fname, int lineno)
219{
220 int nbytes = 0;
221 int n = -1;
222 char *s = buf + 2;
223 unsigned int data;
224 static unsigned char bytes[1024];
225 int i;
226
227 memset (bytes, 0, sizeof bytes);
228 lineno++;
229
230 if (buf[1] != ',')
231 goto syntax_error;
232
233 switch (buf[0])
234 {
235 /* Comment characters and empty lines. */
236 case 0: case '!': case '#':
237 break;
238
239 /* Include another file. */
240 case '@':
241 handle_input_file (fd, s);
242 break;
243
244 /* Raw input (to be expected). */
245 case 'i':
246 do
247 {
248 n = -1;
249 sscanf (s, "%02x%n", &data, &n);
250 s += n;
251 if (n > 0)
252 bytes[nbytes++] = data;
253 }
254 while (n > 0);
255 expect_input (fd, bytes, nbytes, nbytes);
256 if (verbose)
257 {
258 printf ("i,");
259 for (i = 0; i < nbytes; i++)
260 printf ("%02x", bytes[i]);
261 printf ("\n");
262 }
263 break;
264
265 /* Raw output (to be written). */
266 case 'o':
267 do
268 {
269 n = -1;
270 sscanf (s, "%02x%n", &data, &n);
271 if (n > 0)
272 {
273 s += n;
274 bytes[nbytes++] = data;
275 }
276 }
277 while (n > 0);
278 if (*s != 0)
279 goto syntax_error;
280 send_output (fd, bytes, nbytes);
281 if (verbose)
282 {
283 printf ("o,");
284 for (i = 0; i < nbytes; i++)
285 printf ("%02x", bytes[i]);
286 printf ("\n");
287 }
288 break;
289
290 /* Read a register. */
291 case 'r':
292 {
293 unsigned int addr;
294 sscanf (s, "%x,%x%n", &addr, &data, &n);
295 if (n < 0 || s[n] != 0)
296 goto syntax_error;
297 bytes[0] = 11;
298 bytes[1] = 0;
299 bytes[2] = RV_READ_CMD;
300 h2le32 (bytes + 3, addr);
301 expect_input (fd, bytes, 11, 7);
302 h2le32 (bytes + 7, data);
303 send_output (fd, bytes, 11);
304 if (verbose)
305 printf ("r,%x,%x\n", addr, data);
306 }
307 break;
308
309 /* Write a register. */
310 case 'w':
311 {
312 unsigned int addr;
313 sscanf (s, "%x,%x%n", &addr, &data, &n);
314 if (n < 0 || s[n] != 0)
315 goto syntax_error;
316 bytes[0] = 11;
317 bytes[1] = 0;
318 bytes[2] = RV_WRITE_CMD;
319 h2le32 (bytes + 3, addr);
320 h2le32 (bytes + 7, data);
321 expect_input (fd, bytes, 11, 11);
322 send_output (fd, bytes, 11);
323 if (verbose)
324 printf ("w,%x,%x\n", addr, data);
325 }
326 break;
327
328 /* Wait for some milliseconds. */
329 case 't':
330 {
331 int del = 0;
332 struct timeval to;
333 sscanf (s, "%d%n", &del, &n);
334 if (n < 0 || s[n] != 0 || del == 0)
335 goto syntax_error;
336
337 to.tv_sec = del / 1000;
338 to.tv_usec = (del % 1000) * 1000;
339
340 if (select (0, NULL, NULL, NULL, &to) != 0)
341 {
342 fprintf (stderr, "%s: problem waiting for %d ms:\n %s\n",
343 progname, del, strerror (errno));
344 exit (2);
345 }
346 if (verbose)
347 printf ("t,%d\n", del);
348 }
349 break;
350
351 /* Expect a watchdog command. */
352 case 'W':
353 if (*s != 0)
354 goto syntax_error;
355 bytes[0] = 3;
356 bytes[1] = 0;
357 bytes[2] = RV_WATCHDOG_CMD;
358 expect_input (fd, bytes, 3, 3);
359 if (verbose)
360 printf ("W\n");
361 break;
362
363 /* Send an IRQ notification. */
364 case 'I':
365 sscanf (s, "%x%n", &data, &n);
366 if (n < 0 || s[n] != 0)
367 goto syntax_error;
368 bytes[0] = 7;
369 bytes[1] = 0;
370 bytes[2] = RV_IRQ_CMD;
371 h2le32 (bytes + 3, data);
372 send_output (fd, bytes, 7);
373 if (verbose)
374 printf ("I,%x\n", data);
375 break;
376
377 /* DMA store (to CPU). */
378 case 's':
379 {
380 unsigned int addr;
381 sscanf (s, "%x,%n", &addr, &n);
382
383 if (n < 0 || s[n] == 0)
384 goto syntax_error;
385 s += n;
386 do
387 {
388 n = -1;
389 sscanf (s, "%02x%n", &data, &n);
390 if (n > 0)
391 {
392 s += n;
393 bytes[11 + nbytes++] = data;
394 }
395 }
396 while (n > 0);
397
398 if (*s != 0)
399 goto syntax_error;
400 h2le32 (bytes, nbytes + 11);
401 bytes[2] = RV_MEM_WR_CMD;
402 h2le32 (bytes + 3, addr);
403 h2le32 (bytes + 7, nbytes);
404 send_output (fd, bytes, nbytes + 11);
405 if (verbose)
406 {
407 printf ("s,%x,", addr);
408 for (i = 0; i < nbytes; i++)
409 printf ("%02x", bytes[i]);
410 printf ("\n");
411 }
412 }
413 break;
414
415 /* DMA load (from CPU). */
416 case 'l':
417 {
418 unsigned int addr;
419 sscanf (s, "%x,%n", &addr, &n);
420
421 if (n < 0 || s[n] == 0)
422 goto syntax_error;
423 s += n;
424 do
425 {
426 n = -1;
427 sscanf (s, "%02x%n", &data, &n);
428 if (n > 0)
429 {
430 s += n;
431 bytes[11 + nbytes++] = data;
432 }
433 }
434 while (n > 0);
435
436 if (*s != 0)
437 goto syntax_error;
438 h2le32 (bytes, nbytes + 11);
439 bytes[0] = 11;
440 bytes[1] = 0;
441 bytes[2] = RV_MEM_RD_CMD;
442 h2le32 (bytes + 3, addr);
443 h2le32 (bytes + 7, nbytes);
444 send_output (fd, bytes, 11);
445 bytes[0] = (nbytes + 11) & 255;
446 bytes[1] = ((nbytes + 11) >> 8) & 255;
447 expect_input (fd, bytes, nbytes + 11, nbytes + 11);
448 if (verbose)
449 {
450 printf ("l,%x,", addr);
451 for (i = 0; i < nbytes; i++)
452 printf ("%02x", bytes[i]);
453 printf ("\n");
454 }
455 }
456 break;
457
458 syntax_error:
459 default:
460 fprintf (stderr, "%s: invalid command line in %s:%d:\n %s",
461 progname, fname, lineno, strerror (errno));
462 exit (2);
463 }
464}
465
466/* Loop over the contents of FNAME, using handle_input to parse each line.
467 Errors to stderr, exit (2). */
468
469static void
470handle_input_file (int fd, char *fname)
471{
472 static char buf[2048] = {0};
473 int lineno = 0;
474 FILE *f = fopen (fname, "r");
475
476 if (f == NULL)
477 {
478 fprintf (stderr, "%s: problem opening %s: %s\n",
479 progname, fname, strerror (errno));
480 exit (2);
481 }
482
483 /* Let's cut the buffer short, so we always get a newline. */
484 while (fgets (buf, sizeof (buf) - 1, f) != NULL)
485 {
486 buf[strlen (buf) - 1] = 0;
487 lineno++;
488 handle_input (fd, buf, fname, lineno);
489 }
490
491 fclose (f);
492}
493
494int
495main (int argc, char *argv[])
496{
497 int optc;
498 int fd;
499 FILE *f;
500 int i;
501
502 progname = argv[0];
503 while ((optc = getopt_long (argc, argv, "", longopts, NULL)) != -1)
504 switch (optc)
505 {
506 case OPT_PORT:
507 port = atoi (optarg);
508 break;
509
510 case OPT_TIMEOUT:
511 timeout = (time_t) atoi (optarg);
512 break;
513
514 case OPT_VERBOSE:
515 verbose = 1;
516 break;
517 }
518
519 fd = setupsocket ();
363a6e9f 520 if (fd == -1)
aad3b3cb
HPN
521 {
522 fprintf (stderr, "%s: problem setting up the connection: %s\n",
523 progname, strerror (errno));
524 exit (2);
525 }
526
527 for (i = optind; i < argc; i++)
528 handle_input_file (fd, argv[i]);
529
530 /* FIXME: option-controlled test for remaining input? */
531 close (fd);
532 return 1;
533}
534#endif