This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Committed: part 2 of cris/sim dynamic linking support.


Ok, so maybe writev-support isn't strictly necessary; it was
just from a glibc assert that trigged when I missed loading the
program headers. :)

Committed.

sim:
	* 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.

Index: cris/traps.c
===================================================================
RCS file: /cvs/src/src/sim/cris/traps.c,v
retrieving revision 1.14
diff -p -u -r1.14 traps.c
--- cris/traps.c	1 Jan 2008 22:53:24 -0000	1.14
+++ cris/traps.c	30 Dec 2008 13:32:49 -0000
@@ -87,6 +87,7 @@ along with this program.  If not, see <h
 #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_
 		     != (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_
 		/* 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_
 		    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;
@@ -1675,6 +1756,17 @@ cris_break_13_handler (SIM_CPU *current_
 		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 ();
+
 		/* Use the standard read callback to read in "len"
 		   bytes.  */
 		s.func = TARGET_SYS_read;
@@ -1702,31 +1794,47 @@ cris_break_13_handler (SIM_CPU *current_
 	      }
 	    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_
 		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_
 	    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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]