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