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