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