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