ubsan: xgate: left shift of negative value
[deliverable/binutils-gdb.git] / sim / ppc / emul_netbsd.c
index 6d1ad89eb850fbed89ff5f20ce1fbc13b099f0dc..9b80fc25dc812ab4317de3a7481b34a31199cc07 100644 (file)
@@ -1,21 +1,20 @@
 /*  This file is part of the program psim.
 
 /*  This file is part of the program psim.
 
-    Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
+    Copyright (C) 1994-1998, Andrew Cagney <cagney@highland.com.au>
 
     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
 
     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
+    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.
     (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
     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.
+    along with this program; if not, see <http://www.gnu.org/licenses/>.
+
     */
 
 
     */
 
 
 #include <stdio.h>
 #include <signal.h>
 #include <fcntl.h>
 #include <stdio.h>
 #include <signal.h>
 #include <fcntl.h>
-#include <sys/errno.h>
+#include <errno.h>
 #include <sys/param.h>
 #include <sys/time.h>
 #include <sys/param.h>
 #include <sys/time.h>
+
+#ifdef HAVE_GETRUSAGE
+#ifndef HAVE_SYS_RESOURCE_H
+#undef HAVE_GETRUSAGE
+#endif
+#endif
+
+#ifdef HAVE_GETRUSAGE
 #include <sys/resource.h>
 int getrusage();
 #include <sys/resource.h>
 int getrusage();
+#endif
 
 
+#if HAVE_SYS_IOCTL_H
 #include <sys/ioctl.h>
 #include <sys/ioctl.h>
-#include <sys/mount.h>
-#include <sys/dirent.h>
+#endif
+
+#if HAVE_DIRENT_H
+# include <dirent.h>
+# define NAMLEN(dirent) strlen((dirent)->d_name)
+#else
+# define dirent direct
+# define NAMLEN(dirent) (dirent)->d_namlen
+# if HAVE_SYS_NDIR_H
+#  include <sys/ndir.h>
+# endif
+# if HAVE_SYS_DIR_H
+#  include <sys/dir.h>
+# endif
+# if HAVE_NDIR_H
+#  include <ndir.h>
+# endif
+#endif
 
 #ifdef HAVE_UNISTD_H
 
 #ifdef HAVE_UNISTD_H
+#undef MAXPATHLEN              /* sys/param.h might define this also */
 #include <unistd.h>
 #endif
 
 #include <unistd.h>
 #endif
 
@@ -64,7 +90,21 @@ int getrusage();
 #if WITH_NetBSD_HOST /* here NetBSD as that is what we're emulating */
 #include <sys/syscall.h> /* FIXME - should not be including this one */
 #include <sys/sysctl.h>
 #if WITH_NetBSD_HOST /* here NetBSD as that is what we're emulating */
 #include <sys/syscall.h> /* FIXME - should not be including this one */
 #include <sys/sysctl.h>
+#include <sys/mount.h>
 extern int getdirentries(int fd, char *buf, int nbytes, long *basep);
 extern int getdirentries(int fd, char *buf, int nbytes, long *basep);
+
+/* NetBSD post 2.0 has the statfs system call (if COMPAT_20), but does
+   not have struct statfs.  In this case don't implement fstatfs.
+   FIXME: Should implement fstatvfs.  */
+#ifndef HAVE_STRUCT_STATFS
+#undef HAVE_FSTATFS
+#endif
+
+#else
+
+/* If this is not netbsd, don't allow fstatfs or getdirentries at this time */
+#undef HAVE_FSTATFS
+#undef HAVE_GETDIRENTRIES
 #endif
 
 #if (BSD < 199306) /* here BSD as just a bug */
 #endif
 
 #if (BSD < 199306) /* here BSD as just a bug */
@@ -89,9 +129,19 @@ extern int errno;
 #endif
 
 
 #endif
 
 
+/* EMULATION
+
+   NetBSD - Emulation of user programs for NetBSD/PPC
+
+   DESCRIPTION
+
+   */
+
+
 /* NetBSD's idea of what is needed to implement emulations */
 
 struct _os_emul_data {
 /* NetBSD's idea of what is needed to implement emulations */
 
 struct _os_emul_data {
+  device *vm;
   emul_syscall *syscalls;
 };
 
   emul_syscall *syscalls;
 };
 
@@ -109,7 +159,6 @@ write_stat(unsigned_word addr,
   H2T(buf.st_nlink);
   H2T(buf.st_uid);
   H2T(buf.st_gid);
   H2T(buf.st_nlink);
   H2T(buf.st_uid);
   H2T(buf.st_gid);
-  H2T(buf.st_rdev);
   H2T(buf.st_size);
   H2T(buf.st_atime);
   /* H2T(buf.st_spare1); */
   H2T(buf.st_size);
   H2T(buf.st_atime);
   /* H2T(buf.st_spare1); */
@@ -117,8 +166,15 @@ write_stat(unsigned_word addr,
   /* H2T(buf.st_spare2); */
   H2T(buf.st_ctime);
   /* H2T(buf.st_spare3); */
   /* H2T(buf.st_spare2); */
   H2T(buf.st_ctime);
   /* H2T(buf.st_spare3); */
+#ifdef AC_STRUCT_ST_RDEV
+  H2T(buf.st_rdev);
+#endif
+#ifdef AC_STRUCT_ST_BLKSIZE
   H2T(buf.st_blksize);
   H2T(buf.st_blksize);
+#endif
+#ifdef AC_STRUCT_ST_BLOCKS
   H2T(buf.st_blocks);
   H2T(buf.st_blocks);
+#endif
 #if WITH_NetBSD_HOST
   H2T(buf.st_flags);
   H2T(buf.st_gen);
 #if WITH_NetBSD_HOST
   H2T(buf.st_flags);
   H2T(buf.st_gen);
@@ -126,8 +182,8 @@ write_stat(unsigned_word addr,
   emul_write_buffer(&buf, addr, sizeof(buf), processor, cia);
 }
 
   emul_write_buffer(&buf, addr, sizeof(buf), processor, cia);
 }
 
-  
-#if NetBSD
+
+#ifdef HAVE_FSTATFS
 STATIC_INLINE_EMUL_NETBSD void
 write_statfs(unsigned_word addr,
             struct statfs buf,
 STATIC_INLINE_EMUL_NETBSD void
 write_statfs(unsigned_word addr,
             struct statfs buf,
@@ -154,7 +210,7 @@ write_statfs(unsigned_word addr,
 }
 #endif
 
 }
 #endif
 
-  
+
 STATIC_INLINE_EMUL_NETBSD void
 write_timeval(unsigned_word addr,
              struct timeval t,
 STATIC_INLINE_EMUL_NETBSD void
 write_timeval(unsigned_word addr,
              struct timeval t,
@@ -166,7 +222,7 @@ write_timeval(unsigned_word addr,
   emul_write_buffer(&t, addr, sizeof(t), processor, cia);
 }
 
   emul_write_buffer(&t, addr, sizeof(t), processor, cia);
 }
 
-  
+#ifdef HAVE_GETTIMEOFDAY
 STATIC_INLINE_EMUL_NETBSD void
 write_timezone(unsigned_word addr,
               struct timezone tz,
 STATIC_INLINE_EMUL_NETBSD void
 write_timezone(unsigned_word addr,
               struct timezone tz,
@@ -177,9 +233,9 @@ write_timezone(unsigned_word addr,
   H2T(tz.tz_dsttime);
   emul_write_buffer(&tz, addr, sizeof(tz), processor, cia);
 }
   H2T(tz.tz_dsttime);
   emul_write_buffer(&tz, addr, sizeof(tz), processor, cia);
 }
+#endif
 
 
-  
-#if WITH_NetBSD_HOST
+#ifdef HAVE_GETDIRENTRIES
 STATIC_INLINE_EMUL_NETBSD void
 write_direntries(unsigned_word addr,
                 char *buf,
 STATIC_INLINE_EMUL_NETBSD void
 write_direntries(unsigned_word addr,
                 char *buf,
@@ -201,12 +257,13 @@ write_direntries(unsigned_word addr,
     nbytes -= in->d_reclen;
     addr += in->d_reclen;
     buf += in->d_reclen;
     nbytes -= in->d_reclen;
     addr += in->d_reclen;
     buf += in->d_reclen;
-    zfree(out);
+    free(out);
   }
 }
 #endif
 
 
   }
 }
 #endif
 
 
+#ifdef HAVE_GETRUSAGE
 STATIC_INLINE_EMUL_NETBSD void
 write_rusage(unsigned_word addr,
             struct rusage rusage,
 STATIC_INLINE_EMUL_NETBSD void
 write_rusage(unsigned_word addr,
             struct rusage rusage,
@@ -233,8 +290,33 @@ write_rusage(unsigned_word addr,
   H2T(rusage.ru_nivcsw);          /* involuntary context switches */
   emul_write_buffer(&rusage, addr, sizeof(rusage), processor, cia);
 }
   H2T(rusage.ru_nivcsw);          /* involuntary context switches */
   emul_write_buffer(&rusage, addr, sizeof(rusage), processor, cia);
 }
+#endif
+
+
+/* File descriptors 0, 1, and 2 should not be closed.  fd_closed[]
+   tracks whether these descriptors have been closed in do_close()
+   below.  */
+
+static int fd_closed[3];
+
+/* Check for some occurrences of bad file descriptors.  We only check
+   whether fd 0, 1, or 2 are "closed".  By "closed" we mean that these
+   descriptors aren't actually closed, but are considered to be closed
+   by this layer.
+
+   Other checks are performed by the underlying OS call.  */
+
+static int
+fdbad (int fd)
+{
+  if (fd >=0 && fd <= 2 && fd_closed[fd])
+    {
+      errno = EBADF;
+      return -1;
+    }
+  return 0;
+}
 
 
-  
 static void
 do_exit(os_emul_data *emul,
        unsigned call,
 static void
 do_exit(os_emul_data *emul,
        unsigned call,
@@ -264,16 +346,16 @@ do_read(os_emul_data *emul,
   int nbytes = cpu_registers(processor)->gpr[arg0+2];
   int status;
   SYS(read);
   int nbytes = cpu_registers(processor)->gpr[arg0+2];
   int status;
   SYS(read);
-  
+
   if (WITH_TRACE && ppc_trace[trace_os_emul])
     printf_filtered ("%d, 0x%lx, %d", d, (long)buf, nbytes);
 
   /* get a tempoary bufer */
   scratch_buffer = zalloc(nbytes);
   if (WITH_TRACE && ppc_trace[trace_os_emul])
     printf_filtered ("%d, 0x%lx, %d", d, (long)buf, nbytes);
 
   /* get a tempoary bufer */
   scratch_buffer = zalloc(nbytes);
-  
+
   /* check if buffer exists by reading it */
   emul_read_buffer(scratch_buffer, buf, nbytes, processor, cia);
   /* check if buffer exists by reading it */
   emul_read_buffer(scratch_buffer, buf, nbytes, processor, cia);
-  
+
   /* read */
 #if 0
   if (d == 0) {
   /* read */
 #if 0
   if (d == 0) {
@@ -282,18 +364,15 @@ do_read(os_emul_data *emul,
       status = -1;
   }
 #endif
       status = -1;
   }
 #endif
-  status = read (d, scratch_buffer, nbytes);
-  
-  if (status == -1) {
-    cpu_registers(processor)->gpr[0] = errno;
-  } else {
-    cpu_registers(processor)->gpr[3] = status;
-    
-    if (status > 0)
-      emul_write_buffer(scratch_buffer, buf, status, processor, cia);
-  }
-  
-  zfree(scratch_buffer);
+  status = fdbad (d);
+  if (status == 0)
+    status = read (d, scratch_buffer, nbytes);
+
+  emul_write_status(processor, status, errno);
+  if (status > 0)
+    emul_write_buffer(scratch_buffer, buf, status, processor, cia);
+
+  free(scratch_buffer);
 }
 
 
 }
 
 
@@ -305,34 +384,31 @@ do_write(os_emul_data *emul,
         unsigned_word cia)
 {
   void *scratch_buffer = NULL;
         unsigned_word cia)
 {
   void *scratch_buffer = NULL;
-  int nr_moved;
   int d = (int)cpu_registers(processor)->gpr[arg0];
   unsigned_word buf = cpu_registers(processor)->gpr[arg0+1];
   int nbytes = cpu_registers(processor)->gpr[arg0+2];
   int status;
   SYS(write);
   int d = (int)cpu_registers(processor)->gpr[arg0];
   unsigned_word buf = cpu_registers(processor)->gpr[arg0+1];
   int nbytes = cpu_registers(processor)->gpr[arg0+2];
   int status;
   SYS(write);
-  
+
   if (WITH_TRACE && ppc_trace[trace_os_emul])
     printf_filtered ("%d, 0x%lx, %d", d, (long)buf, nbytes);
 
   /* get a tempoary bufer */
   scratch_buffer = zalloc(nbytes); /* FIXME - nbytes == 0 */
   if (WITH_TRACE && ppc_trace[trace_os_emul])
     printf_filtered ("%d, 0x%lx, %d", d, (long)buf, nbytes);
 
   /* get a tempoary bufer */
   scratch_buffer = zalloc(nbytes); /* FIXME - nbytes == 0 */
-  
+
   /* copy in */
   /* copy in */
-  nr_moved = vm_data_map_read_buffer(cpu_data_map(processor),
-                                    scratch_buffer,
-                                    buf,
-                                    nbytes);
-  if (nr_moved != nbytes) {
-    /* FIXME - should handle better */
-    error("system_call()write copy failed (nr_moved=%d != nbytes=%d)\n",
-         nr_moved, nbytes);
-  }
-  
+  emul_read_buffer(scratch_buffer, buf, nbytes,
+                  processor, cia);
+
   /* write */
   /* write */
-  status = write(d, scratch_buffer, nbytes);
+  status = fdbad (d);
+  if (status == 0)
+    status = write(d, scratch_buffer, nbytes);
+
   emul_write_status(processor, status, errno);
   emul_write_status(processor, status, errno);
-  zfree(scratch_buffer);
+  free(scratch_buffer);
+
+  flush_stdoutput();
 }
 
 
 }
 
 
@@ -348,12 +424,34 @@ do_open(os_emul_data *emul,
   char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
   int flags = (int)cpu_registers(processor)->gpr[arg0+1];
   int mode = (int)cpu_registers(processor)->gpr[arg0+2];
   char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
   int flags = (int)cpu_registers(processor)->gpr[arg0+1];
   int mode = (int)cpu_registers(processor)->gpr[arg0+2];
+  int hostflags;
+  int status;
 
   if (WITH_TRACE && ppc_trace[trace_os_emul])
     printf_filtered ("0x%lx [%s], 0x%x, 0x%x", (long)path_addr, path, flags, mode);
 
   SYS(open);
 
   if (WITH_TRACE && ppc_trace[trace_os_emul])
     printf_filtered ("0x%lx [%s], 0x%x, 0x%x", (long)path_addr, path, flags, mode);
 
   SYS(open);
-  emul_write_status(processor, open(path, flags, mode), errno);
+
+  /* Do some translation on 'flags' to match it to the host's version.  */
+  /* These flag values were taken from the NetBSD 1.4 header files.  */
+  if ((flags & 3) == 0)
+    hostflags = O_RDONLY;
+  else if ((flags & 3) == 1)
+    hostflags = O_WRONLY;
+  else
+    hostflags = O_RDWR;
+  if (flags & 0x00000008)
+    hostflags |= O_APPEND;
+  if (flags & 0x00000200)
+    hostflags |= O_CREAT;
+  if (flags & 0x00000400)
+    hostflags |= O_TRUNC;
+  if (flags & 0x00000800)
+    hostflags |= O_EXCL;
+
+  /* Can't combine these statements, cuz open sets errno. */
+  status = open(path, hostflags, mode);
+  emul_write_status(processor, status, errno);
 }
 
 
 }
 
 
@@ -365,12 +463,28 @@ do_close(os_emul_data *emul,
         unsigned_word cia)
 {
   int d = (int)cpu_registers(processor)->gpr[arg0];
         unsigned_word cia)
 {
   int d = (int)cpu_registers(processor)->gpr[arg0];
+  int status;
 
   if (WITH_TRACE && ppc_trace[trace_os_emul])
     printf_filtered ("%d", d);
 
   SYS(close);
 
   if (WITH_TRACE && ppc_trace[trace_os_emul])
     printf_filtered ("%d", d);
 
   SYS(close);
-  emul_write_status(processor, close(d), errno);
+
+  status = fdbad (d);
+  if (status == 0)
+    {
+      /* Do not close stdin, stdout, or stderr. GDB may still need access to
+        these descriptors.  */
+      if (d == 0 || d == 1 || d == 2)
+       {
+         fd_closed[d] = 1;
+         status = 0;
+       }
+      else
+       status = close(d);
+    }
+
+  emul_write_status(processor, status, errno);
 }
 
 
 }
 
 
@@ -380,24 +494,27 @@ do_break(os_emul_data *emul,
         const int arg0,
         cpu *processor,
         unsigned_word cia)
         const int arg0,
         cpu *processor,
         unsigned_word cia)
-     /* just pass this onto the `vm' device */
 {
 {
-  psim *system = cpu_system(processor);
-  device *vm = psim_device(system, "/vm");
+  /* just pass this onto the `vm' device */
+  unsigned_word new_break = cpu_registers(processor)->gpr[arg0];
+  int status;
 
   if (WITH_TRACE && ppc_trace[trace_os_emul])
     printf_filtered ("0x%lx", (long)cpu_registers(processor)->gpr[arg0]);
 
   SYS(break);
 
   if (WITH_TRACE && ppc_trace[trace_os_emul])
     printf_filtered ("0x%lx", (long)cpu_registers(processor)->gpr[arg0]);
 
   SYS(break);
-  device_ioctl(vm,
-              system,
-              processor,
-              cia,
-              0, /*ioctl*/
-              NULL); /*ioctl-data*/
+  status = device_ioctl(emul->vm,
+                       processor,
+                       cia,
+                       device_ioctl_break,
+                       new_break); /*ioctl-data*/
+  emul_write_status(processor, 0, status);
 }
 
 
 }
 
 
+#ifndef HAVE_GETPID
+#define do_getpid 0
+#else
 static void
 do_getpid(os_emul_data *emul,
          unsigned call,
 static void
 do_getpid(os_emul_data *emul,
          unsigned call,
@@ -406,10 +523,13 @@ do_getpid(os_emul_data *emul,
          unsigned_word cia)
 {
   SYS(getpid);
          unsigned_word cia)
 {
   SYS(getpid);
-  cpu_registers(processor)->gpr[3] = (int)getpid();
+  emul_write_status(processor, (int)getpid(), 0);
 }
 }
+#endif
 
 
-
+#ifndef HAVE_GETUID
+#define do_getuid 0
+#else
 static void
 do_getuid(os_emul_data *emul,
          unsigned call,
 static void
 do_getuid(os_emul_data *emul,
          unsigned call,
@@ -418,10 +538,13 @@ do_getuid(os_emul_data *emul,
          unsigned_word cia)
 {
   SYS(getuid);
          unsigned_word cia)
 {
   SYS(getuid);
-  cpu_registers(processor)->gpr[3] = (int)getuid();
+  emul_write_status(processor, (int)getuid(), 0);
 }
 }
+#endif
 
 
-
+#ifndef HAVE_GETEUID
+#define do_geteuid 0
+#else
 static void
 do_geteuid(os_emul_data *emul,
           unsigned call,
 static void
 do_geteuid(os_emul_data *emul,
           unsigned call,
@@ -430,10 +553,13 @@ do_geteuid(os_emul_data *emul,
           unsigned_word cia)
 {
   SYS(geteuid);
           unsigned_word cia)
 {
   SYS(geteuid);
-  cpu_registers(processor)->gpr[3] = (int)geteuid();
+  emul_write_status(processor, (int)geteuid(), 0);
 }
 }
+#endif
 
 
-
+#ifndef HAVE_KILL
+#define do_kill 0
+#else
 static void
 do_kill(os_emul_data *emul,
        unsigned call,
 static void
 do_kill(os_emul_data *emul,
        unsigned call,
@@ -452,8 +578,11 @@ do_kill(os_emul_data *emul,
                  (long)cia);
   cpu_halt(processor, cia, was_signalled, sig);
 }
                  (long)cia);
   cpu_halt(processor, cia, was_signalled, sig);
 }
+#endif
 
 
-
+#ifndef HAVE_DUP
+#define do_dup 0
+#else
 static void
 do_dup(os_emul_data *emul,
        unsigned call,
 static void
 do_dup(os_emul_data *emul,
        unsigned call,
@@ -462,16 +591,20 @@ do_dup(os_emul_data *emul,
        unsigned_word cia)
 {
   int oldd = cpu_registers(processor)->gpr[arg0];
        unsigned_word cia)
 {
   int oldd = cpu_registers(processor)->gpr[arg0];
-  int status = dup(oldd);
+  int status = (fdbad (oldd) < 0) ? -1 : dup(oldd);
+  int err = errno;
 
   if (WITH_TRACE && ppc_trace[trace_os_emul])
     printf_filtered ("%d", oldd);
 
   SYS(dup);
 
   if (WITH_TRACE && ppc_trace[trace_os_emul])
     printf_filtered ("%d", oldd);
 
   SYS(dup);
-  emul_write_status(processor, status, errno);
+  emul_write_status(processor, status, err);
 }
 }
+#endif
 
 
-
+#ifndef HAVE_GETEGID
+#define do_getegid 0
+#else
 static void
 do_getegid(os_emul_data *emul,
           unsigned call,
 static void
 do_getegid(os_emul_data *emul,
           unsigned call,
@@ -480,10 +613,13 @@ do_getegid(os_emul_data *emul,
           unsigned_word cia)
 {
   SYS(getegid);
           unsigned_word cia)
 {
   SYS(getegid);
-  cpu_registers(processor)->gpr[3] = (int)getegid();
+  emul_write_status(processor, (int)getegid(), 0);
 }
 }
+#endif
 
 
-
+#ifndef HAVE_GETGID
+#define do_getgid 0
+#else
 static void
 do_getgid(os_emul_data *emul,
          unsigned call,
 static void
 do_getgid(os_emul_data *emul,
          unsigned call,
@@ -492,10 +628,13 @@ do_getgid(os_emul_data *emul,
          unsigned_word cia)
 {
   SYS(getgid);
          unsigned_word cia)
 {
   SYS(getgid);
-  cpu_registers(processor)->gpr[3] = (int)getgid();
+  emul_write_status(processor, (int)getgid(), 0);
 }
 }
+#endif
 
 
-
+#ifndef HAVE_SIGPROCMASK
+#define do_sigprocmask 0
+#else
 static void
 do_sigprocmask(os_emul_data *emul,
               unsigned call,
 static void
 do_sigprocmask(os_emul_data *emul,
               unsigned call,
@@ -506,16 +645,21 @@ do_sigprocmask(os_emul_data *emul,
   natural_word how = cpu_registers(processor)->gpr[arg0];
   unsigned_word set = cpu_registers(processor)->gpr[arg0+1];
   unsigned_word oset = cpu_registers(processor)->gpr[arg0+2];
   natural_word how = cpu_registers(processor)->gpr[arg0];
   unsigned_word set = cpu_registers(processor)->gpr[arg0+1];
   unsigned_word oset = cpu_registers(processor)->gpr[arg0+2];
+#ifdef SYS_sigprocmask
   SYS(sigprocmask);
   SYS(sigprocmask);
+#endif
 
   if (WITH_TRACE && ppc_trace[trace_os_emul])
     printf_filtered ("%ld, 0x%ld, 0x%ld", (long)how, (long)set, (long)oset);
 
 
   if (WITH_TRACE && ppc_trace[trace_os_emul])
     printf_filtered ("%ld, 0x%ld, 0x%ld", (long)how, (long)set, (long)oset);
 
-  cpu_registers(processor)->gpr[3] = 0;
+  emul_write_status(processor, 0, 0);
   cpu_registers(processor)->gpr[4] = set;
 }
   cpu_registers(processor)->gpr[4] = set;
 }
+#endif
 
 
-
+#ifndef HAVE_IOCTL
+#define do_ioctl 0
+#else
 static void
 do_ioctl(os_emul_data *emul,
         unsigned call,
 static void
 do_ioctl(os_emul_data *emul,
         unsigned call,
@@ -538,15 +682,20 @@ do_ioctl(os_emul_data *emul,
       || dir & IOC_OUT
       || !(dir & IOC_VOID))
     error("do_ioctl() read or write of parameter not implemented\n");
       || dir & IOC_OUT
       || !(dir & IOC_VOID))
     error("do_ioctl() read or write of parameter not implemented\n");
-  status = ioctl(d, request, NULL);
+  status = fdbad (d);
+  if (status == 0)
+    status = ioctl(d, request, NULL);
   emul_write_status(processor, status, errno);
 #endif
 
   if (WITH_TRACE && ppc_trace[trace_os_emul])
     printf_filtered ("%d, 0x%x, 0x%lx", d, request, (long)argp_addr);
 }
   emul_write_status(processor, status, errno);
 #endif
 
   if (WITH_TRACE && ppc_trace[trace_os_emul])
     printf_filtered ("%d, 0x%x, 0x%lx", d, request, (long)argp_addr);
 }
+#endif
 
 
-
+#ifndef HAVE_UMASK
+#define do_umask 0
+#else
 static void
 do_umask(os_emul_data *emul,
         unsigned call,
 static void
 do_umask(os_emul_data *emul,
         unsigned call,
@@ -560,10 +709,13 @@ do_umask(os_emul_data *emul,
     printf_filtered ("0%o", mask);
 
   SYS(umask);
     printf_filtered ("0%o", mask);
 
   SYS(umask);
-  cpu_registers(processor)->gpr[3] = umask(mask);
+  emul_write_status(processor, umask(mask), 0);
 }
 }
+#endif
 
 
-
+#ifndef HAVE_DUP2
+#define do_dup2 0
+#else
 static void
 do_dup2(os_emul_data *emul,
        unsigned call,
 static void
 do_dup2(os_emul_data *emul,
        unsigned call,
@@ -573,16 +725,20 @@ do_dup2(os_emul_data *emul,
 {
   int oldd = cpu_registers(processor)->gpr[arg0];
   int newd = cpu_registers(processor)->gpr[arg0+1];
 {
   int oldd = cpu_registers(processor)->gpr[arg0];
   int newd = cpu_registers(processor)->gpr[arg0+1];
-  int status = dup2(oldd, newd);
+  int status = (fdbad (oldd) < 0) ? -1 : dup2(oldd, newd);
+  int err = errno;
 
   if (WITH_TRACE && ppc_trace[trace_os_emul])
     printf_filtered ("%d, %d", oldd, newd);
 
   SYS(dup2);
 
   if (WITH_TRACE && ppc_trace[trace_os_emul])
     printf_filtered ("%d, %d", oldd, newd);
 
   SYS(dup2);
-  emul_write_status(processor, status, errno);
+  emul_write_status(processor, status, err);
 }
 }
+#endif
 
 
-
+#ifndef HAVE_FCNTL
+#define do_fcntl 0
+#else
 static void
 do_fcntl(os_emul_data *emul,
         unsigned call,
 static void
 do_fcntl(os_emul_data *emul,
         unsigned call,
@@ -599,11 +755,16 @@ do_fcntl(os_emul_data *emul,
     printf_filtered ("%d, %d, %d", fd, cmd, arg);
 
   SYS(fcntl);
     printf_filtered ("%d, %d, %d", fd, cmd, arg);
 
   SYS(fcntl);
-  status = fcntl(fd, cmd, arg);
+  status = fdbad (fd);
+  if (status == 0)
+    status = fcntl(fd, cmd, arg);
   emul_write_status(processor, status, errno);
 }
   emul_write_status(processor, status, errno);
 }
+#endif
 
 
-
+#ifndef HAVE_GETTIMEOFDAY
+#define do_gettimeofday 0
+#else
 static void
 do_gettimeofday(os_emul_data *emul,
                unsigned call,
 static void
 do_gettimeofday(os_emul_data *emul,
                unsigned call,
@@ -617,12 +778,13 @@ do_gettimeofday(os_emul_data *emul,
   struct timezone tz;
   int status = gettimeofday((t_addr != 0 ? &t : NULL),
                            (tz_addr != 0 ? &tz : NULL));
   struct timezone tz;
   int status = gettimeofday((t_addr != 0 ? &t : NULL),
                            (tz_addr != 0 ? &tz : NULL));
+  int err = errno;
 
   if (WITH_TRACE && ppc_trace[trace_os_emul])
     printf_filtered ("0x%lx, 0x%lx", (long)t_addr, (long)tz_addr);
 
   SYS(gettimeofday);
 
   if (WITH_TRACE && ppc_trace[trace_os_emul])
     printf_filtered ("0x%lx, 0x%lx", (long)t_addr, (long)tz_addr);
 
   SYS(gettimeofday);
-  emul_write_status(processor, status, errno);
+  emul_write_status(processor, status, err);
   if (status == 0) {
     if (t_addr != 0)
       write_timeval(t_addr, t, processor, cia);
   if (status == 0) {
     if (t_addr != 0)
       write_timeval(t_addr, t, processor, cia);
@@ -630,8 +792,11 @@ do_gettimeofday(os_emul_data *emul,
       write_timezone(tz_addr, tz, processor, cia);
   }
 }
       write_timezone(tz_addr, tz, processor, cia);
   }
 }
+#endif
 
 
-
+#ifndef HAVE_GETRUSAGE
+#define do_getrusage 0
+#else
 static void
 do_getrusage(os_emul_data *emul,
             unsigned call,
 static void
 do_getrusage(os_emul_data *emul,
             unsigned call,
@@ -643,20 +808,22 @@ do_getrusage(os_emul_data *emul,
   unsigned_word rusage_addr = cpu_registers(processor)->gpr[arg0+1];
   struct rusage rusage;
   int status = getrusage(who, (rusage_addr != 0 ? &rusage : NULL));
   unsigned_word rusage_addr = cpu_registers(processor)->gpr[arg0+1];
   struct rusage rusage;
   int status = getrusage(who, (rusage_addr != 0 ? &rusage : NULL));
+  int err = errno;
 
   if (WITH_TRACE && ppc_trace[trace_os_emul])
     printf_filtered ("%d, 0x%lx", who, (long)rusage_addr);
 
   SYS(getrusage);
 
   if (WITH_TRACE && ppc_trace[trace_os_emul])
     printf_filtered ("%d, 0x%lx", who, (long)rusage_addr);
 
   SYS(getrusage);
-  emul_write_status(processor, status, errno);
+  emul_write_status(processor, status, err);
   if (status == 0) {
     if (rusage_addr != 0)
       write_rusage(rusage_addr, rusage, processor, cia);
   }
 }
   if (status == 0) {
     if (rusage_addr != 0)
       write_rusage(rusage_addr, rusage, processor, cia);
   }
 }
+#endif
 
 
 
 
-#if !WITH_NetBSD_HOST
+#ifndef HAVE_FSTATFS
 #define do_fstatfs 0
 #else
 static void
 #define do_fstatfs 0
 #else
 static void
@@ -675,7 +842,9 @@ do_fstatfs(os_emul_data *emul,
     printf_filtered ("%d, 0x%lx", fd, (long)buf_addr);
 
   SYS(fstatfs);
     printf_filtered ("%d, 0x%lx", fd, (long)buf_addr);
 
   SYS(fstatfs);
-  status = fstatfs(fd, (buf_addr == 0 ? NULL : &buf));
+  status = fdbad (fd);
+  if (status == 0)
+    status = fstatfs(fd, (buf_addr == 0 ? NULL : &buf));
   emul_write_status(processor, status, errno);
   if (status == 0) {
     if (buf_addr != 0)
   emul_write_status(processor, status, errno);
   if (status == 0) {
     if (buf_addr != 0)
@@ -684,7 +853,9 @@ do_fstatfs(os_emul_data *emul,
 }
 #endif
 
 }
 #endif
 
-
+#ifndef HAVE_STAT
+#define do_stat 0
+#else
 static void
 do_stat(os_emul_data *emul,
        unsigned call,
 static void
 do_stat(os_emul_data *emul,
        unsigned call,
@@ -698,14 +869,19 @@ do_stat(os_emul_data *emul,
   char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
   struct stat buf;
   int status;
   char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
   struct stat buf;
   int status;
+#ifdef SYS_stat
   SYS(stat);
   SYS(stat);
+#endif
   status = stat(path, &buf);
   emul_write_status(processor, status, errno);
   if (status == 0)
     write_stat(stat_buf_addr, buf, processor, cia);
 }
   status = stat(path, &buf);
   emul_write_status(processor, status, errno);
   if (status == 0)
     write_stat(stat_buf_addr, buf, processor, cia);
 }
+#endif
 
 
-
+#ifndef HAVE_FSTAT
+#define do_fstat 0
+#else
 static void
 do_fstat(os_emul_data *emul,
         unsigned call,
 static void
 do_fstat(os_emul_data *emul,
         unsigned call,
@@ -716,12 +892,22 @@ do_fstat(os_emul_data *emul,
   int fd = cpu_registers(processor)->gpr[arg0];
   unsigned_word stat_buf_addr = cpu_registers(processor)->gpr[arg0+1];
   struct stat buf;
   int fd = cpu_registers(processor)->gpr[arg0];
   unsigned_word stat_buf_addr = cpu_registers(processor)->gpr[arg0+1];
   struct stat buf;
+  int status;
+#ifdef SYS_fstat
   SYS(fstat);
   SYS(fstat);
-  emul_write_status(processor, fstat(fd, &buf), errno);
+#endif
+  /* Can't combine these statements, cuz fstat sets errno. */
+  status = fdbad (fd);
+  if (status == 0)
+    status = fstat(fd, &buf);
+  emul_write_status(processor, status, errno);
   write_stat(stat_buf_addr, buf, processor, cia);
 }
   write_stat(stat_buf_addr, buf, processor, cia);
 }
+#endif
 
 
-
+#ifndef HAVE_LSTAT
+#define do_lstat 0
+#else
 static void
 do_lstat(os_emul_data *emul,
         unsigned call,
 static void
 do_lstat(os_emul_data *emul,
         unsigned call,
@@ -734,13 +920,18 @@ do_lstat(os_emul_data *emul,
   char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
   unsigned_word stat_buf_addr = cpu_registers(processor)->gpr[arg0+1];
   struct stat buf;
   char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
   unsigned_word stat_buf_addr = cpu_registers(processor)->gpr[arg0+1];
   struct stat buf;
+  int status;
+#ifdef SYS_lstat
   SYS(lstat);
   SYS(lstat);
-  emul_write_status(processor, stat(path, &buf), errno);
+#endif
+  /* Can't combine these statements, cuz lstat sets errno. */
+  status = lstat(path, &buf);
+  emul_write_status(processor, status, errno);
   write_stat(stat_buf_addr, buf, processor, cia);
 }
   write_stat(stat_buf_addr, buf, processor, cia);
 }
+#endif
 
 
-
-#if !WITH_NetBSD_HOST
+#ifndef HAVE_GETDIRENTRIES
 #define do_getdirentries 0
 #else
 static void
 #define do_getdirentries 0
 #else
 static void
@@ -757,7 +948,9 @@ do_getdirentries(os_emul_data *emul,
   unsigned_word basep_addr = cpu_registers(processor)->gpr[arg0+3];
   long basep;
   int status;
   unsigned_word basep_addr = cpu_registers(processor)->gpr[arg0+3];
   long basep;
   int status;
+#ifdef SYS_getdirentries
   SYS(getdirentries);
   SYS(getdirentries);
+#endif
   if (buf_addr != 0 && nbytes >= 0)
     buf = zalloc(nbytes);
   else
   if (buf_addr != 0 && nbytes >= 0)
     buf = zalloc(nbytes);
   else
@@ -772,7 +965,7 @@ do_getdirentries(os_emul_data *emul,
   if (status > 0)
     write_direntries(buf_addr, buf, status, processor, cia);
   if (buf != NULL)
   if (status > 0)
     write_direntries(buf_addr, buf, status, processor, cia);
   if (buf != NULL)
-    zfree(buf);
+    free(buf);
 }
 #endif
 
 }
 #endif
 
@@ -793,7 +986,9 @@ do___syscall(os_emul_data *emul,
                      cia);
 }
 
                      cia);
 }
 
-
+#ifndef HAVE_LSEEK
+#define do_lseek 0
+#else
 static void
 do_lseek(os_emul_data *emul,
         unsigned call,
 static void
 do_lseek(os_emul_data *emul,
         unsigned call,
@@ -806,14 +1001,17 @@ do_lseek(os_emul_data *emul,
   int whence = cpu_registers(processor)->gpr[arg0+4];
   off_t status;
   SYS(lseek);
   int whence = cpu_registers(processor)->gpr[arg0+4];
   off_t status;
   SYS(lseek);
-  status = lseek(fildes, offset, whence);
+  status = fdbad (fildes);
+  if (status == 0)
+    status = lseek(fildes, offset, whence);
   if (status == -1)
     emul_write_status(processor, -1, errno);
   else {
   if (status == -1)
     emul_write_status(processor, -1, errno);
   else {
+    emul_write_status(processor, 0, 0); /* success */
     emul_write_gpr64(processor, 3, status);
   }
 }
     emul_write_gpr64(processor, 3, status);
   }
 }
-
+#endif
 
 static void
 do___sysctl(os_emul_data *emul,
 
 static void
 do___sysctl(os_emul_data *emul,
@@ -840,7 +1038,7 @@ do___sysctl(os_emul_data *emul,
                              processor,
                              cia);
   name += sizeof(mib);
                              processor,
                              cia);
   name += sizeof(mib);
-  
+
   /* see what to do with it ... */
   switch ((int)mib) {
   case 6/*CTL_HW*/:
   /* see what to do with it ... */
   switch ((int)mib) {
   case 6/*CTL_HW*/:
@@ -879,7 +1077,7 @@ do___sysctl(os_emul_data *emul,
     error("sysctl() name[0]=%d unknown\n", (int)mib);
     break;
   }
     error("sysctl() name[0]=%d unknown\n", (int)mib);
     break;
   }
-  cpu_registers(processor)->gpr[3] = 0;
+  emul_write_status(processor, 0, 0); /* always succeed */
 }
 
 
 }
 
 
@@ -887,7 +1085,7 @@ do___sysctl(os_emul_data *emul,
 static emul_syscall_descriptor netbsd_descriptors[] = {
   /* 0 */ { 0, "syscall" },
   /* 1 */ { do_exit, "exit" },
 static emul_syscall_descriptor netbsd_descriptors[] = {
   /* 0 */ { 0, "syscall" },
   /* 1 */ { do_exit, "exit" },
-  /* 2 */ { 0, "fork" },         
+  /* 2 */ { 0, "fork" },
   /* 3 */ { do_read, "read" },
   /* 4 */ { do_write, "write" },
   /* 5 */ { do_open, "open" },
   /* 3 */ { do_read, "read" },
   /* 4 */ { do_write, "write" },
   /* 5 */ { do_open, "open" },
@@ -1091,7 +1289,7 @@ static emul_syscall_descriptor netbsd_descriptors[] = {
   /* 203 */ { 0, "mlock" },
   /* 204 */ { 0, "munlock" },
 };
   /* 203 */ { 0, "mlock" },
   /* 204 */ { 0, "munlock" },
 };
-    
+
 static char *(netbsd_error_names[]) = {
   /* 0 */ "ESUCCESS",
   /* 1 */ "EPERM",
 static char *(netbsd_error_names[]) = {
   /* 0 */ "ESUCCESS",
   /* 1 */ "EPERM",
@@ -1215,11 +1413,11 @@ static char *(netbsd_signal_names[]) = {
 
 static emul_syscall emul_netbsd_syscalls = {
   netbsd_descriptors,
 
 static emul_syscall emul_netbsd_syscalls = {
   netbsd_descriptors,
-  sizeof(netbsd_descriptors) / sizeof(netbsd_descriptors[0]),
+  ARRAY_SIZE (netbsd_descriptors),
   netbsd_error_names,
   netbsd_error_names,
-  sizeof(netbsd_error_names) / sizeof(netbsd_error_names[0]),
+  ARRAY_SIZE (netbsd_error_names),
   netbsd_signal_names,
   netbsd_signal_names,
-  sizeof(netbsd_signal_names) / sizeof(netbsd_signal_names[0]),
+  ARRAY_SIZE (netbsd_signal_names),
 };
 
 
 };
 
 
@@ -1235,6 +1433,8 @@ emul_netbsd_create(device *root,
   unsigned stack_size;
   int elf_binary;
   os_emul_data *bsd_data;
   unsigned stack_size;
   int elf_binary;
   os_emul_data *bsd_data;
+  device *vm;
+  char *filename;
 
   /* check that this emulation is really for us */
   if (name != NULL && strcmp(name, "netbsd") != 0)
 
   /* check that this emulation is really for us */
   if (name != NULL && strcmp(name, "netbsd") != 0)
@@ -1258,60 +1458,42 @@ emul_netbsd_create(device *root,
   }
 
   /* options */
   }
 
   /* options */
-  {
-    device *options = device_tree_add_found(root, "/", "options");
-    device_add_integer_property(options, "smp", 1); /* always */
-    device_add_boolean_property(options, "little-endian?",
-                               !image->xvec->byteorder_big_p);
-    device_add_string_property(options, "env",
-                              (WITH_ENVIRONMENT == USER_ENVIRONMENT
-                               ? "user" : "virtual"));
-    device_add_boolean_property(options, "strict-alignment?",
-                               (WITH_ALIGNMENT == STRICT_ALIGNMENT
-                                || !image->xvec->byteorder_big_p));
-    device_add_boolean_property(options, "floating-point?",
-                               WITH_FLOATING_POINT);
-    device_add_string_property(options, "os-emul", "netbsd");
-  }
+  emul_add_tree_options(root, image, "netbsd",
+                       (WITH_ENVIRONMENT == USER_ENVIRONMENT
+                        ? "user" : "virtual"),
+                       0 /*oea-interrupt-prefix*/);
 
   /* virtual memory - handles growth of stack/heap */
 
   /* virtual memory - handles growth of stack/heap */
-  {
-    device *vm_node = device_tree_add_found_uw_u(root, "/", "vm",
-                                                top_of_stack - stack_size,
-                                                stack_size);
-    device *vm_map_binary = device_tree_add_found(vm_node, "", "map-binary");
-    device_add_null_property(vm_map_binary,
-                            bfd_get_filename(image));
-  }
+  vm = tree_parse(root, "/openprom/vm");
+  tree_parse(vm, "./stack-base 0x%lx",
+            (unsigned long)(top_of_stack - stack_size));
+  tree_parse(vm, "./nr-bytes 0x%x", stack_size);
+
+  filename = tree_quote_property (bfd_get_filename(image));
+  tree_parse(root, "/openprom/vm/map-binary/file-name %s",
+            filename);
+  free (filename);
 
   /* finish the init */
 
   /* finish the init */
-  {
-    device *init = device_tree_add_found(root, "/", "init");
-    {
-      device *init_register = device_tree_add_found(init, "", "register");
-      device_add_integer_property(init_register,
-                                 "pc",
-                                 bfd_get_start_address(image));
-      device_add_integer_property(init_register,
-                                 "sp",
-                                 top_of_stack);
-      device_add_integer_property(init_register,
-                                 "msr",
-                                 (image->xvec->byteorder_big_p
-                                  ? 0
-                                  : msr_little_endian_mode));
-    }
-    {
-      device *init_stack = device_tree_add_found(init, "", "stack");
-      device_add_null_property(init_stack,
-                              (elf_binary
-                               ? "elf"
-                               : "xcoff"));
-    }
-  }
+  tree_parse(root, "/openprom/init/register/pc 0x%lx",
+            (unsigned long)bfd_get_start_address(image));
+  tree_parse(root, "/openprom/init/register/sp 0x%lx",
+            (unsigned long)top_of_stack);
+  tree_parse(root, "/openprom/init/register/msr 0x%x",
+            ((tree_find_boolean_property(root, "/options/little-endian?")
+              ? msr_little_endian_mode
+              : 0)
+             | (tree_find_boolean_property(root, "/openprom/options/floating-point?")
+                ? (msr_floating_point_available
+                   | msr_floating_point_exception_mode_0
+                   | msr_floating_point_exception_mode_1)
+                : 0)));
+  tree_parse(root, "/openprom/init/stack/stack-type %s",
+            (elf_binary ? "ppc-elf" : "ppc-xcoff"));
 
   /* finally our emulation data */
   bsd_data = ZALLOC(os_emul_data);
 
   /* finally our emulation data */
   bsd_data = ZALLOC(os_emul_data);
+  bsd_data->vm = vm;
   bsd_data->syscalls = &emul_netbsd_syscalls;
   return bsd_data;
 }
   bsd_data->syscalls = &emul_netbsd_syscalls;
   return bsd_data;
 }
@@ -1320,7 +1502,9 @@ static void
 emul_netbsd_init(os_emul_data *emul_data,
                 int nr_cpus)
 {
 emul_netbsd_init(os_emul_data *emul_data,
                 int nr_cpus)
 {
-  /* nothing yet */
+  fd_closed[0] = 0;
+  fd_closed[1] = 0;
+  fd_closed[2] = 0;
 }
 
 static void
 }
 
 static void
@@ -1345,4 +1529,4 @@ const os_emul emul_netbsd = {
   0 /*data*/
 };
 
   0 /*data*/
 };
 
-#endif _EMUL_NETBSD_C_
+#endif /* _EMUL_NETBSD_C_ */
This page took 0.034647 seconds and 4 git commands to generate.