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