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