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