Home | History | Annotate | Line # | Download | only in common
      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