* cris/traps.c (TARGET_SYS_writev): New macro.
authorHans-Peter Nilsson <hp@axis.com>
Tue, 30 Dec 2008 13:36:17 +0000 (13:36 +0000)
committerHans-Peter Nilsson <hp@axis.com>
Tue, 30 Dec 2008 13:36:17 +0000 (13:36 +0000)
(is_mapped_only, cris_dump_map): New functions.
(cris_break_13_handler) <case TARGET_SYS_mmap2>: Handle more flags
and prot combinations and a non-zero page-offset.  If
TARGET_MAP_FIXED, unmap pages before mapping them.
<case TARGET_SYS_mprotect>: When checking, allow any length
argument.  Don't actually do anything.
<case TARGET_SYS_writev>: New case.

sim/ChangeLog
sim/cris/traps.c

index fa8bcc60907322bfcef64645868fbbf38ed3d3ca..c4b5eada9b7d1d17dc31afae3981885a64cc702e 100644 (file)
@@ -1,5 +1,14 @@
 2008-12-30  Hans-Peter Nilsson  <hp@axis.com>
 
+       * cris/traps.c (TARGET_SYS_writev): New macro.
+       (is_mapped_only, cris_dump_map): New functions.
+       (cris_break_13_handler) <case TARGET_SYS_mmap2>: Handle more flags
+       and prot combinations and a non-zero page-offset.  If
+       TARGET_MAP_FIXED, unmap pages before mapping them.
+       <case TARGET_SYS_mprotect>: When checking, allow any length
+       argument.  Don't actually do anything.
+       <case TARGET_SYS_writev>: New case.
+
        * cris/Makefile.in (SIM_OBJS): Remove sim-hload.o.
        * cris/sim-if.c: Include elf-bfd.h.
        (struct progbounds): New members end_loadmem, start_nonloadmem.
index 05c364eee201f97521e9c76d7994f4e6f909fe5a..044d6c67ad7548bf4984b13740ee91dc2a922e8a 100644 (file)
@@ -87,6 +87,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 #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
@@ -912,6 +913,57 @@ is_mapped (SIM_DESC sd ATTRIBUTE_UNUSED,
   return 0;
 }
 
+/* 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.  */
 
 static USI
@@ -1617,12 +1669,23 @@ 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))
+               || ((flags & TARGET_MAP_FIXED) == 0
+                   && is_mapped (sd, &current_cpu->highest_mmapped_page,
+                                 addr, (len + 8191) & ~8191)))
              {
                retval
                  = cris_unknown_syscall (current_cpu, pc,
@@ -1647,9 +1710,17 @@ 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, &current_cpu->highest_mmapped_page,
+                                   addr, newlen) != 0)
                  abort ();
 
                newaddr
@@ -1663,6 +1734,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, &current_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;
@@ -1672,6 +1753,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 ();
 
@@ -1702,31 +1794,47 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
              }
            else
              {
-               USI newaddr
-                 = create_map (sd, &current_cpu->highest_mmapped_page, addr,
-                               (len + 8191) & ~8191);
+               USI newlen = (len + 8191) & ~8191;
+               USI newaddr;
+
+               if ((flags & TARGET_MAP_FIXED)
+                   && unmap_pages (sd, &current_cpu->highest_mmapped_page,
+                                   addr, newlen) != 0)
+                 abort ();
+
+               newaddr = create_map (sd, &current_cpu->highest_mmapped_page, addr,
+                               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, &current_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, &current_cpu->highest_mmapped_page, addr,
-                              len))
+           if (prot != TARGET_PROT_NONE
+               || !is_mapped_only (sd, &current_cpu->highest_mmapped_page,
+                                   addr, (len + 8191) & ~8191))
              {
                retval
                  = cris_unknown_syscall (current_cpu, pc,
@@ -1738,10 +1846,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;
          }
@@ -2171,6 +2279,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
This page took 0.029606 seconds and 4 git commands to generate.