X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=sim%2Fcris%2Ftraps.c;h=98d1e03294ed89f211859cf2523ed751728492df;hb=af0b2a3e85df9f49a3528e5b7578fcf9412f1acc;hp=607f72c6345c830b6c0190e5e72420eaf2b92823;hpb=ed1f044ac6423184b2e2b8f805ddc4f76ea1256c;p=deliverable%2Fbinutils-gdb.git diff --git a/sim/cris/traps.c b/sim/cris/traps.c index 607f72c634..98d1e03294 100644 --- a/sim/cris/traps.c +++ b/sim/cris/traps.c @@ -1,28 +1,29 @@ /* CRIS exception, interrupt, and trap (EIT) support - Copyright (C) 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2004-2020 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 . */ #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 #ifdef HAVE_ERRNO_H #include #endif @@ -38,6 +39,21 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifdef HAVE_SYS_STAT_H #include #endif +/* For PATH_MAX, originally. */ +#ifdef HAVE_LIMITS_H +#include +#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. */ @@ -50,6 +66,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #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 @@ -72,6 +89,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #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 @@ -96,6 +114,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #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 @@ -107,6 +127,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #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 @@ -126,10 +147,11 @@ with this program; if not, write to the Free Software Foundation, Inc., #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. */ @@ -225,6 +247,15 @@ with this program; if not, write to the Free Software Foundation, Inc., #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" @@ -233,22 +264,21 @@ static const char stat_map[] = 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_time, TARGET_SYS_time }, - { 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. */ @@ -261,9 +291,9 @@ static const char stat32_map[] = 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 @@ -282,378 +312,378 @@ static const CB_TARGET_DEFS_MAP syscall_stat32_map[] = 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 @@ -664,71 +694,76 @@ static const CB_TARGET_DEFS_MAP errno_map[] = installation and removing synonyms and unnecessary items. Don't forget the end-marker. */ -/* This one we treat specially, as it's used in the fcntl syscall. */ -#define TARGET_O_ACCMODE 3 +/* These we treat specially, as they're used in the fcntl F_GETFL + syscall. For consistency, open_map is also manually edited to use + these macros. */ +#define TARGET_O_ACCMODE 0x3 +#define TARGET_O_RDONLY 0x0 +#define TARGET_O_WRONLY 0x1 static const CB_TARGET_DEFS_MAP open_map[] = { #ifdef O_ACCMODE - { O_ACCMODE, 0x3 }, + { "O_ACCMODE", O_ACCMODE, TARGET_O_ACCMODE }, #endif #ifdef O_RDONLY - { O_RDONLY, 0x0 }, + { "O_RDONLY", O_RDONLY, TARGET_O_RDONLY }, #endif #ifdef O_WRONLY - { O_WRONLY, 0x1 }, + { "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 **, @@ -738,30 +773,6 @@ static USI is_mapped (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: @@ -848,25 +859,25 @@ dump_statistics (SIM_CPU *current_cpu) /* 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. @@ -891,7 +902,59 @@ is_mapped (SIM_DESC sd ATTRIBUTE_UNUSED, 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, @@ -901,9 +964,9 @@ 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) @@ -927,6 +990,10 @@ create_map (SIM_DESC sd, struct cris_sim_mmapped_page **rootp, USI addr, 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)); @@ -957,6 +1024,7 @@ unmap_pages (SIM_DESC sd, struct cris_sim_mmapped_page **rootp, USI addr, 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? */ @@ -965,12 +1033,15 @@ unmap_pages (SIM_DESC sd, struct cris_sim_mmapped_page **rootp, USI addr, /* 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) @@ -1003,6 +1074,7 @@ cris_bmod_handler (SIM_CPU *current_cpu ATTRIBUTE_UNUSED, UINT srcreg ATTRIBUTE_UNUSED, USI dstreg ATTRIBUTE_UNUSED) { + SIM_DESC sd = CPU_STATE (current_cpu); abort (); } @@ -1012,6 +1084,7 @@ h_supr_set_handler (SIM_CPU *current_cpu ATTRIBUTE_UNUSED, USI page ATTRIBUTE_UNUSED, USI newval ATTRIBUTE_UNUSED) { + SIM_DESC sd = CPU_STATE (current_cpu); abort (); } @@ -1020,6 +1093,7 @@ h_supr_get_handler (SIM_CPU *current_cpu ATTRIBUTE_UNUSED, UINT index ATTRIBUTE_UNUSED, USI page ATTRIBUTE_UNUSED) { + SIM_DESC sd = CPU_STATE (current_cpu); abort (); } @@ -1176,6 +1250,7 @@ schedule (SIM_CPU *current_cpu, int next) 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 @@ -1313,6 +1388,7 @@ deliver_signal (SIM_CPU *current_cpu, int sig, unsigned int pid) 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 @@ -1328,6 +1404,31 @@ make_first_thread (SIM_CPU *current_cpu) 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 @@ -1349,7 +1450,16 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, 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) @@ -1359,8 +1469,8 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, 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; @@ -1429,18 +1539,34 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, retval = current_cpu->last_open_flags & TARGET_O_ACCMODE; break; } + else if (arg1 == 0) + { + /* Because we can't freopen fd:s 0, 1, 2 to mean + something else than stdin, stdout and stderr + (sim/common/syscall.c:cb_syscall special cases fd + 0, 1 and 2), we know what flags that we can + sanely return for these fd:s. */ + retval = TARGET_O_RDONLY; + break; + } + else if (arg1 == 1 || arg1 == 2) + { + retval = TARGET_O_WRONLY; + break; + } /* FALLTHROUGH */ - /* Abort for all other cases. */ default: - 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; @@ -1448,16 +1574,23 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, 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)) @@ -1541,6 +1674,11 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, 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? */ @@ -1555,23 +1693,32 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, != (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) @@ -1584,13 +1731,25 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, /* 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) @@ -1600,6 +1759,16 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, 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; @@ -1609,6 +1778,17 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, 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 (); @@ -1621,7 +1801,9 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, 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 @@ -1639,46 +1821,66 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, } 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; } @@ -1730,14 +1932,14 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, || 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; } @@ -1843,19 +2045,22 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, && 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; @@ -1916,7 +2121,7 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, mapped_addr = create_map (sd, ¤t_cpu->highest_mmapped_page, - 0, new_len); + -1, new_len); if (mapped_addr > (USI) -8192) { @@ -1972,15 +2177,18 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, || ((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; } @@ -2025,6 +2233,17 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, break; } + case TARGET_SYS_time: + { + retval = (int) (*cb->time) (cb, 0L); + + /* At time of this writing, CB_SYSCALL_time doesn't do the + part of setting *arg1 to the return value. */ + if (arg1) + sim_core_write_unaligned_4 (current_cpu, pc, 0, arg1, retval); + break; + } + case TARGET_SYS_gettimeofday: if (arg1 != 0) { @@ -2061,12 +2280,13 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, 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; @@ -2090,6 +2310,55 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, 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 @@ -2144,11 +2413,11 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, && 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; } @@ -2219,17 +2488,19 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, || (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 @@ -2295,11 +2566,13 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, 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 @@ -2384,8 +2657,8 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, 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 @@ -2406,13 +2679,63 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, 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; @@ -2424,7 +2747,7 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, 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); @@ -2432,7 +2755,7 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, break; } - if (i + o == MAXPATHLEN) + if (i + o == SIM_PATHMAX) { retval = -cb_host_to_target_errno (cb, ENAMETOOLONG); break; @@ -2449,12 +2772,12 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, 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 == '/') @@ -2468,8 +2791,8 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, } 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) @@ -2484,7 +2807,7 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, } } 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. @@ -2687,19 +3010,19 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, 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; } @@ -2772,11 +3095,13 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, | 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) @@ -2837,13 +3162,25 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, 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); } } @@ -2853,6 +3190,7 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, 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 @@ -2927,13 +3265,15 @@ cris_pipe_nonempty (host_callback *cb ATTRIBUTE_UNUSED, 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++) @@ -2941,6 +3281,7 @@ cris_pipe_empty (host_callback *cb, && 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. */ @@ -2951,19 +3292,25 @@ cris_pipe_empty (host_callback *cb, 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,