X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=sim%2Fcris%2Ftraps.c;h=98d1e03294ed89f211859cf2523ed751728492df;hb=af0b2a3e85df9f49a3528e5b7578fcf9412f1acc;hp=02056ccceb09105f834ce83a1c1496ffc356a092;hpb=6a4669ea53eb49d3caeaa5dcc1a737e9acef530f;p=deliverable%2Fbinutils-gdb.git diff --git a/sim/cris/traps.c b/sim/cris/traps.c index 02056ccceb..98d1e03294 100644 --- a/sim/cris/traps.c +++ b/sim/cris/traps.c @@ -1,24 +1,24 @@ /* CRIS exception, interrupt, and trap (EIT) support - Copyright (C) 2004, 2005, 2007 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. */ @@ -66,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 @@ -88,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 @@ -112,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 @@ -123,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 @@ -142,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. */ @@ -244,6 +250,12 @@ with this program; if not, write to the Free Software Foundation, Inc., /* 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" @@ -252,21 +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_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. */ @@ -279,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 @@ -300,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 @@ -691,66 +703,67 @@ static const CB_TARGET_DEFS_MAP errno_map[] = 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 **, @@ -760,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: @@ -913,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, @@ -923,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) @@ -949,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)); @@ -979,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? */ @@ -987,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) @@ -1025,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 (); } @@ -1034,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 (); } @@ -1042,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 (); } @@ -1198,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 @@ -1335,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 @@ -1396,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) @@ -1406,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; @@ -1511,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)) @@ -1604,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? */ @@ -1618,12 +1693,20 @@ 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))) { retval = cris_unknown_syscall (current_cpu, pc, @@ -1648,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) @@ -1664,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; @@ -1673,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 (); @@ -1685,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 @@ -1703,31 +1821,51 @@ 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)) { retval = cris_unknown_syscall (current_cpu, pc, @@ -1739,10 +1877,10 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1, 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; } @@ -1983,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) { @@ -2039,7 +2177,7 @@ 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) { @@ -2172,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 @@ -2492,6 +2679,56 @@ 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; @@ -2925,6 +3162,17 @@ 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: retval @@ -3022,6 +3270,7 @@ cris_pipe_empty (host_callback *cb, { 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 - cb->pipe_buffer[reader].size;