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