aboutsummaryrefslogtreecommitdiff
path: root/sim/common/syscall.c
diff options
context:
space:
mode:
authorStan Shebs <shebs@codesourcery.com>1999-04-16 01:34:07 +0000
committerStan Shebs <shebs@codesourcery.com>1999-04-16 01:34:07 +0000
commit071ea11e85eb9d529cc5eb3d35f6247466a21b99 (patch)
tree5deda65b8d7b04d1f4cbc534c3206d328e1267ec /sim/common/syscall.c
parent1730ec6b1848f0f32154277f788fb29f88d8475b (diff)
downloadgdb-071ea11e85eb9d529cc5eb3d35f6247466a21b99.zip
gdb-071ea11e85eb9d529cc5eb3d35f6247466a21b99.tar.gz
gdb-071ea11e85eb9d529cc5eb3d35f6247466a21b99.tar.bz2
Initial creation of sourceware repository
Diffstat (limited to 'sim/common/syscall.c')
-rw-r--r--sim/common/syscall.c482
1 files changed, 0 insertions, 482 deletions
diff --git a/sim/common/syscall.c b/sim/common/syscall.c
deleted file mode 100644
index 0bd891e..0000000
--- a/sim/common/syscall.c
+++ /dev/null
@@ -1,482 +0,0 @@
-/* Remote target system call support.
- Copyright 1997 Free Software Foundation, Inc.
- Contributed by Cygnus Solutions.
-
- This file is part of GDB.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GAS; see the file COPYING. If not, write to the Free Software
- Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-/* This interface isn't intended to be specific to any particular kind
- of remote (hardware, simulator, whatever). As such, support for it
- (e.g. sim/common/callback.c) should *not* live in the simulator source
- tree, nor should it live in the gdb source tree. K&R C must be
- supported. */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include "ansidecl.h"
-#include "libiberty.h"
-#ifdef ANSI_PROTOTYPES
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <errno.h>
-#include <fcntl.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include "callback.h"
-#include "targ-vals.h"
-
-#ifndef ENOSYS
-#define ENOSYS EINVAL
-#endif
-#ifndef ENAMETOOLONG
-#define ENAMETOOLONG EINVAL
-#endif
-
-/* Maximum length of a path name. */
-#ifndef MAX_PATH_LEN
-#define MAX_PATH_LEN 1024
-#endif
-
-/* When doing file read/writes, do this many bytes at a time. */
-#define FILE_XFR_SIZE 4096
-
-/* FIXME: for now, need to consider target word size. */
-#define TWORD 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_string (cb, sc, buf, buflen, addr)
- host_callback *cb;
- CB_SYSCALL *sc;
- char *buf;
- int buflen;
- TADDR addr;
-{
- char *p, *pend;
-
- for (p = buf, pend = buf + buflen; p < pend; ++p, ++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 (or otherwise tweak this as desired). */
- unsigned int count = (*sc->read_mem) (cb, sc, addr, p, 1);
-
- if (count != 1)
- return EINVAL;
- if (*p == 0)
- break;
- }
- if (p == pend)
- 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
-cb_syscall (cb, sc)
- host_callback *cb;
- CB_SYSCALL *sc;
-{
- TWORD result = 0, errcode = 0;
-
- if (sc->magic != CB_SYSCALL_MAGIC)
- abort ();
-
- switch (cb_target_to_host_syscall (cb, sc->func))
- {
-#if 0 /* FIXME: wip */
- case CB_SYS_argvlen :
- {
- /* Compute how much space is required to store the argv,envp
- strings so that the program can allocate the space and then
- call SYS_argv to fetch the values. */
- int addr_size = cb->addr_size;
- int argc,envc,arglen,envlen;
- const char **argv = cb->init_argv;
- const char **envp = cb->init_envp;
-
- argc = arglen = 0;
- if (argv)
- {
- for ( ; argv[argc]; ++argc)
- arglen += strlen (argv[argc]) + 1;
- }
- envc = envlen = 0;
- if (envp)
- {
- for ( ; envp[envc]; ++envc)
- envlen += strlen (envp[envc]) + 1;
- }
- result = arglen + envlen;
- break;
- }
-
- case CB_SYS_argv :
- {
- /* Pointer to target's buffer. */
- TADDR tbuf = sc->arg1;
- /* Buffer size. */
- int bufsize = sc->arg2;
- /* Q is the target address of where all the strings go. */
- TADDR q;
- int word_size = cb->word_size;
- int i,argc,envc,len;
- const char **argv = cb->init_argv;
- const char **envp = cb->init_envp;
-
- argc = 0;
- if (argv)
- {
- for ( ; argv[argc]; ++argc)
- {
- int len = strlen (argv[argc]);
- int written = (*sc->write_mem) (cb, sc, tbuf, argv[argc], len + 1);
- if (written != len)
- {
- result = -1;
- errcode = EINVAL;
- goto FinishSyscall;
- }
- tbuf = len + 1;
- }
- }
- if ((*sc->write_mem) (cb, sc, tbuf, "", 1) != 1)
- {
- result = -1;
- errcode = EINVAL;
- goto FinishSyscall;
- }
- tbuf++;
- envc = 0;
- if (envp)
- {
- for ( ; envp[envc]; ++envc)
- {
- int len = strlen (envp[envc]);
- int written = (*sc->write_mem) (cb, sc, tbuf, envp[envc], len + 1);
- if (written != len)
- {
- result = -1;
- errcode = EINVAL;
- goto FinishSyscall;
- }
- tbuf = len + 1;
- }
- }
- if ((*sc->write_mem) (cb, sc, tbuf, "", 1) != 1)
- {
- result = -1;
- errcode = EINVAL;
- goto FinishSyscall;
- }
- result = argc;
- sc->result2 = envc;
- break;
- }
-#endif /* wip */
-
- case CB_SYS_exit :
- /* Caller must catch and handle. */
- break;
-
- case CB_SYS_open :
- {
- char *path;
-
- errcode = get_path (cb, sc, sc->arg1, &path);
- if (errcode != 0)
- {
- result = -1;
- 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 :
- {
- /* ??? Perfect handling of error conditions may require only one
- call to cb->read. One can't assume all the data is
- contiguously stored in host memory so that would require
- malloc'ing/free'ing the space. Maybe later. */
- char buf[FILE_XFR_SIZE];
- int fd = sc->arg1;
- TADDR addr = sc->arg2;
- size_t count = sc->arg3;
- size_t bytes_read = 0;
- int bytes_written;
-
- while (count > 0)
- {
- 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 ErrorFinish;
- if (result == 0) /* EOF */
- break;
- bytes_written = (*sc->write_mem) (cb, sc, addr, buf, result);
- if (bytes_written != result)
- {
- result = -1;
- errcode = EINVAL;
- goto FinishSyscall;
- }
- bytes_read += result;
- count -= result;
- addr += result;
- /* If this is a short read, don't go back for more */
- if (result != FILE_XFR_SIZE)
- break;
- }
- result = bytes_read;
- }
- break;
-
- case CB_SYS_write :
- {
- /* ??? Perfect handling of error conditions may require only one
- call to cb->write. One can't assume all the data is
- contiguously stored in host memory so that would require
- malloc'ing/free'ing the space. Maybe later. */
- char buf[FILE_XFR_SIZE];
- int fd = sc->arg1;
- TADDR addr = sc->arg2;
- size_t count = sc->arg3;
- int bytes_read;
- size_t bytes_written = 0;
-
- while (count > 0)
- {
- int bytes_to_read = count < FILE_XFR_SIZE ? count : FILE_XFR_SIZE;
- bytes_read = (*sc->read_mem) (cb, sc, addr, buf, bytes_to_read);
- if (bytes_read != bytes_to_read)
- {
- result = -1;
- errcode = EINVAL;
- goto FinishSyscall;
- }
- if (fd == 1)
- {
- result = (int) (*cb->write_stdout) (cb, buf, bytes_read);
- (*cb->flush_stdout) (cb);
- }
- else if (fd == 2)
- {
- result = (int) (*cb->write_stderr) (cb, buf, bytes_read);
- (*cb->flush_stderr) (cb);
- }
- else
- result = (int) (*cb->write) (cb, fd, buf, bytes_read);
- if (result == -1)
- goto ErrorFinish;
- bytes_written += result;
- count -= result;
- addr += result;
- }
- result = bytes_written;
- }
- 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;
- errcode = ENOSYS;
- break;
- }
-
- FinishSyscall:
- sc->result = result;
- if (errcode == 0)
- sc->errcode = 0;
- else
- 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;
-}