gdb: add target_ops::supports_displaced_step
[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-2020 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 #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
73 enum 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
84 enum opts { OPT_PORT = 1, OPT_TIMEOUT, OPT_VERBOSE };
85
86 struct 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
94 int port = 10000;
95 time_t timeout = 30000;
96 char *progname = "(unknown)";
97 int verbose = 0;
98
99 /* Required forward-declarations. */
100 static 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
106 static int setupsocket (void)
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);
119 if (s == -1)
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
140 static void
141 h2le32 (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
151 static void
152 send_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
171 static void
172 expect_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
215 static void
216 handle_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
467 static void
468 handle_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
492 int
493 main (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 ();
518 if (fd == -1)
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
This page took 0.043582 seconds and 4 git commands to generate.