]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/cris/rvdummy.c
Update years in copyright notice for the GDB files.
[thirdparty/binutils-gdb.git] / sim / cris / rvdummy.c
1 /* Test-driver for the remote-virtual-component simulator framework
2 for GDB, the GNU Debugger.
3
4 Copyright 2006-2013 Free Software Foundation, Inc.
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
10 the Free Software Foundation; either version 3 of the License, or
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
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20
21 /* Avoid any problems whatsoever building this program if we're not
22 also building hardware support. */
23
24 #if !WITH_HW
25 int
26 main (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
75 enum 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
86 enum opts { OPT_PORT = 1, OPT_TIMEOUT, OPT_VERBOSE };
87
88 struct 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
96 int port = 10000;
97 time_t timeout = 30000;
98 char *progname = "(unknown)";
99 int verbose = 0;
100
101 /* Required forward-declarations. */
102 static 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
108 int 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);
121 if (s == -1)
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
142 static void
143 h2le32 (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
153 static void
154 send_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
173 static void
174 expect_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
217 static void
218 handle_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
469 static void
470 handle_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
494 int
495 main (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 ();
520 if (fd == -1)
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