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