Index: Makefile.tool-flags.am
===================================================================
--- Makefile.tool-flags.am	(revision 3480)
+++ Makefile.tool-flags.am	(working copy)
@@ -1,6 +1,7 @@
 ## Need $(top_builddir)/include because tool.h is built from tool.h.base;
 ## otherwise it will not work if builddir != srcdir.
 add_includes = -I$(top_builddir)/include -I$(top_srcdir)/include \
+		-I$(top_srcdir)/include/kal \
 		-I$(top_srcdir)/include/$(VG_ARCH) \
 		-I$(top_srcdir)/include/$(VG_OS) \
 		-I$(top_srcdir)/include/$(VG_PLATFORM) \
Index: configure.in
===================================================================
--- configure.in	(revision 3480)
+++ configure.in	(working copy)
@@ -394,6 +394,7 @@
    auxprogs/Makefile
    coregrind/Makefile 
    coregrind/demangle/Makefile 
+   coregrind/kal/Makefile
    coregrind/amd64/Makefile
    coregrind/arm/Makefile
    coregrind/x86/Makefile
Index: Makefile.core-AM_CPPFLAGS.am
===================================================================
--- Makefile.core-AM_CPPFLAGS.am	(revision 3480)
+++ Makefile.core-AM_CPPFLAGS.am	(working copy)
@@ -1,5 +1,7 @@
 add_includes = -I$(top_builddir)/coregrind -I$(top_srcdir)/coregrind \
 		-I$(top_srcdir) \
+		-I$(top_srcdir)/coregrind/kal \
+		-I$(top_builddir)/coregrind/kal \
 		-I$(top_srcdir)/coregrind/$(VG_ARCH) \
 		-I$(top_builddir)/coregrind/$(VG_ARCH) \
 		-I$(top_srcdir)/coregrind/$(VG_OS) \
Index: coregrind/vg_memory.c
===================================================================
--- coregrind/vg_memory.c	(revision 3480)
+++ coregrind/vg_memory.c	(working copy)
@@ -953,9 +953,9 @@
    
    while (s && addr <= VG_(valgrind_last)) {
       if (addr < s->addr) {
-         VGP_DO_MMAP(ret, addr, s->addr - addr, 0,
-                     VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
-                     -1, 0);
+         ret = VG_(kal_mmap)(addr, s->addr - addr, 0,
+                             VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
+                             -1, 0);
       }
       addr = s->addr + s->len;
       i++;
@@ -963,9 +963,9 @@
    }
 
    if (addr <= VG_(valgrind_last)) {
-      VGP_DO_MMAP(ret, addr, VG_(valgrind_last) - addr + 1, 0,
-                  VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
-                  -1, 0);
+      ret = VG_(kal_mmap)(addr, VG_(valgrind_last) - addr + 1, 0,
+                          VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS,
+                          -1, 0);
    }
 }
 
@@ -974,14 +974,13 @@
 void VG_(unpad_address_space)(Addr start)
 {
    Addr     addr = (start == 0) ? VG_(client_base) : start;
-   Int      ret;
 
    Int      i = 0;
    Segment* s = i >= segments_used ? NULL : &segments[i];
 
    while (s && addr <= VG_(valgrind_last)) {
       if (addr < s->addr) {
-         ret = VG_(do_syscall2)(__NR_munmap, addr, s->addr - addr);
+         VG_(kal_munmap)(addr, s->addr - addr);
       }
       addr = s->addr + s->len;
       i++;
@@ -989,8 +988,7 @@
    }
 
    if (addr <= VG_(valgrind_last)) {
-      ret = VG_(do_syscall2)(__NR_munmap, addr, 
-                             (VG_(valgrind_last) - addr) + 1);
+      VG_(kal_munmap)(addr, (VG_(valgrind_last) - addr) + 1);
    }
 }
 
Index: coregrind/vg_mylibc.c
===================================================================
--- coregrind/vg_mylibc.c	(revision 3480)
+++ coregrind/vg_mylibc.c	(working copy)
@@ -148,37 +148,26 @@
 */
 Int VG_(sigprocmask)( Int how, const vki_sigset_t* set, vki_sigset_t* oldset)
 {
-   Int res = VG_(do_syscall4)(__NR_rt_sigprocmask, 
-                              how, (UWord)set, (UWord)oldset, 
-                              _VKI_NSIG_WORDS * sizeof(UWord));
-   return VG_(is_kerror)(res) ? -1 : 0;
+   return VG_(kal_sigprocmask)(how, set, oldset);
 }
 
 
 Int VG_(sigaction) ( Int signum, const struct vki_sigaction* act,  
                      struct vki_sigaction* oldact)
 {
-   Int res = VG_(do_syscall4)(__NR_rt_sigaction,
-		              signum, (UWord)act, (UWord)oldact, 
-		              _VKI_NSIG_WORDS * sizeof(UWord));
-   /* VG_(printf)("res = %d\n",res); */
-   return VG_(is_kerror)(res) ? -1 : 0;
+   return VG_(kal_sigaction)(signum, act, oldact);
 }
 
 
 Int VG_(sigaltstack)( const vki_stack_t* ss, vki_stack_t* oss )
 {
-   Int res = VG_(do_syscall2)(__NR_sigaltstack, (UWord)ss, (UWord)oss);
-   return VG_(is_kerror)(res) ? -1 : 0;
+   return VG_(kal_sigaltstack)(ss, oss);
 }
 
 Int VG_(sigtimedwait)( const vki_sigset_t *set, vki_siginfo_t *info, 
                        const struct vki_timespec *timeout )
 {
-   Int res = VG_(do_syscall4)(__NR_rt_sigtimedwait, (UWord)set, (UWord)info, 
-                              (UWord)timeout, sizeof(*set));
-
-   return res;
+   return VG_(kal_sigtimedwait)(set, info, timeout);
 }
  
 Int VG_(signal)(Int signum, void (*sighandler)(Int))
@@ -190,89 +179,34 @@
    sa.sa_restorer = NULL;
    res = VG_(sigemptyset)( &sa.sa_mask );
    vg_assert(res == 0);
-   res = VG_(do_syscall4)(__NR_rt_sigaction, signum, (UWord)&sa, (UWord)NULL,
-			 _VKI_NSIG_WORDS * sizeof(UWord));
-   return VG_(is_kerror)(res) ? -1 : 0;
+   return VG_(kal_sigaction)(signum, &sa, NULL);
 }
 
 
 Int VG_(kill)( Int pid, Int signo )
 {
-   Int res = VG_(do_syscall2)(__NR_kill, pid, signo);
-   return VG_(is_kerror)(res) ? -1 : 0;
+   return VG_(kal_kill)(pid, signo);
 }
 
 
 Int VG_(tkill)( ThreadId tid, Int signo )
 {
-   Int ret = -VKI_ENOSYS;
-
-#if 0
-   /* This isn't right because the client may create a process
-      structure with multiple thread groups */
-   ret = VG_(do_syscall)(__NR_tgkill, VG_(getpid)(), tid, signo);
-#endif
-
-   ret = VG_(do_syscall2)(__NR_tkill, tid, signo);
-
-   if (ret == -VKI_ENOSYS)
-      ret = VG_(do_syscall2)(__NR_kill, tid, signo);
-
-   return VG_(is_kerror)(ret) ? -1 : 0;
+   return VG_(kal_tkill)(tid, signo);
 }
 
 Int VG_(sigpending) ( vki_sigset_t* set )
 {
-// Nb: AMD64/Linux doesn't have __NR_sigpending;  it only provides
-// __NR_rt_sigpending.  This function will have to be abstracted in some
-// way to account for this.  In the meantime, the easy option is to forget
-// about it for AMD64 until it's needed.
-#ifdef __amd64__
-   I_die_here;
-#else
-   Int res = VG_(do_syscall1)(__NR_sigpending, (UWord)set);
-   return VG_(is_kerror)(res) ? -1 : 0;
-#endif
+   return VG_(kal_sigpending)(set);
 }
 
 Int VG_(waitpid)(Int pid, Int *status, Int options)
 {
-   Int ret = VG_(do_syscall4)(__NR_wait4, pid, (UWord)status, options, 0);
-
-   return VG_(is_kerror)(ret) ? -1 : ret;
+   return VG_(kal_waitpid)(pid, status, options);
 }
 
 Int VG_(gettid)(void)
 {
-   Int ret;
-
-   ret = VG_(do_syscall0)(__NR_gettid);
-
-   if (ret == -VKI_ENOSYS) {
-      Char pid[16];
-      
-      /*
-       * The gettid system call does not exist. The obvious assumption
-       * to make at this point would be that we are running on an older
-       * system where the getpid system call actually returns the ID of
-       * the current thread.
-       *
-       * Unfortunately it seems that there are some systems with a kernel
-       * where getpid has been changed to return the ID of the thread group
-       * leader but where the gettid system call has not yet been added.
-       *
-       * So instead of calling getpid here we use readlink to see where
-       * the /proc/self link is pointing...
-       */
-      if ((ret = VG_(do_syscall3)(__NR_readlink, (UWord)"/proc/self",
-                                  (UWord)pid, sizeof(pid))) >= 0) 
-      {
-         pid[ret] = '\0';
-         ret = VG_(atoll)(pid);
-      }
-   }
-
-   return ret;
+   return VG_(kal_gettid)();
 }
 
 
@@ -281,21 +215,6 @@
    mmap/munmap, exit, fcntl
    ------------------------------------------------------------------ */
 
-static Int munmap_inner(void *start, SizeT length)
-{
-   return VG_(do_syscall2)(__NR_munmap, (UWord)start, length );
-}
-
-static Addr mmap_inner(void *start, SizeT length, UInt prot, UInt flags,
-                       UInt fd, OffT offset)
-{
-   Word ret;
-   
-   VGP_DO_MMAP(ret, start, length, prot,
-               flags & ~(VKI_MAP_NOSYMS|VKI_MAP_CLIENT), fd, offset);
-   return ret;
-}
-
 /* Returns -1 on failure. */
 void* VG_(mmap)( void* start, SizeT length,
                  UInt prot, UInt flags, UInt sf_flags, UInt fd, OffT offset)
@@ -310,10 +229,10 @@
    if (start == 0)
       return (void *)-1;
 
-   res = mmap_inner(start, length, prot, flags, fd, offset);
+   res = VG_(kal_mmap)((Addr)start, length, prot, flags & ~(VKI_MAP_NOSYMS|VKI_MAP_CLIENT), fd, offset);
 
    // Check it ended up in the right place.
-   if (!VG_(is_kerror)(res)) {
+   if (res != (Addr)-1) {
       if (flags & VKI_MAP_CLIENT) {
          vg_assert(VG_(client_base) <= res && res+length <= VG_(client_end));
       } else {
@@ -330,35 +249,34 @@
       VG_(map_fd_segment)(res, length, prot, sf_flags, fd, offset, NULL);
    }
 
-   return VG_(is_kerror)(res) ? ((void*)(-1)) : (void*)res;
+   return (void*)res;
 }
 
 /* Returns -1 on failure. */
 Int VG_(munmap)( void* start, SizeT length )
 {
-   Int res = munmap_inner(start, length);
-   if (!VG_(is_kerror)(res))
+   Int res = VG_(kal_munmap)((Addr)start, length);
+   if (res == 0)
       VG_(unmap_range)((Addr)start, length);
-   return VG_(is_kerror)(res) ? -1 : 0;
+   return res;
 }
 
 Int VG_(mprotect)( void *start, SizeT length, UInt prot )
 {
-   Int res = VG_(do_syscall3)(__NR_mprotect, (UWord)start, length, prot );
-   if (!VG_(is_kerror)(res))
+   Int res = VG_(kal_mprotect)((Addr)start, length, prot);
+   if (res == 0)
       VG_(mprotect_range)((Addr)start, length, prot);
-   return VG_(is_kerror)(res) ? -1 : 0;
+   return res;
 }
 Int VG_(mprotect_native)( void *start, SizeT length, UInt prot )
 {
-   Int res = VG_(do_syscall3)(__NR_mprotect, (UWord)start, length, prot );
-   return VG_(is_kerror)(res) ? -1 : 0;
+   return VG_(kal_mprotect)((Addr)start, length, prot);
 }
 
 /* Terminate this single thread */
 void VG_(exit_single)( Int status )
 {
-   (void)VG_(do_syscall1)(__NR_exit, status );
+   (void)VG_(kal_exit)(status);
    /* Why are we still alive here? */
    /*NOTREACHED*/
    *(volatile Int *)0 = 'x';
@@ -368,8 +286,8 @@
 /* Pull down the entire world */
 void VG_(exit)( Int status )
 {
-   (void)VG_(do_syscall1)(__NR_exit_group, status );
-   (void)VG_(do_syscall1)(__NR_exit, status );
+   (void)VG_(kal_exit_group)(status);
+   (void)VG_(kal_exit)(status);
    /* Why are we still alive here? */
    /*NOTREACHED*/
    *(volatile Int *)0 = 'x';
@@ -379,15 +297,12 @@
 /* Returns -1 on error. */
 Int VG_(fcntl) ( Int fd, Int cmd, Int arg )
 {
-   Int res = VG_(do_syscall3)(__NR_fcntl, fd, cmd, arg);
-   return VG_(is_kerror)(res) ? -1 : res;
+   return VG_(kal_fcntl)(fd, cmd, arg);
 }
 
 Int VG_(poll)( struct vki_pollfd *ufds, UInt nfds, Int timeout)
 {
-   Int res = VG_(do_syscall3)(__NR_poll, (UWord)ufds, nfds, timeout);
-
-   return res;
+   return VG_(kal_poll)(ufds, nfds, timeout);
 }
 
 
@@ -1261,87 +1176,66 @@
 /* Returns -1 on failure. */
 Int VG_(open) ( const Char* pathname, Int flags, Int mode )
 {  
-   Int fd = VG_(do_syscall3)(__NR_open, (UWord)pathname, flags, mode);
-   return fd;
+   return VG_(kal_open)(pathname, flags, mode);
 }
 
 Int VG_(pipe) ( Int fd[2] )
 {
-   Int ret = VG_(do_syscall1)(__NR_pipe, (UWord)fd);
-   return VG_(is_kerror)(ret) ? -1 : 0;
+   return VG_(kal_pipe)(fd);
 }
 
 void VG_(close) ( Int fd )
 {
-   VG_(do_syscall1)(__NR_close, fd);
+   VG_(kal_close)(fd);
 }
 
 
 Int VG_(read) ( Int fd, void* buf, Int count)
 {
-   Int res;
-   res = VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count);
-   return res;
+   return VG_(kal_read)(fd, buf, count);
 }
 
 Int VG_(write) ( Int fd, const void* buf, Int count)
 {
-   Int res;
-   res = VG_(do_syscall3)(__NR_write, fd, (UWord)buf, count);
-   return res;
+   return VG_(kal_write)(fd, buf, count);
 }
 
 OffT VG_(lseek) ( Int fd, OffT offset, Int whence)
 {
-   Int res;
-   res = VG_(do_syscall3)(__NR_lseek, fd, offset, whence);
-   if (VG_(is_kerror)(res)) res = -1;
-   return res;
+   return VG_(kal_lseek)(fd, offset, whence);
 }
 
 Int VG_(stat) ( Char* file_name, struct vki_stat* buf )
 {
-   Int res;
-   res = VG_(do_syscall2)(__NR_stat, (UWord)file_name, (UWord)buf);
-   return res;			/* return -ve error */
+   return VG_(kal_stat)(file_name, buf);
 }
 
 Int VG_(fstat) ( Int fd, struct vki_stat* buf )
 {
-   Int res;
-   res = VG_(do_syscall2)(__NR_fstat, fd, (UWord)buf);
-   return VG_(is_kerror)(res) ? (-1) : 0;
+   return VG_(kal_fstat)(fd, buf);
 }
 
 Int VG_(dup2) ( Int oldfd, Int newfd )
 {
-   Int res;
-   res = VG_(do_syscall2)(__NR_dup2, oldfd, newfd);
-   return VG_(is_kerror)(res) ? (-1) : res;
+   return VG_(kal_dup2)(oldfd, newfd);
 }
 
 Int VG_(rename) ( Char* old_name, Char* new_name )
 {
-   Int res;
-   res = VG_(do_syscall2)(__NR_rename, (UWord)old_name, (UWord)new_name);
-   return VG_(is_kerror)(res) ? (-1) : 0;
+   return VG_(rename)(old_name, new_name);
 }
 
 Int VG_(unlink) ( Char* file_name )
 {
-   Int res;
-   res = VG_(do_syscall1)(__NR_unlink, (UWord)file_name);
-   return VG_(is_kerror)(res) ? (-1) : 0;
+   return VG_(unlink)(file_name);
 }
 
 /* Nb: we do not allow the Linux extension which malloc()s memory for the
    buffer if buf==NULL, because we don't want Linux calling malloc() */
 Char* VG_(getcwd) ( Char* buf, SizeT size )
 {
-   Word res;
    vg_assert(buf != NULL);
-   res = VG_(do_syscall2)(__NR_getcwd, (UWord)buf, size);
-   return VG_(is_kerror)(res) ? ((Char*)NULL) : (Char*)res;
+   return VG_(kal_getcwd)(buf, size);
 }
 
 /* Alternative version that does allocate the memory.  Easier to use. */
@@ -1352,7 +1246,7 @@
    *out = NULL;
    while (True) {
       *out = VG_(malloc)(size);
-      if (NULL == VG_(getcwd)(*out, size)) {
+      if (NULL == VG_(kal_getcwd)(*out, size)) {
          VG_(free)(*out);
          if (size > 65535)
             return False;
@@ -1467,78 +1361,50 @@
 }
 
 /* Support for getrlimit. */
-Int VG_(getrlimit) (Int resource, struct vki_rlimit *rlim)
+Int VG_(getrlimit) (Int resource, UWord *soft, UWord *hard)
 {
-   Int res = -VKI_ENOSYS;
-   /* res = getrlimit( resource, rlim ); */
-#  ifdef __NR_ugetrlimit
-   res = VG_(do_syscall2)(__NR_ugetrlimit, resource, (UWord)rlim);
-#  endif
-   if (res == -VKI_ENOSYS)
-      res = VG_(do_syscall2)(__NR_getrlimit, resource, (UWord)rlim);
-   if (VG_(is_kerror)(res)) res = -1;
-   return res;
+   return VG_(kal_getrlimit)(resource, soft, hard);
 }
 
 
 /* Support for setrlimit. */
-Int VG_(setrlimit) (Int resource, const struct vki_rlimit *rlim)
+Int VG_(setrlimit) (Int resource, UWord soft, UWord hard)
 {
-   Int res;
-   /* res = setrlimit( resource, rlim ); */
-   res = VG_(do_syscall2)(__NR_setrlimit, resource, (UWord)rlim);
-   if (VG_(is_kerror)(res)) res = -1;
-   return res;
+   return VG_(kal_setrlimit)(resource, soft, hard);
 }
 
 
 /* Support for getdents. */
 Int VG_(getdents) (UInt fd, struct vki_dirent *dirp, UInt count)
 {
-   Int res;
-   /* res = getdents( fd, dirp, count ); */
-   res = VG_(do_syscall3)(__NR_getdents, fd, (UWord)dirp, count);
-   if (VG_(is_kerror)(res)) res = -1;
-   return res;
+   return VG_(kal_getdents)(fd, dirp, count);
 }
 
 /* Support for a readlink.  */
 Int VG_(readlink) (Char* path, Char* buf, UInt bufsiz)
 {
-   Int res;
-   /* res = readlink( path, buf, bufsiz ); */
-   res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz);
-   if (VG_(is_kerror)(res)) res = -1;
-   return res;
+   return VG_(kal_readlink)(path, buf, bufsiz);
 }
 
 /* You'd be amazed how many places need to know the current pid. */
 Int VG_(getpid) ( void )
 {
-   Int res;
-   /* res = getpid(); */
-   res = VG_(do_syscall0)(__NR_getpid);
-   return res;
+   return VG_(kal_getpid)();
 }
 
 Int VG_(getpgrp) ( void )
 {
-   Int res;
-   /* res = getpgid(); */
-   res = VG_(do_syscall0)(__NR_getpgrp);
-   return res;
+   return VG_(kal_getpgrp)();
 }
 
 Int VG_(getppid) ( void )
 {
-   Int res;
-   res = VG_(do_syscall0)(__NR_getppid);
-   return res;
+   return VG_(getppid)();
 }
 
 Int VG_(setpgid) ( Int pid, Int pgrp )
 {
-   return VG_(do_syscall2)(__NR_setpgid, pid, pgrp);
+   return VG_(kal_setpgid)(pid, pgrp);
 }
 
 /* Walk through a colon-separated environment variable, and remove the
@@ -1644,8 +1510,8 @@
    Int pid, res;
    if (cmd == NULL)
       return 1;
-   pid = VG_(do_syscall0)(__NR_fork);
-   if (VG_(is_kerror)(pid))
+   pid = VG_(kal_fork)();
+   if (pid < 0)
       return -1;
    if (pid == 0) {
       /* child */
@@ -1653,7 +1519,8 @@
       Char* argv[4];
 
       /* restore the DATA rlimit for the child */
-      VG_(setrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
+      VG_(setrlimit)(VKI_RLIMIT_DATA, VG_(client_rlimit_data).rlim_cur,
+                     VG_(client_rlimit_data).rlim_max);
 
       envp = env_clone(VG_(client_envp));
       VG_(env_remove_valgrind_env_stuff)( envp ); 
@@ -1663,15 +1530,14 @@
       argv[2] = cmd;
       argv[3] = 0;
 
-      (void)VG_(do_syscall3)(__NR_execve, 
-                             (UWord)"/bin/sh", (UWord)argv, (UWord)envp);
+      (void)VG_(kal_execve)("/bin/sh", argv, envp);
 
       /* If we're still alive here, execve failed. */
       VG_(exit)(1);
    } else {
       /* parent */
-      res = VG_(waitpid)(pid, NULL, 0);
-      if (VG_(is_kerror)(res)) {
+      res = VG_(kal_waitpid)(pid, NULL, 0);
+      if (res < 0) {
          return -1;
       } else {
 	 return 0;
@@ -1687,13 +1553,9 @@
 UInt VG_(read_millisecond_timer) ( void )
 {
    static ULong base = 0;
-   struct vki_timeval tv_now;
    ULong now;
-   Int res;
-
-   res = VG_(do_syscall2)(__NR_gettimeofday, (UWord)&tv_now, (UWord)NULL);
    
-   now = tv_now.tv_sec * 1000000ULL + tv_now.tv_usec;
+   now = VG_(kal_gettimeofday)();
    
    if (base == 0)
       base = now;
@@ -1701,12 +1563,6 @@
    return (now - base) / 1000;
 }
 
-
-void VG_(nanosleep)(struct vki_timespec *ts)
-{
-   VG_(do_syscall2)(__NR_nanosleep, (UWord)ts, (UWord)NULL);
-}
-
 /* ---------------------------------------------------------------------
    Primitive support for bagging memory via mmap.
    ------------------------------------------------------------------ */
@@ -1849,13 +1705,6 @@
 static
 Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port );
 
-static
-Int my_socket ( Int domain, Int type, Int protocol );
-
-static
-Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, 
-                 Int addrlen );
-
 static 
 UInt my_htonl ( UInt x )
 {
@@ -1903,15 +1752,15 @@
    servAddr.sin_port = my_htons(port);
 
    /* create socket */
-   sd = my_socket(VKI_AF_INET, VKI_SOCK_STREAM, 0 /* IPPROTO_IP ? */);
+   sd = VG_(kal_socket)(VKI_AF_INET, VKI_SOCK_STREAM, 0 /* IPPROTO_IP ? */);
    if (sd < 0) {
      /* this shouldn't happen ... nevertheless */
      return -2;
    }
 			
    /* connect to server */
-   res = my_connect(sd, (struct vki_sockaddr_in *) &servAddr, 
-                        sizeof(servAddr));
+   res = VG_(kal_connect)(sd, (struct vki_sockaddr_in *) &servAddr, 
+                          sizeof(servAddr));
    if (res < 0) {
      /* connection failed */
      return -2;
@@ -1966,132 +1815,25 @@
 }
 
 
-static
-Int my_socket ( Int domain, Int type, Int protocol )
-{
-// AMD64/Linux doesn't define __NR_socketcall... see comment above
-// VG_(sigpending)() for more details.
-#ifdef __amd64__
-   I_die_here;
-#else
-   Int res;
-   UWord args[3];
-   args[0] = domain;
-   args[1] = type;
-   args[2] = protocol;
-   res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SOCKET, (UWord)&args);
-   if (VG_(is_kerror)(res)) 
-      res = -1;
-   return res;
-#endif
-}
-
-static
-Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, 
-                 Int addrlen )
-{
-// AMD64/Linux doesn't define __NR_socketcall... see comment above
-// VG_(sigpending)() for more details.
-#ifdef __amd64__
-   I_die_here;
-#else
-   Int res;
-   UWord args[3];
-   args[0] = sockfd;
-   args[1] = (UWord)serv_addr;
-   args[2] = addrlen;
-   res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_CONNECT, (UWord)&args);
-   if (VG_(is_kerror)(res)) 
-      res = -1;
-   return res;
-#endif
-}
-
 Int VG_(write_socket)( Int sd, void *msg, Int count )
 {
-// AMD64/Linux doesn't define __NR_socketcall... see comment above
-// VG_(sigpending)() for more details.
-#ifdef __amd64__
-   I_die_here;
-#else
-   /* This is actually send(). */
-
-   /* Requests not to send SIGPIPE on errors on stream oriented
-      sockets when the other end breaks the connection. The EPIPE
-      error is still returned. */
-   Int flags = VKI_MSG_NOSIGNAL;
-
-   Int res;
-   UWord args[4];
-   args[0] = sd;
-   args[1] = (UWord)msg;
-   args[2] = count;
-   args[3] = flags;
-   res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SEND, (UWord)&args);
-   if (VG_(is_kerror)(res)) 
-      res = -1;
-   return res;
-#endif
+   return VG_(kal_send)(sd, msg, count);
 }
 
 Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
 {
-// AMD64/Linux doesn't define __NR_socketcall... see comment above
-// VG_(sigpending)() for more details.
-#ifdef __amd64__
-   I_die_here;
-#else
-   Int res;
-   UWord args[3];
-   args[0] = sd;
-   args[1] = (UWord)name;
-   args[2] = (UWord)namelen;
-   res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKNAME, (UWord)&args);
-   if(VG_(is_kerror)(res))
-      res = -1;
-   return res;
-#endif
+   return VG_(kal_getsockname)(sd, name, namelen);
 }
 
 Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen)
 {
-// AMD64/Linux doesn't define __NR_socketcall... see comment above
-// VG_(sigpending)() for more details.
-#ifdef __amd64__
-   I_die_here;
-#else
-   Int res;
-   UWord args[3];
-   args[0] = sd;
-   args[1] = (UWord)name;
-   args[2] = (UWord)namelen;
-   res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETPEERNAME, (UWord)&args);
-   if(VG_(is_kerror)(res))
-      res = -1;
-   return res;
-#endif
+   return VG_(kal_getpeername)(sd, name, namelen);
 }
 
 Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval,
                       Int *optlen)
 {
-// AMD64/Linux doesn't define __NR_socketcall... see comment above
-// VG_(sigpending)() for more details.
-#ifdef __amd64__
-   I_die_here;
-#else
-   Int res;
-   UWord args[5];
-   args[0] = sd;
-   args[1] = level;
-   args[2] = optname;
-   args[3] = (UWord)optval;
-   args[4] = (UWord)optlen;
-   res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (UWord)&args);
-   if(VG_(is_kerror)(res))
-      res = -1;
-   return res;
-#endif
+   return VG_(kal_getsockopt)(sd, level, optname, optval, optlen);
 }
 
 /*--------------------------------------------------------------------*/
Index: coregrind/vg_main.c
===================================================================
--- coregrind/vg_main.c	(revision 3480)
+++ coregrind/vg_main.c	(working copy)
@@ -2129,27 +2129,28 @@
 
 static void setup_file_descriptors(void)
 {
-   struct vki_rlimit rl;
+   UWord soft;
+   UWord hard;
 
    /* Get the current file descriptor limits. */
-   if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
-      rl.rlim_cur = 1024;
-      rl.rlim_max = 1024;
+   if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &soft, &hard) < 0) {
+      soft = 1024;
+      hard = 1024;
    }
 
    /* Work out where to move the soft limit to. */
-   if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
-      rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
+   if (soft + N_RESERVED_FDS <= hard) {
+      soft = soft + N_RESERVED_FDS;
    } else {
-      rl.rlim_cur = rl.rlim_max;
+      soft = hard;
    }
 
    /* Reserve some file descriptors for our use. */
-   VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
-   VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
+   VG_(fd_soft_limit) = soft - N_RESERVED_FDS;
+   VG_(fd_hard_limit) = soft - N_RESERVED_FDS;
 
    /* Update the soft limit. */
-   VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
+   VG_(setrlimit)(VKI_RLIMIT_NOFILE, soft, hard);
 
    if (vgexecfd != -1)
       vgexecfd = VG_(safe_fd)( vgexecfd );
@@ -2426,7 +2427,6 @@
    Addr client_eip;
    Addr sp_at_startup;     /* client's SP at the point we gained control. */
    UInt * client_auxv;
-   struct vki_rlimit zero = { 0, 0 };
    Int padfile;
 
    //============================================================
@@ -2448,12 +2448,13 @@
    // This prevents any internal uses of brk() from having any effect.
    // We remember the old value so we can restore it on exec, so that
    // child processes will have a reasonable brk value.
-   VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
-   zero.rlim_max = VG_(client_rlimit_data).rlim_max;
-   VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
+   VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data).rlim_cur,
+                  &VG_(client_rlimit_data).rlim_max);
+   VG_(setrlimit)(VKI_RLIMIT_DATA, 0, VG_(client_rlimit_data).rlim_max);
 
    // Get the current process stack rlimit.
-   VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
+   VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack).rlim_cur,
+                  &VG_(client_rlimit_stack).rlim_max);
 
    //--------------------------------------------------------------
    // Check we were launched by stage1
Index: coregrind/kal/pub_tool_kal.h
===================================================================
--- coregrind/kal/pub_tool_kal.h	(revision 0)
+++ coregrind/kal/pub_tool_kal.h	(revision 0)
@@ -0,0 +1,39 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Tool visible kernel abstraction layer interface.             ---*/
+/*---                                           kal/pub_tool_kal.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+   This file is part of Valgrind, a dynamic binary instrumentation
+   framework.
+
+   Copyright (C) 2000-2005 Tom Hughes
+      tom@compton.nu
+
+   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 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.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_TOOL_KAL_H
+#define __PUB_TOOL_KAL_H
+
+#endif   // __PUB_TOOL_KAL_H
+
+/*--------------------------------------------------------------------*/
+/*--- end                                                          ---*/
+/*--------------------------------------------------------------------*/
Index: coregrind/kal/kal-linux.c
===================================================================
--- coregrind/kal/kal-linux.c	(revision 0)
+++ coregrind/kal/kal-linux.c	(revision 0)
@@ -0,0 +1,338 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Linux-specific kernel abstraction layer.     kal/kal-linux.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+   This file is part of Valgrind, a dynamic binary instrumentation
+   framework.
+
+   Copyright (C) 2000-2005 Tom Hughes
+      tom@compton.nu
+
+   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 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.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "core.h"
+
+Int VG_(kal_sigprocmask)(Int how, const vki_sigset_t *set, vki_sigset_t *oldset)
+{
+   Int res = VG_(do_syscall4)(__NR_rt_sigprocmask, 
+                              how, (UWord)set, (UWord)oldset, 
+                              _VKI_NSIG_WORDS * sizeof(UWord));
+   return VG_(is_kerror)(res) ? -1 : 0;
+}
+
+Int VG_(kal_sigaction)(Int signum, const struct vki_sigaction *act,
+                       struct vki_sigaction *oldact)
+{
+   Int res = VG_(do_syscall4)(__NR_rt_sigaction,
+		              signum, (UWord)act, (UWord)oldact, 
+		              _VKI_NSIG_WORDS * sizeof(UWord));
+   return VG_(is_kerror)(res) ? -1 : 0;
+}
+
+Int VG_(kal_sigaltstack)(const vki_stack_t *ss, vki_stack_t *oss)
+{
+   Int res = VG_(do_syscall2)(__NR_sigaltstack, (UWord)ss, (UWord)oss);
+   return VG_(is_kerror)(res) ? -1 : 0;
+}
+
+Int VG_(kal_sigtimedwait)(const vki_sigset_t *set, vki_siginfo_t *info,
+                          const struct vki_timespec *timeout)
+{
+   Int res = VG_(do_syscall4)(__NR_rt_sigtimedwait, (UWord)set, (UWord)info, 
+                              (UWord)timeout, sizeof(*set));
+   return res;
+}
+ 
+Int VG_(kal_kill)(Int pid, Int signo)
+{
+   Int res = VG_(do_syscall2)(__NR_kill, pid, signo);
+   return VG_(is_kerror)(res) ? -1 : 0;
+}
+
+Int VG_(kal_tkill)(ThreadId tid, Int signo)
+{
+   Int ret = -VKI_ENOSYS;
+
+#if 0
+   /* This isn't right because the client may create a process
+      structure with multiple thread groups */
+   ret = VG_(do_syscall)(__NR_tgkill, VG_(getpid)(), tid, signo);
+#endif
+
+   ret = VG_(do_syscall2)(__NR_tkill, tid, signo);
+
+   if (ret == -VKI_ENOSYS)
+      ret = VG_(do_syscall2)(__NR_kill, tid, signo);
+
+   return VG_(is_kerror)(ret) ? -1 : 0;
+}
+
+Int VG_(kal_waitpid)(Int pid, Int *status, Int options)
+{
+   Int ret = VG_(do_syscall4)(__NR_wait4, pid, (UWord)status, options, 0);
+   return VG_(is_kerror)(ret) ? -1 : ret;
+}
+
+Int VG_(kal_getpid)(void)
+{
+   return VG_(do_syscall0)(__NR_getpid);
+}
+
+Int VG_(kal_getppid)(void)
+{
+   return VG_(do_syscall0)(__NR_getppid);
+}
+
+Int VG_(kal_getpgrp)(void)
+{
+   return VG_(do_syscall0)(__NR_getpgrp);
+}
+
+Int VG_(kal_gettid)(void)
+{
+   Int ret;
+
+   ret = VG_(do_syscall0)(__NR_gettid);
+
+   if (ret == -VKI_ENOSYS) {
+      Char pid[16];
+      
+      /*
+       * The gettid system call does not exist. The obvious assumption
+       * to make at this point would be that we are running on an older
+       * system where the getpid system call actually returns the ID of
+       * the current thread.
+       *
+       * Unfortunately it seems that there are some systems with a kernel
+       * where getpid has been changed to return the ID of the thread group
+       * leader but where the gettid system call has not yet been added.
+       *
+       * So instead of calling getpid here we use readlink to see where
+       * the /proc/self link is pointing...
+       */
+      if ((ret = VG_(do_syscall3)(__NR_readlink, (UWord)"/proc/self",
+                                  (UWord)pid, sizeof(pid))) >= 0) 
+      {
+         pid[ret] = '\0';
+         ret = VG_(atoll)(pid);
+      }
+   }
+
+   return ret;
+}
+
+Int VG_(kal_setpgid)(Int pid, Int pgrp)
+{
+   return VG_(do_syscall2)(__NR_setpgid, pid, pgrp);
+}
+
+Int VG_(kal_exit)(Int status)
+{
+   Int res = VG_(do_syscall1)(__NR_exit, status);
+   return VG_(is_kerror)(res) ? -1 : 0;
+}
+
+Int VG_(kal_exit_group)(Int status)
+{
+   Int res = VG_(do_syscall1)(__NR_exit_group, status);
+   return VG_(is_kerror)(res) ? -1 : 0;
+}
+
+Int VG_(kal_munmap)(Addr start, SizeT length)
+{
+   return VG_(do_syscall2)(__NR_munmap, start, length);
+}
+
+Int VG_(kal_mprotect)(Addr start, SizeT length, UInt prot)
+{
+   Int res = VG_(do_syscall3)(__NR_mprotect, start, length, prot);
+   return VG_(is_kerror)(res) ? -1 : 0;
+}
+
+Int VG_(kal_open)(const Char* pathname, Int flags, Int mode)
+{  
+   return VG_(do_syscall3)(__NR_open, (UWord)pathname, flags, mode);
+}
+
+void VG_(kal_close)(Int fd)
+{
+   VG_(do_syscall1)(__NR_close, fd);
+   return;
+}
+
+Int VG_(kal_read)(Int fd, void* buf, Int count)
+{
+   return VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count);
+}
+
+Int VG_(kal_write)(Int fd, const void* buf, Int count)
+{
+   return VG_(do_syscall3)(__NR_write, fd, (UWord)buf, count);
+}
+
+OffT VG_(kal_lseek)(Int fd, OffT offset, Int whence)
+{
+   Int res = VG_(do_syscall3)(__NR_lseek, fd, offset, whence);
+   if (VG_(is_kerror)(res)) res = -1;
+   return res;
+}
+
+Int VG_(kal_fcntl)(Int fd, Int cmd, Int arg)
+{
+   Int res = VG_(do_syscall3)(__NR_fcntl, fd, cmd, arg);
+   return VG_(is_kerror)(res) ? -1 : res;
+}
+
+Int VG_(kal_poll)(struct vki_pollfd *ufds, UInt nfds, Int timeout)
+{
+   return VG_(do_syscall3)(__NR_poll, (UWord)ufds, nfds, timeout);
+}
+
+Int VG_(kal_pipe)(Int fd[2])
+{
+   Int ret = VG_(do_syscall1)(__NR_pipe, (UWord)fd);
+   return VG_(is_kerror)(ret) ? -1 : 0;
+}
+
+Int VG_(kal_stat)(Char *file_name, struct vki_stat *buf)
+{
+   return VG_(do_syscall2)(__NR_stat, (UWord)file_name, (UWord)buf);
+}
+
+Int VG_(kal_fstat)(Int fd, struct vki_stat *buf)
+{
+   Int res = VG_(do_syscall2)(__NR_fstat, fd, (UWord)buf);
+   return VG_(is_kerror)(res) ? (-1) : 0;
+}
+
+Int VG_(kal_dup2)(Int oldfd, Int newfd)
+{
+   Int res = VG_(do_syscall2)(__NR_dup2, oldfd, newfd);
+   return VG_(is_kerror)(res) ? (-1) : res;
+}
+
+Int VG_(kal_rename)(Char *old_name, Char *new_name)
+{
+   Int res = VG_(do_syscall2)(__NR_rename, (UWord)old_name, (UWord)new_name);
+   return VG_(is_kerror)(res) ? (-1) : 0;
+}
+
+Int VG_(kal_unlink)(Char *file_name)
+{
+   Int res = VG_(do_syscall1)(__NR_unlink, (UWord)file_name);
+   return VG_(is_kerror)(res) ? (-1) : 0;
+}
+
+Int VG_(kal_readlink)(Char* path, Char* buf, UInt bufsiz)
+{
+   Int res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz);
+   return VG_(is_kerror)(res) ? (-1) : res;
+}
+
+Int VG_(kal_getdents)(UInt fd, struct vki_dirent *dirp, UInt count)
+{
+   Int res = VG_(do_syscall3)(__NR_getdents, fd, (UWord)dirp, count);
+   return VG_(is_kerror)(res) ? (-1) : res;
+}
+
+Char *VG_(kal_getcwd)(Char *buf, SizeT size)
+{
+   Word res;
+   vg_assert(buf != NULL);
+   res = VG_(do_syscall2)(__NR_getcwd, (UWord)buf, size);
+   return VG_(is_kerror)(res) ? ((Char*)NULL) : (Char*)res;
+}
+
+Int VG_(kal_getrlimit)(Int resource, UWord *soft, UWord *hard)
+{
+   struct vki_rlimit rlim;
+   Int res = -VKI_ENOSYS;
+
+#ifdef __NR_ugetrlimit
+   res = VG_(do_syscall2)(__NR_ugetrlimit, resource, (UWord)&rlim);
+#endif
+
+   if (res == -VKI_ENOSYS)
+      res = VG_(do_syscall2)(__NR_getrlimit, resource, (UWord)&rlim);
+
+   *soft = rlim.rlim_cur;
+   *hard = rlim.rlim_max;
+
+   return VG_(is_kerror)(res) ? (-1) : res;
+}
+
+Int VG_(kal_setrlimit)(Int resource, UWord soft, UWord hard)
+{
+   struct vki_rlimit rlim;
+   Int res;
+
+   rlim.rlim_cur = soft;
+   rlim.rlim_max = hard;
+
+   res = VG_(do_syscall2)(__NR_setrlimit, resource, (UWord)&rlim);
+
+   return VG_(is_kerror)(res) ? (-1) : res;
+}
+
+Int VG_(kal_fork)(void)
+{
+   Int res = VG_(do_syscall0)(__NR_fork);
+   return VG_(is_kerror)(res) ? (-1) : res;
+}
+
+Int VG_(kal_execve)(const Char *filename, Char **argv, Char **envp)
+{
+   Int res = VG_(do_syscall3)(__NR_execve, (UWord)filename, (UWord)argv, (UWord)envp);
+   return VG_(is_kerror)(res) ? -1 : 0;
+}
+
+ULong VG_(kal_gettimeofday)(void)
+{
+   struct vki_timeval now;
+   Int res;
+
+   res = VG_(do_syscall2)(__NR_gettimeofday, (UWord)&now, (UWord)NULL);
+   
+   return now.tv_sec * 1000000ULL + now.tv_usec;
+}
+
+void VG_(kal_nanosleep)(ULong ns)
+{
+   struct vki_timespec ts;
+
+   ts.tv_sec = ns / 1000000000ULL;
+   ts.tv_nsec = ns % 1000000000ULL;
+
+   VG_(do_syscall2)(__NR_nanosleep, (UWord)&ts, (UWord)NULL);
+
+   return;
+}
+
+void VG_(kal_yield)(void)
+{
+   VG_(do_syscall0)(__NR_sched_yield);
+
+   return;
+}
+
+/*--------------------------------------------------------------------*/
+/*--- end                                                          ---*/
+/*--------------------------------------------------------------------*/
Index: coregrind/kal/kal-x86-linux.c
===================================================================
--- coregrind/kal/kal-x86-linux.c	(revision 0)
+++ coregrind/kal/kal-x86-linux.c	(revision 0)
@@ -0,0 +1,148 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Linux/x86-specific kernel abstraction layer.                 ---*/
+/*                                             kal/kal-x86-linux.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+   This file is part of Valgrind, a dynamic binary instrumentation
+   framework.
+
+   Copyright (C) 2000-2005 Tom Hughes
+      tom@compton.nu
+
+   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 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.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "core.h"
+
+Int VG_(kal_sigpending)(vki_sigset_t *set)
+{
+   Int res = VG_(do_syscall1)(__NR_sigpending, (UWord)set);
+   return VG_(is_kerror)(res) ? -1 : 0;
+}
+
+Addr VG_(kal_mmap)(Addr start, SizeT length, UInt prot, UInt flags,
+                   UInt fd, OffT offset)
+{
+   UWord args[6];
+
+   args[0] = start;
+   args[1] = length;
+   args[2] = prot;
+   args[3] = flags;
+   args[4] = fd;
+   args[5] = offset;
+
+   return VG_(do_syscall1)(__NR_mmap, (UWord)args);
+}
+
+Int VG_(kal_socket)(Int domain, Int type, Int protocol)
+{
+   UWord args[3];
+   Int res;
+
+   args[0] = domain;
+   args[1] = type;
+   args[2] = protocol;
+
+   res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SOCKET, (UWord)&args);
+
+   return VG_(is_kerror)(res) ? -1 : res;
+}
+
+Int VG_(kal_connect)(Int sockfd, struct vki_sockaddr_in *serv_addr, Int addrlen)
+{
+   UWord args[3];
+   Int res;
+
+   args[0] = sockfd;
+   args[1] = (UWord)serv_addr;
+   args[2] = addrlen;
+
+   res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_CONNECT, (UWord)&args);
+
+   return VG_(is_kerror)(res) ? -1 : res;
+}
+
+Int VG_(kal_send)(Int sd, void *msg, Int count)
+{
+   UWord args[4];
+   Int res;
+
+   args[0] = sd;
+   args[1] = (UWord)msg;
+   args[2] = count;
+
+   /* Requests not to send SIGPIPE on errors on stream oriented
+      sockets when the other end breaks the connection. The EPIPE
+      error is still returned. */
+   args[3] = VKI_MSG_NOSIGNAL;
+
+   res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SEND, (UWord)&args);
+
+   return VG_(is_kerror)(res) ? -1 : res;
+}
+
+Int VG_(kal_getsockname)(Int sd, struct vki_sockaddr *name, Int *namelen)
+{
+   UWord args[3];
+   Int res;
+
+   args[0] = sd;
+   args[1] = (UWord)name;
+   args[2] = (UWord)namelen;
+
+   res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKNAME, (UWord)&args);
+
+   return VG_(is_kerror)(res) ? -1 : res;
+}
+
+Int VG_(kal_getpeername)(Int sd, struct vki_sockaddr *name, Int *namelen)
+{
+   UWord args[3];
+   Int res;
+
+   args[0] = sd;
+   args[1] = (UWord)name;
+   args[2] = (UWord)namelen;
+
+   res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETPEERNAME, (UWord)&args);
+
+   return VG_(is_kerror)(res) ? -1 : res;
+}
+
+Int VG_(kal_getsockopt)(Int sd, Int level, Int optname, void *optval, Int *optlen)
+{
+   UWord args[5];
+   Int res;
+
+   args[0] = sd;
+   args[1] = level;
+   args[2] = optname;
+   args[3] = (UWord)optval;
+   args[4] = (UWord)optlen;
+
+   res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (UWord)&args);
+
+   return VG_(is_kerror)(res) ? -1 : res;
+}
+
+/*--------------------------------------------------------------------*/
+/*--- end                                                          ---*/
+/*--------------------------------------------------------------------*/
Index: coregrind/kal/Makefile.am
===================================================================
--- coregrind/kal/Makefile.am	(revision 0)
+++ coregrind/kal/Makefile.am	(revision 0)
@@ -0,0 +1,20 @@
+include $(top_srcdir)/Makefile.all.am
+include $(top_srcdir)/Makefile.core-AM_CPPFLAGS.am
+
+AM_CFLAGS = $(WERROR) -Wmissing-prototypes -Winline -Wall -Wshadow -O -g
+
+noinst_HEADERS = \
+	pub_core_kal.h \
+	pub_tool_kal.h
+
+noinst_LIBRARIES = libkal.a
+
+libkal_a_SOURCES = \
+	kal-@VG_OS@.c \
+	kal-@VG_PLATFORM@.c
+
+if USE_PIE
+libkal_a_CFLAGS = $(AM_CFLAGS) -fpie
+else
+libkal_a_CFLAGS = $(AM_CFLAGS)
+endif
Index: coregrind/kal/pub_core_kal.h
===================================================================
--- coregrind/kal/pub_core_kal.h	(revision 0)
+++ coregrind/kal/pub_core_kal.h	(revision 0)
@@ -0,0 +1,101 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Core visible kernel abstraction layer interface.             ---*/
+/*---                                           kal/pub_core_kal.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+   This file is part of Valgrind, a dynamic binary instrumentation
+   framework.
+
+   Copyright (C) 2000-2005 Tom Hughes
+      tom@compton.nu
+
+   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 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.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_CORE_KAL_H
+#define __PUB_CORE_KAL_H
+
+Int VG_(kal_sigprocmask)(Int how, const vki_sigset_t* set, vki_sigset_t* oldset);
+Int VG_(kal_sigaction)(Int signum, const struct vki_sigaction *act,
+                       struct vki_sigaction *oldact);
+Int VG_(kal_sigaltstack)(const vki_stack_t *ss, vki_stack_t *oss);
+Int VG_(kal_sigtimedwait)(const vki_sigset_t *set, vki_siginfo_t *info,
+                          const struct vki_timespec *timeout);
+Int VG_(kal_sigpending)(vki_sigset_t *set);
+
+Int VG_(kal_kill)(Int pid, Int signo);
+Int VG_(kal_tkill)(ThreadId tid, Int signo);
+
+Int VG_(kal_waitpid)(Int pid, Int *status, Int options);
+
+Int VG_(kal_getpid)(void);
+Int VG_(kal_getppid)(void);
+Int VG_(kal_getpgrp)(void);
+Int VG_(kal_gettid)(void);
+Int VG_(kal_setpgid)(Int pid, Int pgrp);
+
+Addr VG_(kal_mmap)(Addr start, SizeT length, UInt prot, UInt flags,
+                   UInt fd, OffT offset);
+Int VG_(kal_munmap)(Addr start, SizeT length);
+Int VG_(kal_mprotect)(Addr start, SizeT length, UInt prot);
+
+Int VG_(kal_exit)(Int status);
+Int VG_(kal_exit_group)(Int status);
+
+Int VG_(kal_open)(const Char* pathname, Int flags, Int mode);
+void VG_(kal_close)(Int fd);
+Int VG_(kal_read)(Int fd, void* buf, Int count);
+Int VG_(kal_write)(Int fd, const void* buf, Int count);
+OffT VG_(kal_lseek)(Int fd, OffT offset, Int whence);
+Int VG_(kal_fcntl)(Int fd, Int cmd, Int arg);
+Int VG_(kal_poll)(struct vki_pollfd *ufds, UInt nfds, Int timeout);
+Int VG_(kal_pipe)(Int fd[2]);
+Int VG_(kal_stat)(Char *file_name, struct vki_stat *buf);
+Int VG_(kal_fstat)(Int fd, struct vki_stat *buf);
+Int VG_(kal_dup2)(Int oldfd, Int newfd);
+Int VG_(kal_rename)(Char *old_name, Char *new_name);
+Int VG_(kal_unlink)(Char *file_name);
+Int VG_(kal_readlink)(Char* path, Char* buf, UInt bufsiz);
+Int VG_(kal_getdents)(UInt fd, struct vki_dirent *dirp, UInt count);
+
+Char *VG_(kal_getcwd)(Char *buf, SizeT size);
+
+Int VG_(kal_getrlimit)(Int resource, UWord *soft, UWord *hard);
+Int VG_(kal_setrlimit)(Int resource, UWord soft, UWord hard);
+
+Int VG_(kal_fork)(void);
+Int VG_(kal_execve)(const Char *filename, Char **argv, Char **envp);
+
+ULong VG_(kal_gettimeofday)(void);
+void VG_(kal_nanosleep)(ULong ns);
+void VG_(kal_yield)(void);
+
+Int VG_(kal_socket)(Int domain, Int type, Int protocol);
+Int VG_(kal_connect)(Int sockfd, struct vki_sockaddr_in *serv_addr, Int addrlen);
+Int VG_(kal_send)(Int sd, void *msg, Int count);
+Int VG_(kal_getsockname)(Int sd, struct vki_sockaddr *name, Int *namelen);
+Int VG_(kal_getpeername)(Int sd, struct vki_sockaddr *name, Int *namelen);
+Int VG_(kal_getsockopt)(Int sd, Int level, Int optname, void *optval, Int *optlen);
+
+#endif   // __PUB_CORE_KAL_H
+
+/*--------------------------------------------------------------------*/
+/*--- end                                                          ---*/
+/*--------------------------------------------------------------------*/
Index: coregrind/kal/kal-amd64-linux.c
===================================================================
--- coregrind/kal/kal-amd64-linux.c	(revision 0)
+++ coregrind/kal/kal-amd64-linux.c	(revision 0)
@@ -0,0 +1,92 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Linux/amd64-specific kernel abstraction layer.               ---*/
+/*                                           kal/kal-amd64-linux.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+   This file is part of Valgrind, a dynamic binary instrumentation
+   framework.
+
+   Copyright (C) 2000-2005 Tom Hughes
+      tom@compton.nu
+
+   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 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.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "core.h"
+
+Int VG_(kal_sigpending)(vki_sigset_t *set)
+{
+   Int res = VG_(do_syscall2)(__NR_rt_sigpending, (UWord)set,
+                              _VKI_NSIG_WORDS * sizeof(UWord));
+   return VG_(is_kerror)(res) ? -1 : 0;
+}
+
+Addr VG_(kal_mmap)(Addr start, SizeT length, UInt prot, UInt flags,
+                   UInt fd, OffT offset)
+{
+   return VG_(do_syscall6)(__NR_mmap, start, length, prot, flags, fd, offset);
+}
+
+Int VG_(kal_socket)(Int domain, Int type, Int protocol)
+{
+   Int res = VG_(do_syscall3)(__NR_socket, domain, type, protocol);
+   return VG_(is_kerror)(res) ? -1 : res;
+}
+
+Int VG_(kal_connect)(Int sockfd, struct vki_sockaddr_in *serv_addr, Int addrlen)
+{
+   Int res = VG_(do_syscall3)(__NR_connect, sockfd, (UWord)serv_addr, addrlen);
+   return VG_(is_kerror)(res) ? -1 : res;
+}
+
+Int VG_(kal_send)(Int sd, void *msg, Int count)
+{
+   Int res;
+
+   /* Requests not to send SIGPIPE on errors on stream oriented
+      sockets when the other end breaks the connection. The EPIPE
+      error is still returned. */
+   res = VG_(do_syscall6)(__NR_sendto, sd, (UWord)msg, count, VKI_MSG_NOSIGNAL, 0, 0);
+
+   return VG_(is_kerror)(res) ? -1 : res;
+}
+
+Int VG_(kal_getsockname)(Int sd, struct vki_sockaddr *name, Int *namelen)
+{
+   Int res = VG_(do_syscall3)(__NR_getsockname, sd, (UWord)name, (UWord)namelen);
+   return VG_(is_kerror)(res) ? -1 : res;
+}
+
+Int VG_(kal_getpeername)(Int sd, struct vki_sockaddr *name, Int *namelen)
+{
+   Int res = VG_(do_syscall3)(__NR_getpeername, sd, (UWord)name, (UWord)namelen);
+   return VG_(is_kerror)(res) ? -1 : res;
+}
+
+Int VG_(kal_getsockopt)(Int sd, Int level, Int optname, void *optval, Int *optlen)
+{
+   Int res = VG_(do_syscall5)(__NR_getsockopt, sd, level, optname,
+                              (UWord)optval, (UWord)optlen);
+   return VG_(is_kerror)(res) ? -1 : res;
+}
+
+/*--------------------------------------------------------------------*/
+/*--- end                                                          ---*/
+/*--------------------------------------------------------------------*/
Index: coregrind/core.h
===================================================================
--- coregrind/core.h	(revision 3480)
+++ coregrind/core.h	(working copy)
@@ -95,6 +95,8 @@
 
 #include "pub_core_stacktrace.h"  // for type 'StackTrace'
 
+#include "pub_core_kal.h"  // kernel abstraction layer
+
 #include "valgrind.h"
 
 #undef TL_
@@ -827,7 +829,6 @@
 extern void   VG_(env_unsetenv) ( Char **env, const Char *varname );
 extern void   VG_(env_remove_valgrind_env_stuff) ( Char** env ); 
 
-extern void   VG_(nanosleep)(struct vki_timespec *);
 /* ---------------------------------------------------------------------
    Exports of vg_message.c
    ------------------------------------------------------------------ */
Index: coregrind/x86-linux/core_platform.h
===================================================================
--- coregrind/x86-linux/core_platform.h	(revision 3480)
+++ coregrind/x86-linux/core_platform.h	(working copy)
@@ -92,19 +92,6 @@
    mmap() stuff
    ------------------------------------------------------------------ */
 
-#define VGP_DO_MMAP(ret, start, length, prot, flags, fd, offset) {      \
-   UWord __args[6];                                                     \
-                                                                        \
-   __args[0] = (UWord)(start);                                          \
-   __args[1] = (length);                                                \
-   __args[2] = (prot);                                                  \
-   __args[3] = (flags);                                                 \
-   __args[4] = (fd);                                                    \
-   __args[5] = (offset);                                                \
-                                                                        \
-   ret = VG_(do_syscall1)(__NR_mmap, (UWord)(&(__args[0])) );           \
-} while (0)
-
 #define VGP_GET_MMAP_ARGS(tst, a1, a2, a3, a4, a5, a6) do {     \
    UInt *arg_block = (UInt*)SYSCALL_ARG1(tst->arch);            \
    PRE_MEM_READ( "old_mmap(args)", (Addr)arg_block, 6*sizeof(UWord) );\
Index: coregrind/vg_scheduler.c
===================================================================
--- coregrind/vg_scheduler.c	(revision 3480)
+++ coregrind/vg_scheduler.c	(working copy)
@@ -393,7 +393,6 @@
  */
 void VG_(vg_yield)(void)
 {
-   struct vki_timespec ts = { 0, 1 };
    ThreadId tid = running_tid;
 
    vg_assert(tid != VG_INVALID_THREADID);
@@ -407,9 +406,9 @@
       Tell the kernel we're yielding.
     */
    if (1)
-      VG_(do_syscall0)(__NR_sched_yield);
+      VG_(kal_yield)();
    else
-      VG_(nanosleep)(&ts);
+      VG_(kal_nanosleep)(1);
 
    VG_(set_running)(tid);
 
Index: coregrind/amd64-linux/core_platform.h
===================================================================
--- coregrind/amd64-linux/core_platform.h	(revision 3480)
+++ coregrind/amd64-linux/core_platform.h	(working copy)
@@ -94,11 +94,6 @@
    mmap() stuff
    ------------------------------------------------------------------ */
 
-#define VGP_DO_MMAP(ret, start, length, prot, flags, fd, offset) { \
-   ret = VG_(do_syscall6)(__NR_mmap, (UWord)(start), (length),          \
-                         (prot), (flags), (fd), (offset));              \
-} while (0)
-
 #define VGP_GET_MMAP_ARGS(tst, a1, a2, a3, a4, a5, a6) do {\
    I_die_here; \
 } while (0)
Index: coregrind/Makefile.am
===================================================================
--- coregrind/Makefile.am	(revision 3480)
+++ coregrind/Makefile.am	(working copy)
@@ -4,8 +4,8 @@
 ## When building, we are only interested in the current arch/OS/platform.
 ## But when doing 'make dist', we are interested in every arch/OS/platform.
 ## That's what DIST_SUBDIRS specifies.
-SUBDIRS      = $(VG_ARCH)     $(VG_OS)     $(VG_PLATFORM)     demangle .
-DIST_SUBDIRS = $(VG_ARCH_ALL) $(VG_OS_ALL) $(VG_PLATFORM_ALL) demangle .
+SUBDIRS      = $(VG_ARCH)     $(VG_OS)     $(VG_PLATFORM)     demangle kal .
+DIST_SUBDIRS = $(VG_ARCH_ALL) $(VG_OS_ALL) $(VG_PLATFORM_ALL) demangle kal .
 
 AM_CPPFLAGS += -DVG_LIBDIR="\"$(valdir)"\" -I$(srcdir)/demangle \
 		-DKICKSTART_BASE=@KICKSTART_BASE@ \
@@ -87,6 +87,7 @@
 ## libplatform.a must be before libarch.a and libos.a, it seems.
 stage2_extra= \
 	demangle/libdemangle.a \
+	kal/libkal.a \
 	${VG_PLATFORM}/libplatform.a \
 	${VG_ARCH}/libarch.a \
 	${VG_OS}/libos.a \
Index: coregrind/vg_syscalls.c
===================================================================
--- coregrind/vg_syscalls.c	(revision 3480)
+++ coregrind/vg_syscalls.c	(working copy)
@@ -612,20 +612,18 @@
 static
 void do_hacky_preopened()
 {
-   struct vki_rlimit lim;
-   unsigned int count;
+   UWord soft;
+   UWord hard;
    int i;
 
-   if (VG_(getrlimit) (VKI_RLIMIT_NOFILE, &lim) == -1) {
+   if (VG_(getrlimit) (VKI_RLIMIT_NOFILE, &soft, &hard) == -1) {
       /* Hmm.  getrlimit() failed.  Now we're screwed, so just choose
          an arbitrarily high number.  1024 happens to be the limit in
          the 2.4 kernels. */
-      count = 1024;
-   } else {
-      count = lim.rlim_cur;
+      soft = 1024;
    }
 
-   for (i = 0; i < count; i++)
+   for (i = 0; i < soft; i++)
       if(VG_(fcntl)(i, VKI_F_GETFL, 0) != -1)
          VG_(record_fd_open)(-1, i, NULL);
 }
@@ -2384,7 +2382,8 @@
    }
 
    /* restore the DATA rlimit for the child */
-   VG_(setrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
+   VG_(setrlimit)(VKI_RLIMIT_DATA, VG_(client_rlimit_data).rlim_cur,
+                  VG_(client_rlimit_data).rlim_max);
 
    /*
       Set the signal state up for exec.
@@ -4510,7 +4509,7 @@
    }
 
    if (RES != -VKI_ENOMEM) {
-      VGP_DO_MMAP(RES, a1, a2, a3, a4, a5, a6);
+      RES = VG_(kal_mmap)(a1, a2, a3, a4, a5, a6);
       SET_RESULT(RES);
 
       if (!VG_(is_kerror)(RES)) {
Index: coregrind/vg_signals.c
===================================================================
--- coregrind/vg_signals.c	(revision 3480)
+++ coregrind/vg_signals.c	(working copy)
@@ -1240,7 +1240,8 @@
    Int  sigNo     = info->si_signo;
    Bool terminate = False;	/* kills process         */
    Bool core      = False;	/* kills process w/ core */
-   struct vki_rlimit corelim;
+   UWord coresoftlim;
+   UWord corehardlim;
    Bool could_core;
 
    vg_assert(VG_(is_running_thread)(tid));
@@ -1292,9 +1293,9 @@
       /* If they set the core-size limit to zero, don't generate a
 	 core file */
 	 
-      VG_(getrlimit)(VKI_RLIMIT_CORE, &corelim);
+      VG_(getrlimit)(VKI_RLIMIT_CORE, &coresoftlim, &corehardlim);
 
-      if (corelim.rlim_cur == 0)
+      if (coresoftlim == 0)
 	 core = False;
    }
 
