/* CRIS exception, interrupt, and trap (EIT) support
- Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2004-2019 Free Software Foundation, Inc.
Contributed by Axis Communications.
This file is part of the GNU simulators.
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, or (at your option)
-any later version.
+the Free Software Foundation; either version 3 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 this program; if not, write to the Free Software Foundation, Inc.,
-59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "sim-main.h"
+#include "sim-syscall.h"
#include "sim-options.h"
#include "bfd.h"
/* FIXME: get rid of targ-vals.h usage everywhere else. */
+#include <stdarg.h>
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
+/* For PATH_MAX, originally. */
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+/* From ld/sysdep.h. */
+#ifdef PATH_MAX
+# define SIM_PATHMAX PATH_MAX
+#else
+# ifdef MAXPATHLEN
+# define SIM_PATHMAX MAXPATHLEN
+# else
+# define SIM_PATHMAX 1024
+# endif
+#endif
/* The verbatim values are from asm-cris/unistd.h. */
#define TARGET_SYS_time 13
#define TARGET_SYS_lseek 19
#define TARGET_SYS_getpid 20
+#define TARGET_SYS_access 33
#define TARGET_SYS_kill 37
#define TARGET_SYS_rename 38
#define TARGET_SYS_pipe 42
#define TARGET_SYS_uname 122
#define TARGET_SYS_mprotect 125
#define TARGET_SYS_llseek 140
+#define TARGET_SYS_writev 146
#define TARGET_SYS__sysctl 149
#define TARGET_SYS_sched_setparam 154
#define TARGET_SYS_sched_getparam 155
#define TARGET_SYS_getegid32 202
#define TARGET_SYS_getgid32 200
#define TARGET_SYS_fcntl64 221
+#define TARGET_SYS_set_thread_area 243
+#define TARGET_SYS_exit_group 252
#define TARGET_PROT_READ 0x1
#define TARGET_PROT_WRITE 0x2
#define TARGET_MAP_TYPE 0x0f
#define TARGET_MAP_FIXED 0x10
#define TARGET_MAP_ANONYMOUS 0x20
+#define TARGET_MAP_DENYWRITE 0x800
#define TARGET_CTL_KERN 1
#define TARGET_CTL_VM 2
#define TARGET_TCGETS 0x5401
-#define TARGET_UTSNAME "#38 Sun Apr 1 00:00:00 MET 2001"
+#define TARGET_UTSNAME "#7 Thu Jan 1 00:00:00 MET 2009"
-/* Seconds since the above date + 10 minutes. */
-#define TARGET_EPOCH 986080200
+/* Seconds since 1970-01-01 to the above date + 10 minutes;
+ 'date -d "Thu Jan 1 00:00:10 MET 2009" +%s'. */
+#define TARGET_EPOCH 1230764410
/* Milliseconds since start of run. We use the number of syscalls to
avoid introducing noise in the execution time. */
#define TARGET___WALL 0x40000000
#define TARGET___WCLONE 0x80000000
+/* From linux/limits.h. */
+#define TARGET_PIPE_BUF 4096
+
+/* From unistd.h. */
+#define TARGET_R_OK 4
+#define TARGET_W_OK 2
+#define TARGET_X_OK 1
+#define TARGET_F_OK 0
+
static const char stat_map[] =
"st_dev,2:space,10:space,4:st_mode,4:st_nlink,4:st_uid,4"
":st_gid,4:st_rdev,2:space,10:st_size,8:st_blksize,4:st_blocks,4"
static const CB_TARGET_DEFS_MAP syscall_map[] =
{
- { CB_SYS_open, TARGET_SYS_open },
- { CB_SYS_close, TARGET_SYS_close },
- { CB_SYS_read, TARGET_SYS_read },
- { CB_SYS_write, TARGET_SYS_write },
- { CB_SYS_lseek, TARGET_SYS_lseek },
- { CB_SYS_unlink, TARGET_SYS_unlink },
- { CB_SYS_getpid, TARGET_SYS_getpid },
- { CB_SYS_fstat, TARGET_SYS_fstat64 },
- { CB_SYS_lstat, TARGET_SYS_lstat64 },
- { CB_SYS_stat, TARGET_SYS_stat64 },
- { CB_SYS_pipe, TARGET_SYS_pipe },
- { CB_SYS_rename, TARGET_SYS_rename },
- { CB_SYS_truncate, TARGET_SYS_truncate },
- { CB_SYS_ftruncate, TARGET_SYS_ftruncate },
- { 0, -1 }
+ { "open", CB_SYS_open, TARGET_SYS_open },
+ { "close", CB_SYS_close, TARGET_SYS_close },
+ { "read", CB_SYS_read, TARGET_SYS_read },
+ { "write", CB_SYS_write, TARGET_SYS_write },
+ { "lseek", CB_SYS_lseek, TARGET_SYS_lseek },
+ { "unlink", CB_SYS_unlink, TARGET_SYS_unlink },
+ { "getpid", CB_SYS_getpid, TARGET_SYS_getpid },
+ { "fstat", CB_SYS_fstat, TARGET_SYS_fstat64 },
+ { "lstat", CB_SYS_lstat, TARGET_SYS_lstat64 },
+ { "stat", CB_SYS_stat, TARGET_SYS_stat64 },
+ { "pipe", CB_SYS_pipe, TARGET_SYS_pipe },
+ { "rename", CB_SYS_rename, TARGET_SYS_rename },
+ { "truncate", CB_SYS_truncate, TARGET_SYS_truncate },
+ { "ftruncate", CB_SYS_ftruncate, TARGET_SYS_ftruncate },
+ { 0, -1, -1 }
};
/* An older, 32-bit-only stat mapping. */
newlib Linux mapping. */
static const CB_TARGET_DEFS_MAP syscall_stat32_map[] =
{
- { CB_SYS_fstat, TARGET_SYS_fstat },
- { CB_SYS_stat, TARGET_SYS_stat },
- { 0, -1 }
+ { "fstat", CB_SYS_fstat, TARGET_SYS_fstat },
+ { "stat", CB_SYS_stat, TARGET_SYS_stat },
+ { 0, -1, -1 }
};
/* Giving the true value for the running sim process will lead to
static const CB_TARGET_DEFS_MAP errno_map[] =
{
#ifdef EPERM
- { EPERM, 1 },
+ { "EPERM", EPERM, 1 },
#endif
#ifdef ENOENT
- { ENOENT, 2 },
+ { "ENOENT", ENOENT, 2 },
#endif
#ifdef ESRCH
- { ESRCH, 3 },
+ { "ESRCH", ESRCH, 3 },
#endif
#ifdef EINTR
- { EINTR, 4 },
+ { "EINTR", EINTR, 4 },
#endif
#ifdef EIO
- { EIO, 5 },
+ { "EIO", EIO, 5 },
#endif
#ifdef ENXIO
- { ENXIO, 6 },
+ { "ENXIO", ENXIO, 6 },
#endif
#ifdef E2BIG
- { E2BIG, 7 },
+ { "E2BIG", E2BIG, 7 },
#endif
#ifdef ENOEXEC
- { ENOEXEC, 8 },
+ { "ENOEXEC", ENOEXEC, 8 },
#endif
#ifdef EBADF
- { EBADF, 9 },
+ { "EBADF", EBADF, 9 },
#endif
#ifdef ECHILD
- { ECHILD, 10 },
+ { "ECHILD", ECHILD, 10 },
#endif
#ifdef EAGAIN
- { EAGAIN, 11 },
+ { "EAGAIN", EAGAIN, 11 },
#endif
#ifdef ENOMEM
- { ENOMEM, 12 },
+ { "ENOMEM", ENOMEM, 12 },
#endif
#ifdef EACCES
- { EACCES, 13 },
+ { "EACCES", EACCES, 13 },
#endif
#ifdef EFAULT
- { EFAULT, 14 },
+ { "EFAULT", EFAULT, 14 },
#endif
#ifdef ENOTBLK
- { ENOTBLK, 15 },
+ { "ENOTBLK", ENOTBLK, 15 },
#endif
#ifdef EBUSY
- { EBUSY, 16 },
+ { "EBUSY", EBUSY, 16 },
#endif
#ifdef EEXIST
- { EEXIST, 17 },
+ { "EEXIST", EEXIST, 17 },
#endif
#ifdef EXDEV
- { EXDEV, 18 },
+ { "EXDEV", EXDEV, 18 },
#endif
#ifdef ENODEV
- { ENODEV, 19 },
+ { "ENODEV", ENODEV, 19 },
#endif
#ifdef ENOTDIR
- { ENOTDIR, 20 },
+ { "ENOTDIR", ENOTDIR, 20 },
#endif
#ifdef EISDIR
- { EISDIR, 21 },
+ { "EISDIR", EISDIR, 21 },
#endif
#ifdef EINVAL
- { EINVAL, 22 },
+ { "EINVAL", EINVAL, 22 },
#endif
#ifdef ENFILE
- { ENFILE, 23 },
+ { "ENFILE", ENFILE, 23 },
#endif
#ifdef EMFILE
- { EMFILE, 24 },
+ { "EMFILE", EMFILE, 24 },
#endif
#ifdef ENOTTY
- { ENOTTY, 25 },
+ { "ENOTTY", ENOTTY, 25 },
#endif
#ifdef ETXTBSY
- { ETXTBSY, 26 },
+ { "ETXTBSY", ETXTBSY, 26 },
#endif
#ifdef EFBIG
- { EFBIG, 27 },
+ { "EFBIG", EFBIG, 27 },
#endif
#ifdef ENOSPC
- { ENOSPC, 28 },
+ { "ENOSPC", ENOSPC, 28 },
#endif
#ifdef ESPIPE
- { ESPIPE, 29 },
+ { "ESPIPE", ESPIPE, 29 },
#endif
#ifdef EROFS
- { EROFS, 30 },
+ { "EROFS", EROFS, 30 },
#endif
#ifdef EMLINK
- { EMLINK, 31 },
+ { "EMLINK", EMLINK, 31 },
#endif
#ifdef EPIPE
- { EPIPE, 32 },
+ { "EPIPE", EPIPE, 32 },
#endif
#ifdef EDOM
- { EDOM, 33 },
+ { "EDOM", EDOM, 33 },
#endif
#ifdef ERANGE
- { ERANGE, 34 },
+ { "ERANGE", ERANGE, 34 },
#endif
#ifdef EDEADLK
- { EDEADLK, 35 },
+ { "EDEADLK", EDEADLK, 35 },
#endif
#ifdef ENAMETOOLONG
- { ENAMETOOLONG, 36 },
+ { "ENAMETOOLONG", ENAMETOOLONG, 36 },
#endif
#ifdef ENOLCK
- { ENOLCK, 37 },
+ { "ENOLCK", ENOLCK, 37 },
#endif
#ifdef ENOSYS
- { ENOSYS, 38 },
+ { "ENOSYS", ENOSYS, 38 },
#endif
#ifdef ENOTEMPTY
- { ENOTEMPTY, 39 },
+ { "ENOTEMPTY", ENOTEMPTY, 39 },
#endif
#ifdef ELOOP
- { ELOOP, 40 },
+ { "ELOOP", ELOOP, 40 },
#endif
#ifdef EWOULDBLOCK
- { EWOULDBLOCK, 11 },
+ { "EWOULDBLOCK", EWOULDBLOCK, 11 },
#endif
#ifdef ENOMSG
- { ENOMSG, 42 },
+ { "ENOMSG", ENOMSG, 42 },
#endif
#ifdef EIDRM
- { EIDRM, 43 },
+ { "EIDRM", EIDRM, 43 },
#endif
#ifdef ECHRNG
- { ECHRNG, 44 },
+ { "ECHRNG", ECHRNG, 44 },
#endif
#ifdef EL2NSYNC
- { EL2NSYNC, 45 },
+ { "EL2NSYNC", EL2NSYNC, 45 },
#endif
#ifdef EL3HLT
- { EL3HLT, 46 },
+ { "EL3HLT", EL3HLT, 46 },
#endif
#ifdef EL3RST
- { EL3RST, 47 },
+ { "EL3RST", EL3RST, 47 },
#endif
#ifdef ELNRNG
- { ELNRNG, 48 },
+ { "ELNRNG", ELNRNG, 48 },
#endif
#ifdef EUNATCH
- { EUNATCH, 49 },
+ { "EUNATCH", EUNATCH, 49 },
#endif
#ifdef ENOCSI
- { ENOCSI, 50 },
+ { "ENOCSI", ENOCSI, 50 },
#endif
#ifdef EL2HLT
- { EL2HLT, 51 },
+ { "EL2HLT", EL2HLT, 51 },
#endif
#ifdef EBADE
- { EBADE, 52 },
+ { "EBADE", EBADE, 52 },
#endif
#ifdef EBADR
- { EBADR, 53 },
+ { "EBADR", EBADR, 53 },
#endif
#ifdef EXFULL
- { EXFULL, 54 },
+ { "EXFULL", EXFULL, 54 },
#endif
#ifdef ENOANO
- { ENOANO, 55 },
+ { "ENOANO", ENOANO, 55 },
#endif
#ifdef EBADRQC
- { EBADRQC, 56 },
+ { "EBADRQC", EBADRQC, 56 },
#endif
#ifdef EBADSLT
- { EBADSLT, 57 },
+ { "EBADSLT", EBADSLT, 57 },
#endif
#ifdef EDEADLOCK
- { EDEADLOCK, 35 },
+ { "EDEADLOCK", EDEADLOCK, 35 },
#endif
#ifdef EBFONT
- { EBFONT, 59 },
+ { "EBFONT", EBFONT, 59 },
#endif
#ifdef ENOSTR
- { ENOSTR, 60 },
+ { "ENOSTR", ENOSTR, 60 },
#endif
#ifdef ENODATA
- { ENODATA, 61 },
+ { "ENODATA", ENODATA, 61 },
#endif
#ifdef ETIME
- { ETIME, 62 },
+ { "ETIME", ETIME, 62 },
#endif
#ifdef ENOSR
- { ENOSR, 63 },
+ { "ENOSR", ENOSR, 63 },
#endif
#ifdef ENONET
- { ENONET, 64 },
+ { "ENONET", ENONET, 64 },
#endif
#ifdef ENOPKG
- { ENOPKG, 65 },
+ { "ENOPKG", ENOPKG, 65 },
#endif
#ifdef EREMOTE
- { EREMOTE, 66 },
+ { "EREMOTE", EREMOTE, 66 },
#endif
#ifdef ENOLINK
- { ENOLINK, 67 },
+ { "ENOLINK", ENOLINK, 67 },
#endif
#ifdef EADV
- { EADV, 68 },
+ { "EADV", EADV, 68 },
#endif
#ifdef ESRMNT
- { ESRMNT, 69 },
+ { "ESRMNT", ESRMNT, 69 },
#endif
#ifdef ECOMM
- { ECOMM, 70 },
+ { "ECOMM", ECOMM, 70 },
#endif
#ifdef EPROTO
- { EPROTO, 71 },
+ { "EPROTO", EPROTO, 71 },
#endif
#ifdef EMULTIHOP
- { EMULTIHOP, 72 },
+ { "EMULTIHOP", EMULTIHOP, 72 },
#endif
#ifdef EDOTDOT
- { EDOTDOT, 73 },
+ { "EDOTDOT", EDOTDOT, 73 },
#endif
#ifdef EBADMSG
- { EBADMSG, 74 },
+ { "EBADMSG", EBADMSG, 74 },
#endif
#ifdef EOVERFLOW
- { EOVERFLOW, 75 },
+ { "EOVERFLOW", EOVERFLOW, 75 },
#endif
#ifdef ENOTUNIQ
- { ENOTUNIQ, 76 },
+ { "ENOTUNIQ", ENOTUNIQ, 76 },
#endif
#ifdef EBADFD
- { EBADFD, 77 },
+ { "EBADFD", EBADFD, 77 },
#endif
#ifdef EREMCHG
- { EREMCHG, 78 },
+ { "EREMCHG", EREMCHG, 78 },
#endif
#ifdef ELIBACC
- { ELIBACC, 79 },
+ { "ELIBACC", ELIBACC, 79 },
#endif
#ifdef ELIBBAD
- { ELIBBAD, 80 },
+ { "ELIBBAD", ELIBBAD, 80 },
#endif
#ifdef ELIBSCN
- { ELIBSCN, 81 },
+ { "ELIBSCN", ELIBSCN, 81 },
#endif
#ifdef ELIBMAX
- { ELIBMAX, 82 },
+ { "ELIBMAX", ELIBMAX, 82 },
#endif
#ifdef ELIBEXEC
- { ELIBEXEC, 83 },
+ { "ELIBEXEC", ELIBEXEC, 83 },
#endif
#ifdef EILSEQ
- { EILSEQ, 84 },
+ { "EILSEQ", EILSEQ, 84 },
#endif
#ifdef ERESTART
- { ERESTART, 85 },
+ { "ERESTART", ERESTART, 85 },
#endif
#ifdef ESTRPIPE
- { ESTRPIPE, 86 },
+ { "ESTRPIPE", ESTRPIPE, 86 },
#endif
#ifdef EUSERS
- { EUSERS, 87 },
+ { "EUSERS", EUSERS, 87 },
#endif
#ifdef ENOTSOCK
- { ENOTSOCK, 88 },
+ { "ENOTSOCK", ENOTSOCK, 88 },
#endif
#ifdef EDESTADDRREQ
- { EDESTADDRREQ, 89 },
+ { "EDESTADDRREQ", EDESTADDRREQ, 89 },
#endif
#ifdef EMSGSIZE
- { EMSGSIZE, 90 },
+ { "EMSGSIZE", EMSGSIZE, 90 },
#endif
#ifdef EPROTOTYPE
- { EPROTOTYPE, 91 },
+ { "EPROTOTYPE", EPROTOTYPE, 91 },
#endif
#ifdef ENOPROTOOPT
- { ENOPROTOOPT, 92 },
+ { "ENOPROTOOPT", ENOPROTOOPT, 92 },
#endif
#ifdef EPROTONOSUPPORT
- { EPROTONOSUPPORT, 93 },
+ { "EPROTONOSUPPORT", EPROTONOSUPPORT, 93 },
#endif
#ifdef ESOCKTNOSUPPORT
- { ESOCKTNOSUPPORT, 94 },
+ { "ESOCKTNOSUPPORT", ESOCKTNOSUPPORT, 94 },
#endif
#ifdef EOPNOTSUPP
- { EOPNOTSUPP, 95 },
+ { "EOPNOTSUPP", EOPNOTSUPP, 95 },
#endif
#ifdef EPFNOSUPPORT
- { EPFNOSUPPORT, 96 },
+ { "EPFNOSUPPORT", EPFNOSUPPORT, 96 },
#endif
#ifdef EAFNOSUPPORT
- { EAFNOSUPPORT, 97 },
+ { "EAFNOSUPPORT", EAFNOSUPPORT, 97 },
#endif
#ifdef EADDRINUSE
- { EADDRINUSE, 98 },
+ { "EADDRINUSE", EADDRINUSE, 98 },
#endif
#ifdef EADDRNOTAVAIL
- { EADDRNOTAVAIL, 99 },
+ { "EADDRNOTAVAIL", EADDRNOTAVAIL, 99 },
#endif
#ifdef ENETDOWN
- { ENETDOWN, 100 },
+ { "ENETDOWN", ENETDOWN, 100 },
#endif
#ifdef ENETUNREACH
- { ENETUNREACH, 101 },
+ { "ENETUNREACH", ENETUNREACH, 101 },
#endif
#ifdef ENETRESET
- { ENETRESET, 102 },
+ { "ENETRESET", ENETRESET, 102 },
#endif
#ifdef ECONNABORTED
- { ECONNABORTED, 103 },
+ { "ECONNABORTED", ECONNABORTED, 103 },
#endif
#ifdef ECONNRESET
- { ECONNRESET, 104 },
+ { "ECONNRESET", ECONNRESET, 104 },
#endif
#ifdef ENOBUFS
- { ENOBUFS, 105 },
+ { "ENOBUFS", ENOBUFS, 105 },
#endif
#ifdef EISCONN
- { EISCONN, 106 },
+ { "EISCONN", EISCONN, 106 },
#endif
#ifdef ENOTCONN
- { ENOTCONN, 107 },
+ { "ENOTCONN", ENOTCONN, 107 },
#endif
#ifdef ESHUTDOWN
- { ESHUTDOWN, 108 },
+ { "ESHUTDOWN", ESHUTDOWN, 108 },
#endif
#ifdef ETOOMANYREFS
- { ETOOMANYREFS, 109 },
+ { "ETOOMANYREFS", ETOOMANYREFS, 109 },
#endif
#ifdef ETIMEDOUT
- { ETIMEDOUT, 110 },
+ { "ETIMEDOUT", ETIMEDOUT, 110 },
#endif
#ifdef ECONNREFUSED
- { ECONNREFUSED, 111 },
+ { "ECONNREFUSED", ECONNREFUSED, 111 },
#endif
#ifdef EHOSTDOWN
- { EHOSTDOWN, 112 },
+ { "EHOSTDOWN", EHOSTDOWN, 112 },
#endif
#ifdef EHOSTUNREACH
- { EHOSTUNREACH, 113 },
+ { "EHOSTUNREACH", EHOSTUNREACH, 113 },
#endif
#ifdef EALREADY
- { EALREADY, 114 },
+ { "EALREADY", EALREADY, 114 },
#endif
#ifdef EINPROGRESS
- { EINPROGRESS, 115 },
+ { "EINPROGRESS", EINPROGRESS, 115 },
#endif
#ifdef ESTALE
- { ESTALE, 116 },
+ { "ESTALE", ESTALE, 116 },
#endif
#ifdef EUCLEAN
- { EUCLEAN, 117 },
+ { "EUCLEAN", EUCLEAN, 117 },
#endif
#ifdef ENOTNAM
- { ENOTNAM, 118 },
+ { "ENOTNAM", ENOTNAM, 118 },
#endif
#ifdef ENAVAIL
- { ENAVAIL, 119 },
+ { "ENAVAIL", ENAVAIL, 119 },
#endif
#ifdef EISNAM
- { EISNAM, 120 },
+ { "EISNAM", EISNAM, 120 },
#endif
#ifdef EREMOTEIO
- { EREMOTEIO, 121 },
+ { "EREMOTEIO", EREMOTEIO, 121 },
#endif
#ifdef EDQUOT
- { EDQUOT, 122 },
+ { "EDQUOT", EDQUOT, 122 },
#endif
#ifdef ENOMEDIUM
- { ENOMEDIUM, 123 },
+ { "ENOMEDIUM", ENOMEDIUM, 123 },
#endif
#ifdef EMEDIUMTYPE
- { EMEDIUMTYPE, 124 },
+ { "EMEDIUMTYPE", EMEDIUMTYPE, 124 },
#endif
- { 0, -1 }
+ { 0, 0, 0 }
};
/* Extracted by applying
static const CB_TARGET_DEFS_MAP open_map[] = {
#ifdef O_ACCMODE
- { O_ACCMODE, TARGET_O_ACCMODE },
+ { "O_ACCMODE", O_ACCMODE, TARGET_O_ACCMODE },
#endif
#ifdef O_RDONLY
- { O_RDONLY, TARGET_O_RDONLY },
+ { "O_RDONLY", O_RDONLY, TARGET_O_RDONLY },
#endif
#ifdef O_WRONLY
- { O_WRONLY, TARGET_O_WRONLY },
+ { "O_WRONLY", O_WRONLY, TARGET_O_WRONLY },
#endif
#ifdef O_RDWR
- { O_RDWR, 0x2 },
+ { "O_RDWR", O_RDWR, 0x2 },
#endif
#ifdef O_CREAT
- { O_CREAT, 0x40 },
+ { "O_CREAT", O_CREAT, 0x40 },
#endif
#ifdef O_EXCL
- { O_EXCL, 0x80 },
+ { "O_EXCL", O_EXCL, 0x80 },
#endif
#ifdef O_NOCTTY
- { O_NOCTTY, 0x100 },
+ { "O_NOCTTY", O_NOCTTY, 0x100 },
#endif
#ifdef O_TRUNC
- { O_TRUNC, 0x200 },
+ { "O_TRUNC", O_TRUNC, 0x200 },
#endif
#ifdef O_APPEND
- { O_APPEND, 0x400 },
+ { "O_APPEND", O_APPEND, 0x400 },
#endif
#ifdef O_NONBLOCK
- { O_NONBLOCK, 0x800 },
+ { "O_NONBLOCK", O_NONBLOCK, 0x800 },
#endif
#ifdef O_NDELAY
- { O_NDELAY, 0x0 },
+ { "O_NDELAY", O_NDELAY, 0x0 },
#endif
#ifdef O_SYNC
- { O_SYNC, 0x1000 },
+ { "O_SYNC", O_SYNC, 0x1000 },
#endif
#ifdef FASYNC
- { FASYNC, 0x2000 },
+ { "FASYNC", FASYNC, 0x2000 },
#endif
#ifdef O_DIRECT
- { O_DIRECT, 0x4000 },
+ { "O_DIRECT", O_DIRECT, 0x4000 },
#endif
#ifdef O_LARGEFILE
- { O_LARGEFILE, 0x8000 },
+ { "O_LARGEFILE", O_LARGEFILE, 0x8000 },
#endif
#ifdef O_DIRECTORY
- { O_DIRECTORY, 0x10000 },
+ { "O_DIRECTORY", O_DIRECTORY, 0x10000 },
#endif
#ifdef O_NOFOLLOW
- { O_NOFOLLOW, 0x20000 },
+ { "O_NOFOLLOW", O_NOFOLLOW, 0x20000 },
#endif
- { -1, -1 }
+ { 0, -1, -1 }
};
+/* Let's be less drastic and more traceable. FIXME: mark as noreturn. */
+#define abort() \
+ sim_io_error (sd, "simulator unhandled condition at %s:%d", \
+ __FUNCTION__, __LINE__)
+
/* Needed for the cris_pipe_nonempty and cris_pipe_empty syscalls. */
static SIM_CPU *current_cpu_for_cb_callback;
-static int syscall_read_mem (host_callback *, struct cb_syscall *,
- unsigned long, char *, int);
-static int syscall_write_mem (host_callback *, struct cb_syscall *,
- unsigned long, const char *, int);
static USI create_map (SIM_DESC, struct cris_sim_mmapped_page **,
USI addr, USI len);
static USI unmap_pages (SIM_DESC, struct cris_sim_mmapped_page **,
static void dump_statistics (SIM_CPU *current_cpu);
static void make_first_thread (SIM_CPU *current_cpu);
-/* Read/write functions for system call interface. */
-
-static int
-syscall_read_mem (host_callback *cb ATTRIBUTE_UNUSED,
- struct cb_syscall *sc,
- unsigned long taddr, char *buf, int bytes)
-{
- SIM_DESC sd = (SIM_DESC) sc->p1;
- SIM_CPU *cpu = (SIM_CPU *) sc->p2;
-
- return sim_core_read_buffer (sd, cpu, read_map, buf, taddr, bytes);
-}
-
-static int
-syscall_write_mem (host_callback *cb ATTRIBUTE_UNUSED,
- struct cb_syscall *sc,
- unsigned long taddr, const char *buf, int bytes)
-{
- SIM_DESC sd = (SIM_DESC) sc->p1;
- SIM_CPU *cpu = (SIM_CPU *) sc->p2;
-
- return sim_core_write_buffer (sd, cpu, write_map, buf, taddr, bytes);
-}
-
/* When we risk running self-modified code (as in trampolines), this is
called from special-case insns. The silicon CRIS CPU:s have enough
cache snooping implemented making this a simulator-only issue. Tests:
/* For v32, unaligned_mem_dword_count should always be 0. For
v10, memsrc_stall_count should always be 0. */
- sim_io_eprintf (sd, "Memory source stall cycles: %lld\n",
- profp->memsrc_stall_count
- + profp->unaligned_mem_dword_count);
- sim_io_eprintf (sd, "Memory read-after-write stall cycles: %lld\n",
- profp->memraw_stall_count);
- sim_io_eprintf (sd, "Movem source stall cycles: %lld\n",
- profp->movemsrc_stall_count);
- sim_io_eprintf (sd, "Movem destination stall cycles: %lld\n",
- profp->movemdst_stall_count);
- sim_io_eprintf (sd, "Movem address stall cycles: %lld\n",
- profp->movemaddr_stall_count);
- sim_io_eprintf (sd, "Multiplication source stall cycles: %lld\n",
- profp->mulsrc_stall_count);
- sim_io_eprintf (sd, "Jump source stall cycles: %lld\n",
- profp->jumpsrc_stall_count);
- sim_io_eprintf (sd, "Branch misprediction stall cycles: %lld\n",
- profp->branch_stall_count);
- sim_io_eprintf (sd, "Jump target stall cycles: %lld\n",
- profp->jumptarget_stall_count);
+ sim_io_eprintf (sd, "Memory source stall cycles: %llu\n",
+ (unsigned long long) (profp->memsrc_stall_count
+ + profp->unaligned_mem_dword_count));
+ sim_io_eprintf (sd, "Memory read-after-write stall cycles: %llu\n",
+ (unsigned long long) profp->memraw_stall_count);
+ sim_io_eprintf (sd, "Movem source stall cycles: %llu\n",
+ (unsigned long long) profp->movemsrc_stall_count);
+ sim_io_eprintf (sd, "Movem destination stall cycles: %llu\n",
+ (unsigned long long) profp->movemdst_stall_count);
+ sim_io_eprintf (sd, "Movem address stall cycles: %llu\n",
+ (unsigned long long) profp->movemaddr_stall_count);
+ sim_io_eprintf (sd, "Multiplication source stall cycles: %llu\n",
+ (unsigned long long) profp->mulsrc_stall_count);
+ sim_io_eprintf (sd, "Jump source stall cycles: %llu\n",
+ (unsigned long long) profp->jumpsrc_stall_count);
+ sim_io_eprintf (sd, "Branch misprediction stall cycles: %llu\n",
+ (unsigned long long) profp->branch_stall_count);
+ sim_io_eprintf (sd, "Jump target stall cycles: %llu\n",
+ (unsigned long long) profp->jumptarget_stall_count);
}
/* Check whether any part of [addr .. addr + len - 1] is already mapped.
return 0;
}
-/* Create mmapped memory. */
+/* Check whether any part of [addr .. addr + len - 1] is *un*mapped.
+ Return 1 if the whole area is mapped, 0 otherwise. */
+
+static USI
+is_mapped_only (SIM_DESC sd ATTRIBUTE_UNUSED,
+ struct cris_sim_mmapped_page **rootp,
+ USI addr, USI len)
+{
+ struct cris_sim_mmapped_page *mapp;
+
+ if (len == 0 || (len & 8191))
+ abort ();
+
+ /* Iterate over the reverse-address sorted pages until we find a page
+ lower than the checked area. */
+ for (mapp = *rootp; mapp != NULL && mapp->addr >= addr; mapp = mapp->prev)
+ if (addr == mapp->addr && len == 8192)
+ return 1;
+ else if (addr + len > mapp->addr)
+ len -= 8192;
+
+ return 0;
+}
+
+/* Debug helper; to be run from gdb. */
+
+void
+cris_dump_map (SIM_CPU *current_cpu)
+{
+ struct cris_sim_mmapped_page *mapp;
+ USI start, end;
+
+ for (mapp = current_cpu->highest_mmapped_page,
+ start = mapp == NULL ? 0 : mapp->addr + 8192,
+ end = mapp == NULL ? 0 : mapp->addr + 8191;
+ mapp != NULL;
+ mapp = mapp->prev)
+ {
+ if (mapp->addr != start - 8192)
+ {
+ sim_io_eprintf (CPU_STATE (current_cpu), "0x%x..0x%x\n", start, end);
+ end = mapp->addr + 8191;
+ }
+
+ start = mapp->addr;
+ }
+
+ if (current_cpu->highest_mmapped_page != NULL)
+ sim_io_eprintf (CPU_STATE (current_cpu), "0x%x..0x%x\n", start, end);
+}
+
+/* Create mmapped memory. ADDR is -1 if any address will do. Caller
+ must make sure that the address isn't already mapped. */
static USI
create_map (SIM_DESC sd, struct cris_sim_mmapped_page **rootp, USI addr,
struct cris_sim_mmapped_page **higher_prevp = rootp;
USI new_addr = 0x40000000;
- if (addr != 0)
+ if (addr != (USI) -1)
new_addr = addr;
- else if (*rootp)
+ else if (*rootp && rootp[0]->addr >= new_addr)
new_addr = rootp[0]->addr + 8192;
if (len != 8192)
mapp = mapp->prev)
higher_prevp = &mapp->prev;
+ /* Assert for consistency that we don't create duplicate maps. */
+ if (is_mapped (sd, rootp, new_addr, len))
+ abort ();
+
/* Allocate the new page, on the next higher page from the last one
allocated, and link in the new descriptor before previous ones. */
mapp = malloc (sizeof (*mapp));
if (len != 8192)
{
USI page_addr;
+ int ret = 0;
if (len & 8191)
/* Which is better: return an error for this, or just round it up? */
/* Loop backwards to make each call is O(1) over the number of pages
allocated, if we're unmapping from the high end of the pages. */
for (page_addr = addr + len - 8192;
- page_addr >= addr;
+ page_addr > addr;
page_addr -= 8192)
- if (unmap_pages (sd, rootp, page_addr, 8192) != 0)
- abort ();
+ if (unmap_pages (sd, rootp, page_addr, 8192))
+ ret = EINVAL;
+
+ if (unmap_pages (sd, rootp, addr, 8192))
+ ret = EINVAL;
- return 0;
+ return ret;
}
for (mapp = *rootp; mapp != NULL && mapp->addr > addr; mapp = mapp->prev)
UINT srcreg ATTRIBUTE_UNUSED,
USI dstreg ATTRIBUTE_UNUSED)
{
+ SIM_DESC sd = CPU_STATE (current_cpu);
abort ();
}
USI page ATTRIBUTE_UNUSED,
USI newval ATTRIBUTE_UNUSED)
{
+ SIM_DESC sd = CPU_STATE (current_cpu);
abort ();
}
UINT index ATTRIBUTE_UNUSED,
USI page ATTRIBUTE_UNUSED)
{
+ SIM_DESC sd = CPU_STATE (current_cpu);
abort ();
}
static void
reschedule (SIM_CPU *current_cpu)
{
+ SIM_DESC sd = CPU_STATE (current_cpu);
int i;
/* Iterate over all thread slots, because after a few thread creations
static void
make_first_thread (SIM_CPU *current_cpu)
{
+ SIM_DESC sd = CPU_STATE (current_cpu);
current_cpu->thread_data
= xcalloc (1,
SIM_TARGET_MAX_THREADS
abort ();
}
+/* Handle unknown system calls. Returns (if it does) the syscall
+ return value. */
+
+static USI
+cris_unknown_syscall (SIM_CPU *current_cpu, USI pc, char *s, ...)
+{
+ SIM_DESC sd = CPU_STATE (current_cpu);
+ host_callback *cb = STATE_CALLBACK (sd);
+
+ if (cris_unknown_syscall_action == CRIS_USYSC_MSG_STOP
+ || cris_unknown_syscall_action == CRIS_USYSC_MSG_ENOSYS)
+ {
+ va_list ap;
+
+ va_start (ap, s);
+ sim_io_evprintf (sd, s, ap);
+ va_end (ap);
+
+ if (cris_unknown_syscall_action == CRIS_USYSC_MSG_STOP)
+ sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGILL);
+ }
+
+ return -cb_host_to_target_errno (cb, ENOSYS);
+}
+
/* Main function: the handler of the "break 13" syscall insn. */
USI
s.arg2 = arg2;
s.arg3 = arg3;
- if (callnum == TARGET_SYS_exit && current_cpu->m1threads == 0)
+ /* The type of s.arg2 is long, so for hosts with 64-bit longs, we need
+ to sign-extend the lseek offset to be passed as a signed number,
+ else we'll truncate it to something > 2GB on hosts where sizeof
+ long > sizeof USI. We avoid doing it for all syscalls, as arg2 is
+ e.g. an address for some syscalls. */
+ if (callnum == TARGET_SYS_lseek)
+ s.arg2 = (SI) arg2;
+
+ if (callnum == TARGET_SYS_exit_group
+ || (callnum == TARGET_SYS_exit && current_cpu->m1threads == 0))
{
if (CPU_CRIS_MISC_PROFILE (current_cpu)->flags
& FLAG_CRIS_MISC_PROFILE_ALL)
s.p1 = (PTR) sd;
s.p2 = (PTR) current_cpu;
- s.read_mem = syscall_read_mem;
- s.write_mem = syscall_write_mem;
+ s.read_mem = sim_syscall_read_mem;
+ s.write_mem = sim_syscall_write_mem;
current_cpu_for_cb_callback = current_cpu;
}
/* FALLTHROUGH */
default:
- /* Abort for all other cases. */
- sim_io_eprintf (sd, "Unimplemented %s syscall "
- "(fd: 0x%lx: cmd: 0x%lx arg: 0x%lx)\n",
- callnum == TARGET_SYS_fcntl
- ? "fcntl" : "fcntl64",
- (unsigned long) (USI) arg1,
- (unsigned long) (USI) arg2,
- (unsigned long) (USI) arg3);
- sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
- SIM_SIGILL);
+ /* Nothing else is implemented. */
+ retval
+ = cris_unknown_syscall (current_cpu, pc,
+ "Unimplemented %s syscall "
+ "(fd: 0x%lx: cmd: 0x%lx arg: "
+ "0x%lx)\n",
+ callnum == TARGET_SYS_fcntl
+ ? "fcntl" : "fcntl64",
+ (unsigned long) (USI) arg1,
+ (unsigned long) (USI) arg2,
+ (unsigned long) (USI) arg3);
break;
}
break;
case TARGET_SYS_uname:
{
/* Fill in a few constants to appease glibc. */
- static const char sim_utsname[6][65] =
+ static char sim_utsname[6][65] =
{
"Linux",
"sim-target",
- "2.4.5",
+ "2.6.27",
TARGET_UTSNAME,
- "cris",
+ "cris", /* Overwritten below. */
"localdomain"
};
+ /* Having the hardware type in Linux equal to the bfd
+ printable name is deliberate: if you make config.guess
+ work on your Linux-type system the usual way, it
+ probably will; either the bfd printable_name or the
+ ambiguous arch_name. */
+ strcpy (sim_utsname[4], STATE_ARCHITECTURE (sd)->printable_name);
+
if ((s.write_mem) (cb, &s, arg1, (const char *) sim_utsname,
sizeof (sim_utsname))
!= sizeof (sim_utsname))
USI fd = arg5;
USI pgoff = arg6;
+ /* At 2.6.27, Linux (many (all?) ports, in the mmap2 syscalls)
+ still masked away this bit, so let's just ignore
+ it. */
+ flags &= ~TARGET_MAP_DENYWRITE;
+
/* If the simulator wants to mmap more than the very large
limit, something is wrong. FIXME: Return an error or
abort? Have command-line selectable? */
!= (TARGET_PROT_READ
| TARGET_PROT_WRITE
| TARGET_PROT_EXEC))
+ && (prot != (TARGET_PROT_READ | TARGET_PROT_EXEC))
&& prot != TARGET_PROT_READ)
|| (flags != (TARGET_MAP_ANONYMOUS | TARGET_MAP_PRIVATE)
&& flags != TARGET_MAP_PRIVATE
+ && flags != (TARGET_MAP_ANONYMOUS
+ | TARGET_MAP_PRIVATE | TARGET_MAP_FIXED)
+ && flags != (TARGET_MAP_PRIVATE | TARGET_MAP_FIXED)
&& flags != TARGET_MAP_SHARED)
- || (fd != (USI) -1 && prot != TARGET_PROT_READ)
- || pgoff != 0)
+ || (fd != (USI) -1
+ && prot != TARGET_PROT_READ
+ && prot != (TARGET_PROT_READ | TARGET_PROT_EXEC)
+ && prot != (TARGET_PROT_READ | TARGET_PROT_WRITE))
+ || (fd == (USI) -1 && pgoff != 0)
+ || (fd != (USI) -1 && (flags & TARGET_MAP_ANONYMOUS)))
{
- sim_io_eprintf (sd, "Unimplemented mmap2 call "
- "(0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
- (unsigned long) arg1,
- (unsigned long) arg2,
- (unsigned long) arg3,
- (unsigned long) arg4,
- (unsigned long) arg5,
- (unsigned long) arg6);
- sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
- SIM_SIGILL);
+ retval
+ = cris_unknown_syscall (current_cpu, pc,
+ "Unimplemented mmap2 call "
+ "(0x%lx, 0x%lx, 0x%lx, "
+ "0x%lx, 0x%lx, 0x%lx)\n",
+ (unsigned long) arg1,
+ (unsigned long) arg2,
+ (unsigned long) arg3,
+ (unsigned long) arg4,
+ (unsigned long) arg5,
+ (unsigned long) arg6);
break;
}
else if (fd != (USI) -1)
/* A non-aligned argument is allowed for files. */
USI newlen = (len + 8191) & ~8191;
- /* We only support read, which we should already have
- checked. Check again anyway. */
- if (prot != TARGET_PROT_READ)
+ /* We only support read, read|exec, and read|write,
+ which we should already have checked. Check again
+ anyway. */
+ if (prot != TARGET_PROT_READ
+ && prot != (TARGET_PROT_READ | TARGET_PROT_EXEC)
+ && prot != (TARGET_PROT_READ | TARGET_PROT_WRITE))
abort ();
+ if (flags & TARGET_MAP_FIXED)
+ unmap_pages (sd, ¤t_cpu->highest_mmapped_page,
+ addr, newlen);
+ else if (is_mapped (sd, ¤t_cpu->highest_mmapped_page,
+ addr, newlen))
+ addr = 0;
+
newaddr
- = create_map (sd, ¤t_cpu->highest_mmapped_page, addr,
+ = create_map (sd, ¤t_cpu->highest_mmapped_page,
+ addr != 0 || (flags & TARGET_MAP_FIXED)
+ ? addr : -1,
newlen);
if (newaddr >= (USI) -8191)
break;
}
+ /* We were asked for MAP_FIXED, but couldn't. */
+ if ((flags & TARGET_MAP_FIXED) && newaddr != addr)
+ {
+ abort ();
+ unmap_pages (sd, ¤t_cpu->highest_mmapped_page,
+ newaddr, newlen);
+ retval = -cb_host_to_target_errno (cb, EINVAL);
+ break;
+ }
+
/* Find the current position in the file. */
s.func = TARGET_SYS_lseek;
s.arg1 = fd;
abort ();
pos = s.result;
+ if (s.result < 0)
+ abort ();
+
+ /* Move to the correct offset in the file. */
+ s.func = TARGET_SYS_lseek;
+ s.arg1 = fd;
+ s.arg2 = pgoff*8192;
+ s.arg3 = SEEK_SET;
+ if (cb_syscall (cb, &s) != CB_RC_OK)
+ abort ();
+
if (s.result < 0)
abort ();
if (cb_syscall (cb, &s) != CB_RC_OK)
abort ();
- if ((USI) s.result != len)
+ /* If the result is a page or more lesser than what
+ was requested, something went wrong. */
+ if (len >= 8192 && (USI) s.result <= len - 8192)
abort ();
/* After reading, we need to go back to the previous
}
else
{
- USI newaddr
- = create_map (sd, ¤t_cpu->highest_mmapped_page, addr,
- (len + 8191) & ~8191);
+ USI newlen = (len + 8191) & ~8191;
+ USI newaddr;
+
+ if (flags & TARGET_MAP_FIXED)
+ unmap_pages (sd, ¤t_cpu->highest_mmapped_page,
+ addr, newlen);
+ else if (is_mapped (sd, ¤t_cpu->highest_mmapped_page,
+ addr, newlen))
+ addr = 0;
+
+ newaddr = create_map (sd, ¤t_cpu->highest_mmapped_page,
+ addr != 0 || (flags & TARGET_MAP_FIXED)
+ ? addr : -1,
+ newlen);
if (newaddr >= (USI) -8191)
retval = -cb_host_to_target_errno (cb, -(SI) newaddr);
else
retval = newaddr;
+
+ if ((flags & TARGET_MAP_FIXED) && newaddr != addr)
+ {
+ abort ();
+ unmap_pages (sd, ¤t_cpu->highest_mmapped_page,
+ newaddr, newlen);
+ retval = -cb_host_to_target_errno (cb, EINVAL);
+ break;
+ }
}
break;
}
case TARGET_SYS_mprotect:
{
- /* We only cover the case of linuxthreads mprotecting out its
- stack guard page. */
+ /* We only cover the case of linuxthreads mprotecting out
+ its stack guard page and of dynamic loading mprotecting
+ away the data (for some reason the whole library, then
+ mprotects away the data part and mmap-FIX:es it again. */
USI addr = arg1;
USI len = arg2;
USI prot = arg3;
- if ((addr & 8191) != 0
- || len != 8192
- || prot != TARGET_PROT_NONE
- || !is_mapped (sd, ¤t_cpu->highest_mmapped_page, addr,
- len))
+ if (prot != TARGET_PROT_NONE
+ || !is_mapped_only (sd, ¤t_cpu->highest_mmapped_page,
+ addr, (len + 8191) & ~8191))
{
- sim_io_eprintf (sd, "Unimplemented mprotect call "
- "(0x%lx, 0x%lx, 0x%lx)\n",
- (unsigned long) arg1,
- (unsigned long) arg2,
- (unsigned long) arg3);
- sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
- SIM_SIGILL);
+ retval
+ = cris_unknown_syscall (current_cpu, pc,
+ "Unimplemented mprotect call "
+ "(0x%lx, 0x%lx, 0x%lx)\n",
+ (unsigned long) arg1,
+ (unsigned long) arg2,
+ (unsigned long) arg3);
break;
}
- /* FIXME: We should account for pages like this that are
- "mprotected out". For now, we just tell the simulator
- core to remove that page from its map. */
- sim_core_detach (sd, NULL, 0, 0, addr);
+ /* Just ignore this. We could make this equal to munmap,
+ but then we'd have to make sure no anon mmaps gets this
+ address before a subsequent MAP_FIXED mmap intended to
+ override it. */
retval = 0;
break;
}
|| rusagep != 0
|| current_cpu->thread_data == NULL)
{
- sim_io_eprintf (sd, "Unimplemented wait4 call "
- "(0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
- (unsigned long) arg1,
- (unsigned long) arg2,
- (unsigned long) arg3,
- (unsigned long) arg4);
- sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
- SIM_SIGILL);
+ retval
+ = cris_unknown_syscall (current_cpu, pc,
+ "Unimplemented wait4 call "
+ "(0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
+ (unsigned long) arg1,
+ (unsigned long) arg2,
+ (unsigned long) arg3,
+ (unsigned long) arg4);
break;
}
&& target_sa_flags != (TARGET_SA_RESTART|TARGET_SA_SIGINFO))
|| target_sa_handler == 0)
{
- sim_io_eprintf (sd, "Unimplemented rt_sigaction "
- "syscall (0x%lx, "
- "0x%lx: [0x%x, 0x%x, 0x%x, "
- "{0x%x, 0x%x}], "
- "0x%lx)\n",
- (unsigned long) arg1,
- (unsigned long) arg2,
- target_sa_handler, target_sa_flags,
- target_sa_restorer,
- target_sa_mask_low, target_sa_mask_high,
- (unsigned long) arg3);
- sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
- SIM_SIGILL);
+ retval
+ = cris_unknown_syscall (current_cpu, pc,
+ "Unimplemented rt_sigaction "
+ "syscall "
+ "(0x%lx, 0x%lx: "
+ "[0x%x, 0x%x, 0x%x, "
+ "{0x%x, 0x%x}], 0x%lx)\n",
+ (unsigned long) arg1,
+ (unsigned long) arg2,
+ target_sa_handler,
+ target_sa_flags,
+ target_sa_restorer,
+ target_sa_mask_low,
+ target_sa_mask_high,
+ (unsigned long) arg3);
+ break;
}
current_cpu->sighandler[signum] = target_sa_handler;
mapped_addr
= create_map (sd, ¤t_cpu->highest_mmapped_page,
- 0, new_len);
+ -1, new_len);
if (mapped_addr > (USI) -8192)
{
|| ((events = sim_core_read_unaligned_2 (current_cpu, pc,
0, ufds + 4))
!= TARGET_POLLIN)
- || ((cb->fstat) (cb, fd, &buf) != 0
+ || ((cb->to_fstat) (cb, fd, &buf) != 0
|| (buf.st_mode & S_IFIFO) == 0)
|| current_cpu->thread_data == NULL)
{
- sim_io_eprintf (sd, "Unimplemented poll syscall "
- "(0x%lx: [0x%x, 0x%x, x], 0x%lx, 0x%lx)\n",
- (unsigned long) arg1, fd, events,
- (unsigned long) arg2, (unsigned long) arg3);
- sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGILL);
+ retval
+ = cris_unknown_syscall (current_cpu, pc,
+ "Unimplemented poll syscall "
+ "(0x%lx: [0x%x, 0x%x, x], "
+ "0x%lx, 0x%lx)\n",
+ (unsigned long) arg1, fd, events,
+ (unsigned long) arg2,
+ (unsigned long) arg3);
break;
}
if (!((offs_hi == 0 && offs_lo >= 0)
|| (offs_hi == -1 && offs_lo < 0)))
{
- sim_io_eprintf (sd,
- "Unimplemented llseek offset,"
- " fd %d: 0x%x:0x%x\n",
- fd, (unsigned) arg2, (unsigned) arg3);
- sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
- SIM_SIGILL);
+ retval
+ = cris_unknown_syscall (current_cpu, pc,
+ "Unimplemented llseek offset,"
+ " fd %d: 0x%x:0x%x\n",
+ fd, (unsigned) arg2,
+ (unsigned) arg3);
+ break;
}
s.func = TARGET_SYS_lseek;
break;
}
+ /* ssize_t writev(int fd, const struct iovec *iov, int iovcnt);
+ where:
+ struct iovec {
+ void *iov_base; Starting address
+ size_t iov_len; Number of bytes to transfer
+ }; */
+ case TARGET_SYS_writev:
+ {
+ SI fd = arg1;
+ SI iov = arg2;
+ SI iovcnt = arg3;
+ SI retcnt = 0;
+ int i;
+
+ /* We'll ignore strict error-handling and just do multiple write calls. */
+ for (i = 0; i < iovcnt; i++)
+ {
+ int sysret;
+ USI iov_base
+ = sim_core_read_unaligned_4 (current_cpu, pc, 0,
+ iov + 8*i);
+ USI iov_len
+ = sim_core_read_unaligned_4 (current_cpu, pc, 0,
+ iov + 8*i + 4);
+
+ s.func = TARGET_SYS_write;
+ s.arg1 = fd;
+ s.arg2 = iov_base;
+ s.arg3 = iov_len;
+
+ if (cb_syscall (cb, &s) != CB_RC_OK)
+ abort ();
+ sysret = s.result == -1 ? -s.errcode : s.result;
+
+ if (sysret != iov_len)
+ {
+ if (i != 0)
+ abort ();
+ retcnt = sysret;
+ break;
+ }
+
+ retcnt += iov_len;
+ }
+
+ retval = retcnt;
+ }
+ break;
+
/* This one does have a generic callback function, but at the time
of this writing, cb_syscall does not have code for it, and we
need target-specific code for the threads implementation
&& how != TARGET_SIG_SETMASK
&& how != TARGET_SIG_UNBLOCK)
{
- sim_io_eprintf (sd, "Unimplemented rt_sigprocmask syscall "
- "(0x%x, 0x%x, 0x%x)\n", arg1, arg2, arg3);
- sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
- SIM_SIGILL);
- retval = 0;
+ retval
+ = cris_unknown_syscall (current_cpu, pc,
+ "Unimplemented rt_sigprocmask "
+ "syscall (0x%x, 0x%x, 0x%x)\n",
+ arg1, arg2, arg3);
break;
}
|| (current_cpu->thread_data[threadno].cpu_context_atsignal
== NULL))
{
- sim_io_eprintf (sd, "Invalid sigreturn syscall: no signal"
- " handler active "
- "(0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
- (unsigned long) arg1,
- (unsigned long) arg2,
- (unsigned long) arg3,
- (unsigned long) arg4,
- (unsigned long) arg5,
- (unsigned long) arg6);
- sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
- SIM_SIGILL);
+ retval
+ = cris_unknown_syscall (current_cpu, pc,
+ "Invalid sigreturn syscall: "
+ "no signal handler active "
+ "(0x%lx, 0x%lx, 0x%lx, 0x%lx, "
+ "0x%lx, 0x%lx)\n",
+ (unsigned long) arg1,
+ (unsigned long) arg2,
+ (unsigned long) arg3,
+ (unsigned long) arg4,
+ (unsigned long) arg5,
+ (unsigned long) arg6);
+ break;
}
was_sigsuspended
if (setsize != 8)
{
- sim_io_eprintf (sd, "Unimplemented rt_sigsuspend syscall"
- " arguments (0x%lx, 0x%lx)\n",
- (unsigned long) arg1, (unsigned long) arg2);
- sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
- SIM_SIGILL);
+ retval
+ = cris_unknown_syscall (current_cpu, pc,
+ "Unimplemented rt_sigsuspend syscall"
+ " arguments (0x%lx, 0x%lx)\n",
+ (unsigned long) arg1,
+ (unsigned long) arg2);
+ break;
}
/* Don't change the signal mask if we're already in
USI buf = arg1;
USI size = arg2;
- char *cwd = xmalloc (MAXPATHLEN);
- if (cwd != getcwd (cwd, MAXPATHLEN))
+ char *cwd = xmalloc (SIM_PATHMAX);
+ if (cwd != getcwd (cwd, SIM_PATHMAX))
abort ();
/* FIXME: When and if we support chdir, we need something
break;
}
+ case TARGET_SYS_access:
+ {
+ SI path = arg1;
+ SI mode = arg2;
+ char *pbuf = xmalloc (SIM_PATHMAX);
+ int i;
+ int o = 0;
+ int hmode = 0;
+
+ if (sim_core_read_unaligned_1 (current_cpu, pc, 0, path) == '/')
+ {
+ strcpy (pbuf, simulator_sysroot);
+ o += strlen (simulator_sysroot);
+ }
+
+ for (i = 0; i + o < SIM_PATHMAX; i++)
+ {
+ pbuf[i + o]
+ = sim_core_read_unaligned_1 (current_cpu, pc, 0, path + i);
+ if (pbuf[i + o] == 0)
+ break;
+ }
+
+ if (i + o == SIM_PATHMAX)
+ {
+ retval = -cb_host_to_target_errno (cb, ENAMETOOLONG);
+ break;
+ }
+
+ /* Assert that we don't get calls for files for which we
+ don't have support. */
+ if (strncmp (pbuf + strlen (simulator_sysroot),
+ "/proc/", 6) == 0)
+ abort ();
+#define X_AFLAG(x) if (mode & TARGET_ ## x) hmode |= x
+ X_AFLAG (R_OK);
+ X_AFLAG (W_OK);
+ X_AFLAG (X_OK);
+ X_AFLAG (F_OK);
+#undef X_AFLAG
+
+ if (access (pbuf, hmode) != 0)
+ retval = -cb_host_to_target_errno (cb, errno);
+ else
+ retval = 0;
+
+ free (pbuf);
+ break;
+ }
+
case TARGET_SYS_readlink:
{
SI path = arg1;
SI buf = arg2;
SI bufsiz = arg3;
- char *pbuf = xmalloc (MAXPATHLEN);
- char *lbuf = xmalloc (MAXPATHLEN);
+ char *pbuf = xmalloc (SIM_PATHMAX);
+ char *lbuf = xmalloc (SIM_PATHMAX);
char *lbuf_alloc = lbuf;
int nchars = -1;
int i;
o += strlen (simulator_sysroot);
}
- for (i = 0; i + o < MAXPATHLEN; i++)
+ for (i = 0; i + o < SIM_PATHMAX; i++)
{
pbuf[i + o]
= sim_core_read_unaligned_1 (current_cpu, pc, 0, path + i);
break;
}
- if (i + o == MAXPATHLEN)
+ if (i + o == SIM_PATHMAX)
{
retval = -cb_host_to_target_errno (cb, ENAMETOOLONG);
break;
if (argv0 == NULL || *argv0 == '.')
{
- sim_io_eprintf (sd, "Unimplemented readlink syscall "
- "(0x%lx: [\"%s\"], 0x%lx)\n",
- (unsigned long) arg1, pbuf,
- (unsigned long) arg2);
- sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
- SIM_SIGILL);
+ retval
+ = cris_unknown_syscall (current_cpu, pc,
+ "Unimplemented readlink syscall "
+ "(0x%lx: [\"%s\"], 0x%lx)\n",
+ (unsigned long) arg1, pbuf,
+ (unsigned long) arg2);
break;
}
else if (*argv0 == '/')
}
else
{
- if (getcwd (lbuf, MAXPATHLEN) != NULL
- && strlen (lbuf) + 2 + strlen (argv0) < MAXPATHLEN)
+ if (getcwd (lbuf, SIM_PATHMAX) != NULL
+ && strlen (lbuf) + 2 + strlen (argv0) < SIM_PATHMAX)
{
if (strncmp (simulator_sysroot, lbuf,
strlen (simulator_sysroot)) == 0)
}
}
else
- nchars = readlink (pbuf, lbuf, MAXPATHLEN);
+ nchars = readlink (pbuf, lbuf, SIM_PATHMAX);
/* We trust that the readlink result returns a *relative*
link, or one already adjusted for the file-path-prefix.
break;
}
- sim_io_eprintf (sd, "Unimplemented _sysctl syscall "
- "(0x%lx: [0x%lx, 0x%lx],"
- " 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
- (unsigned long) name,
- (unsigned long) name0,
- (unsigned long) name1,
- (unsigned long) nlen,
- (unsigned long) oldval,
- (unsigned long) oldlenp,
- (unsigned long) newval,
- (unsigned long) newlen);
- sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
- SIM_SIGILL);
+ retval
+ = cris_unknown_syscall (current_cpu, pc,
+ "Unimplemented _sysctl syscall "
+ "(0x%lx: [0x%lx, 0x%lx],"
+ " 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
+ (unsigned long) name,
+ (unsigned long) name0,
+ (unsigned long) name1,
+ (unsigned long) nlen,
+ (unsigned long) oldval,
+ (unsigned long) oldlenp,
+ (unsigned long) newval,
+ (unsigned long) newlen);
break;
}
| TARGET_CLONE_SIGHAND)
|| newsp == 0)
{
- sim_io_eprintf (sd,
- "Unimplemented clone syscall (0x%lx, 0x%lx)\n",
- (unsigned long) arg1, (unsigned long) arg2);
- sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
- SIM_SIGILL);
+ retval
+ = cris_unknown_syscall (current_cpu, pc,
+ "Unimplemented clone syscall "
+ "(0x%lx, 0x%lx)\n",
+ (unsigned long) arg1,
+ (unsigned long) arg2);
+ break;
}
if (current_cpu->thread_data == NULL)
retval = -cb_host_to_target_errno (cb, ENOSYS);
break;
+ case TARGET_SYS_set_thread_area:
+ /* Do the same error check as Linux. */
+ if (arg1 & 255)
+ {
+ retval = -cb_host_to_target_errno (cb, EINVAL);
+ break;
+ }
+ (*current_cpu->set_target_thread_data) (current_cpu, arg1);
+ retval = 0;
+ break;
+
unimplemented_syscall:
default:
- sim_io_eprintf (sd, "Unimplemented syscall: %d "
- "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", callnum,
- arg1, arg2, arg3, arg4, arg5, arg6);
- sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
- SIM_SIGILL);
+ retval
+ = cris_unknown_syscall (current_cpu, pc,
+ "Unimplemented syscall: %d "
+ "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
+ callnum, arg1, arg2, arg3, arg4, arg5,
+ arg6);
}
}
current_cpu->last_open_fd = retval;
current_cpu->last_open_flags = arg2;
}
+
current_cpu->last_syscall = callnum;
/* A system call is a rescheduling point. For the time being, we don't
static void
cris_pipe_empty (host_callback *cb,
- int reader ATTRIBUTE_UNUSED,
+ int reader,
int writer)
{
int i;
SIM_CPU *cpu = current_cpu_for_cb_callback;
+ SIM_DESC sd = CPU_STATE (current_cpu_for_cb_callback);
bfd_byte r10_buf[4];
- int remaining = cb->pipe_buffer[writer].size;
+ int remaining
+ = cb->pipe_buffer[writer].size - cb->pipe_buffer[reader].size;
/* We need to find the thread that waits for this pipe. */
for (i = 0; i < SIM_TARGET_MAX_THREADS; i++)
&& cpu->thread_data[i].pipe_write_fd == writer)
{
int retval;
+
/* Temporarily switch to this cpu context, so we can change the
PC by ordinary calls. */
cpu->thread_data[i].cpu_context,
cpu->thread_cpu_data_size);
- /* The return value is supposed to contain the number of written
- bytes, which is the number of bytes requested and returned at
- the write call. We subtract the remaining bytes from that,
- but making sure we still get a positive number.
- The return value may also be a negative number; an error
- value. We cover this case by comparing against remaining,
- which is always >= 0. */
+ /* The return value is supposed to contain the number of
+ written bytes, which is the number of bytes requested and
+ returned at the write call. You might think the right
+ thing is to adjust the return-value to be only the
+ *consumed* number of bytes, but it isn't. We're only
+ called if the pipe buffer is fully consumed or it is being
+ closed, possibly with remaining bytes. For the latter
+ case, the writer is still supposed to see success for
+ PIPE_BUF bytes (a constant which we happen to know and is
+ unlikely to change). The return value may also be a
+ negative number; an error value. This case is covered
+ because "remaining" is always >= 0. */
(*CPU_REG_FETCH (cpu)) (cpu, H_GR_R10, r10_buf, 4);
retval = (int) bfd_getl_signed_32 (r10_buf);
- if (retval >= remaining)
- bfd_putl32 (retval - remaining, r10_buf);
- (*CPU_REG_STORE (cpu)) (cpu, H_GR_R10, r10_buf, 4);
-
+ if (retval - remaining > TARGET_PIPE_BUF)
+ {
+ bfd_putl32 (retval - remaining, r10_buf);
+ (*CPU_REG_STORE (cpu)) (cpu, H_GR_R10, r10_buf, 4);
+ }
sim_pc_set (cpu, sim_pc_get (cpu) + 2);
memcpy (cpu->thread_data[i].cpu_context,
&cpu->cpu_data_placeholder,