1/* Remote target system call support. 2 Copyright 1997-2020 Free Software Foundation, Inc. 3 Contributed by Cygnus Solutions. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20/* This interface isn't intended to be specific to any particular kind 21 of remote (hardware, simulator, whatever). As such, support for it 22 (e.g. sim/common/callback.c) should *not* live in the simulator source 23 tree, nor should it live in the gdb source tree. K&R C must be 24 supported. */ 25 26#ifdef HAVE_CONFIG_H 27#include "config.h" 28#endif 29#include "ansidecl.h" 30#include "libiberty.h" 31#include <stdarg.h> 32#include <stdio.h> 33#ifdef HAVE_STDLIB_H 34#include <stdlib.h> 35#endif 36#ifdef HAVE_STRING_H 37#include <string.h> 38#elif defined (HAVE_STRINGS_H) 39#include <strings.h> 40#endif 41#ifdef HAVE_UNISTD_H 42#include <unistd.h> 43#endif 44#include <errno.h> 45#include <fcntl.h> 46#include <time.h> 47#include <sys/types.h> 48#include <sys/stat.h> 49#include "gdb/callback.h" 50#include "targ-vals.h" 51 52#ifndef ENOSYS 53#define ENOSYS EINVAL 54#endif 55#ifndef ENAMETOOLONG 56#define ENAMETOOLONG EINVAL 57#endif 58 59/* Maximum length of a path name. */ 60#ifndef MAX_PATH_LEN 61#define MAX_PATH_LEN 1024 62#endif 63 64/* When doing file read/writes, do this many bytes at a time. */ 65#define FILE_XFR_SIZE 4096 66 67/* FIXME: for now, need to consider target word size. */ 68#define TWORD long 69#define TADDR unsigned long 70 71/* Path to be prepended to syscalls with absolute paths, and to be 72 chdir:ed at startup, if not empty. */ 73char *simulator_sysroot = ""; 74 75/* Utility of cb_syscall to fetch a path name or other string from the target. 76 The result is 0 for success or a host errno value. */ 77 78int 79cb_get_string (host_callback *cb, CB_SYSCALL *sc, char *buf, int buflen, 80 TADDR addr) 81{ 82 char *p, *pend; 83 84 for (p = buf, pend = buf + buflen; p < pend; ++p, ++addr) 85 { 86 /* No, it isn't expected that this would cause one transaction with 87 the remote target for each byte. The target could send the 88 path name along with the syscall request, and cache the file 89 name somewhere (or otherwise tweak this as desired). */ 90 unsigned int count = (*sc->read_mem) (cb, sc, addr, p, 1); 91 92 if (count != 1) 93 return EINVAL; 94 if (*p == 0) 95 break; 96 } 97 if (p == pend) 98 return ENAMETOOLONG; 99 return 0; 100} 101 102/* Utility of cb_syscall to fetch a path name. 103 The buffer is malloc'd and the address is stored in BUFP. 104 The result is that of get_string, but prepended with 105 simulator_sysroot if the string starts with '/'. 106 If an error occurs, no buffer is left malloc'd. */ 107 108static int 109get_path (host_callback *cb, CB_SYSCALL *sc, TADDR addr, char **bufp) 110{ 111 char *buf = xmalloc (MAX_PATH_LEN); 112 int result; 113 int sysroot_len = strlen (simulator_sysroot); 114 115 result = cb_get_string (cb, sc, buf, MAX_PATH_LEN - sysroot_len, addr); 116 if (result == 0) 117 { 118 /* Prepend absolute paths with simulator_sysroot. Relative paths 119 are supposed to be relative to a chdir within that path, but at 120 this point unknown where. */ 121 if (simulator_sysroot[0] != '\0' && *buf == '/') 122 { 123 /* Considering expected rareness of syscalls with absolute 124 file paths (compared to relative file paths and insn 125 execution), it does not seem worthwhile to rearrange things 126 to get rid of the string moves here; we'd need at least an 127 extra call to check the initial '/' in the path. */ 128 memmove (buf + sysroot_len, buf, sysroot_len); 129 memcpy (buf, simulator_sysroot, sysroot_len); 130 } 131 132 *bufp = buf; 133 } 134 else 135 free (buf); 136 return result; 137} 138 139/* Perform a system call on behalf of the target. */ 140 141CB_RC 142cb_syscall (host_callback *cb, CB_SYSCALL *sc) 143{ 144 TWORD result = 0, errcode = 0; 145 146 if (sc->magic != CB_SYSCALL_MAGIC) 147 abort (); 148 149 switch (cb_target_to_host_syscall (cb, sc->func)) 150 { 151#if 0 /* FIXME: wip */ 152 case CB_SYS_argvlen : 153 { 154 /* Compute how much space is required to store the argv,envp 155 strings so that the program can allocate the space and then 156 call SYS_argv to fetch the values. */ 157 int addr_size = cb->addr_size; 158 int argc,envc,arglen,envlen; 159 const char **argv = cb->init_argv; 160 const char **envp = cb->init_envp; 161 162 argc = arglen = 0; 163 if (argv) 164 { 165 for ( ; argv[argc]; ++argc) 166 arglen += strlen (argv[argc]) + 1; 167 } 168 envc = envlen = 0; 169 if (envp) 170 { 171 for ( ; envp[envc]; ++envc) 172 envlen += strlen (envp[envc]) + 1; 173 } 174 result = arglen + envlen; 175 break; 176 } 177 178 case CB_SYS_argv : 179 { 180 /* Pointer to target's buffer. */ 181 TADDR tbuf = sc->arg1; 182 /* Buffer size. */ 183 int bufsize = sc->arg2; 184 /* Q is the target address of where all the strings go. */ 185 TADDR q; 186 int word_size = cb->word_size; 187 int i,argc,envc,len; 188 const char **argv = cb->init_argv; 189 const char **envp = cb->init_envp; 190 191 argc = 0; 192 if (argv) 193 { 194 for ( ; argv[argc]; ++argc) 195 { 196 int len = strlen (argv[argc]); 197 int written = (*sc->write_mem) (cb, sc, tbuf, argv[argc], len + 1); 198 if (written != len) 199 { 200 result = -1; 201 errcode = EINVAL; 202 goto FinishSyscall; 203 } 204 tbuf = len + 1; 205 } 206 } 207 if ((*sc->write_mem) (cb, sc, tbuf, "", 1) != 1) 208 { 209 result = -1; 210 errcode = EINVAL; 211 goto FinishSyscall; 212 } 213 tbuf++; 214 envc = 0; 215 if (envp) 216 { 217 for ( ; envp[envc]; ++envc) 218 { 219 int len = strlen (envp[envc]); 220 int written = (*sc->write_mem) (cb, sc, tbuf, envp[envc], len + 1); 221 if (written != len) 222 { 223 result = -1; 224 errcode = EINVAL; 225 goto FinishSyscall; 226 } 227 tbuf = len + 1; 228 } 229 } 230 if ((*sc->write_mem) (cb, sc, tbuf, "", 1) != 1) 231 { 232 result = -1; 233 errcode = EINVAL; 234 goto FinishSyscall; 235 } 236 result = argc; 237 sc->result2 = envc; 238 break; 239 } 240#endif /* wip */ 241 242 case CB_SYS_exit : 243 /* Caller must catch and handle; see sim_syscall as an example. */ 244 break; 245 246 case CB_SYS_open : 247 { 248 char *path; 249 250 errcode = get_path (cb, sc, sc->arg1, &path); 251 if (errcode != 0) 252 { 253 result = -1; 254 goto FinishSyscall; 255 } 256 result = (*cb->open) (cb, path, sc->arg2 /*, sc->arg3*/); 257 free (path); 258 if (result < 0) 259 goto ErrorFinish; 260 } 261 break; 262 263 case CB_SYS_close : 264 result = (*cb->close) (cb, sc->arg1); 265 if (result < 0) 266 goto ErrorFinish; 267 break; 268 269 case CB_SYS_read : 270 { 271 /* ??? Perfect handling of error conditions may require only one 272 call to cb->read. One can't assume all the data is 273 contiguously stored in host memory so that would require 274 malloc'ing/free'ing the space. Maybe later. */ 275 char buf[FILE_XFR_SIZE]; 276 int fd = sc->arg1; 277 TADDR addr = sc->arg2; 278 size_t count = sc->arg3; 279 size_t bytes_read = 0; 280 int bytes_written; 281 282 while (count > 0) 283 { 284 if (cb_is_stdin (cb, fd)) 285 result = (int) (*cb->read_stdin) (cb, buf, 286 (count < FILE_XFR_SIZE 287 ? count : FILE_XFR_SIZE)); 288 else 289 result = (int) (*cb->read) (cb, fd, buf, 290 (count < FILE_XFR_SIZE 291 ? count : FILE_XFR_SIZE)); 292 if (result == -1) 293 goto ErrorFinish; 294 if (result == 0) /* EOF */ 295 break; 296 bytes_written = (*sc->write_mem) (cb, sc, addr, buf, result); 297 if (bytes_written != result) 298 { 299 result = -1; 300 errcode = EINVAL; 301 goto FinishSyscall; 302 } 303 bytes_read += result; 304 count -= result; 305 addr += result; 306 /* If this is a short read, don't go back for more */ 307 if (result != FILE_XFR_SIZE) 308 break; 309 } 310 result = bytes_read; 311 } 312 break; 313 314 case CB_SYS_write : 315 { 316 /* ??? Perfect handling of error conditions may require only one 317 call to cb->write. One can't assume all the data is 318 contiguously stored in host memory so that would require 319 malloc'ing/free'ing the space. Maybe later. */ 320 char buf[FILE_XFR_SIZE]; 321 int fd = sc->arg1; 322 TADDR addr = sc->arg2; 323 size_t count = sc->arg3; 324 int bytes_read; 325 size_t bytes_written = 0; 326 327 while (count > 0) 328 { 329 int bytes_to_read = count < FILE_XFR_SIZE ? count : FILE_XFR_SIZE; 330 bytes_read = (*sc->read_mem) (cb, sc, addr, buf, bytes_to_read); 331 if (bytes_read != bytes_to_read) 332 { 333 result = -1; 334 errcode = EINVAL; 335 goto FinishSyscall; 336 } 337 if (cb_is_stdout (cb, fd)) 338 { 339 result = (int) (*cb->write_stdout) (cb, buf, bytes_read); 340 (*cb->flush_stdout) (cb); 341 } 342 else if (cb_is_stderr (cb, fd)) 343 { 344 result = (int) (*cb->write_stderr) (cb, buf, bytes_read); 345 (*cb->flush_stderr) (cb); 346 } 347 else 348 result = (int) (*cb->write) (cb, fd, buf, bytes_read); 349 if (result == -1) 350 goto ErrorFinish; 351 bytes_written += result; 352 count -= result; 353 addr += result; 354 } 355 result = bytes_written; 356 } 357 break; 358 359 case CB_SYS_lseek : 360 { 361 int fd = sc->arg1; 362 unsigned long offset = sc->arg2; 363 int whence = sc->arg3; 364 365 result = (*cb->lseek) (cb, fd, offset, whence); 366 if (result < 0) 367 goto ErrorFinish; 368 } 369 break; 370 371 case CB_SYS_unlink : 372 { 373 char *path; 374 375 errcode = get_path (cb, sc, sc->arg1, &path); 376 if (errcode != 0) 377 { 378 result = -1; 379 goto FinishSyscall; 380 } 381 result = (*cb->unlink) (cb, path); 382 free (path); 383 if (result < 0) 384 goto ErrorFinish; 385 } 386 break; 387 388 case CB_SYS_truncate : 389 { 390 char *path; 391 long len = sc->arg2; 392 393 errcode = get_path (cb, sc, sc->arg1, &path); 394 if (errcode != 0) 395 { 396 result = -1; 397 errcode = EFAULT; 398 goto FinishSyscall; 399 } 400 result = (*cb->truncate) (cb, path, len); 401 free (path); 402 if (result < 0) 403 goto ErrorFinish; 404 } 405 break; 406 407 case CB_SYS_ftruncate : 408 { 409 int fd = sc->arg1; 410 long len = sc->arg2; 411 412 result = (*cb->ftruncate) (cb, fd, len); 413 if (result < 0) 414 goto ErrorFinish; 415 } 416 break; 417 418 case CB_SYS_rename : 419 { 420 char *path1, *path2; 421 422 errcode = get_path (cb, sc, sc->arg1, &path1); 423 if (errcode != 0) 424 { 425 result = -1; 426 errcode = EFAULT; 427 goto FinishSyscall; 428 } 429 errcode = get_path (cb, sc, sc->arg2, &path2); 430 if (errcode != 0) 431 { 432 result = -1; 433 errcode = EFAULT; 434 free (path1); 435 goto FinishSyscall; 436 } 437 result = (*cb->rename) (cb, path1, path2); 438 free (path1); 439 free (path2); 440 if (result < 0) 441 goto ErrorFinish; 442 } 443 break; 444 445 case CB_SYS_stat : 446 { 447 char *path,*buf; 448 int buflen; 449 struct stat statbuf; 450 TADDR addr = sc->arg2; 451 452 errcode = get_path (cb, sc, sc->arg1, &path); 453 if (errcode != 0) 454 { 455 result = -1; 456 goto FinishSyscall; 457 } 458 result = (*cb->to_stat) (cb, path, &statbuf); 459 free (path); 460 if (result < 0) 461 goto ErrorFinish; 462 buflen = cb_host_to_target_stat (cb, NULL, NULL); 463 buf = xmalloc (buflen); 464 if (cb_host_to_target_stat (cb, &statbuf, buf) != buflen) 465 { 466 /* The translation failed. This is due to an internal 467 host program error, not the target's fault. */ 468 free (buf); 469 errcode = ENOSYS; 470 result = -1; 471 goto FinishSyscall; 472 } 473 if ((*sc->write_mem) (cb, sc, addr, buf, buflen) != buflen) 474 { 475 free (buf); 476 errcode = EINVAL; 477 result = -1; 478 goto FinishSyscall; 479 } 480 free (buf); 481 } 482 break; 483 484 case CB_SYS_fstat : 485 { 486 char *buf; 487 int buflen; 488 struct stat statbuf; 489 TADDR addr = sc->arg2; 490 491 result = (*cb->to_fstat) (cb, sc->arg1, &statbuf); 492 if (result < 0) 493 goto ErrorFinish; 494 buflen = cb_host_to_target_stat (cb, NULL, NULL); 495 buf = xmalloc (buflen); 496 if (cb_host_to_target_stat (cb, &statbuf, buf) != buflen) 497 { 498 /* The translation failed. This is due to an internal 499 host program error, not the target's fault. */ 500 free (buf); 501 errcode = ENOSYS; 502 result = -1; 503 goto FinishSyscall; 504 } 505 if ((*sc->write_mem) (cb, sc, addr, buf, buflen) != buflen) 506 { 507 free (buf); 508 errcode = EINVAL; 509 result = -1; 510 goto FinishSyscall; 511 } 512 free (buf); 513 } 514 break; 515 516 case CB_SYS_lstat : 517 { 518 char *path, *buf; 519 int buflen; 520 struct stat statbuf; 521 TADDR addr = sc->arg2; 522 523 errcode = get_path (cb, sc, sc->arg1, &path); 524 if (errcode != 0) 525 { 526 result = -1; 527 goto FinishSyscall; 528 } 529 result = (*cb->to_lstat) (cb, path, &statbuf); 530 free (path); 531 if (result < 0) 532 goto ErrorFinish; 533 534 buflen = cb_host_to_target_stat (cb, NULL, NULL); 535 buf = xmalloc (buflen); 536 if (cb_host_to_target_stat (cb, &statbuf, buf) != buflen) 537 { 538 /* The translation failed. This is due to an internal 539 host program error, not the target's fault. 540 Unfortunately, it's hard to test this case, so there's no 541 test-case for this execution path. */ 542 free (buf); 543 errcode = ENOSYS; 544 result = -1; 545 goto FinishSyscall; 546 } 547 548 if ((*sc->write_mem) (cb, sc, addr, buf, buflen) != buflen) 549 { 550 free (buf); 551 errcode = EINVAL; 552 result = -1; 553 goto FinishSyscall; 554 } 555 556 free (buf); 557 } 558 break; 559 560 case CB_SYS_pipe : 561 { 562 int p[2]; 563 char *target_p = xcalloc (1, cb->target_sizeof_int * 2); 564 565 result = (*cb->pipe) (cb, p); 566 if (result != 0) 567 goto ErrorFinish; 568 569 cb_store_target_endian (cb, target_p, cb->target_sizeof_int, p[0]); 570 cb_store_target_endian (cb, target_p + cb->target_sizeof_int, 571 cb->target_sizeof_int, p[1]); 572 if ((*sc->write_mem) (cb, sc, sc->arg1, target_p, 573 cb->target_sizeof_int * 2) 574 != cb->target_sizeof_int * 2) 575 { 576 /* Close the pipe fd:s. */ 577 (*cb->close) (cb, p[0]); 578 (*cb->close) (cb, p[1]); 579 errcode = EFAULT; 580 result = -1; 581 } 582 583 free (target_p); 584 } 585 break; 586 587 case CB_SYS_time : 588 { 589 /* FIXME: May wish to change CB_SYS_time to something else. 590 We might also want gettimeofday or times, but if system calls 591 can be built on others, we can keep the number we have to support 592 here down. */ 593 time_t t = (*cb->time) (cb, (time_t *) 0); 594 result = t; 595 /* It is up to target code to process the argument to time(). */ 596 } 597 break; 598 599 case CB_SYS_chdir : 600 case CB_SYS_chmod : 601 case CB_SYS_utime : 602 /* fall through for now */ 603 604 default : 605 result = -1; 606 errcode = ENOSYS; 607 break; 608 } 609 610 FinishSyscall: 611 sc->result = result; 612 if (errcode == 0) 613 sc->errcode = 0; 614 else 615 sc->errcode = cb_host_to_target_errno (cb, errcode); 616 return CB_RC_OK; 617 618 ErrorFinish: 619 sc->result = result; 620 sc->errcode = (*cb->get_errno) (cb); 621 return CB_RC_OK; 622} 623