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