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