From f33673061fce208257e4c7039c32ddc46fd199e3 Mon Sep 17 00:00:00 2001 From: Doug Evans Date: Tue, 25 Nov 1997 09:33:34 +0000 Subject: * callback.c (os_stat): Make 3rd arg a host struct stat ptr. (os_fstat): Likewise. Validate fd argument. (cb_host_to_target_stat): Delete big_p arg. If HS arg is NULL, just compute target stat struct length. * syscall.c: #include "libiberty.h", , . (ENOSYS,ENAMETOOLONG): Provide definitions if missing. (get_string): Return host errno values so they can be properly translated later. (cb_syscall): Likewise. (cb_syscall, cases open,unlink): Use get_path instead of get_string. (cb_syscall, case read): Use read_stdin for file descriptor 0. (cb_syscall, case write): Use write_stderr for file descriptor 2. (cb_syscall): Add cases for lseek, unlink, stat, fstat, time. (get_path): New function. --- sim/common/syscall.c | 239 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 201 insertions(+), 38 deletions(-) (limited to 'sim/common/syscall.c') diff --git a/sim/common/syscall.c b/sim/common/syscall.c index 4bbb0c5..7ff49b5 100644 --- a/sim/common/syscall.c +++ b/sim/common/syscall.c @@ -28,6 +28,7 @@ #include "config.h" #endif #include "ansidecl.h" +#include "libiberty.h" #ifdef ANSI_PROTOTYPES #include #else @@ -37,35 +38,46 @@ #ifdef HAVE_STDLIB_H #include #endif +#ifdef HAVE_UNISTD_H +#include +#endif #include #include #include +#include +#include #include "callback.h" -#include "remote-sim.h" #include "targ-vals.h" -#ifdef HAVE_UNISTD_H -#include +#ifndef ENOSYS +#define ENOSYS EINVAL +#endif +#ifndef ENAMETOOLONG +#define ENAMETOOLONG EINVAL #endif - -/* When doing file read/writes, do this many bytes at a time. */ -#define FILE_XFR_SIZE 4096 /* Maximum length of a path name. */ #ifndef MAX_PATH_LEN #define MAX_PATH_LEN 1024 #endif -/* Utility of cb_syscall to fetch a path name from the target. - The result is 0 for success or a target errno value. */ +/* When doing file read/writes, do this many bytes at a time. */ +#define FILE_XFR_SIZE 4096 + +/* FIXME: for now */ +#define TWORD unsigned long +#define TADDR unsigned long + +/* Utility of cb_syscall to fetch a path name or other string from the target. + The result is 0 for success or a host errno value. */ static int -get_path (cb, sc, buf, buflen, addr) +get_string (cb, sc, buf, buflen, addr) host_callback *cb; CB_SYSCALL *sc; char *buf; int buflen; - long addr; + TADDR addr; { char *p, *pend; @@ -74,19 +86,42 @@ get_path (cb, sc, buf, buflen, addr) /* No, it isn't expected that this would cause one transaction with the remote target for each byte. The target could send the path name along with the syscall request, and cache the file - name somewhere. */ + name somewhere (or otherwise tweak this as desired). */ unsigned int count = (*sc->read_mem) (cb, sc, addr, p, 1); if (count != 1) - return TARGET_EINVAL; + return EINVAL; if (*p == 0) break; } if (p == pend) - return TARGET_ENAMETOOLONG; + return ENAMETOOLONG; return 0; } +/* Utility of cb_syscall to fetch a path name. + The buffer is malloc'd and the address is stored in BUFP. + The result is that of get_string. + If an error occurs, no buffer is left malloc'd. */ + +static int +get_path (cb, sc, addr, bufp) + host_callback *cb; + CB_SYSCALL *sc; + TADDR addr; + char **bufp; +{ + char *buf = xmalloc (MAX_PATH_LEN); + int result; + + result = get_string (cb, sc, buf, MAX_PATH_LEN, addr); + if (result == 0) + *bufp = buf; + else + free (buf); + return result; +} + /* Perform a system call on behalf of the target. */ CB_RC @@ -129,11 +164,11 @@ cb_syscall (cb, sc) case CB_SYS_argv : { /* Pointer to target's buffer. */ - SIM_ADDR tbuf = sc->arg1; + TADDR tbuf = sc->arg1; /* Buffer size. */ int bufsize = sc->arg2; /* Q is the target address of where all the strings go. */ - SIM_ADDR q; + TADDR q; int word_size = cb->word_size; int i,argc,envc,len; const char **argv = cb->init_argv; @@ -149,7 +184,7 @@ cb_syscall (cb, sc) if (written != len) { result = -1; - errcode = TARGET_EINVAL; + errcode = EINVAL; goto FinishSyscall; } tbuf = len + 1; @@ -158,7 +193,7 @@ cb_syscall (cb, sc) if ((*sc->write_mem) (cb, sc, tbuf, "", 1) != 1) { result = -1; - errcode = TARGET_EINVAL; + errcode = EINVAL; goto FinishSyscall; } tbuf++; @@ -172,7 +207,7 @@ cb_syscall (cb, sc) if (written != len) { result = -1; - errcode = TARGET_EINVAL; + errcode = EINVAL; goto FinishSyscall; } tbuf = len + 1; @@ -181,7 +216,7 @@ cb_syscall (cb, sc) if ((*sc->write_mem) (cb, sc, tbuf, "", 1) != 1) { result = -1; - errcode = TARGET_EINVAL; + errcode = EINVAL; goto FinishSyscall; } result = argc; @@ -196,22 +231,25 @@ cb_syscall (cb, sc) case CB_SYS_open : { - char path[MAX_PATH_LEN]; - int errcode; + char *path; - errcode = get_path (cb, sc, path, MAX_PATH_LEN, sc->arg1); + errcode = get_path (cb, sc, sc->arg1, &path); if (errcode != 0) { result = -1; - errcode = errcode; goto FinishSyscall; } result = (*cb->open) (cb, path, sc->arg2 /*, sc->arg3*/); + free (path); + if (result < 0) + goto ErrorFinish; } break; case CB_SYS_close : result = (*cb->close) (cb, sc->arg1); + if (result < 0) + goto ErrorFinish; break; case CB_SYS_read : @@ -222,22 +260,28 @@ cb_syscall (cb, sc) malloc'ing/free'ing the space. Maybe later. */ char buf[FILE_XFR_SIZE]; int fd = sc->arg1; - SIM_ADDR addr = sc->arg2; + TADDR addr = sc->arg2; size_t count = sc->arg3; size_t bytes_read = 0; int bytes_written; while (count > 0) { - result = (int) (*cb->read) (cb, fd, buf, - count < FILE_XFR_SIZE ? count : FILE_XFR_SIZE); + if (fd == 0) + result = (int) (*cb->read_stdin) (cb, buf, + (count < FILE_XFR_SIZE + ? count : FILE_XFR_SIZE)); + else + result = (int) (*cb->read) (cb, fd, buf, + (count < FILE_XFR_SIZE + ? count : FILE_XFR_SIZE)); if (result == -1) - goto FinishSyscall; + goto ErrorFinish; bytes_written = (*sc->write_mem) (cb, sc, addr, buf, result); if (bytes_written != result) { result = -1; - errcode = TARGET_EINVAL; + errcode = EINVAL; goto FinishSyscall; } bytes_read += result; @@ -256,7 +300,7 @@ cb_syscall (cb, sc) malloc'ing/free'ing the space. Maybe later. */ char buf[FILE_XFR_SIZE]; int fd = sc->arg1; - SIM_ADDR addr = sc->arg2; + TADDR addr = sc->arg2; size_t count = sc->arg3; int bytes_read; size_t bytes_written = 0; @@ -268,15 +312,17 @@ cb_syscall (cb, sc) if (bytes_read != bytes_to_read) { result = -1; - errcode = TARGET_EINVAL; + errcode = EINVAL; goto FinishSyscall; } if (fd == 1) result = (int) (*cb->write_stdout) (cb, buf, bytes_read); + if (fd == 2) + result = (int) (*cb->write_stderr) (cb, buf, bytes_read); else result = (int) (*cb->write) (cb, fd, buf, bytes_read); if (result == -1) - goto FinishSyscall; + goto ErrorFinish; bytes_written += result; count -= result; addr += result; @@ -285,22 +331,139 @@ cb_syscall (cb, sc) } break; + case CB_SYS_lseek : + { + int fd = sc->arg1; + unsigned long offset = sc->arg2; + int whence = sc->arg3; + + result = (*cb->lseek) (cb, fd, offset, whence); + if (result < 0) + goto ErrorFinish; + } + break; + + case CB_SYS_unlink : + { + char *path; + + errcode = get_path (cb, sc, sc->arg1, &path); + if (errcode != 0) + { + result = -1; + goto FinishSyscall; + } + result = (*cb->unlink) (cb, path); + free (path); + if (result < 0) + goto ErrorFinish; + } + break; + + case CB_SYS_stat : + { + char *path,*buf; + int buflen; + struct stat statbuf; + TADDR addr = sc->arg2; + + errcode = get_path (cb, sc, sc->arg1, &path); + if (errcode != 0) + { + result = -1; + goto FinishSyscall; + } + result = (*cb->stat) (cb, path, &statbuf); + free (path); + if (result < 0) + goto ErrorFinish; + buflen = cb_host_to_target_stat (cb, NULL, NULL); + buf = xmalloc (buflen); + if (cb_host_to_target_stat (cb, &statbuf, buf) != buflen) + { + /* The translation failed. This is due to an internal + host program error, not the target's fault. */ + free (buf); + errcode = ENOSYS; + result = -1; + goto FinishSyscall; + } + if ((*sc->write_mem) (cb, sc, addr, buf, buflen) != buflen) + { + free (buf); + errcode = EINVAL; + result = -1; + goto FinishSyscall; + } + free (buf); + } + break; + + case CB_SYS_fstat : + { + char *buf; + int buflen; + struct stat statbuf; + TADDR addr = sc->arg2; + + result = (*cb->fstat) (cb, sc->arg1, &statbuf); + if (result < 0) + goto ErrorFinish; + buflen = cb_host_to_target_stat (cb, NULL, NULL); + buf = xmalloc (buflen); + if (cb_host_to_target_stat (cb, &statbuf, buf) != buflen) + { + /* The translation failed. This is due to an internal + host program error, not the target's fault. */ + free (buf); + errcode = ENOSYS; + result = -1; + goto FinishSyscall; + } + if ((*sc->write_mem) (cb, sc, addr, buf, buflen) != buflen) + { + free (buf); + errcode = EINVAL; + result = -1; + goto FinishSyscall; + } + free (buf); + } + break; + + case CB_SYS_time : + { + /* FIXME: May wish to change CB_SYS_time to something else. + We might also want gettimeofday or times, but if system calls + can be built on others, we can keep the number we have to support + here down. */ + time_t t = (*cb->time) (cb, (time_t *) 0); + result = t; + /* It is up to target code to process the argument to time(). */ + } + break; + + case CB_SYS_chdir : + case CB_SYS_chmod : + case CB_SYS_utime : + /* fall through for now */ + default : result = -1; -#ifdef TARGET_ENOSYS - errcode = TARGET_ENOSYS; -#else - errcode = TARGET_EINVAL; -#endif + errcode = ENOSYS; break; } FinishSyscall: sc->result = result; if (errcode == 0) - sc->errcode = (*cb->get_errno) (cb); + sc->errcode = 0; else - sc->errcode = errcode; + sc->errcode = cb_host_to_target_errno (cb, errcode); + return CB_RC_OK; + ErrorFinish: + sc->result = result; + sc->errcode = (*cb->get_errno) (cb); return CB_RC_OK; } -- cgit v1.1