xref: /netbsd-src/external/gpl3/gdb/dist/sim/ppc/emul_netbsd.c (revision 889f3bb010ad20d396fb291b89f202288dac2c87)
1 /*  This file is part of the program psim.
2 
3     Copyright (C) 1994-1998, Andrew Cagney <cagney@highland.com.au>
4 
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 3 of the License, or
8     (at your option) any later version.
9 
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14 
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, see <http://www.gnu.org/licenses/>.
17 
18     */
19 
20 
21 #ifndef _EMUL_NETBSD_C_
22 #define _EMUL_NETBSD_C_
23 
24 
25 /* Note: this module is called via a table.  There is no benefit in
26    making it inline */
27 
28 #include "defs.h"
29 
30 #include <string.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <stdio.h>
34 #include <signal.h>
35 #include <fcntl.h>
36 #include <dirent.h>
37 #include <errno.h>
38 #include <sys/param.h>
39 #include <sys/time.h>
40 
41 #include "emul_generic.h"
42 #include "emul_netbsd.h"
43 
44 #ifdef HAVE_SYS_RESOURCE_H
45 #include <sys/resource.h>
46 #endif
47 
48 #if HAVE_SYS_IOCTL_H
49 #include <sys/ioctl.h>
50 #endif
51 
52 #if HAVE_DIRENT_H
53 # include <dirent.h>
54 # define NAMLEN(dirent) strlen((dirent)->d_name)
55 #else
56 # define dirent direct
57 # define NAMLEN(dirent) (dirent)->d_namlen
58 # if HAVE_SYS_NDIR_H
59 #  include <sys/ndir.h>
60 # endif
61 # if HAVE_SYS_DIR_H
62 #  include <sys/dir.h>
63 # endif
64 # if HAVE_NDIR_H
65 #  include <ndir.h>
66 # endif
67 #endif
68 
69 #undef MAXPATHLEN		/* sys/param.h might define this also */
70 #include <unistd.h>
71 
72 #include <stdlib.h>
73 
74 #define WITH_NetBSD_HOST (NetBSD >= 199306)
75 #if WITH_NetBSD_HOST /* here NetBSD as that is what we're emulating */
76 #include <sys/syscall.h> /* FIXME - should not be including this one */
77 #include <sys/sysctl.h>
78 #include <sys/mount.h>
79 extern int getdirentries(int fd, char *buf, int nbytes, long *basep);
80 
81 /* NetBSD post 2.0 has the statfs system call (if COMPAT_20), but does
82    not have struct statfs.  In this case don't implement fstatfs.
83    FIXME: Should implement fstatvfs.  */
84 #ifndef HAVE_STRUCT_STATFS
85 #undef HAVE_FSTATFS
86 #endif
87 
88 #else
89 
90 /* If this is not netbsd, don't allow fstatfs or getdirentries at this time */
91 #undef HAVE_FSTATFS
92 #undef HAVE_GETDIRENTRIES
93 #endif
94 
95 #ifndef STATIC_INLINE_EMUL_NETBSD
96 #define STATIC_INLINE_EMUL_NETBSD STATIC_INLINE
97 #endif
98 
99 
100 #if WITH_NetBSD_HOST
101 #define SYS(X) ASSERT(call == (SYS_##X))
102 #else
103 #define SYS(X)
104 #endif
105 
106 #if WITH_NetBSD_HOST && (PATH_MAX != 1024)
107 #error "PATH_MAX not 1024"
108 #elif !defined(PATH_MAX)
109 #define PATH_MAX 1024
110 #endif
111 
112 
113 /* EMULATION
114 
115    NetBSD - Emulation of user programs for NetBSD/PPC
116 
117    DESCRIPTION
118 
119    */
120 
121 
122 /* NetBSD's idea of what is needed to implement emulations */
123 
124 struct _os_emul_data {
125   device *vm;
126   emul_syscall *syscalls;
127 };
128 
129 
130 
131 STATIC_INLINE_EMUL_NETBSD void
132 write_stat(unsigned_word addr,
133 	   struct stat buf,
134 	   cpu *processor,
135 	   unsigned_word cia)
136 {
137   H2T(buf.st_dev);
138   H2T(buf.st_ino);
139   H2T(buf.st_mode);
140   H2T(buf.st_nlink);
141   H2T(buf.st_uid);
142   H2T(buf.st_gid);
143   H2T(buf.st_size);
144   H2T(buf.st_atime);
145   /* H2T(buf.st_spare1); */
146   H2T(buf.st_mtime);
147   /* H2T(buf.st_spare2); */
148   H2T(buf.st_ctime);
149   /* H2T(buf.st_spare3); */
150 #ifdef AC_STRUCT_ST_RDEV
151   H2T(buf.st_rdev);
152 #endif
153 #ifdef AC_STRUCT_ST_BLKSIZE
154   H2T(buf.st_blksize);
155 #endif
156 #ifdef AC_STRUCT_ST_BLOCKS
157   H2T(buf.st_blocks);
158 #endif
159 #if WITH_NetBSD_HOST
160   H2T(buf.st_flags);
161   H2T(buf.st_gen);
162 #endif
163   emul_write_buffer(&buf, addr, sizeof(buf), processor, cia);
164 }
165 
166 
167 #ifdef HAVE_FSTATFS
168 STATIC_INLINE_EMUL_NETBSD void
169 write_statfs(unsigned_word addr,
170 	     struct statfs buf,
171 	     cpu *processor,
172 	     unsigned_word cia)
173 {
174   H2T(buf.f_type);
175   H2T(buf.f_flags);
176   H2T(buf.f_bsize);
177   H2T(buf.f_iosize);
178   H2T(buf.f_blocks);
179   H2T(buf.f_bfree);
180   H2T(buf.f_bavail);
181   H2T(buf.f_files);
182   H2T(buf.f_ffree);
183   H2T(buf.f_fsid.val[0]);
184   H2T(buf.f_fsid.val[1]);
185   H2T(buf.f_owner);
186   /* f_spare[4]; */
187   /* f_fstypename[MFSNAMELEN]; */
188   /* f_mntonname[MNAMELEN]; */
189   /* f_mntfromname[MNAMELEN]; */
190   emul_write_buffer(&buf, addr, sizeof(buf), processor, cia);
191 }
192 #endif
193 
194 
195 STATIC_INLINE_EMUL_NETBSD void
196 write_timeval(unsigned_word addr,
197 	      struct timeval t,
198 	      cpu *processor,
199 	      unsigned_word cia)
200 {
201   H2T(t.tv_sec);
202   H2T(t.tv_usec);
203   emul_write_buffer(&t, addr, sizeof(t), processor, cia);
204 }
205 
206 #ifdef HAVE_GETTIMEOFDAY
207 STATIC_INLINE_EMUL_NETBSD void
208 write_timezone(unsigned_word addr,
209 	       struct timezone tz,
210 	       cpu *processor,
211 	       unsigned_word cia)
212 {
213   H2T(tz.tz_minuteswest);
214   H2T(tz.tz_dsttime);
215   emul_write_buffer(&tz, addr, sizeof(tz), processor, cia);
216 }
217 #endif
218 
219 #ifdef HAVE_GETDIRENTRIES
220 STATIC_INLINE_EMUL_NETBSD void
221 write_direntries(unsigned_word addr,
222 		 char *buf,
223 		 int nbytes,
224 		 cpu *processor,
225 		 unsigned_word cia)
226 {
227   while (nbytes > 0) {
228     struct dirent *out;
229     struct dirent *in = (struct dirent*)buf;
230     ASSERT(in->d_reclen <= nbytes);
231     out = (struct dirent*)zalloc(in->d_reclen);
232     memcpy(out/*dest*/, in/*src*/, in->d_reclen);
233     H2T(out->d_fileno);
234     H2T(out->d_reclen);
235     H2T(out->d_type);
236     H2T(out->d_namlen);
237     emul_write_buffer(out, addr, in->d_reclen, processor, cia);
238     nbytes -= in->d_reclen;
239     addr += in->d_reclen;
240     buf += in->d_reclen;
241     free(out);
242   }
243 }
244 #endif
245 
246 
247 #ifdef HAVE_GETRUSAGE
248 STATIC_INLINE_EMUL_NETBSD void
249 write_rusage(unsigned_word addr,
250 	     struct rusage rusage,
251 	     cpu *processor,
252 	     unsigned_word cia)
253 {
254   H2T(rusage.ru_utime.tv_sec); /* user time used */
255   H2T(rusage.ru_utime.tv_usec);
256   H2T(rusage.ru_stime.tv_sec); /* system time used */
257   H2T(rusage.ru_stime.tv_usec);
258   H2T(rusage.ru_maxrss);          /* integral max resident set size */
259   H2T(rusage.ru_ixrss);           /* integral shared text memory size */
260   H2T(rusage.ru_idrss);           /* integral unshared data size */
261   H2T(rusage.ru_isrss);           /* integral unshared stack size */
262   H2T(rusage.ru_minflt);          /* page reclaims */
263   H2T(rusage.ru_majflt);          /* page faults */
264   H2T(rusage.ru_nswap);           /* swaps */
265   H2T(rusage.ru_inblock);         /* block input operations */
266   H2T(rusage.ru_oublock);         /* block output operations */
267   H2T(rusage.ru_msgsnd);          /* messages sent */
268   H2T(rusage.ru_msgrcv);          /* messages received */
269   H2T(rusage.ru_nsignals);        /* signals received */
270   H2T(rusage.ru_nvcsw);           /* voluntary context switches */
271   H2T(rusage.ru_nivcsw);          /* involuntary context switches */
272   emul_write_buffer(&rusage, addr, sizeof(rusage), processor, cia);
273 }
274 #endif
275 
276 
277 /* File descriptors 0, 1, and 2 should not be closed.  fd_closed[]
278    tracks whether these descriptors have been closed in do_close()
279    below.  */
280 
281 static int fd_closed[3];
282 
283 /* Check for some occurrences of bad file descriptors.  We only check
284    whether fd 0, 1, or 2 are "closed".  By "closed" we mean that these
285    descriptors aren't actually closed, but are considered to be closed
286    by this layer.
287 
288    Other checks are performed by the underlying OS call.  */
289 
290 static int
291 fdbad (int fd)
292 {
293   if (fd >=0 && fd <= 2 && fd_closed[fd])
294     {
295       errno = EBADF;
296       return -1;
297     }
298   return 0;
299 }
300 
301 static void
302 do_exit(os_emul_data *emul,
303 	unsigned call,
304 	const int arg0,
305 	cpu *processor,
306 	unsigned_word cia)
307 {
308   int status = (int)cpu_registers(processor)->gpr[arg0];
309   SYS(exit);
310   if (WITH_TRACE && ppc_trace[trace_os_emul])
311     printf_filtered ("%d)\n", status);
312 
313   cpu_halt(processor, cia, was_exited, status);
314 }
315 
316 
317 static void
318 do_read(os_emul_data *emul,
319 	unsigned call,
320 	const int arg0,
321 	cpu *processor,
322 	unsigned_word cia)
323 {
324   void *scratch_buffer;
325   int d = (int)cpu_registers(processor)->gpr[arg0];
326   unsigned_word buf = cpu_registers(processor)->gpr[arg0+1];
327   int nbytes = cpu_registers(processor)->gpr[arg0+2];
328   int status;
329   SYS(read);
330 
331   if (WITH_TRACE && ppc_trace[trace_os_emul])
332     printf_filtered ("%d, 0x%lx, %d", d, (long)buf, nbytes);
333 
334   /* get a tempoary bufer */
335   scratch_buffer = zalloc(nbytes);
336 
337   /* check if buffer exists by reading it */
338   emul_read_buffer(scratch_buffer, buf, nbytes, processor, cia);
339 
340   /* read */
341 #if 0
342   if (d == 0) {
343     status = fread (scratch_buffer, 1, nbytes, stdin);
344     if (status == 0 && ferror (stdin))
345       status = -1;
346   }
347 #endif
348   status = fdbad (d);
349   if (status == 0)
350     status = read (d, scratch_buffer, nbytes);
351 
352   emul_write_status(processor, status, errno);
353   if (status > 0)
354     emul_write_buffer(scratch_buffer, buf, status, processor, cia);
355 
356   free(scratch_buffer);
357 }
358 
359 
360 static void
361 do_write(os_emul_data *emul,
362 	 unsigned call,
363 	 const int arg0,
364 	 cpu *processor,
365 	 unsigned_word cia)
366 {
367   void *scratch_buffer = NULL;
368   int d = (int)cpu_registers(processor)->gpr[arg0];
369   unsigned_word buf = cpu_registers(processor)->gpr[arg0+1];
370   int nbytes = cpu_registers(processor)->gpr[arg0+2];
371   int status;
372   SYS(write);
373 
374   if (WITH_TRACE && ppc_trace[trace_os_emul])
375     printf_filtered ("%d, 0x%lx, %d", d, (long)buf, nbytes);
376 
377   /* get a tempoary bufer */
378   scratch_buffer = zalloc(nbytes); /* FIXME - nbytes == 0 */
379 
380   /* copy in */
381   emul_read_buffer(scratch_buffer, buf, nbytes,
382 		   processor, cia);
383 
384   /* write */
385   status = fdbad (d);
386   if (status == 0)
387     status = write(d, scratch_buffer, nbytes);
388 
389   emul_write_status(processor, status, errno);
390   free(scratch_buffer);
391 
392   flush_stdoutput();
393 }
394 
395 
396 static void
397 do_open(os_emul_data *emul,
398 	unsigned call,
399 	const int arg0,
400 	cpu *processor,
401 	unsigned_word cia)
402 {
403   unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
404   char path_buf[PATH_MAX];
405   char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
406   int flags = (int)cpu_registers(processor)->gpr[arg0+1];
407   int mode = (int)cpu_registers(processor)->gpr[arg0+2];
408   int hostflags;
409   int status;
410 
411   if (WITH_TRACE && ppc_trace[trace_os_emul])
412     printf_filtered ("0x%lx [%s], 0x%x, 0x%x", (long)path_addr, path, flags, mode);
413 
414   SYS(open);
415 
416   /* Do some translation on 'flags' to match it to the host's version.  */
417   /* These flag values were taken from the NetBSD 1.4 header files.  */
418   if ((flags & 3) == 0)
419     hostflags = O_RDONLY;
420   else if ((flags & 3) == 1)
421     hostflags = O_WRONLY;
422   else
423     hostflags = O_RDWR;
424   if (flags & 0x00000008)
425     hostflags |= O_APPEND;
426   if (flags & 0x00000200)
427     hostflags |= O_CREAT;
428   if (flags & 0x00000400)
429     hostflags |= O_TRUNC;
430   if (flags & 0x00000800)
431     hostflags |= O_EXCL;
432 
433   /* Can't combine these statements, cuz open sets errno. */
434   status = open(path, hostflags, mode);
435   emul_write_status(processor, status, errno);
436 }
437 
438 
439 static void
440 do_close(os_emul_data *emul,
441 	 unsigned call,
442 	 const int arg0,
443 	 cpu *processor,
444 	 unsigned_word cia)
445 {
446   int d = (int)cpu_registers(processor)->gpr[arg0];
447   int status;
448 
449   if (WITH_TRACE && ppc_trace[trace_os_emul])
450     printf_filtered ("%d", d);
451 
452   SYS(close);
453 
454   status = fdbad (d);
455   if (status == 0)
456     {
457       /* Do not close stdin, stdout, or stderr. GDB may still need access to
458 	 these descriptors.  */
459       if (d == 0 || d == 1 || d == 2)
460 	{
461 	  fd_closed[d] = 1;
462 	  status = 0;
463 	}
464       else
465 	status = close(d);
466     }
467 
468   emul_write_status(processor, status, errno);
469 }
470 
471 
472 static void
473 do_break(os_emul_data *emul,
474 	 unsigned call,
475 	 const int arg0,
476 	 cpu *processor,
477 	 unsigned_word cia)
478 {
479   /* just pass this onto the `vm' device */
480   unsigned_word new_break = cpu_registers(processor)->gpr[arg0];
481   int status;
482 
483   if (WITH_TRACE && ppc_trace[trace_os_emul])
484     printf_filtered ("0x%lx", (long)cpu_registers(processor)->gpr[arg0]);
485 
486   SYS(break);
487   status = device_ioctl(emul->vm,
488 			processor,
489 			cia,
490 			device_ioctl_break,
491 			new_break); /*ioctl-data*/
492   emul_write_status(processor, 0, status);
493 }
494 
495 
496 #ifndef HAVE_GETPID
497 #define do_getpid 0
498 #else
499 static void
500 do_getpid(os_emul_data *emul,
501 	  unsigned call,
502 	  const int arg0,
503 	  cpu *processor,
504 	  unsigned_word cia)
505 {
506   SYS(getpid);
507   emul_write_status(processor, (int)getpid(), 0);
508 }
509 #endif
510 
511 #ifndef HAVE_GETUID
512 #define do_getuid 0
513 #else
514 static void
515 do_getuid(os_emul_data *emul,
516 	  unsigned call,
517 	  const int arg0,
518 	  cpu *processor,
519 	  unsigned_word cia)
520 {
521   SYS(getuid);
522   emul_write_status(processor, (int)getuid(), 0);
523 }
524 #endif
525 
526 #ifndef HAVE_GETEUID
527 #define do_geteuid 0
528 #else
529 static void
530 do_geteuid(os_emul_data *emul,
531 	   unsigned call,
532 	   const int arg0,
533 	   cpu *processor,
534 	   unsigned_word cia)
535 {
536   SYS(geteuid);
537   emul_write_status(processor, (int)geteuid(), 0);
538 }
539 #endif
540 
541 #ifndef HAVE_KILL
542 #define do_kill 0
543 #else
544 static void
545 do_kill(os_emul_data *emul,
546 	unsigned call,
547 	const int arg0,
548 	cpu *processor,
549 	unsigned_word cia)
550 {
551   pid_t pid = cpu_registers(processor)->gpr[arg0];
552   int sig = cpu_registers(processor)->gpr[arg0+1];
553 
554   if (WITH_TRACE && ppc_trace[trace_os_emul])
555     printf_filtered ("%d, %d", (int)pid, sig);
556 
557   SYS(kill);
558   printf_filtered("SYS_kill at 0x%lx - more to this than just being killed\n",
559 		  (long)cia);
560   cpu_halt(processor, cia, was_signalled, sig);
561 }
562 #endif
563 
564 #ifndef HAVE_DUP
565 #define do_dup 0
566 #else
567 static void
568 do_dup(os_emul_data *emul,
569        unsigned call,
570        const int arg0,
571        cpu *processor,
572        unsigned_word cia)
573 {
574   int oldd = cpu_registers(processor)->gpr[arg0];
575   int status = (fdbad (oldd) < 0) ? -1 : dup(oldd);
576   int err = errno;
577 
578   if (WITH_TRACE && ppc_trace[trace_os_emul])
579     printf_filtered ("%d", oldd);
580 
581   SYS(dup);
582   emul_write_status(processor, status, err);
583 }
584 #endif
585 
586 #ifndef HAVE_GETEGID
587 #define do_getegid 0
588 #else
589 static void
590 do_getegid(os_emul_data *emul,
591 	   unsigned call,
592 	   const int arg0,
593 	   cpu *processor,
594 	   unsigned_word cia)
595 {
596   SYS(getegid);
597   emul_write_status(processor, (int)getegid(), 0);
598 }
599 #endif
600 
601 #ifndef HAVE_GETGID
602 #define do_getgid 0
603 #else
604 static void
605 do_getgid(os_emul_data *emul,
606 	  unsigned call,
607 	  const int arg0,
608 	  cpu *processor,
609 	  unsigned_word cia)
610 {
611   SYS(getgid);
612   emul_write_status(processor, (int)getgid(), 0);
613 }
614 #endif
615 
616 #ifndef HAVE_SIGPROCMASK
617 #define do_sigprocmask 0
618 #else
619 static void
620 do_sigprocmask(os_emul_data *emul,
621 	       unsigned call,
622 	       const int arg0,
623 	       cpu *processor,
624 	       unsigned_word cia)
625 {
626   signed_word how = cpu_registers(processor)->gpr[arg0];
627   unsigned_word set = cpu_registers(processor)->gpr[arg0+1];
628   unsigned_word oset = cpu_registers(processor)->gpr[arg0+2];
629 #ifdef SYS_sigprocmask
630   SYS(sigprocmask);
631 #endif
632 
633   if (WITH_TRACE && ppc_trace[trace_os_emul])
634     printf_filtered ("%ld, 0x%lx, 0x%lx", (long)how, (long)set, (long)oset);
635 
636   emul_write_status(processor, 0, 0);
637   cpu_registers(processor)->gpr[4] = set;
638 }
639 #endif
640 
641 #ifndef HAVE_IOCTL
642 #define do_ioctl 0
643 #else
644 static void
645 do_ioctl(os_emul_data *emul,
646 	 unsigned call,
647 	 const int arg0,
648 	 cpu *processor,
649 	 unsigned_word cia)
650 {
651   int d = cpu_registers(processor)->gpr[arg0];
652   unsigned request = cpu_registers(processor)->gpr[arg0+1];
653   unsigned_word argp_addr = cpu_registers(processor)->gpr[arg0+2];
654 
655 #if !WITH_NetBSD_HOST
656   cpu_registers(processor)->gpr[arg0] = 0; /* just succeed */
657 #else
658   unsigned dir = request & IOC_DIRMASK;
659   int status;
660   SYS(ioctl);
661   /* what we haven't done */
662   if (dir & IOC_IN /* write into the io device */
663       || dir & IOC_OUT
664       || !(dir & IOC_VOID))
665     error("do_ioctl() read or write of parameter not implemented\n");
666   status = fdbad (d);
667   if (status == 0)
668     status = ioctl(d, request, NULL);
669   emul_write_status(processor, status, errno);
670 #endif
671 
672   if (WITH_TRACE && ppc_trace[trace_os_emul])
673     printf_filtered ("%d, 0x%x, 0x%lx", d, request, (long)argp_addr);
674 }
675 #endif
676 
677 #ifndef HAVE_UMASK
678 #define do_umask 0
679 #else
680 static void
681 do_umask(os_emul_data *emul,
682 	 unsigned call,
683 	 const int arg0,
684 	 cpu *processor,
685 	 unsigned_word cia)
686 {
687   int mask = cpu_registers(processor)->gpr[arg0];
688 
689   if (WITH_TRACE && ppc_trace[trace_os_emul])
690     printf_filtered ("0%o", mask);
691 
692   SYS(umask);
693   emul_write_status(processor, umask(mask), 0);
694 }
695 #endif
696 
697 #ifndef HAVE_DUP2
698 #define do_dup2 0
699 #else
700 static void
701 do_dup2(os_emul_data *emul,
702 	unsigned call,
703 	const int arg0,
704 	cpu *processor,
705 	unsigned_word cia)
706 {
707   int oldd = cpu_registers(processor)->gpr[arg0];
708   int newd = cpu_registers(processor)->gpr[arg0+1];
709   int status = (fdbad (oldd) < 0) ? -1 : dup2(oldd, newd);
710   int err = errno;
711 
712   if (WITH_TRACE && ppc_trace[trace_os_emul])
713     printf_filtered ("%d, %d", oldd, newd);
714 
715   SYS(dup2);
716   emul_write_status(processor, status, err);
717 }
718 #endif
719 
720 #ifndef HAVE_FCNTL
721 #define do_fcntl 0
722 #else
723 static void
724 do_fcntl(os_emul_data *emul,
725 	 unsigned call,
726 	 const int arg0,
727 	 cpu *processor,
728 	 unsigned_word cia)
729 {
730   int fd = cpu_registers(processor)->gpr[arg0];
731   int cmd = cpu_registers(processor)->gpr[arg0+1];
732   int arg = cpu_registers(processor)->gpr[arg0+2];
733   int status;
734 
735   if (WITH_TRACE && ppc_trace[trace_os_emul])
736     printf_filtered ("%d, %d, %d", fd, cmd, arg);
737 
738   SYS(fcntl);
739   status = fdbad (fd);
740   if (status == 0)
741     status = fcntl(fd, cmd, arg);
742   emul_write_status(processor, status, errno);
743 }
744 #endif
745 
746 #ifndef HAVE_GETTIMEOFDAY
747 #define do_gettimeofday 0
748 #else
749 static void
750 do_gettimeofday(os_emul_data *emul,
751 		unsigned call,
752 		const int arg0,
753 		cpu *processor,
754 		unsigned_word cia)
755 {
756   unsigned_word t_addr = cpu_registers(processor)->gpr[arg0];
757   unsigned_word tz_addr = cpu_registers(processor)->gpr[arg0+1];
758   struct timeval t;
759   struct timezone tz;
760   int status = gettimeofday(&t, (tz_addr != 0 ? &tz : NULL));
761   int err = errno;
762 
763   if (WITH_TRACE && ppc_trace[trace_os_emul])
764     printf_filtered ("0x%lx, 0x%lx", (long)t_addr, (long)tz_addr);
765 
766   SYS(__gettimeofday50);
767   emul_write_status(processor, status, err);
768   if (status == 0) {
769     if (t_addr != 0)
770       write_timeval(t_addr, t, processor, cia);
771     if (tz_addr != 0)
772       write_timezone(tz_addr, tz, processor, cia);
773   }
774 }
775 #endif
776 
777 #ifndef HAVE_GETRUSAGE
778 #define do_getrusage 0
779 #else
780 static void
781 do_getrusage(os_emul_data *emul,
782 	     unsigned call,
783 	     const int arg0,
784 	     cpu *processor,
785 	     unsigned_word cia)
786 {
787   int who = cpu_registers(processor)->gpr[arg0];
788   unsigned_word rusage_addr = cpu_registers(processor)->gpr[arg0+1];
789   struct rusage rusage;
790   int status = getrusage(who, (rusage_addr != 0 ? &rusage : NULL));
791   int err = errno;
792 
793   if (WITH_TRACE && ppc_trace[trace_os_emul])
794     printf_filtered ("%d, 0x%lx", who, (long)rusage_addr);
795 
796   SYS(__getrusage50);
797   emul_write_status(processor, status, err);
798   if (status == 0) {
799     if (rusage_addr != 0)
800       write_rusage(rusage_addr, rusage, processor, cia);
801   }
802 }
803 #endif
804 
805 
806 #ifndef HAVE_FSTATFS
807 #define do_fstatfs 0
808 #else
809 static void
810 do_fstatfs(os_emul_data *emul,
811 	   unsigned call,
812 	   const int arg0,
813 	   cpu *processor,
814 	   unsigned_word cia)
815 {
816   int fd = cpu_registers(processor)->gpr[arg0];
817   unsigned_word buf_addr = cpu_registers(processor)->gpr[arg0+1];
818   struct statfs buf;
819   int status;
820 
821   if (WITH_TRACE && ppc_trace[trace_os_emul])
822     printf_filtered ("%d, 0x%lx", fd, (long)buf_addr);
823 
824   SYS(fstatfs);
825   status = fdbad (fd);
826   if (status == 0)
827     status = fstatfs(fd, (buf_addr == 0 ? NULL : &buf));
828   emul_write_status(processor, status, errno);
829   if (status == 0) {
830     if (buf_addr != 0)
831       write_statfs(buf_addr, buf, processor, cia);
832   }
833 }
834 #endif
835 
836 #ifndef HAVE_STAT
837 #define do_stat 0
838 #else
839 static void
840 do_stat(os_emul_data *emul,
841 	unsigned call,
842 	const int arg0,
843 	cpu *processor,
844 	unsigned_word cia)
845 {
846   char path_buf[PATH_MAX];
847   unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
848   unsigned_word stat_buf_addr = cpu_registers(processor)->gpr[arg0+1];
849   char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
850   struct stat buf;
851   int status;
852 #ifdef SYS_stat
853   SYS(stat);
854 #endif
855   status = stat(path, &buf);
856   emul_write_status(processor, status, errno);
857   if (status == 0)
858     write_stat(stat_buf_addr, buf, processor, cia);
859 }
860 #endif
861 
862 #ifndef HAVE_FSTAT
863 #define do_fstat 0
864 #else
865 static void
866 do_fstat(os_emul_data *emul,
867 	 unsigned call,
868 	 const int arg0,
869 	 cpu *processor,
870 	 unsigned_word cia)
871 {
872   int fd = cpu_registers(processor)->gpr[arg0];
873   unsigned_word stat_buf_addr = cpu_registers(processor)->gpr[arg0+1];
874   struct stat buf = {};
875   int status;
876 #ifdef SYS_fstat
877   SYS(fstat);
878 #endif
879   /* Can't combine these statements, cuz fstat sets errno. */
880   status = fdbad (fd);
881   if (status == 0)
882     status = fstat(fd, &buf);
883   emul_write_status(processor, status, errno);
884   write_stat(stat_buf_addr, buf, processor, cia);
885 }
886 #endif
887 
888 #ifndef HAVE_LSTAT
889 #define do_lstat 0
890 #else
891 static void
892 do_lstat(os_emul_data *emul,
893 	 unsigned call,
894 	 const int arg0,
895 	 cpu *processor,
896 	 unsigned_word cia)
897 {
898   char path_buf[PATH_MAX];
899   unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
900   char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
901   unsigned_word stat_buf_addr = cpu_registers(processor)->gpr[arg0+1];
902   struct stat buf;
903   int status;
904 #ifdef SYS_lstat
905   SYS(lstat);
906 #endif
907   /* Can't combine these statements, cuz lstat sets errno. */
908   status = lstat(path, &buf);
909   emul_write_status(processor, status, errno);
910   write_stat(stat_buf_addr, buf, processor, cia);
911 }
912 #endif
913 
914 #ifndef HAVE_GETDIRENTRIES
915 #define do_getdirentries 0
916 #else
917 static void
918 do_getdirentries(os_emul_data *emul,
919 		 unsigned call,
920 		 const int arg0,
921 		 cpu *processor,
922 		 unsigned_word cia)
923 {
924   int fd = cpu_registers(processor)->gpr[arg0];
925   unsigned_word buf_addr = cpu_registers(processor)->gpr[arg0+1];
926   char *buf;
927   int nbytes = cpu_registers(processor)->gpr[arg0+2];
928   unsigned_word basep_addr = cpu_registers(processor)->gpr[arg0+3];
929   long basep;
930   int status;
931 #ifdef SYS_getdirentries
932   SYS(getdirentries);
933 #endif
934   if (buf_addr != 0 && nbytes >= 0)
935     buf = zalloc(nbytes);
936   else
937     buf = NULL;
938   status = getdirentries(fd,
939 			 (buf_addr == 0 ? NULL : buf),
940 			 nbytes,
941 			 (basep_addr == 0 ? NULL : &basep));
942   emul_write_status(processor, status, errno);
943   if (basep_addr != 0)
944     emul_write_word(basep_addr, basep, processor, cia);
945   if (status > 0)
946     write_direntries(buf_addr, buf, status, processor, cia);
947   if (buf != NULL)
948     free(buf);
949 }
950 #endif
951 
952 
953 static void
954 do___syscall(os_emul_data *emul,
955 	     unsigned call,
956 	     const int arg0,
957 	     cpu *processor,
958 	     unsigned_word cia)
959 {
960   SYS(__syscall);
961   emul_do_system_call(emul,
962 		      emul->syscalls,
963 		      cpu_registers(processor)->gpr[arg0],
964 		      arg0 + 1,
965 		      processor,
966 		      cia);
967 }
968 
969 #ifndef HAVE_LSEEK
970 #define do_lseek 0
971 #else
972 static void
973 do_lseek(os_emul_data *emul,
974 	 unsigned call,
975 	 const int arg0,
976 	 cpu *processor,
977 	 unsigned_word cia)
978 {
979   int fildes = cpu_registers(processor)->gpr[arg0];
980   off_t offset = emul_read_gpr64(processor, arg0+2);
981   int whence = cpu_registers(processor)->gpr[arg0+4];
982   off_t status;
983   SYS(lseek);
984   status = fdbad (fildes);
985   if (status == 0)
986     status = lseek(fildes, offset, whence);
987   if (status == -1)
988     emul_write_status(processor, -1, errno);
989   else {
990     emul_write_status(processor, 0, 0); /* success */
991     emul_write_gpr64(processor, 3, status);
992   }
993 }
994 #endif
995 
996 static void
997 do___sysctl(os_emul_data *emul,
998 	    unsigned call,
999 	    const int arg0,
1000 	    cpu *processor,
1001 	    unsigned_word cia)
1002 {
1003   /* call the arguments by their real name */
1004   unsigned_word name = cpu_registers(processor)->gpr[arg0];
1005   signed_word namelen = cpu_registers(processor)->gpr[arg0+1];
1006   unsigned_word oldp = cpu_registers(processor)->gpr[arg0+2];
1007   unsigned_word oldlenp = cpu_registers(processor)->gpr[arg0+3];
1008   signed_word oldlen;
1009   signed_word mib;
1010   signed_word int_val;
1011   SYS(__sysctl);
1012 
1013   /* pluck out the management information base id */
1014   if (namelen < 1)
1015     error("system_call()SYS___sysctl bad name[0]\n");
1016   mib = vm_data_map_read_word(cpu_data_map(processor),
1017 			      name,
1018 			      processor,
1019 			      cia);
1020   name += sizeof(mib);
1021 
1022   /* see what to do with it ... */
1023   switch ((int)mib) {
1024   case 6/*CTL_HW*/:
1025 #if WITH_NetBSD_HOST && (CTL_HW != 6)
1026 #  error "CTL_HW"
1027 #endif
1028     if (namelen < 2)
1029       error("system_call()SYS___sysctl - CTL_HW - bad name[1]\n");
1030     mib = vm_data_map_read_word(cpu_data_map(processor),
1031 				name,
1032 				processor,
1033 				cia);
1034     name += sizeof(mib);
1035     switch ((int)mib) {
1036     case 7/*HW_PAGESIZE*/:
1037 #if WITH_NetBSD_HOST && (HW_PAGESIZE != 7)
1038 #  error "HW_PAGESIZE"
1039 #endif
1040       oldlen = vm_data_map_read_word(cpu_data_map(processor),
1041 				     oldlenp,
1042 				     processor,
1043 				     cia);
1044       if (sizeof(signed_word) > oldlen)
1045 	error("system_call()sysctl - CTL_HW.HW_PAGESIZE - to small\n");
1046       int_val = 8192;
1047       oldlen = sizeof(int_val);
1048       emul_write_word(oldp, int_val, processor, cia);
1049       emul_write_word(oldlenp, oldlen, processor, cia);
1050       break;
1051     default:
1052       error("sysctl() CTL_HW.%d unknown\n", mib);
1053       break;
1054     }
1055     break;
1056   default:
1057     error("sysctl() name[0]=%d unknown\n", (int)mib);
1058     break;
1059   }
1060   emul_write_status(processor, 0, 0); /* always succeed */
1061 }
1062 
1063 
1064 
1065 static emul_syscall_descriptor netbsd_descriptors[] = {
1066   /* 0 */ { 0, "syscall" },
1067   /* 1 */ { do_exit, "exit" },
1068   /* 2 */ { 0, "fork" },
1069   /* 3 */ { do_read, "read" },
1070   /* 4 */ { do_write, "write" },
1071   /* 5 */ { do_open, "open" },
1072   /* 6 */ { do_close, "close" },
1073   { 0, }, /* 7 is old wait4 */
1074   { 0, }, /* 8 is old creat */
1075   /* 9 */ { 0, "link" },
1076   /* 10 */ { 0, "unlink" },
1077   { 0, }, /* 11 is obsolete execv */
1078   /* 12 */ { 0, "chdir" },
1079   /* 13 */ { 0, "fchdir" },
1080   { 0, }, /* 14 is old mknod */
1081   /* 15 */ { 0, "chmod" },
1082   /* 16 */ { 0, "chown" },
1083   /* 17 */ { do_break, "break" },
1084   { 0, }, /* 18 is old getfsstat */
1085   { 0, }, /* 19 is old lseek */
1086   /* 20 */ { do_getpid, "getpid" },
1087   { 0, }, /* 21 is old mount */
1088   /* 22 */ { 0, "unmount" },
1089   /* 23 */ { 0, "setuid" },
1090   /* 24 */ { do_getuid, "getuid" },
1091   /* 25 */ { do_geteuid, "geteuid" },
1092   /* 26 */ { 0, "ptrace" },
1093   /* 27 */ { 0, "recvmsg" },
1094   /* 28 */ { 0, "sendmsg" },
1095   /* 29 */ { 0, "recvfrom" },
1096   /* 30 */ { 0, "accept" },
1097   /* 31 */ { 0, "getpeername" },
1098   /* 32 */ { 0, "getsockname" },
1099   /* 33 */ { 0, "access" },
1100   /* 34 */ { 0, "chflags" },
1101   /* 35 */ { 0, "fchflags" },
1102   /* 36 */ { 0, "sync" },
1103   /* 37 */ { do_kill, "kill" },
1104   { 0, }, /* 38 is old stat */
1105   /* 39 */ { 0, "getppid" },
1106   { 0, }, /* 40 is old lstat */
1107   /* 41 */ { do_dup, "dup" },
1108   /* 42 */ { 0, "pipe" },
1109   /* 43 */ { do_getegid, "getegid" },
1110   /* 44 */ { 0, "profil" },
1111   /* 45 */ { 0, "ktrace" },
1112   { 0, }, /* 46 is old sigaction */
1113   /* 47 */ { do_getgid, "getgid" },
1114   { 0, }, /* 48 is old sigprocmask */
1115   /* 49 */ { 0, "getlogin" },
1116   /* 50 */ { 0, "setlogin" },
1117   /* 51 */ { 0, "acct" },
1118   { 0, }, /* 52 is old sigpending */
1119   { 0, }, /* 53 is old sigaltstack */
1120   /* 54 */ { do_ioctl, "ioctl" },
1121   { 0, }, /* 55 is old reboot */
1122   /* 56 */ { 0, "revoke" },
1123   /* 57 */ { 0, "symlink" },
1124   /* 58 */ { 0, "readlink" },
1125   /* 59 */ { 0, "execve" },
1126   /* 60 */ { do_umask, "umask" },
1127   /* 61 */ { 0, "chroot" },
1128   { 0, }, /* 62 is old fstat */
1129   { 0, }, /* 63 is old getkerninfo */
1130   { 0, }, /* 64 is old getpagesize */
1131   { 0, }, /* 65 is old msync */
1132   /* 66 */ { 0, "vfork" },
1133   { 0, }, /* 67 is obsolete vread */
1134   { 0, }, /* 68 is obsolete vwrite */
1135   /* 69 */ { 0, "sbrk" },
1136   { 0, }, /* 70 is obsolete sstk */
1137   { 0, }, /* 71 is old mmap */
1138   { 0, }, /* 72 is obsolete vadvise */
1139   /* 73 */ { 0, "munmap" },
1140   /* 74 */ { 0, "mprotect" },
1141   /* 75 */ { 0, "madvise" },
1142   { 0, }, /* 76 is obsolete vhangup */
1143   { 0, }, /* 77 is obsolete vlimit */
1144   /* 78 */ { 0, "mincore" },
1145   /* 79 */ { 0, "getgroups" },
1146   /* 80 */ { 0, "setgroups" },
1147   /* 81 */ { 0, "getpgrp" },
1148   /* 82 */ { 0, "setpgid" },
1149   { 0, }, /* 83 is old setitimer */
1150   { 0, }, /* 84 is old wait */
1151   { 0, }, /* 85 is old swapon */
1152   { 0, }, /* 86 is old getitimer */
1153   { 0, }, /* 87 is old gethostname */
1154   { 0, }, /* 88 is old sethostname */
1155   { 0, }, /* 89 is old getdtablesize */
1156   { do_dup2, "dup2" },
1157   { 0, }, /* 91 */
1158   /* 92 */ { do_fcntl, "fcntl" },
1159   { 0, }, /* 93 is old select */
1160   { 0, }, /* 94 */
1161   /* 95 */ { 0, "fsync" },
1162   /* 96 */ { 0, "setpriority" },
1163   { 0, }, /* 97 is old socket */
1164   { 0, }, /* 98 is old connect */
1165   { 0, }, /* 99 is old accept */
1166   /* 100 */ { 0, "getpriority" },
1167   { 0, }, /* 101 is old send */
1168   { 0, }, /* 102 is old recv */
1169   { 0, }, /* 103 is old sigreturn */
1170   /* 104 */ { 0, "bind" },
1171   /* 105 */ { 0, "setsockopt" },
1172   /* 106 */ { 0, "listen" },
1173   { 0, }, /* 107 is obsolete vtimes */
1174   { 0, }, /* 108 is old sigvec */
1175   { 0, }, /* 109 is old sigblock */
1176   { 0, }, /* 110 is old sigsetmask */
1177   { 0, }, /* 111 is old sigsuspend */
1178   { 0, }, /* 112 is old sigstack */
1179   { 0, }, /* 113 is old recvmsg */
1180   { 0, }, /* 114 is old sendmsg */
1181   /* - is obsolete vtrace */ { 0, "vtrace	115" },
1182   { 0, }, /* 116 is old gettimeofday */
1183   { 0, }, /* 117 is old getrusage */
1184   /* 118 */ { 0, "getsockopt" },
1185   /* - is obsolete resuba */ { 0, "resuba	119" },
1186   /* 120 */ { 0, "readv" },
1187   /* 121 */ { 0, "writev" },
1188   { 0, }, /* 122 is old settimeofday */
1189   /* 123 */ { 0, "fchown" },
1190   /* 124 */ { 0, "fchmod" },
1191   { 0, }, /* 125 is old recvfrom */
1192   { 0, }, /* 126 is old setreuid */
1193   { 0, }, /* 127 is old setregid */
1194   /* 126 */ { 0, "setreuid" },
1195   /* 127 */ { 0, "setregid" },
1196   /* 128 */ { 0, "rename" },
1197   { 0, }, /* 129 is old truncate */
1198   { 0, }, /* 130 is old ftruncate */
1199   /* 131 */ { 0, "flock" },
1200   /* 132 */ { 0, "mkfifo" },
1201   /* 133 */ { 0, "sendto" },
1202   /* 134 */ { 0, "shutdown" },
1203   /* 135 */ { 0, "socketpair" },
1204   /* 136 */ { 0, "mkdir" },
1205   /* 137 */ { 0, "rmdir" },
1206   { 0, }, /* 138 is old utimes */
1207   { 0, }, /* 139 is obsolete 4.2 sigreturn */
1208   { 0, }, /* 140 is old adjtime */
1209   { 0, }, /* 141 is old getpeername */
1210   { 0, }, /* 142 is old gethostid */
1211   { 0, }, /* 143 is old sethostid */
1212   { 0, }, /* 144 is old getrlimit */
1213   { 0, }, /* 145 is old setrlimit */
1214   { 0, }, /* 146 is old killpg */
1215   /* 147 */ { 0, "setsid" },
1216   /* 148 */ { 0, "quotactl" },
1217   { 0, }, /* 149 is old quota */
1218   { 0, }, /* 150 is old getsockname */
1219   { 0, }, /* 151 */
1220   { 0, }, /* 152 */
1221   { 0, }, /* 153 */
1222   { 0, }, /* 154 */
1223   /* 155 */ { 0, "nfssvc" },
1224   { 0, }, /* 156 is old getdirentries */
1225   { 0, }, /* 157 is old statfs */
1226   { 0, }, /* 158 is old fstatfs */
1227   { 0, }, /* 159 */
1228   { 0, }, /* 160 */
1229   { 0, }, /* 161 is old getfh */
1230   { 0, }, /* 162 is old getdomainname */
1231   { 0, }, /* 163 is old setdomainname */
1232   { 0, }, /* 164 is old uname */
1233   /* 165 */ { 0, "sysarch" },
1234   { 0, }, /* 166 */
1235   { 0, }, /* 167 */
1236   { 0, }, /* 168 */
1237   { 0, }, /* 169 is old semsys */
1238   { 0, }, /* 170 is old msgsys */
1239   { 0, }, /* 171 is old shmsys */
1240   { 0, }, /* 172 */
1241   /* 173 */ { 0, "pread" },
1242   /* 174 */ { 0, "pwrite" },
1243   { 0, }, /* 175 is old ntp_gettime */
1244   /* 176 */ { 0, "ntp_adjtime" },
1245   { 0, }, /* 177 */
1246   { 0, }, /* 178 */
1247   { 0, }, /* 179 */
1248   { 0, }, /* 180 */
1249   /* 181 */ { 0, "setgid" },
1250   /* 182 */ { 0, "setegid" },
1251   /* 183 */ { 0, "seteuid" },
1252   /* 184 */ { 0, "lfs_bmapv" },
1253   /* 185 */ { 0, "lfs_markv" },
1254   /* 186 */ { 0, "lfs_segclean" },
1255   /* 187 */ { 0, "lfs_segwait" },
1256   { 0, }, /* 188 is old stat" */
1257   { 0, }, /* 189 is old fstat */
1258   { 0, }, /* 190 is old lstat */
1259   /* 191 */ { 0, "pathconf" },
1260   /* 192 */ { 0, "fpathconf" },
1261   { 0, }, /* 193 */
1262   /* 194 */ { 0, "getrlimit" },
1263   /* 195 */ { 0, "setrlimit" },
1264   { 0, }, /* 196 is old getdirentries */
1265   /* 197 */ { 0, "mmap" },
1266   /* 198 */ { do___syscall, "__syscall" },
1267   /* 199 */ { do_lseek, "lseek" },
1268   /* 200 */ { 0, "truncate" },
1269   /* 201 */ { 0, "ftruncate" },
1270   /* 202 */ { do___sysctl, "__sysctl" },
1271   /* 203 */ { 0, "mlock" },
1272   /* 204 */ { 0, "munlock" },
1273   /* 205 */ { 0, "undelete" },
1274   { 0, }, /* 206 is old futimes */
1275   /* 207 */ { 0, "getpgid" },
1276   /* 208 */ { 0, "reboot" },
1277   /* 209 */ { 0, "poll" },
1278   { 0, }, /* 210 */
1279   { 0, }, /* 211 */
1280   { 0, }, /* 212 */
1281   { 0, }, /* 213 */
1282   { 0, }, /* 214 */
1283   { 0, }, /* 215 */
1284   { 0, }, /* 216 */
1285   { 0, }, /* 217 */
1286   { 0, }, /* 218 */
1287   { 0, }, /* 219 */
1288   { 0, }, /* 220 is old semctl */
1289   /* 221 */ { 0, "semget" },
1290   /* 222 */ { 0, "semop" },
1291   /* 223 */ { 0, "semconfig" },
1292   { 0, }, /* 224 is old msgctl */
1293   /* 225 */ { 0, "msgget" },
1294   /* 226 */ { 0, "msgsnd" },
1295   /* 227 */ { 0, "msgrcv" },
1296   /* 228 */ { 0, "shmat" },
1297   { 0, }, /* 229 is old shmctl */
1298   /* 230 */ { 0, "shmdt" },
1299   /* 231 */ { 0, "shmget" },
1300   { 0, }, /* 232 is old clock_gettime */
1301   { 0, }, /* 233 is old clock_settime */
1302   { 0, }, /* 234 is old clock_getres */
1303   /* 235 */ { 0, "timer_create" },
1304   /* 236 */ { 0, "timer_delete" },
1305   { 0, }, /* 237 is old timer_settime */
1306   { 0, }, /* 238 is old timer_gettime */
1307   /* 239 */ { 0, "timer_getoverrun" },
1308   { 0, }, /* 240 is old nanosleep */
1309   /* 241 */ { 0, "fdatasync" },
1310   /* 242 */ { 0, "mlockall" },
1311   /* 243 */ { 0, "munlockall" },
1312   { 0, }, /* 244 is old sigtimedwait */
1313   { 0, }, /* 245 */
1314   /* 246 */ { 0, "modctl" },
1315   /* 247 */ { 0, "_ksem_init" },
1316   /* 248 */ { 0, "_ksem_open" },
1317   /* 249 */ { 0, "_ksem_unlink" },
1318   /* 250 */ { 0, "_ksem_close" },
1319   /* 251 */ { 0, "_ksem_post" },
1320   /* 252 */ { 0, "_ksem_wait" },
1321   /* 253 */ { 0, "_ksem_trywait" },
1322   /* 254 */ { 0, "_ksem_getvalue" },
1323   /* 255 */ { 0, "_ksem_destroy" },
1324   /* 256 */ { 0, "_ksem_timedwait" },
1325   /* 257 */ { 0, "mq_open" },
1326   /* 258 */ { 0, "mq_close" },
1327   /* 259 */ { 0, "mq_unlink" },
1328   /* 260 */ { 0, "mq_getattr" },
1329   /* 261 */ { 0, "mq_setattr" },
1330   /* 262 */ { 0, "mq_notify" },
1331   /* 263 */ { 0, "mq_send" },
1332   /* 264 */ { 0, "mq_receive" },
1333   { 0, }, /* 265 is old mq_timedsend */
1334   { 0, }, /* 266 is old mq_timedrecive */
1335   { 0, }, /* 267 */
1336   { 0, }, /* 268 */
1337   { 0, }, /* 269 */
1338   /* 270 */ { 0, "__posix_rename" },
1339   /* 271 */ { 0, "swapctl" },
1340   { 0, }, /* 272 is old getdents */
1341   /* 273 */ { 0, "minherit" },
1342   /* 274 */ { 0, "lchmod" },
1343   /* 275 */ { 0, "lchown" },
1344   { 0, }, /* 276 is old lutimes */
1345   /* 277 */ { 0, "__msync13" },
1346   { 0, }, /* 278 is old stat */
1347   { 0, }, /* 279 is old fstat */
1348   { 0, }, /* 280 is old lstat */
1349   /* 281 */ { 0, "__sigaltstack13" },
1350   /* 282 */ { 0, "__vfork14" },
1351   /* 283 */ { 0, "__posix_chown" },
1352   /* 284 */ { 0, "__posix_fchown" },
1353   /* 285 */ { 0, "__posix_lchown" },
1354   /* 286 */ { 0, "getsid" },
1355   /* 287 */ { 0, "__clone" },
1356   /* 288 */ { 0, "fktrace" },
1357   /* 289 */ { 0, "preadv" },
1358   /* 290 */ { 0, "pwritev" },
1359   { 0, }, /* 291 is old sigaction */
1360   /* 292 */ { 0, "__sigpending14" },
1361   /* 293 */ { do_sigprocmask, "__sigprocmask14" },
1362   /* 294 */ { 0, "__sigsuspend14" },
1363   /* 295 */ { 0, "__sigreturn14" },
1364   /* 296 */ { 0, "__getcwd" },
1365   /* 297 */ { 0, "fchroot" },
1366   { 0, }, /* 298 is old fhopen */
1367   { 0, }, /* 299 is old fhstat */
1368   { 0, }, /* 300 is old fhstatfs */
1369   { 0, }, /* 301 is old semctl */
1370   { 0, }, /* 302 is old msgctl */
1371   { 0, }, /* 303 is old shmctl */
1372   /* 304 */ { 0, "lchflags" },
1373   /* 305 */ { 0, "issetugid" },
1374   /* 306 */ { 0, "utrace" },
1375   /* 307 */ { 0, "getcontext" },
1376   /* 308 */ { 0, "setcontext" },
1377   /* 309 */ { 0, "_lwp_create" },
1378   /* 310 */ { 0, "_lwp_exit" },
1379   /* 311 */ { 0, "_lwp_self" },
1380   /* 312 */ { 0, "_lwp_wait" },
1381   /* 313 */ { 0, "_lwp_suspend" },
1382   /* 314 */ { 0, "_lwp_continue" },
1383   /* 315 */ { 0, "_lwp_wakeup" },
1384   /* 316 */ { 0, "_lwp_getprivate" },
1385   /* 317 */ { 0, "_lwp_setprivate" },
1386   /* 318 */ { 0, "_lwp_kill" },
1387   /* 319 */ { 0, "_lwp_detach" },
1388   { 0, }, /* 320 is old _lwp_park */
1389   /* 321 */ { 0, "_lwp_unpark" },
1390   /* 322 */ { 0, "_lwp_unpark_all" },
1391   /* 323 */ { 0, "_lwp_setname" },
1392   /* 324 */ { 0, "_lwp_getname" },
1393   /* 325 */ { 0, "_lwp_ctl" },
1394   { 0, }, /* 326 */
1395   { 0, }, /* 327 */
1396   { 0, }, /* 328 */
1397   { 0, }, /* 329 */
1398   /* 330 */ { 0, "sa_register" },
1399   /* 331 */ { 0, "sa_stacks" },
1400   /* 332 */ { 0, "sa_enable" },
1401   /* 333 */ { 0, "sa_setconcurrency" },
1402   /* 334 */ { 0, "sa_yield" },
1403   /* 335 */ { 0, "sa_preempt" },
1404   { 0, }, /* 336 */
1405   { 0, }, /* 337 */
1406   { 0, }, /* 338 */
1407   { 0, }, /* 339 */
1408   /* 340 */ { 0, "__sigaction_sigtramp" },
1409   /* 341 */ { 0, "pmc_get_info" },
1410   /* 342 */ { 0, "pmc_control" },
1411   /* 343 */ { 0, "rasctl" },
1412   /* 344 */ { 0, "kqueue" },
1413   { 0, }, /* 345 is old kevent */
1414   /* 346 */ { 0, "_sched_setparam" },
1415   /* 347 */ { 0, "_sched_getparam" },
1416   /* 348 */ { 0, "_sched_setaffinity" },
1417   /* 349 */ { 0, "_sched_getaffinity" },
1418   /* 350 */ { 0, "sched_yield" },
1419   { 0, }, /* 351 */
1420   { 0, }, /* 352 */
1421   { 0, }, /* 353 */
1422   /* 354 */ { 0, "fsync_range" },
1423   /* 355 */ { 0, "uuidgen" },
1424   /* 356 */ { 0, "getvfsstat" },
1425   /* 357 */ { 0, "statvfs1" },
1426   /* 358 */ { 0, "fstatvfs1" },
1427   { 0, }, /* 359 is old fhstatvfs1 */
1428   /* 360 */ { 0, "extattrctl" },
1429   /* 361 */ { 0, "extattr_set_file" },
1430   /* 362 */ { 0, "extattr_get_file" },
1431   /* 363 */ { 0, "extattr_delete_file" },
1432   /* 364 */ { 0, "extattr_set_fd" },
1433   /* 365 */ { 0, "extattr_get_fd" },
1434   /* 366 */ { 0, "extattr_delete_fd" },
1435   /* 367 */ { 0, "extattr_set_link" },
1436   /* 368 */ { 0, "extattr_get_link" },
1437   /* 369 */ { 0, "extattr_delete_link" },
1438   /* 370 */ { 0, "extattr_list_fd" },
1439   /* 371 */ { 0, "extattr_list_file" },
1440   /* 372 */ { 0, "extattr_list_link" },
1441   { 0, }, /* 373 is old pselect */
1442   { 0, }, /* 374 is old pollts */
1443   /* 375 */ { 0, "setxattr" },
1444   /* 376 */ { 0, "lsetxattr" },
1445   /* 377 */ { 0, "fsetxattr" },
1446   /* 378 */ { 0, "getxattr" },
1447   /* 379 */ { 0, "lgetxattr" },
1448   /* 380 */ { 0, "fgetxattr" },
1449   /* 381 */ { 0, "listxattr" },
1450   /* 382 */ { 0, "llistxattr" },
1451   /* 383 */ { 0, "flistxattr" },
1452   /* 384 */ { 0, "removexattr" },
1453   /* 385 */ { 0, "lremovexattr" },
1454   /* 386 */ { 0, "fremovexattr" },
1455   { 0, }, /* 387 is old stat */
1456   { 0, }, /* 388 is old fstat */
1457   { 0, }, /* 389 is old lstat */
1458   /* 390 */ { do_getdirentries, "__getdents30" },
1459   { 0, }, /* 391 is old posix_fadvise */
1460   { 0, }, /* 392 is old fhstat */
1461   { 0, }, /* 393 is old ntp_gettime */
1462   /* 394 */ { 0, "__socket30" },
1463   /* 395 */ { 0, "__getfh30" },
1464   /* 396 */ { 0, "__fhopen40" },
1465   /* 397 */ { 0, "__fhstatvfs140" },
1466   { 0, }, /* 398 is old fhstat */
1467   /* 399 */ { 0, "aio_cancel" },
1468   /* 400 */ { 0, "aio_error" },
1469   /* 401 */ { 0, "aio_fsync" },
1470   /* 402 */ { 0, "aio_read" },
1471   /* 403 */ { 0, "aio_return" },
1472   { 0, }, /* 404 is old aio_suspend */
1473   /* 405 */ { 0, "aio_write" },
1474   /* 406 */ { 0, "lio_listio" },
1475   { 0, }, /* 407 */
1476   { 0, }, /* 408 */
1477   { 0, }, /* 409 */
1478   /* 410 */ { 0, "__mount50" },
1479   /* 411 */ { 0, "mremap" },
1480   /* 412 */ { 0, "pset_create" },
1481   /* 413 */ { 0, "pset_destroy" },
1482   /* 414 */ { 0, "pset_assign" },
1483   /* 415 */ { 0, "_pset_bind" },
1484   /* 416 */ { 0, "__posix_fadvise50" },
1485   /* 417 */ { 0, "__select50" },
1486   /* 418 */ { do_gettimeofday, "__gettimeofday50" },
1487   /* 419 */ { 0, "__settimeofday50" },
1488   /* 420 */ { 0, "__utimes50" },
1489   /* 421 */ { 0, "__adjtime50" },
1490   /* 422 */ { 0, "__lfs_segwait50" },
1491   /* 423 */ { 0, "__futimes50" },
1492   /* 424 */ { 0, "__lutimes50" },
1493   /* 425 */ { 0, "__setitimer50" },
1494   /* 426 */ { 0, "__getitimer50" },
1495   /* 427 */ { 0, "__clock_gettime50" },
1496   /* 428 */ { 0, "__clock_settime50" },
1497   /* 429 */ { 0, "__clock_getres50" },
1498   /* 430 */ { 0, "__nanosleep50" },
1499   /* 431 */ { 0, "____sigtimedwait50" },
1500   /* 432 */ { 0, "__mq_timedsend50" },
1501   /* 433 */ { 0, "__mq_timedreceive50" },
1502   /* 434 */ { 0, "____lwp_park50" },
1503   /* 435 */ { 0, "__kevent50" },
1504   /* 436 */ { 0, "__pselect50" },
1505   /* 437 */ { 0, "__pollts50" },
1506   /* 438 */ { 0, "__aio_suspend50" },
1507   /* 439 */ { do_stat, "__stat50" },
1508   /* 440 */ { do_fstat, "__fstat50" },
1509   /* 441 */ { do_lstat, "__lstat50" },
1510   /* 442 */ { 0, "____semctl50" },
1511   /* 443 */ { 0, "__shmctl50" },
1512   /* 444 */ { 0, "__msgctl50" },
1513   /* 445 */ { do_getrusage, "__getrusage50" },
1514   /* 446 */ { 0, "__timer_settime50" },
1515   /* 447 */ { 0, "__timer_gettime50" },
1516   /* 448 */ { 0, "__ntp_gettime50" },
1517   /* 449 */ { 0, "__wait450" },
1518   /* 450 */ { 0, "__mknod50" },
1519   /* 451 */ { 0, "__fhstat50" },
1520   { 0, }, /* 452 is obsolete 5.99 __quotactl50 */
1521   /* 453 */ { 0, "pipe2" },
1522   /* 454 */ { 0, "dup3" },
1523   /* 455 */ { 0, "kqueue1" },
1524   /* 456 */ { 0, "paccept" },
1525   /* 457 */ { 0, "linkat" },
1526   /* 458 */ { 0, "renameat" },
1527   /* 459 */ { 0, "mkfifoat" },
1528   /* 460 */ { 0, "mknodat" },
1529   /* 461 */ { 0, "mkdirat" },
1530   /* 462 */ { 0, "faccessat" },
1531   /* 463 */ { 0, "fchmodat" },
1532   /* 464 */ { 0, "fchownat" },
1533   /* 465 */ { 0, "fexecve" },
1534   /* 466 */ { 0, "fstatat" },
1535   /* 467 */ { 0, "utimensat" },
1536   /* 468 */ { 0, "openat" },
1537   /* 469 */ { 0, "readlinkat" },
1538   /* 470 */ { 0, "symlinkat" },
1539   /* 471 */ { 0, "unlinkat" },
1540   /* 472 */ { 0, "futimens" },
1541   /* 473 */ { 0, "__quotactl" },
1542 };
1543 
1544 static char *(netbsd_error_names[]) = {
1545   /* 0 */ "ESUCCESS",
1546   /* 1 */ "EPERM",
1547   /* 2 */ "ENOENT",
1548   /* 3 */ "ESRCH",
1549   /* 4 */ "EINTR",
1550   /* 5 */ "EIO",
1551   /* 6 */ "ENXIO",
1552   /* 7 */ "E2BIG",
1553   /* 8 */ "ENOEXEC",
1554   /* 9 */ "EBADF",
1555   /* 10 */ "ECHILD",
1556   /* 11 */ "EDEADLK",
1557   /* 12 */ "ENOMEM",
1558   /* 13 */ "EACCES",
1559   /* 14 */ "EFAULT",
1560   /* 15 */ "ENOTBLK",
1561   /* 16 */ "EBUSY",
1562   /* 17 */ "EEXIST",
1563   /* 18 */ "EXDEV",
1564   /* 19 */ "ENODEV",
1565   /* 20 */ "ENOTDIR",
1566   /* 21 */ "EISDIR",
1567   /* 22 */ "EINVAL",
1568   /* 23 */ "ENFILE",
1569   /* 24 */ "EMFILE",
1570   /* 25 */ "ENOTTY",
1571   /* 26 */ "ETXTBSY",
1572   /* 27 */ "EFBIG",
1573   /* 28 */ "ENOSPC",
1574   /* 29 */ "ESPIPE",
1575   /* 30 */ "EROFS",
1576   /* 31 */ "EMLINK",
1577   /* 32 */ "EPIPE",
1578   /* 33 */ "EDOM",
1579   /* 34 */ "ERANGE",
1580   /* 35 */ "EAGAIN",
1581   /* 36 */ "EINPROGRESS",
1582   /* 37 */ "EALREADY",
1583   /* 38 */ "ENOTSOCK",
1584   /* 39 */ "EDESTADDRREQ",
1585   /* 40 */ "EMSGSIZE",
1586   /* 41 */ "EPROTOTYPE",
1587   /* 42 */ "ENOPROTOOPT",
1588   /* 43 */ "EPROTONOSUPPORT",
1589   /* 44 */ "ESOCKTNOSUPPORT",
1590   /* 45 */ "EOPNOTSUPP",
1591   /* 46 */ "EPFNOSUPPORT",
1592   /* 47 */ "EAFNOSUPPORT",
1593   /* 48 */ "EADDRINUSE",
1594   /* 49 */ "EADDRNOTAVAIL",
1595   /* 50 */ "ENETDOWN",
1596   /* 51 */ "ENETUNREACH",
1597   /* 52 */ "ENETRESET",
1598   /* 53 */ "ECONNABORTED",
1599   /* 54 */ "ECONNRESET",
1600   /* 55 */ "ENOBUFS",
1601   /* 56 */ "EISCONN",
1602   /* 57 */ "ENOTCONN",
1603   /* 58 */ "ESHUTDOWN",
1604   /* 59 */ "ETOOMANYREFS",
1605   /* 60 */ "ETIMEDOUT",
1606   /* 61 */ "ECONNREFUSED",
1607   /* 62 */ "ELOOP",
1608   /* 63 */ "ENAMETOOLONG",
1609   /* 64 */ "EHOSTDOWN",
1610   /* 65 */ "EHOSTUNREACH",
1611   /* 66 */ "ENOTEMPTY",
1612   /* 67 */ "EPROCLIM",
1613   /* 68 */ "EUSERS",
1614   /* 69 */ "EDQUOT",
1615   /* 70 */ "ESTALE",
1616   /* 71 */ "EREMOTE",
1617   /* 72 */ "EBADRPC",
1618   /* 73 */ "ERPCMISMATCH",
1619   /* 74 */ "EPROGUNAVAIL",
1620   /* 75 */ "EPROGMISMATCH",
1621   /* 76 */ "EPROCUNAVAIL",
1622   /* 77 */ "ENOLCK",
1623   /* 78 */ "ENOSYS",
1624   /* 79 */ "EFTYPE",
1625   /* 80 */ "EAUTH",
1626   /* 81 */ "ENEEDAUTH",
1627   /* 82 */ "EIDRM",
1628   /* 83 */ "ENOMSG",
1629   /* 84 */ "EOVERFLOW",
1630   /* 85 */ "EILSEQ",
1631   /* 86 */ "ENOTSUP",
1632   /* 87 */ "ECANCELED",
1633   /* 88 */ "EBADMSG",
1634   /* 89 */ "ENODATA",
1635   /* 90 */ "ENOSR",
1636   /* 91 */ "ENOSTR",
1637   /* 92 */ "ETIME",
1638   /* 93 */ "ENOATTR",
1639   /* 94 */ "EMULTIHOP",
1640   /* 95 */ "ENOLINK",
1641   /* 96 */ "EPROTO",
1642   /* 97 */ "EOWNERDEAD",
1643   /* 98 */ "ENOTRECOVERABLE",
1644   /* 98 */ "ELAST",
1645 };
1646 
1647 static char *(netbsd_signal_names[]) = {
1648   /* 0 */ 0,
1649   /* 1 */ "SIGHUP",
1650   /* 2 */ "SIGINT",
1651   /* 3 */ "SIGQUIT",
1652   /* 4 */ "SIGILL",
1653   /* 5 */ "SIGTRAP",
1654   /* 6 */ "SIGABRT",
1655   /* 7 */ "SIGEMT",
1656   /* 8 */ "SIGFPE",
1657   /* 9 */ "SIGKILL",
1658   /* 10 */ "SIGBUS",
1659   /* 11 */ "SIGSEGV",
1660   /* 12 */ "SIGSYS",
1661   /* 13 */ "SIGPIPE",
1662   /* 14 */ "SIGALRM",
1663   /* 15 */ "SIGTERM",
1664   /* 16 */ "SIGURG",
1665   /* 17 */ "SIGSTOP",
1666   /* 18 */ "SIGTSTP",
1667   /* 19 */ "SIGCONT",
1668   /* 20 */ "SIGCHLD",
1669   /* 21 */ "SIGTTIN",
1670   /* 22 */ "SIGTTOU",
1671   /* 23 */ "SIGIO",
1672   /* 24 */ "SIGXCPU",
1673   /* 25 */ "SIGXFSZ",
1674   /* 26 */ "SIGVTALRM",
1675   /* 27 */ "SIGPROF",
1676   /* 28 */ "SIGWINCH",
1677   /* 29 */ "SIGINFO",
1678   /* 30 */ "SIGUSR1",
1679   /* 31 */ "SIGUSR2",
1680   /* 32 */ "SIGPWR",
1681   /* 33 */ "SIGRTMIN",
1682   /* 34 */ "SIGRTMIN+1",
1683   /* 35 */ "SIGRTMIN+2",
1684   /* 36 */ "SIGRTMIN+3",
1685   /* 37 */ "SIGRTMIN+4",
1686   /* 38 */ "SIGRTMIN+5",
1687   /* 39 */ "SIGRTMIN+6",
1688   /* 40 */ "SIGRTMIN+7",
1689   /* 41 */ "SIGRTMIN+8",
1690   /* 42 */ "SIGRTMIN+9",
1691   /* 43 */ "SIGRTMIN+10",
1692   /* 44 */ "SIGRTMIN+11",
1693   /* 45 */ "SIGRTMIN+12",
1694   /* 46 */ "SIGRTMIN+13",
1695   /* 47 */ "SIGRTMIN+14",
1696   /* 48 */ "SIGRTMIN+15",
1697   /* 49 */ "SIGRTMIN+16",
1698   /* 50 */ "SIGRTMIN+17",
1699   /* 51 */ "SIGRTMIN+18",
1700   /* 52 */ "SIGRTMIN+19",
1701   /* 53 */ "SIGRTMIN+20",
1702   /* 54 */ "SIGRTMIN+21",
1703   /* 55 */ "SIGRTMIN+22",
1704   /* 56 */ "SIGRTMIN+23",
1705   /* 57 */ "SIGRTMIN+24",
1706   /* 58 */ "SIGRTMIN+25",
1707   /* 59 */ "SIGRTMIN+26",
1708   /* 60 */ "SIGRTMIN+27",
1709   /* 61 */ "SIGRTMIN+28",
1710   /* 62 */ "SIGRTMIN+29",
1711   /* 63 */ "SIGRTMAX",
1712 };
1713 
1714 static emul_syscall emul_netbsd_syscalls = {
1715   netbsd_descriptors,
1716   ARRAY_SIZE (netbsd_descriptors),
1717   netbsd_error_names,
1718   ARRAY_SIZE (netbsd_error_names),
1719   netbsd_signal_names,
1720   ARRAY_SIZE (netbsd_signal_names),
1721 };
1722 
1723 
1724 /* NetBSD's os_emul interface, most are just passed on to the generic
1725    syscall stuff */
1726 
1727 static os_emul_data *
1728 emul_netbsd_create(device *root,
1729 		   bfd *image,
1730 		   const char *name)
1731 {
1732   unsigned_word top_of_stack;
1733   unsigned stack_size;
1734   int elf_binary;
1735   os_emul_data *bsd_data;
1736   device *vm;
1737   char *filename;
1738 
1739   /* check that this emulation is really for us */
1740   if (name != NULL && strcmp(name, "netbsd") != 0)
1741     return NULL;
1742   if (image == NULL)
1743     return NULL;
1744 
1745 
1746   /* merge any emulation specific entries into the device tree */
1747 
1748   /* establish a few defaults */
1749   if (image->xvec->flavour == bfd_target_elf_flavour) {
1750     elf_binary = 1;
1751     top_of_stack = 0xe0000000;
1752     stack_size =   0x00100000;
1753   }
1754   else {
1755     elf_binary = 0;
1756     top_of_stack = 0x20000000;
1757     stack_size =   0x00100000;
1758   }
1759 
1760   /* options */
1761   emul_add_tree_options(root, image, "netbsd",
1762 			(WITH_ENVIRONMENT == USER_ENVIRONMENT
1763 			 ? "user" : "virtual"),
1764 			0 /*oea-interrupt-prefix*/);
1765 
1766   /* virtual memory - handles growth of stack/heap */
1767   vm = tree_parse(root, "/openprom/vm");
1768   tree_parse(vm, "./stack-base 0x%lx",
1769 	     (unsigned long)(top_of_stack - stack_size));
1770   tree_parse(vm, "./nr-bytes 0x%x", stack_size);
1771 
1772   filename = tree_quote_property (bfd_get_filename(image));
1773   tree_parse(root, "/openprom/vm/map-binary/file-name %s",
1774 	     filename);
1775   free (filename);
1776 
1777   /* finish the init */
1778   tree_parse(root, "/openprom/init/register/pc 0x%lx",
1779 	     (unsigned long)bfd_get_start_address(image));
1780   tree_parse(root, "/openprom/init/register/sp 0x%lx",
1781 	     (unsigned long)top_of_stack);
1782   tree_parse(root, "/openprom/init/register/msr 0x%x",
1783 	     ((tree_find_boolean_property(root, "/options/little-endian?")
1784 	       ? msr_little_endian_mode
1785 	       : 0)
1786 	      | (tree_find_boolean_property(root, "/openprom/options/floating-point?")
1787 		 ? (msr_floating_point_available
1788 		    | msr_floating_point_exception_mode_0
1789 		    | msr_floating_point_exception_mode_1)
1790 		 : 0)));
1791   tree_parse(root, "/openprom/init/stack/stack-type %s",
1792 	     (elf_binary ? "ppc-elf" : "ppc-xcoff"));
1793 
1794   /* finally our emulation data */
1795   bsd_data = ZALLOC(os_emul_data);
1796   bsd_data->vm = vm;
1797   bsd_data->syscalls = &emul_netbsd_syscalls;
1798   return bsd_data;
1799 }
1800 
1801 static void
1802 emul_netbsd_init(os_emul_data *emul_data,
1803 		 int nr_cpus)
1804 {
1805   fd_closed[0] = 0;
1806   fd_closed[1] = 0;
1807   fd_closed[2] = 0;
1808 }
1809 
1810 static void
1811 emul_netbsd_system_call(cpu *processor,
1812 			unsigned_word cia,
1813 			os_emul_data *emul_data)
1814 {
1815   emul_do_system_call(emul_data,
1816 		      emul_data->syscalls,
1817 		      cpu_registers(processor)->gpr[0],
1818 		      3, /*r3 contains arg0*/
1819 		      processor,
1820 		      cia);
1821 }
1822 
1823 const os_emul emul_netbsd = {
1824   "netbsd",
1825   emul_netbsd_create,
1826   emul_netbsd_init,
1827   emul_netbsd_system_call,
1828   0, /*instruction_call*/
1829   0 /*data*/
1830 };
1831 
1832 #endif	/* _EMUL_NETBSD_C_ */
1833