1/*  This file is part of the program psim.
2
3    Copyright (C) 1996-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_UNIX_C_
22#define _EMUL_UNIX_C_
23
24
25/* Note: this module is called via a table.  There is no benefit in
26   making it inline */
27
28#include "emul_generic.h"
29#include "emul_unix.h"
30
31#ifdef HAVE_STRING_H
32#include <string.h>
33#else
34#ifdef HAVE_STRINGS_H
35#include <strings.h>
36#endif
37#endif
38
39#ifdef HAVE_SYS_TYPES_H
40#include <sys/types.h>
41#endif
42
43#ifdef HAVE_SYS_TYPES_H
44#include <sys/stat.h>
45#else
46#undef HAVE_STAT
47#undef HAVE_LSTAT
48#undef HAVE_FSTAT
49#endif
50
51#include <stdio.h>
52#include <signal.h>
53#include <errno.h>
54
55#ifdef HAVE_FCNTL_H
56#include <fcntl.h>
57#endif
58
59#ifdef HAVE_SYS_PARAM_H
60#include <sys/param.h>
61#endif
62
63#ifdef HAVE_SYS_TIME_H
64#include <sys/time.h>
65#endif
66
67#ifndef HAVE_TERMIOS_STRUCTURE
68#undef HAVE_SYS_TERMIOS_H
69#undef HAVE_TCGETATTR
70#else
71#ifndef HAVE_SYS_TERMIOS_H
72#undef HAVE_TERMIOS_STRUCTURE
73#endif
74#endif
75
76#ifdef HAVE_TERMIOS_STRUCTURE
77#include <sys/termios.h>
78
79/* If we have TERMIOS, use that for the termio structure, since some systems
80   don't like including both sys/termios.h and sys/termio.h at the same
81   time.  */
82#undef	HAVE_TERMIO_STRUCTURE
83#undef	TCGETA
84#undef	termio
85#define termio termios
86#endif
87
88#ifndef HAVE_TERMIO_STRUCTURE
89#undef HAVE_SYS_TERMIO_H
90#else
91#ifndef HAVE_SYS_TERMIO_H
92#undef HAVE_TERMIO_STRUCTURE
93#endif
94#endif
95
96#ifdef HAVE_TERMIO_STRUCTURE
97#include <sys/termio.h>
98#endif
99
100#ifdef HAVE_GETRUSAGE
101#ifndef HAVE_SYS_RESOURCE_H
102#undef HAVE_GETRUSAGE
103#endif
104#endif
105
106#ifdef HAVE_GETRUSAGE
107#include <sys/resource.h>
108int getrusage();
109#endif
110
111#if HAVE_DIRENT_H
112# include <dirent.h>
113# define NAMLEN(dirent) strlen((dirent)->d_name)
114#else
115# define dirent direct
116# define NAMLEN(dirent) (dirent)->d_namlen
117# if HAVE_SYS_NDIR_H
118#  include <sys/ndir.h>
119# endif
120# if HAVE_SYS_DIR_H
121#  include <sys/dir.h>
122# endif
123# if HAVE_NDIR_H
124#  include <ndir.h>
125# endif
126#endif
127
128#ifdef HAVE_UNISTD_H
129#undef MAXPATHLEN		/* sys/param.h might define this also */
130#include <unistd.h>
131#endif
132
133#ifdef HAVE_STDLIB_H
134#include <stdlib.h>
135#endif
136
137#if defined(BSD) && !defined(errno) && (BSD < 199306)	/* here BSD as just a bug */
138extern int errno;
139#endif
140
141#ifndef STATIC_INLINE_EMUL_UNIX
142#define STATIC_INLINE_EMUL_UNIX STATIC_INLINE
143#endif
144
145#ifndef PATH_MAX
146#define PATH_MAX 1024
147#endif
148
149#ifndef EINVAL
150#define EINVAL -1
151#endif
152
153/* UNIX's idea of what is needed to implement emulations */
154
155struct _os_emul_data {
156  device *vm;
157  emul_syscall *syscalls;
158};
159
160
161/* Emulation of simple UNIX system calls that are common on all systems.  */
162
163/* Structures that are common agmonst the UNIX varients */
164struct unix_timeval {
165  signed32 tv_sec;		/* seconds */
166  signed32 tv_usec;		/* microseconds */
167};
168
169struct unix_timezone {
170  signed32 tz_minuteswest;	/* minutes west of Greenwich */
171  signed32 tz_dsttime;		/* type of dst correction */
172};
173
174#define	UNIX_RUSAGE_SELF	0
175#define	UNIX_RUSAGE_CHILDREN	(-1)
176#define UNIX_RUSAGE_BOTH	(-2)	/* sys_wait4() uses this */
177
178struct	unix_rusage {
179	struct unix_timeval ru_utime;	/* user time used */
180	struct unix_timeval ru_stime;	/* system time used */
181	signed32 ru_maxrss;		/* maximum resident set size */
182	signed32 ru_ixrss;		/* integral shared memory size */
183	signed32 ru_idrss;		/* integral unshared data size */
184	signed32 ru_isrss;		/* integral unshared stack size */
185	signed32 ru_minflt;		/* any page faults not requiring I/O */
186	signed32 ru_majflt;		/* any page faults requiring I/O */
187	signed32 ru_nswap;		/* swaps */
188	signed32 ru_inblock;		/* block input operations */
189	signed32 ru_oublock;		/* block output operations */
190	signed32 ru_msgsnd;		/* messages sent */
191	signed32 ru_msgrcv;		/* messages received */
192	signed32 ru_nsignals;		/* signals received */
193	signed32 ru_nvcsw;		/* voluntary context switches */
194	signed32 ru_nivcsw;		/* involuntary " */
195};
196
197
198/* File descriptors 0, 1, and 2 should not be closed.  fd_closed[]
199   tracks whether these descriptors have been closed in do_close()
200   below.  */
201
202static int fd_closed[3];
203
204/* Check for some occurrences of bad file descriptors.  We only check
205   whether fd 0, 1, or 2 are "closed".  By "closed" we mean that these
206   descriptors aren't actually closed, but are considered to be closed
207   by this layer.
208
209   Other checks are performed by the underlying OS call.  */
210
211static int
212fdbad (int fd)
213{
214  if (fd >=0 && fd <= 2 && fd_closed[fd])
215    {
216      errno = EBADF;
217      return -1;
218    }
219  return 0;
220}
221
222static void
223do_unix_exit(os_emul_data *emul,
224	     unsigned call,
225	     const int arg0,
226	     cpu *processor,
227	     unsigned_word cia)
228{
229  int status = (int)cpu_registers(processor)->gpr[arg0];
230  if (WITH_TRACE && ppc_trace[trace_os_emul])
231    printf_filtered ("%d)\n", status);
232
233  cpu_halt(processor, cia, was_exited, status);
234}
235
236
237static void
238do_unix_read(os_emul_data *emul,
239	     unsigned call,
240	     const int arg0,
241	     cpu *processor,
242	     unsigned_word cia)
243{
244  void *scratch_buffer;
245  int d = (int)cpu_registers(processor)->gpr[arg0];
246  unsigned_word buf = cpu_registers(processor)->gpr[arg0+1];
247  int nbytes = cpu_registers(processor)->gpr[arg0+2];
248  int status;
249
250  if (WITH_TRACE && ppc_trace[trace_os_emul])
251    printf_filtered ("%d, 0x%lx, %d", d, (long)buf, nbytes);
252
253  /* get a tempoary bufer */
254  scratch_buffer = zalloc(nbytes);
255
256  /* check if buffer exists by reading it */
257  emul_read_buffer(scratch_buffer, buf, nbytes, processor, cia);
258
259  status = fdbad (d);
260  /* read */
261  if (status == 0)
262    status = read (d, scratch_buffer, nbytes);
263
264  emul_write_status(processor, status, errno);
265  if (status > 0)
266    emul_write_buffer(scratch_buffer, buf, status, processor, cia);
267
268  free(scratch_buffer);
269}
270
271
272static void
273do_unix_write(os_emul_data *emul,
274	      unsigned call,
275	      const int arg0,
276	      cpu *processor,
277	      unsigned_word cia)
278{
279  void *scratch_buffer = NULL;
280  int d = (int)cpu_registers(processor)->gpr[arg0];
281  unsigned_word buf = cpu_registers(processor)->gpr[arg0+1];
282  int nbytes = cpu_registers(processor)->gpr[arg0+2];
283  int status;
284
285  if (WITH_TRACE && ppc_trace[trace_os_emul])
286    printf_filtered ("%d, 0x%lx, %d", d, (long)buf, nbytes);
287
288  /* get a tempoary bufer */
289  scratch_buffer = zalloc(nbytes); /* FIXME - nbytes == 0 */
290
291  /* copy in */
292  emul_read_buffer(scratch_buffer, buf, nbytes,
293		   processor, cia);
294
295  status = fdbad (d);
296  /* write */
297  if (status == 0)
298    status = write(d, scratch_buffer, nbytes);
299  emul_write_status(processor, status, errno);
300  free(scratch_buffer);
301
302  flush_stdoutput();
303}
304
305
306static void
307do_unix_open(os_emul_data *emul,
308	     unsigned call,
309	     const int arg0,
310	     cpu *processor,
311	     unsigned_word cia)
312{
313  unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
314  char path_buf[PATH_MAX];
315  char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
316  int flags = (int)cpu_registers(processor)->gpr[arg0+1];
317  int mode = (int)cpu_registers(processor)->gpr[arg0+2];
318  int status;
319
320  if (WITH_TRACE && ppc_trace[trace_os_emul])
321    printf_filtered ("0x%lx [%s], 0x%x, 0x%x", (long)path_addr, path, flags, mode);
322
323  status = open(path, flags, mode);
324  emul_write_status(processor, status, errno);
325}
326
327
328static void
329do_unix_close(os_emul_data *emul,
330	      unsigned call,
331	      const int arg0,
332	      cpu *processor,
333	      unsigned_word cia)
334{
335  int d = (int)cpu_registers(processor)->gpr[arg0];
336  int status;
337
338  if (WITH_TRACE && ppc_trace[trace_os_emul])
339    printf_filtered ("%d", d);
340
341  status = fdbad (d);
342  if (status == 0)
343    {
344      /* Do not close stdin, stdout, or stderr. GDB may still need access to
345	 these descriptors.  */
346      if (d == 0 || d == 1 || d == 2)
347	{
348	  fd_closed[d] = 1;
349	  status = 0;
350	}
351      else
352	status = close(d);
353    }
354
355  emul_write_status(processor, status, errno);
356}
357
358
359static void
360do_unix_break(os_emul_data *emul,
361	      unsigned call,
362	      const int arg0,
363	      cpu *processor,
364	      unsigned_word cia)
365{
366  /* just pass this onto the `vm' device */
367  unsigned_word new_break = cpu_registers(processor)->gpr[arg0];
368  int status;
369
370  if (WITH_TRACE && ppc_trace[trace_os_emul])
371    printf_filtered ("0x%lx", (long)cpu_registers(processor)->gpr[arg0]);
372
373  status = device_ioctl(emul->vm,
374			processor,
375			cia,
376			device_ioctl_break,
377			new_break); /*ioctl-data*/
378
379  emul_write_status(processor, 0, status);
380}
381
382#ifndef HAVE_ACCESS
383#define do_unix_access 0
384#else
385static void
386do_unix_access(os_emul_data *emul,
387	       unsigned call,
388	       const int arg0,
389	       cpu *processor,
390	       unsigned_word cia)
391{
392  unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
393  char path_buf[PATH_MAX];
394  char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
395  int mode = (int)cpu_registers(processor)->gpr[arg0+1];
396  int status;
397
398  if (WITH_TRACE && ppc_trace[trace_os_emul])
399    printf_filtered ("0x%lx [%s], 0x%x [0%o]", (long)path_addr, path, mode, mode);
400
401  status = access(path, mode);
402  emul_write_status(processor, status, errno);
403}
404#endif
405
406#ifndef HAVE_GETPID
407#define do_unix_getpid 0
408#else
409static void
410do_unix_getpid(os_emul_data *emul,
411	       unsigned call,
412	       const int arg0,
413	       cpu *processor,
414	       unsigned_word cia)
415{
416  pid_t status = getpid();
417  emul_write_status(processor, (int)status, errno);
418}
419#endif
420
421#ifndef HAVE_GETPPID
422#define do_unix_getppid 0
423#else
424static void
425do_unix_getppid(os_emul_data *emul,
426		unsigned call,
427		const int arg0,
428		cpu *processor,
429		unsigned_word cia)
430{
431  pid_t status = getppid();
432  emul_write_status(processor, (int)status, errno);
433}
434#endif
435
436#if !defined(HAVE_GETPID) || !defined(HAVE_GETPPID)
437#define do_unix_getpid2 0
438#else
439static void
440do_unix_getpid2(os_emul_data *emul,
441		unsigned call,
442		const int arg0,
443		cpu *processor,
444		unsigned_word cia)
445{
446  int pid  = (int)getpid();
447  int ppid = (int)getppid();
448  emul_write2_status(processor, pid, ppid, errno);
449}
450#endif
451
452#if !defined(HAVE_GETUID) || !defined(HAVE_GETEUID)
453#define do_unix_getuid2 0
454#else
455static void
456do_unix_getuid2(os_emul_data *emul,
457		unsigned call,
458		const int arg0,
459		cpu *processor,
460		unsigned_word cia)
461{
462  uid_t uid  = getuid();
463  uid_t euid = geteuid();
464  emul_write2_status(processor, (int)uid, (int)euid, errno);
465}
466#endif
467
468#ifndef HAVE_GETUID
469#define do_unix_getuid 0
470#else
471static void
472do_unix_getuid(os_emul_data *emul,
473	       unsigned call,
474	       const int arg0,
475	       cpu *processor,
476	       unsigned_word cia)
477{
478  uid_t status = getuid();
479  emul_write_status(processor, (int)status, errno);
480}
481#endif
482
483#ifndef HAVE_GETEUID
484#define do_unix_geteuid 0
485#else
486static void
487do_unix_geteuid(os_emul_data *emul,
488		unsigned call,
489		const int arg0,
490		cpu *processor,
491		unsigned_word cia)
492{
493  uid_t status = geteuid();
494  emul_write_status(processor, (int)status, errno);
495}
496#endif
497
498#if 0
499#ifndef HAVE_KILL
500#define do_unix_kill 0
501#else
502static void
503do_unix_kill(os_emul_data *emul,
504	     unsigned call,
505	     const int arg0,
506	     cpu *processor,
507	     unsigned_word cia)
508{
509  pid_t pid = cpu_registers(processor)->gpr[arg0];
510  int sig = cpu_registers(processor)->gpr[arg0+1];
511
512  if (WITH_TRACE && ppc_trace[trace_os_emul])
513    printf_filtered ("%d, %d", (int)pid, sig);
514
515  printf_filtered("SYS_kill at 0x%lx - more to this than just being killed\n",
516		  (long)cia);
517
518  cpu_halt(processor, cia, was_signalled, sig);
519}
520#endif
521#endif
522
523#ifndef HAVE_DUP
524#define do_unix_dup 0
525#else
526static void
527do_unix_dup(os_emul_data *emul,
528	    unsigned call,
529	    const int arg0,
530	    cpu *processor,
531	    unsigned_word cia)
532{
533  int oldd = cpu_registers(processor)->gpr[arg0];
534  int status = (fdbad (oldd) < 0) ? -1 : dup(oldd);
535  int err = errno;
536
537  if (WITH_TRACE && ppc_trace[trace_os_emul])
538    printf_filtered ("%d", oldd);
539
540  emul_write_status(processor, status, err);
541}
542#endif
543
544#ifndef HAVE_DUP2
545#define do_unix_dup2 0
546#else
547static void
548do_unix_dup2(os_emul_data *emul,
549	     unsigned call,
550	     const int arg0,
551	     cpu *processor,
552	     unsigned_word cia)
553{
554  int oldd = cpu_registers(processor)->gpr[arg0];
555  int newd = cpu_registers(processor)->gpr[arg0+1];
556  int status = (fdbad (oldd) < 0) ? -1 : dup2(oldd, newd);
557  int err = errno;
558
559  if (WITH_TRACE && ppc_trace[trace_os_emul])
560    printf_filtered ("%d, %d", oldd, newd);
561
562  emul_write_status(processor, status, err);
563}
564#endif
565
566#ifndef HAVE_LSEEK
567#define do_unix_lseek 0
568#else
569static void
570do_unix_lseek(os_emul_data *emul,
571	      unsigned call,
572	      const int arg0,
573	      cpu *processor,
574	      unsigned_word cia)
575{
576  int fildes   = (int)cpu_registers(processor)->gpr[arg0];
577  off_t offset = (off_t)cpu_registers(processor)->gpr[arg0+1];
578  int whence   = (int)cpu_registers(processor)->gpr[arg0+2];
579  off_t status;
580
581  if (WITH_TRACE && ppc_trace[trace_os_emul])
582    printf_filtered ("%d %ld %d", fildes, (long)offset, whence);
583
584  status = fdbad (fildes);
585  if (status == 0)
586    status = lseek(fildes, offset, whence);
587  emul_write_status(processor, (int)status, errno);
588}
589#endif
590
591
592#if !defined(HAVE_GETGID) || !defined(HAVE_GETEGID)
593#define do_unix_getgid2 0
594#else
595static void
596do_unix_getgid2(os_emul_data *emul,
597		unsigned call,
598		const int arg0,
599		cpu *processor,
600		unsigned_word cia)
601{
602  gid_t gid  = getgid();
603  gid_t egid = getegid();
604  emul_write2_status(processor, (int)gid, (int)egid, errno);
605}
606#endif
607
608#ifndef HAVE_GETGID
609#define do_unix_getgid 0
610#else
611static void
612do_unix_getgid(os_emul_data *emul,
613	       unsigned call,
614	       const int arg0,
615	       cpu *processor,
616	       unsigned_word cia)
617{
618  gid_t status = getgid();
619  emul_write_status(processor, (int)status, errno);
620}
621#endif
622
623#ifndef HAVE_GETEGID
624#define do_unix_getegid 0
625#else
626static void
627do_unix_getegid(os_emul_data *emul,
628		unsigned call,
629		const int arg0,
630		cpu *processor,
631		unsigned_word cia)
632{
633  gid_t status = getegid();
634  emul_write_status(processor, (int)status, errno);
635}
636#endif
637
638#ifndef HAVE_UMASK
639#define do_unix_umask 0
640#else
641static void
642do_unix_umask(os_emul_data *emul,
643	      unsigned call,
644	      const int arg0,
645	      cpu *processor,
646	      unsigned_word cia)
647{
648  mode_t mask = (mode_t)cpu_registers(processor)->gpr[arg0];
649  int status = umask(mask);
650
651  if (WITH_TRACE && ppc_trace[trace_os_emul])
652    printf_filtered ("0%o", (unsigned int)mask);
653
654  emul_write_status(processor, status, errno);
655}
656#endif
657
658#ifndef HAVE_CHDIR
659#define do_unix_chdir 0
660#else
661static void
662do_unix_chdir(os_emul_data *emul,
663	      unsigned call,
664	      const int arg0,
665	      cpu *processor,
666	      unsigned_word cia)
667{
668  unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
669  char path_buf[PATH_MAX];
670  char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
671  int status;
672
673  if (WITH_TRACE && ppc_trace[trace_os_emul])
674    printf_filtered ("0x%lx [%s]", (long)path_addr, path);
675
676  status = chdir(path);
677  emul_write_status(processor, status, errno);
678}
679#endif
680
681#ifndef HAVE_LINK
682#define do_unix_link 0
683#else
684static void
685do_unix_link(os_emul_data *emul,
686	     unsigned call,
687	     const int arg0,
688	     cpu *processor,
689	     unsigned_word cia)
690{
691  unsigned_word path1_addr = cpu_registers(processor)->gpr[arg0];
692  char path1_buf[PATH_MAX];
693  char *path1 = emul_read_string(path1_buf, path1_addr, PATH_MAX, processor, cia);
694  unsigned_word path2_addr = cpu_registers(processor)->gpr[arg0+1];
695  char path2_buf[PATH_MAX];
696  char *path2 = emul_read_string(path2_buf, path2_addr, PATH_MAX, processor, cia);
697  int status;
698
699  if (WITH_TRACE && ppc_trace[trace_os_emul])
700    printf_filtered ("0x%lx [%s], 0x%lx [%s]", (long)path1_addr, path1, (long)path2_addr, path2);
701
702  status = link(path1, path2);
703  emul_write_status(processor, status, errno);
704}
705#endif
706
707#ifndef HAVE_SYMLINK
708#define do_unix_symlink 0
709#else
710static void
711do_unix_symlink(os_emul_data *emul,
712		unsigned call,
713		const int arg0,
714		cpu *processor,
715		unsigned_word cia)
716{
717  unsigned_word path1_addr = cpu_registers(processor)->gpr[arg0];
718  char path1_buf[PATH_MAX];
719  char *path1 = emul_read_string(path1_buf, path1_addr, PATH_MAX, processor, cia);
720  unsigned_word path2_addr = cpu_registers(processor)->gpr[arg0+1];
721  char path2_buf[PATH_MAX];
722  char *path2 = emul_read_string(path2_buf, path2_addr, PATH_MAX, processor, cia);
723  int status;
724
725  if (WITH_TRACE && ppc_trace[trace_os_emul])
726    printf_filtered ("0x%lx [%s], 0x%lx [%s]", (long)path1_addr, path1, (long)path2_addr, path2);
727
728  status = symlink(path1, path2);
729  emul_write_status(processor, status, errno);
730}
731#endif
732
733#ifndef HAVE_UNLINK
734#define do_unix_unlink 0
735#else
736static void
737do_unix_unlink(os_emul_data *emul,
738	       unsigned call,
739	       const int arg0,
740	       cpu *processor,
741	       unsigned_word cia)
742{
743  unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
744  char path_buf[PATH_MAX];
745  char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
746  int status;
747
748  if (WITH_TRACE && ppc_trace[trace_os_emul])
749    printf_filtered ("0x%lx [%s]", (long)path_addr, path);
750
751  status = unlink(path);
752  emul_write_status(processor, status, errno);
753}
754#endif
755
756#ifndef HAVE_MKDIR
757#define do_unix_mkdir 0
758#else
759static void
760do_unix_mkdir(os_emul_data *emul,
761	      unsigned call,
762	      const int arg0,
763	      cpu *processor,
764	      unsigned_word cia)
765{
766  unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
767  char path_buf[PATH_MAX];
768  char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
769  int mode = (int)cpu_registers(processor)->gpr[arg0+1];
770  int status;
771
772  if (WITH_TRACE && ppc_trace[trace_os_emul])
773    printf_filtered ("0x%lx [%s], 0%3o", (long)path_addr, path, mode);
774
775#ifdef USE_WIN32API
776  status = mkdir(path);
777#else
778  status = mkdir(path, mode);
779#endif
780  emul_write_status(processor, status, errno);
781}
782#endif
783
784#ifndef HAVE_RMDIR
785#define do_unix_rmdir 0
786#else
787static void
788do_unix_rmdir(os_emul_data *emul,
789	      unsigned call,
790	      const int arg0,
791	      cpu *processor,
792	      unsigned_word cia)
793{
794  unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
795  char path_buf[PATH_MAX];
796  char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
797  int status;
798
799  if (WITH_TRACE && ppc_trace[trace_os_emul])
800    printf_filtered ("0x%lx [%s]", (long)path_addr, path);
801
802  status = rmdir(path);
803  emul_write_status(processor, status, errno);
804}
805#endif
806
807#ifndef HAVE_TIME
808#define do_unix_time 0
809#else
810static void
811do_unix_time(os_emul_data *emul,
812	     unsigned call,
813	     const int arg0,
814	     cpu *processor,
815	     unsigned_word cia)
816{
817  unsigned_word tp = cpu_registers(processor)->gpr[arg0];
818  time_t now = time ((time_t *)0);
819  unsigned_word status = H2T_4(now);
820
821  if (WITH_TRACE && ppc_trace[trace_os_emul])
822    printf_filtered ("0x%lx", (long)tp);
823
824  emul_write_status(processor, (int)status, errno);
825
826  if (tp)
827    emul_write_buffer(&status, tp, sizeof(status), processor, cia);
828}
829#endif
830
831#if !defined(HAVE_GETTIMEOFDAY) || !defined(HAVE_SYS_TIME_H)
832#define do_unix_gettimeofday 0
833#else
834static void
835do_unix_gettimeofday(os_emul_data *emul,
836		     unsigned call,
837		     const int arg0,
838		     cpu *processor,
839		     unsigned_word cia)
840{
841  unsigned_word tv = cpu_registers(processor)->gpr[arg0];
842  unsigned_word tz = cpu_registers(processor)->gpr[arg0+1];
843  struct unix_timeval target_timeval;
844  struct timeval host_timeval;
845  struct unix_timezone target_timezone;
846  struct timezone host_timezone;
847  int status;
848
849  if (WITH_TRACE && ppc_trace[trace_os_emul])
850    printf_filtered ("0x%lx, 0x%lx", (long)tv, (long)tz);
851
852  /* Just in case the system doesn't set the timezone structure */
853  host_timezone.tz_minuteswest = 0;
854  host_timezone.tz_dsttime = 0;
855
856  status = gettimeofday(&host_timeval, &host_timezone);
857  if (status >= 0) {
858    if (tv) {
859      target_timeval.tv_sec = H2T_4(host_timeval.tv_sec);
860      target_timeval.tv_usec = H2T_4(host_timeval.tv_usec);
861      emul_write_buffer((void *) &target_timeval, tv, sizeof(target_timeval), processor, cia);
862    }
863
864    if (tz) {
865      target_timezone.tz_minuteswest = H2T_4(host_timezone.tz_minuteswest);
866      target_timezone.tz_dsttime = H2T_4(host_timezone.tz_dsttime);
867      emul_write_buffer((void *) &target_timezone, tv, sizeof(target_timezone), processor, cia);
868    }
869  }
870
871  emul_write_status(processor, (int)status, errno);
872}
873#endif
874
875
876#ifndef HAVE_GETRUSAGE
877#define do_unix_getrusage 0
878#else
879static void
880do_unix_getrusage(os_emul_data *emul,
881		  unsigned call,
882		  const int arg0,
883		  cpu *processor,
884		  unsigned_word cia)
885{
886  signed_word who = (signed_word)cpu_registers(processor)->gpr[arg0];
887  unsigned_word usage = cpu_registers(processor)->gpr[arg0+1];
888  struct rusage host_rusage, host_rusage2;
889  struct unix_rusage target_rusage;
890  int status;
891
892  if (WITH_TRACE && ppc_trace[trace_os_emul])
893    printf_filtered ("%ld, 0x%lx", (long)who, (long)usage);
894
895  switch (who) {
896  default:
897    status = -1;
898    errno = EINVAL;
899    break;
900
901  case UNIX_RUSAGE_SELF:
902    status = getrusage(RUSAGE_SELF, &host_rusage);
903    break;
904
905  case UNIX_RUSAGE_CHILDREN:
906    status = getrusage(RUSAGE_CHILDREN, &host_rusage);
907    break;
908
909  case UNIX_RUSAGE_BOTH:
910    status = getrusage(RUSAGE_SELF, &host_rusage);
911    if (status >= 0) {
912      status = getrusage(RUSAGE_CHILDREN, &host_rusage2);
913      if (status >= 0) {
914	host_rusage.ru_utime.tv_sec += host_rusage2.ru_utime.tv_sec;
915	host_rusage.ru_utime.tv_usec += host_rusage2.ru_utime.tv_usec;
916	host_rusage.ru_stime.tv_sec += host_rusage2.ru_stime.tv_sec;
917	host_rusage.ru_stime.tv_usec += host_rusage2.ru_stime.tv_usec;
918	host_rusage.ru_maxrss += host_rusage2.ru_maxrss;
919	host_rusage.ru_ixrss += host_rusage2.ru_ixrss;
920	host_rusage.ru_idrss += host_rusage2.ru_idrss;
921	host_rusage.ru_isrss += host_rusage2.ru_isrss;
922	host_rusage.ru_minflt += host_rusage2.ru_minflt;
923	host_rusage.ru_majflt += host_rusage2.ru_majflt;
924	host_rusage.ru_nswap += host_rusage2.ru_nswap;
925	host_rusage.ru_inblock += host_rusage2.ru_inblock;
926	host_rusage.ru_oublock += host_rusage2.ru_oublock;
927	host_rusage.ru_msgsnd += host_rusage2.ru_msgsnd;
928	host_rusage.ru_msgrcv += host_rusage2.ru_msgrcv;
929	host_rusage.ru_nsignals += host_rusage2.ru_nsignals;
930	host_rusage.ru_nvcsw += host_rusage2.ru_nvcsw;
931	host_rusage.ru_nivcsw += host_rusage2.ru_nivcsw;
932      }
933    }
934  }
935
936  if (status >= 0) {
937    target_rusage.ru_utime.tv_sec = H2T_4(host_rusage2.ru_utime.tv_sec);
938    target_rusage.ru_utime.tv_usec = H2T_4(host_rusage2.ru_utime.tv_usec);
939    target_rusage.ru_stime.tv_sec = H2T_4(host_rusage2.ru_stime.tv_sec);
940    target_rusage.ru_stime.tv_usec = H2T_4(host_rusage2.ru_stime.tv_usec);
941    target_rusage.ru_maxrss = H2T_4(host_rusage2.ru_maxrss);
942    target_rusage.ru_ixrss = H2T_4(host_rusage2.ru_ixrss);
943    target_rusage.ru_idrss = H2T_4(host_rusage2.ru_idrss);
944    target_rusage.ru_isrss = H2T_4(host_rusage2.ru_isrss);
945    target_rusage.ru_minflt = H2T_4(host_rusage2.ru_minflt);
946    target_rusage.ru_majflt = H2T_4(host_rusage2.ru_majflt);
947    target_rusage.ru_nswap = H2T_4(host_rusage2.ru_nswap);
948    target_rusage.ru_inblock = H2T_4(host_rusage2.ru_inblock);
949    target_rusage.ru_oublock = H2T_4(host_rusage2.ru_oublock);
950    target_rusage.ru_msgsnd = H2T_4(host_rusage2.ru_msgsnd);
951    target_rusage.ru_msgrcv = H2T_4(host_rusage2.ru_msgrcv);
952    target_rusage.ru_nsignals = H2T_4(host_rusage2.ru_nsignals);
953    target_rusage.ru_nvcsw = H2T_4(host_rusage2.ru_nvcsw);
954    target_rusage.ru_nivcsw = H2T_4(host_rusage2.ru_nivcsw);
955    emul_write_buffer((void *) &target_rusage, usage, sizeof(target_rusage), processor, cia);
956  }
957
958  emul_write_status(processor, status, errno);
959}
960#endif
961
962
963static void
964do_unix_nop(os_emul_data *emul,
965	    unsigned call,
966	    const int arg0,
967	    cpu *processor,
968	    unsigned_word cia)
969{
970  if (WITH_TRACE && ppc_trace[trace_os_emul])
971    printf_filtered ("0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx",
972		     (long)cpu_registers(processor)->gpr[arg0],
973		     (long)cpu_registers(processor)->gpr[arg0+1],
974		     (long)cpu_registers(processor)->gpr[arg0+2],
975		     (long)cpu_registers(processor)->gpr[arg0+3],
976		     (long)cpu_registers(processor)->gpr[arg0+4],
977		     (long)cpu_registers(processor)->gpr[arg0+5]);
978
979  emul_write_status(processor, 0, errno);
980}
981
982
983/* Common code for initializing the system call stuff */
984
985static os_emul_data *
986emul_unix_create(device *root,
987		 bfd *image,
988		 const char *name,
989		 emul_syscall *syscall)
990{
991  unsigned_word top_of_stack;
992  unsigned stack_size;
993  int elf_binary;
994  os_emul_data *data;
995  device *vm;
996  char *filename;
997
998  /* merge any emulation specific entries into the device tree */
999
1000  /* establish a few defaults */
1001  if (image->xvec->flavour == bfd_target_elf_flavour) {
1002    elf_binary = 1;
1003    top_of_stack = 0xe0000000;
1004    stack_size =   0x00100000;
1005  }
1006  else {
1007    elf_binary = 0;
1008    top_of_stack = 0x20000000;
1009    stack_size =   0x00100000;
1010  }
1011
1012  /* options */
1013  emul_add_tree_options(root, image, name,
1014			(WITH_ENVIRONMENT == USER_ENVIRONMENT
1015			 ? "user" : "virtual"),
1016			0 /*oea-interrupt-prefix*/);
1017
1018  /* virtual memory - handles growth of stack/heap */
1019  vm = tree_parse(root, "/openprom/vm@0x%lx",
1020		  (unsigned long)(top_of_stack - stack_size));
1021  tree_parse(vm, "./stack-base 0x%lx",
1022	     (unsigned long)(top_of_stack - stack_size));
1023  tree_parse(vm, "./nr-bytes 0x%x", stack_size);
1024
1025  filename = tree_quote_property (bfd_get_filename(image));
1026  tree_parse(root, "/openprom/vm/map-binary/file-name %s",
1027	     filename);
1028  free (filename);
1029
1030  /* finish the init */
1031  tree_parse(root, "/openprom/init/register/pc 0x%lx",
1032	     (unsigned long)bfd_get_start_address(image));
1033  tree_parse(root, "/openprom/init/register/sp 0x%lx",
1034	     (unsigned long)top_of_stack);
1035  tree_parse(root, "/openprom/init/register/msr 0x%x",
1036	     ((tree_find_boolean_property(root, "/options/little-endian?")
1037	       ? msr_little_endian_mode
1038	       : 0)
1039	      | (tree_find_boolean_property(root, "/openprom/options/floating-point?")
1040		 ? (msr_floating_point_available
1041		    | msr_floating_point_exception_mode_0
1042		    | msr_floating_point_exception_mode_1)
1043		 : 0)));
1044  tree_parse(root, "/openprom/init/stack/stack-type %s",
1045	     (elf_binary ? "ppc-elf" : "ppc-xcoff"));
1046
1047  /* finally our emulation data */
1048  data = ZALLOC(os_emul_data);
1049  data->vm = vm;
1050  data->syscalls = syscall;
1051  return data;
1052}
1053
1054
1055/* EMULATION
1056
1057   Solaris - Emulation of user programs for Solaris/PPC
1058
1059   DESCRIPTION
1060
1061   */
1062
1063
1064/* Solaris specific implementation */
1065
1066typedef	signed32	solaris_uid_t;
1067typedef	signed32	solaris_gid_t;
1068typedef signed32	solaris_off_t;
1069typedef signed32	solaris_pid_t;
1070typedef signed32	solaris_time_t;
1071typedef unsigned32	solaris_dev_t;
1072typedef unsigned32	solaris_ino_t;
1073typedef unsigned32	solaris_mode_t;
1074typedef	unsigned32	solaris_nlink_t;
1075
1076#ifdef HAVE_SYS_STAT_H
1077#define	SOLARIS_ST_FSTYPSZ 16		/* array size for file system type name */
1078
1079/* AIX 7.1 defines st_pad[123] to st_[amc]tim.tv_pad, respectively */
1080#undef st_pad1
1081#undef st_pad2
1082#undef st_pad3
1083
1084struct solaris_stat {
1085  solaris_dev_t		st_dev;
1086  signed32		st_pad1[3];	/* reserved for network id */
1087  solaris_ino_t		st_ino;
1088  solaris_mode_t	st_mode;
1089  solaris_nlink_t 	st_nlink;
1090  solaris_uid_t 	st_uid;
1091  solaris_gid_t 	st_gid;
1092  solaris_dev_t		st_rdev;
1093  signed32		st_pad2[2];
1094  solaris_off_t		st_size;
1095  signed32		st_pad3;	/* future off_t expansion */
1096  struct unix_timeval	st_atim;
1097  struct unix_timeval	st_mtim;
1098  struct unix_timeval	st_ctim;
1099  signed32		st_blksize;
1100  signed32		st_blocks;
1101  char			st_fstype[SOLARIS_ST_FSTYPSZ];
1102  signed32		st_pad4[8];	/* expansion area */
1103};
1104
1105/* Convert from host stat structure to solaris stat structure */
1106STATIC_INLINE_EMUL_UNIX void
1107convert_to_solaris_stat(unsigned_word addr,
1108			struct stat *host,
1109			cpu *processor,
1110			unsigned_word cia)
1111{
1112  struct solaris_stat target;
1113  int i;
1114
1115  target.st_dev   = H2T_4(host->st_dev);
1116  target.st_ino   = H2T_4(host->st_ino);
1117  target.st_mode  = H2T_4(host->st_mode);
1118  target.st_nlink = H2T_4(host->st_nlink);
1119  target.st_uid   = H2T_4(host->st_uid);
1120  target.st_gid   = H2T_4(host->st_gid);
1121  target.st_size  = H2T_4(host->st_size);
1122
1123#ifdef HAVE_ST_RDEV
1124  target.st_rdev  = H2T_4(host->st_rdev);
1125#else
1126  target.st_rdev  = 0;
1127#endif
1128
1129#ifdef HAVE_ST_BLKSIZE
1130  target.st_blksize = H2T_4(host->st_blksize);
1131#else
1132  target.st_blksize = 0;
1133#endif
1134
1135#ifdef HAVE_ST_BLOCKS
1136  target.st_blocks  = H2T_4(host->st_blocks);
1137#else
1138  target.st_blocks  = 0;
1139#endif
1140
1141  target.st_atim.tv_sec  = H2T_4(host->st_atime);
1142  target.st_atim.tv_usec = 0;
1143
1144  target.st_ctim.tv_sec  = H2T_4(host->st_ctime);
1145  target.st_ctim.tv_usec = 0;
1146
1147  target.st_mtim.tv_sec  = H2T_4(host->st_mtime);
1148  target.st_mtim.tv_usec = 0;
1149
1150  for (i = 0; i < ARRAY_SIZE (target.st_pad1); i++)
1151    target.st_pad1[i] = 0;
1152
1153  for (i = 0; i < ARRAY_SIZE (target.st_pad2); i++)
1154    target.st_pad2[i] = 0;
1155
1156  target.st_pad3 = 0;
1157
1158  for (i = 0; i < ARRAY_SIZE (target.st_pad4); i++)
1159    target.st_pad4[i] = 0;
1160
1161  /* For now, just punt and always say it is a ufs file */
1162  strcpy (target.st_fstype, "ufs");
1163
1164  emul_write_buffer(&target, addr, sizeof(target), processor, cia);
1165}
1166#endif /* HAVE_SYS_STAT_H */
1167
1168#ifndef HAVE_STAT
1169#define do_solaris_stat 0
1170#else
1171static void
1172do_solaris_stat(os_emul_data *emul,
1173		unsigned call,
1174		const int arg0,
1175		cpu *processor,
1176		unsigned_word cia)
1177{
1178  unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
1179  unsigned_word stat_pkt = cpu_registers(processor)->gpr[arg0+1];
1180  char path_buf[PATH_MAX];
1181  struct stat buf;
1182  char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
1183  int status;
1184
1185  if (WITH_TRACE && ppc_trace[trace_os_emul])
1186    printf_filtered ("0x%lx [%s], 0x%lx", (long)path_addr, path, (long)stat_pkt);
1187
1188  status = stat (path, &buf);
1189  if (status == 0)
1190    convert_to_solaris_stat (stat_pkt, &buf, processor, cia);
1191
1192  emul_write_status(processor, status, errno);
1193}
1194#endif
1195
1196#ifndef HAVE_LSTAT
1197#define do_solaris_lstat 0
1198#else
1199static void
1200do_solaris_lstat(os_emul_data *emul,
1201		 unsigned call,
1202		 const int arg0,
1203		 cpu *processor,
1204		 unsigned_word cia)
1205{
1206  unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
1207  unsigned_word stat_pkt = cpu_registers(processor)->gpr[arg0+1];
1208  char path_buf[PATH_MAX];
1209  struct stat buf;
1210  char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
1211  int status;
1212
1213  if (WITH_TRACE && ppc_trace[trace_os_emul])
1214    printf_filtered ("0x%lx [%s], 0x%lx", (long)path_addr, path, (long)stat_pkt);
1215
1216  status = lstat (path, &buf);
1217  if (status == 0)
1218    convert_to_solaris_stat (stat_pkt, &buf, processor, cia);
1219
1220  emul_write_status(processor, status, errno);
1221}
1222#endif
1223
1224#ifndef HAVE_FSTAT
1225#define do_solaris_fstat 0
1226#else
1227static void
1228do_solaris_fstat(os_emul_data *emul,
1229		 unsigned call,
1230		 const int arg0,
1231		 cpu *processor,
1232		 unsigned_word cia)
1233{
1234  int fildes = (int)cpu_registers(processor)->gpr[arg0];
1235  unsigned_word stat_pkt = cpu_registers(processor)->gpr[arg0+1];
1236  struct stat buf;
1237  int status;
1238
1239  if (WITH_TRACE && ppc_trace[trace_os_emul])
1240    printf_filtered ("%d, 0x%lx", fildes, (long)stat_pkt);
1241
1242  status = fdbad (fildes);
1243  if (status == 0)
1244    status = fstat (fildes, &buf);
1245  if (status == 0)
1246    convert_to_solaris_stat (stat_pkt, &buf, processor, cia);
1247
1248  emul_write_status(processor, status, errno);
1249}
1250#endif
1251
1252#if defined(HAVE_TERMIO_STRUCTURE) || defined(HAVE_TERMIOS_STRUCTURE)
1253#define	SOLARIS_TIOC	  ('T'<<8)
1254#define SOLARIS_NCC	  8
1255#define SOLARIS_NCCS	  19
1256
1257#define	SOLARIS_VINTR	  0
1258#define	SOLARIS_VQUIT	  1
1259#define	SOLARIS_VERASE	  2
1260#define	SOLARIS_VKILL	  3
1261#define	SOLARIS_VEOF	  4
1262#define	SOLARIS_VEOL	  5
1263#define	SOLARIS_VEOL2	  6
1264#define	SOLARIS_VSWTCH	  7
1265#define	SOLARIS_VSTART	  8
1266#define	SOLARIS_VSTOP	  9
1267#define	SOLARIS_VSUSP	 10
1268#define	SOLARIS_VDSUSP	 11
1269#define	SOLARIS_VREPRINT 12
1270#define	SOLARIS_VDISCARD 13
1271#define	SOLARIS_VWERASE	 14
1272#define	SOLARIS_VLNEXT	 15
1273#endif
1274
1275#if defined(HAVE_TERMIO_STRUCTURE) || defined(HAVE_TERMIOS_STRUCTURE)
1276/* Convert to/from host termio structure */
1277
1278struct solaris_termio {
1279	unsigned16	c_iflag;		/* input modes */
1280	unsigned16	c_oflag;		/* output modes */
1281	unsigned16	c_cflag;		/* control modes */
1282	unsigned16	c_lflag;		/* line discipline modes */
1283	unsigned8	c_line;			/* line discipline */
1284	unsigned8	c_cc[SOLARIS_NCC];	/* control chars */
1285};
1286
1287STATIC_INLINE_EMUL_UNIX void
1288convert_to_solaris_termio(unsigned_word addr,
1289			  struct termio *host,
1290			  cpu *processor,
1291			  unsigned_word cia)
1292{
1293  struct solaris_termio target;
1294  int i;
1295
1296  target.c_iflag = H2T_2 (host->c_iflag);
1297  target.c_oflag = H2T_2 (host->c_oflag);
1298  target.c_cflag = H2T_2 (host->c_cflag);
1299  target.c_lflag = H2T_2 (host->c_lflag);
1300
1301#if defined(HAVE_TERMIO_CLINE) || defined(HAVE_TERMIOS_CLINE)
1302  target.c_line  = host->c_line;
1303#else
1304  target.c_line  = 0;
1305#endif
1306
1307  for (i = 0; i < SOLARIS_NCC; i++)
1308    target.c_cc[i] = 0;
1309
1310#ifdef VINTR
1311  target.c_cc[SOLARIS_VINTR] = host->c_cc[VINTR];
1312#endif
1313
1314#ifdef VQUIT
1315  target.c_cc[SOLARIS_VQUIT] = host->c_cc[VQUIT];
1316#endif
1317
1318#ifdef VERASE
1319  target.c_cc[SOLARIS_VERASE] = host->c_cc[VERASE];
1320#endif
1321
1322#ifdef VKILL
1323  target.c_cc[SOLARIS_VKILL] = host->c_cc[VKILL];
1324#endif
1325
1326#ifdef VEOF
1327  target.c_cc[SOLARIS_VEOF] = host->c_cc[VEOF];
1328#endif
1329
1330#ifdef VEOL
1331  target.c_cc[SOLARIS_VEOL] = host->c_cc[VEOL];
1332#endif
1333
1334#ifdef VEOL2
1335  target.c_cc[SOLARIS_VEOL2] = host->c_cc[VEOL2];
1336#endif
1337
1338#ifdef VSWTCH
1339  target.c_cc[SOLARIS_VSWTCH] = host->c_cc[VSWTCH];
1340
1341#else
1342#ifdef VSWTC
1343  target.c_cc[SOLARIS_VSWTCH] = host->c_cc[VSWTC];
1344#endif
1345#endif
1346
1347  emul_write_buffer(&target, addr, sizeof(target), processor, cia);
1348}
1349#endif /* HAVE_TERMIO_STRUCTURE || HAVE_TERMIOS_STRUCTURE */
1350
1351#ifdef HAVE_TERMIOS_STRUCTURE
1352/* Convert to/from host termios structure */
1353
1354typedef unsigned32 solaris_tcflag_t;
1355typedef unsigned8  solaris_cc_t;
1356typedef unsigned32 solaris_speed_t;
1357
1358struct solaris_termios {
1359  solaris_tcflag_t	c_iflag;
1360  solaris_tcflag_t	c_oflag;
1361  solaris_tcflag_t	c_cflag;
1362  solaris_tcflag_t	c_lflag;
1363  solaris_cc_t		c_cc[SOLARIS_NCCS];
1364};
1365
1366STATIC_INLINE_EMUL_UNIX void
1367convert_to_solaris_termios(unsigned_word addr,
1368			   struct termios *host,
1369			   cpu *processor,
1370			   unsigned_word cia)
1371{
1372  struct solaris_termios target;
1373  int i;
1374
1375  target.c_iflag = H2T_4 (host->c_iflag);
1376  target.c_oflag = H2T_4 (host->c_oflag);
1377  target.c_cflag = H2T_4 (host->c_cflag);
1378  target.c_lflag = H2T_4 (host->c_lflag);
1379
1380  for (i = 0; i < SOLARIS_NCCS; i++)
1381    target.c_cc[i] = 0;
1382
1383#ifdef VINTR
1384  target.c_cc[SOLARIS_VINTR] = host->c_cc[VINTR];
1385#endif
1386
1387#ifdef VQUIT
1388  target.c_cc[SOLARIS_VQUIT] = host->c_cc[VQUIT];
1389#endif
1390
1391#ifdef VERASE
1392  target.c_cc[SOLARIS_VERASE] = host->c_cc[VERASE];
1393#endif
1394
1395#ifdef VKILL
1396  target.c_cc[SOLARIS_VKILL] = host->c_cc[VKILL];
1397#endif
1398
1399#ifdef VEOF
1400  target.c_cc[SOLARIS_VEOF] = host->c_cc[VEOF];
1401#endif
1402
1403#ifdef VEOL
1404  target.c_cc[SOLARIS_VEOL] = host->c_cc[VEOL];
1405#endif
1406
1407#ifdef VEOL2
1408  target.c_cc[SOLARIS_VEOL2] = host->c_cc[VEOL2];
1409#endif
1410
1411#ifdef VSWTCH
1412  target.c_cc[SOLARIS_VSWTCH] = host->c_cc[VSWTCH];
1413
1414#else
1415#ifdef VSWTC
1416  target.c_cc[SOLARIS_VSWTCH] = host->c_cc[VSWTC];
1417#endif
1418#endif
1419
1420#ifdef VSTART
1421  target.c_cc[SOLARIS_VSTART] = host->c_cc[VSTART];
1422#endif
1423
1424#ifdef VSTOP
1425  target.c_cc[SOLARIS_VSTOP] = host->c_cc[VSTOP];
1426#endif
1427
1428#ifdef VSUSP
1429  target.c_cc[SOLARIS_VSUSP] = host->c_cc[VSUSP];
1430#endif
1431
1432#ifdef VDSUSP
1433  target.c_cc[SOLARIS_VDSUSP] = host->c_cc[VDSUSP];
1434#endif
1435
1436#ifdef VREPRINT
1437  target.c_cc[SOLARIS_VREPRINT] = host->c_cc[VREPRINT];
1438#endif
1439
1440#ifdef VDISCARD
1441  target.c_cc[SOLARIS_VDISCARD] = host->c_cc[VDISCARD];
1442#endif
1443
1444#ifdef VWERASE
1445  target.c_cc[SOLARIS_VWERASE] = host->c_cc[VWERASE];
1446#endif
1447
1448#ifdef VLNEXT
1449  target.c_cc[SOLARIS_VLNEXT] = host->c_cc[VLNEXT];
1450#endif
1451
1452  emul_write_buffer(&target, addr, sizeof(target), processor, cia);
1453}
1454#endif /* HAVE_TERMIOS_STRUCTURE */
1455
1456#ifndef HAVE_IOCTL
1457#define do_solaris_ioctl 0
1458#else
1459static void
1460do_solaris_ioctl(os_emul_data *emul,
1461		 unsigned call,
1462		 const int arg0,
1463		 cpu *processor,
1464		 unsigned_word cia)
1465{
1466  int fildes = cpu_registers(processor)->gpr[arg0];
1467  unsigned request = cpu_registers(processor)->gpr[arg0+1];
1468  unsigned_word argp_addr = cpu_registers(processor)->gpr[arg0+2];
1469  int status = 0;
1470  const char *name = "<unknown>";
1471
1472#ifdef HAVE_TERMIOS_STRUCTURE
1473  struct termios host_termio;
1474
1475#else
1476#ifdef HAVE_TERMIO_STRUCTURE
1477  struct termio host_termio;
1478#endif
1479#endif
1480
1481  status = fdbad (fildes);
1482  if (status != 0)
1483    goto done;
1484
1485  switch (request)
1486    {
1487    case 0:					/* make sure we have at least one case */
1488    default:
1489      status = -1;
1490      errno = EINVAL;
1491      break;
1492
1493#if defined(HAVE_TERMIO_STRUCTURE) || defined(HAVE_TERMIOS_STRUCTURE)
1494#if defined(TCGETA) || defined(TCGETS) || defined(HAVE_TCGETATTR)
1495    case SOLARIS_TIOC | 1:			/* TCGETA */
1496      name = "TCGETA";
1497#ifdef HAVE_TCGETATTR
1498      status = tcgetattr(fildes, &host_termio);
1499#elif defined(TCGETS)
1500      status = ioctl (fildes, TCGETS, &host_termio);
1501#else
1502      status = ioctl (fildes, TCGETA, &host_termio);
1503#endif
1504      if (status == 0)
1505	convert_to_solaris_termio (argp_addr, &host_termio, processor, cia);
1506      break;
1507#endif /* TCGETA */
1508#endif /* HAVE_TERMIO_STRUCTURE */
1509
1510#ifdef HAVE_TERMIOS_STRUCTURE
1511#if defined(TCGETS) || defined(HAVE_TCGETATTR)
1512    case SOLARIS_TIOC | 13:			/* TCGETS */
1513      name = "TCGETS";
1514#ifdef HAVE_TCGETATTR
1515      status = tcgetattr(fildes, &host_termio);
1516#else
1517      status = ioctl (fildes, TCGETS, &host_termio);
1518#endif
1519      if (status == 0)
1520	convert_to_solaris_termios (argp_addr, &host_termio, processor, cia);
1521      break;
1522#endif /* TCGETS */
1523#endif /* HAVE_TERMIOS_STRUCTURE */
1524    }
1525
1526done:
1527  emul_write_status(processor, status, errno);
1528
1529  if (WITH_TRACE && ppc_trace[trace_os_emul])
1530    printf_filtered ("%d, 0x%x [%s], 0x%lx", fildes, request, name, (long)argp_addr);
1531}
1532#endif /* HAVE_IOCTL */
1533
1534static emul_syscall_descriptor solaris_descriptors[] = {
1535  /*   0 */ { 0, "syscall" },
1536  /*   1 */ { do_unix_exit, "exit" },
1537  /*   2 */ { 0, "fork" },
1538  /*   3 */ { do_unix_read, "read" },
1539  /*   4 */ { do_unix_write, "write" },
1540  /*   5 */ { do_unix_open, "open" },
1541  /*   6 */ { do_unix_close, "close" },
1542  /*   7 */ { 0, "wait" },
1543  /*   8 */ { 0, "creat" },
1544  /*   9 */ { do_unix_link, "link" },
1545  /*  10 */ { do_unix_unlink, "unlink" },
1546  /*  11 */ { 0, "exec" },
1547  /*  12 */ { do_unix_chdir, "chdir" },
1548  /*  13 */ { do_unix_time, "time" },
1549  /*  14 */ { 0, "mknod" },
1550  /*  15 */ { 0, "chmod" },
1551  /*  16 */ { 0, "chown" },
1552  /*  17 */ { do_unix_break, "brk" },
1553  /*  18 */ { do_solaris_stat, "stat" },
1554  /*  19 */ { do_unix_lseek, "lseek" },
1555  /*  20 */ { do_unix_getpid2, "getpid" },
1556  /*  21 */ { 0, "mount" },
1557  /*  22 */ { 0, "umount" },
1558  /*  23 */ { 0, "setuid" },
1559  /*  24 */ { do_unix_getuid2, "getuid" },
1560  /*  25 */ { 0, "stime" },
1561  /*  26 */ { 0, "ptrace" },
1562  /*  27 */ { 0, "alarm" },
1563  /*  28 */ { do_solaris_fstat, "fstat" },
1564  /*  29 */ { 0, "pause" },
1565  /*  30 */ { 0, "utime" },
1566  /*  31 */ { 0, "stty" },
1567  /*  32 */ { 0, "gtty" },
1568  /*  33 */ { do_unix_access, "access" },
1569  /*  34 */ { 0, "nice" },
1570  /*  35 */ { 0, "statfs" },
1571  /*  36 */ { 0, "sync" },
1572  /*  37 */ { 0, "kill" },
1573  /*  38 */ { 0, "fstatfs" },
1574  /*  39 */ { 0, "pgrpsys" },
1575  /*  40 */ { 0, "xenix" },
1576  /*  41 */ { do_unix_dup, "dup" },
1577  /*  42 */ { 0, "pipe" },
1578  /*  43 */ { 0, "times" },
1579  /*  44 */ { 0, "profil" },
1580  /*  45 */ { 0, "plock" },
1581  /*  46 */ { 0, "setgid" },
1582  /*  47 */ { do_unix_getgid2, "getgid" },
1583  /*  48 */ { 0, "signal" },
1584  /*  49 */ { 0, "msgsys" },
1585  /*  50 */ { 0, "syssun" },
1586  /*  51 */ { 0, "acct" },
1587  /*  52 */ { 0, "shmsys" },
1588  /*  53 */ { 0, "semsys" },
1589  /*  54 */ { do_solaris_ioctl, "ioctl" },
1590  /*  55 */ { 0, "uadmin" },
1591  /*  56 */ { 0, 0 /* reserved for exch */ },
1592  /*  57 */ { 0, "utssys" },
1593  /*  58 */ { 0, "fdsync" },
1594  /*  59 */ { 0, "execve" },
1595  /*  60 */ { do_unix_umask, "umask" },
1596  /*  61 */ { 0, "chroot" },
1597  /*  62 */ { 0, "fcntl" },
1598  /*  63 */ { 0, "ulimit" },
1599  /*  64 */ { 0, 0 /* reserved for UNIX PC */ },
1600  /*  64 */ { 0, 0 /* reserved for UNIX PC */ },
1601  /*  65 */ { 0, 0 /* reserved for UNIX PC */ },
1602  /*  66 */ { 0, 0 /* reserved for UNIX PC */ },
1603  /*  67 */ { 0, 0 /* reserved for UNIX PC */ },
1604  /*  68 */ { 0, 0 /* reserved for UNIX PC */ },
1605  /*  69 */ { 0, 0 /* reserved for UNIX PC */ },
1606  /*  70 */ { 0, 0 /* was advfs */ },
1607  /*  71 */ { 0, 0 /* was unadvfs */ },
1608  /*  72 */ { 0, 0 /* was rmount */ },
1609  /*  73 */ { 0, 0 /* was rumount */ },
1610  /*  74 */ { 0, 0 /* was rfstart */ },
1611  /*  75 */ { 0, 0 /* was sigret */ },
1612  /*  76 */ { 0, 0 /* was rdebug */ },
1613  /*  77 */ { 0, 0 /* was rfstop */ },
1614  /*  78 */ { 0, 0 /* was rfsys */ },
1615  /*  79 */ { do_unix_rmdir, "rmdir" },
1616  /*  80 */ { do_unix_mkdir, "mkdir" },
1617  /*  81 */ { 0, "getdents" },
1618  /*  82 */ { 0, 0 /* was libattach */ },
1619  /*  83 */ { 0, 0 /* was libdetach */ },
1620  /*  84 */ { 0, "sysfs" },
1621  /*  85 */ { 0, "getmsg" },
1622  /*  86 */ { 0, "putmsg" },
1623  /*  87 */ { 0, "poll" },
1624  /*  88 */ { do_solaris_lstat, "lstat" },
1625  /*  89 */ { do_unix_symlink, "symlink" },
1626  /*  90 */ { 0, "readlink" },
1627  /*  91 */ { 0, "setgroups" },
1628  /*  92 */ { 0, "getgroups" },
1629  /*  93 */ { 0, "fchmod" },
1630  /*  94 */ { 0, "fchown" },
1631  /*  95 */ { 0, "sigprocmask" },
1632  /*  96 */ { 0, "sigsuspend" },
1633  /*  97 */ { do_unix_nop, "sigaltstack" },
1634  /*  98 */ { do_unix_nop, "sigaction" },
1635  /*  99 */ { 0, "sigpending" },
1636  /* 100 */ { 0, "context" },
1637  /* 101 */ { 0, "evsys" },
1638  /* 102 */ { 0, "evtrapret" },
1639  /* 103 */ { 0, "statvfs" },
1640  /* 104 */ { 0, "fstatvfs" },
1641  /* 105 */ { 0, 0 /* reserved */ },
1642  /* 106 */ { 0, "nfssys" },
1643  /* 107 */ { 0, "waitsys" },
1644  /* 108 */ { 0, "sigsendsys" },
1645  /* 109 */ { 0, "hrtsys" },
1646  /* 110 */ { 0, "acancel" },
1647  /* 111 */ { 0, "async" },
1648  /* 112 */ { 0, "priocntlsys" },
1649  /* 113 */ { 0, "pathconf" },
1650  /* 114 */ { 0, "mincore" },
1651  /* 115 */ { 0, "mmap" },
1652  /* 116 */ { 0, "mprotect" },
1653  /* 117 */ { 0, "munmap" },
1654  /* 118 */ { 0, "fpathconf" },
1655  /* 119 */ { 0, "vfork" },
1656  /* 120 */ { 0, "fchdir" },
1657  /* 121 */ { 0, "readv" },
1658  /* 122 */ { 0, "writev" },
1659  /* 123 */ { 0, "xstat" },
1660  /* 124 */ { 0, "lxstat" },
1661  /* 125 */ { 0, "fxstat" },
1662  /* 126 */ { 0, "xmknod" },
1663  /* 127 */ { 0, "clocal" },
1664  /* 128 */ { 0, "setrlimit" },
1665  /* 129 */ { 0, "getrlimit" },
1666  /* 130 */ { 0, "lchown" },
1667  /* 131 */ { 0, "memcntl" },
1668  /* 132 */ { 0, "getpmsg" },
1669  /* 133 */ { 0, "putpmsg" },
1670  /* 134 */ { 0, "rename" },
1671  /* 135 */ { 0, "uname" },
1672  /* 136 */ { 0, "setegid" },
1673  /* 137 */ { 0, "sysconfig" },
1674  /* 138 */ { 0, "adjtime" },
1675  /* 139 */ { 0, "systeminfo" },
1676  /* 140 */ { 0, 0 /* reserved */ },
1677  /* 141 */ { 0, "seteuid" },
1678  /* 142 */ { 0, "vtrace" },
1679  /* 143 */ { 0, "fork1" },
1680  /* 144 */ { 0, "sigtimedwait" },
1681  /* 145 */ { 0, "lwp_info" },
1682  /* 146 */ { 0, "yield" },
1683  /* 147 */ { 0, "lwp_sema_wait" },
1684  /* 148 */ { 0, "lwp_sema_post" },
1685  /* 149 */ { 0, 0 /* reserved */ },
1686  /* 150 */ { 0, 0 /* reserved */ },
1687  /* 151 */ { 0, 0 /* reserved */ },
1688  /* 152 */ { 0, "modctl" },
1689  /* 153 */ { 0, "fchroot" },
1690  /* 154 */ { 0, "utimes" },
1691  /* 155 */ { 0, "vhangup" },
1692  /* 156 */ { do_unix_gettimeofday, "gettimeofday" },
1693  /* 157 */ { 0, "getitimer" },
1694  /* 158 */ { 0, "setitimer" },
1695  /* 159 */ { 0, "lwp_create" },
1696  /* 160 */ { 0, "lwp_exit" },
1697  /* 161 */ { 0, "lwp_suspend" },
1698  /* 162 */ { 0, "lwp_continue" },
1699  /* 163 */ { 0, "lwp_kill" },
1700  /* 164 */ { 0, "lwp_self" },
1701  /* 165 */ { 0, "lwp_setprivate" },
1702  /* 166 */ { 0, "lwp_getprivate" },
1703  /* 167 */ { 0, "lwp_wait" },
1704  /* 168 */ { 0, "lwp_mutex_unlock" },
1705  /* 169 */ { 0, "lwp_mutex_lock" },
1706  /* 170 */ { 0, "lwp_cond_wait" },
1707  /* 171 */ { 0, "lwp_cond_signal" },
1708  /* 172 */ { 0, "lwp_cond_broadcast" },
1709  /* 173 */ { 0, "pread" },
1710  /* 174 */ { 0, "pwrite" },
1711  /* 175 */ { 0, "llseek" },
1712  /* 176 */ { 0, "inst_sync" },
1713  /* 177 */ { 0, 0 /* reserved */ },
1714  /* 178 */ { 0, "kaio" },
1715  /* 179 */ { 0, 0 /* reserved */ },
1716  /* 180 */ { 0, 0 /* reserved */ },
1717  /* 181 */ { 0, 0 /* reserved */ },
1718  /* 182 */ { 0, 0 /* reserved */ },
1719  /* 183 */ { 0, 0 /* reserved */ },
1720  /* 184 */ { 0, "tsolsys" },
1721  /* 185 */ { 0, "acl" },
1722  /* 186 */ { 0, "auditsys" },
1723  /* 187 */ { 0, "processor_bind" },
1724  /* 188 */ { 0, "processor_info" },
1725  /* 189 */ { 0, "p_online" },
1726  /* 190 */ { 0, "sigqueue" },
1727  /* 191 */ { 0, "clock_gettime" },
1728  /* 192 */ { 0, "clock_settime" },
1729  /* 193 */ { 0, "clock_getres" },
1730  /* 194 */ { 0, "timer_create" },
1731  /* 195 */ { 0, "timer_delete" },
1732  /* 196 */ { 0, "timer_settime" },
1733  /* 197 */ { 0, "timer_gettime" },
1734  /* 198 */ { 0, "timer_getoverrun" },
1735  /* 199 */ { 0, "nanosleep" },
1736  /* 200 */ { 0, "facl" },
1737  /* 201 */ { 0, "door" },
1738  /* 202 */ { 0, "setreuid" },
1739  /* 203 */ { 0, "setregid" },
1740  /* 204 */ { 0, "install_utrap" },
1741  /* 205 */ { 0, 0 /* reserved */ },
1742  /* 206 */ { 0, 0 /* reserved */ },
1743  /* 207 */ { 0, 0 /* reserved */ },
1744  /* 208 */ { 0, 0 /* reserved */ },
1745  /* 209 */ { 0, 0 /* reserved */ },
1746  /* 210 */ { 0, "signotifywait" },
1747  /* 211 */ { 0, "lwp_sigredirect" },
1748  /* 212 */ { 0, "lwp_alarm" },
1749};
1750
1751static char *(solaris_error_names[]) = {
1752  /*   0 */ "ESUCCESS",
1753  /*   1 */ "EPERM",
1754  /*   2 */ "ENOENT",
1755  /*   3 */ "ESRCH",
1756  /*   4 */ "EINTR",
1757  /*   5 */ "EIO",
1758  /*   6 */ "ENXIO",
1759  /*   7 */ "E2BIG",
1760  /*   8 */ "ENOEXEC",
1761  /*   9 */ "EBADF",
1762  /*  10 */ "ECHILD",
1763  /*  11 */ "EAGAIN",
1764  /*  12 */ "ENOMEM",
1765  /*  13 */ "EACCES",
1766  /*  14 */ "EFAULT",
1767  /*  15 */ "ENOTBLK",
1768  /*  16 */ "EBUSY",
1769  /*  17 */ "EEXIST",
1770  /*  18 */ "EXDEV",
1771  /*  19 */ "ENODEV",
1772  /*  20 */ "ENOTDIR",
1773  /*  21 */ "EISDIR",
1774  /*  22 */ "EINVAL",
1775  /*  23 */ "ENFILE",
1776  /*  24 */ "EMFILE",
1777  /*  25 */ "ENOTTY",
1778  /*  26 */ "ETXTBSY",
1779  /*  27 */ "EFBIG",
1780  /*  28 */ "ENOSPC",
1781  /*  29 */ "ESPIPE",
1782  /*  30 */ "EROFS",
1783  /*  31 */ "EMLINK",
1784  /*  32 */ "EPIPE",
1785  /*  33 */ "EDOM",
1786  /*  34 */ "ERANGE",
1787  /*  35 */ "ENOMSG",
1788  /*  36 */ "EIDRM",
1789  /*  37 */ "ECHRNG",
1790  /*  38 */ "EL2NSYNC",
1791  /*  39 */ "EL3HLT",
1792  /*  40 */ "EL3RST",
1793  /*  41 */ "ELNRNG",
1794  /*  42 */ "EUNATCH",
1795  /*  43 */ "ENOCSI",
1796  /*  44 */ "EL2HLT",
1797  /*  45 */ "EDEADLK",
1798  /*  46 */ "ENOLCK",
1799  /*  47 */ "ECANCELED",
1800  /*  48 */ "ENOTSUP",
1801  /*  49 */ "EDQUOT",
1802  /*  50 */ "EBADE",
1803  /*  51 */ "EBADR",
1804  /*  52 */ "EXFULL",
1805  /*  53 */ "ENOANO",
1806  /*  54 */ "EBADRQC",
1807  /*  55 */ "EBADSLT",
1808  /*  56 */ "EDEADLOCK",
1809  /*  57 */ "EBFONT",
1810  /*  58 */ "Error code 58",
1811  /*  59 */ "Error code 59",
1812  /*  60 */ "ENOSTR",
1813  /*  61 */ "ENODATA",
1814  /*  62 */ "ETIME",
1815  /*  63 */ "ENOSR",
1816  /*  64 */ "ENONET",
1817  /*  65 */ "ENOPKG",
1818  /*  66 */ "EREMOTE",
1819  /*  67 */ "ENOLINK",
1820  /*  68 */ "EADV",
1821  /*  69 */ "ESRMNT",
1822  /*  70 */ "ECOMM",
1823  /*  71 */ "EPROTO",
1824  /*  72 */ "Error code 72",
1825  /*  73 */ "Error code 73",
1826  /*  74 */ "EMULTIHOP",
1827  /*  75 */ "Error code 75",
1828  /*  76 */ "Error code 76",
1829  /*  77 */ "EBADMSG",
1830  /*  78 */ "ENAMETOOLONG",
1831  /*  79 */ "EOVERFLOW",
1832  /*  80 */ "ENOTUNIQ",
1833  /*  81 */ "EBADFD",
1834  /*  82 */ "EREMCHG",
1835  /*  83 */ "ELIBACC",
1836  /*  84 */ "ELIBBAD",
1837  /*  85 */ "ELIBSCN",
1838  /*  86 */ "ELIBMAX",
1839  /*  87 */ "ELIBEXEC",
1840  /*  88 */ "EILSEQ",
1841  /*  89 */ "ENOSYS",
1842  /*  90 */ "ELOOP",
1843  /*  91 */ "ERESTART",
1844  /*  92 */ "ESTRPIPE",
1845  /*  93 */ "ENOTEMPTY",
1846  /*  94 */ "EUSERS",
1847  /*  95 */ "ENOTSOCK",
1848  /*  96 */ "EDESTADDRREQ",
1849  /*  97 */ "EMSGSIZE",
1850  /*  98 */ "EPROTOTYPE",
1851  /*  99 */ "ENOPROTOOPT",
1852  /* 100 */ "Error code 100",
1853  /* 101 */ "Error code 101",
1854  /* 102 */ "Error code 102",
1855  /* 103 */ "Error code 103",
1856  /* 104 */ "Error code 104",
1857  /* 105 */ "Error code 105",
1858  /* 106 */ "Error code 106",
1859  /* 107 */ "Error code 107",
1860  /* 108 */ "Error code 108",
1861  /* 109 */ "Error code 109",
1862  /* 110 */ "Error code 110",
1863  /* 111 */ "Error code 111",
1864  /* 112 */ "Error code 112",
1865  /* 113 */ "Error code 113",
1866  /* 114 */ "Error code 114",
1867  /* 115 */ "Error code 115",
1868  /* 116 */ "Error code 116",
1869  /* 117 */ "Error code 117",
1870  /* 118 */ "Error code 118",
1871  /* 119 */ "Error code 119",
1872  /* 120 */ "EPROTONOSUPPORT",
1873  /* 121 */ "ESOCKTNOSUPPORT",
1874  /* 122 */ "EOPNOTSUPP",
1875  /* 123 */ "EPFNOSUPPORT",
1876  /* 124 */ "EAFNOSUPPORT",
1877  /* 125 */ "EADDRINUSE",
1878  /* 126 */ "EADDRNOTAVAIL",
1879  /* 127 */ "ENETDOWN",
1880  /* 128 */ "ENETUNREACH",
1881  /* 129 */ "ENETRESET",
1882  /* 130 */ "ECONNABORTED",
1883  /* 131 */ "ECONNRESET",
1884  /* 132 */ "ENOBUFS",
1885  /* 133 */ "EISCONN",
1886  /* 134 */ "ENOTCONN",
1887  /* 135 */ "Error code 135",	/* XENIX has 135 - 142 */
1888  /* 136 */ "Error code 136",
1889  /* 137 */ "Error code 137",
1890  /* 138 */ "Error code 138",
1891  /* 139 */ "Error code 139",
1892  /* 140 */ "Error code 140",
1893  /* 141 */ "Error code 141",
1894  /* 142 */ "Error code 142",
1895  /* 143 */ "ESHUTDOWN",
1896  /* 144 */ "ETOOMANYREFS",
1897  /* 145 */ "ETIMEDOUT",
1898  /* 146 */ "ECONNREFUSED",
1899  /* 147 */ "EHOSTDOWN",
1900  /* 148 */ "EHOSTUNREACH",
1901  /* 149 */ "EALREADY",
1902  /* 150 */ "EINPROGRESS",
1903  /* 151 */ "ESTALE",
1904};
1905
1906static char *(solaris_signal_names[]) = {
1907  /*  0 */ 0,
1908  /*  1 */ "SIGHUP",
1909  /*  2 */ "SIGINT",
1910  /*  3 */ "SIGQUIT",
1911  /*  4 */ "SIGILL",
1912  /*  5 */ "SIGTRAP",
1913  /*  6 */ "SIGABRT",
1914  /*  7 */ "SIGEMT",
1915  /*  8 */ "SIGFPE",
1916  /*  9 */ "SIGKILL",
1917  /* 10 */ "SIGBUS",
1918  /* 11 */ "SIGSEGV",
1919  /* 12 */ "SIGSYS",
1920  /* 13 */ "SIGPIPE",
1921  /* 14 */ "SIGALRM",
1922  /* 15 */ "SIGTERM",
1923  /* 16 */ "SIGUSR1",
1924  /* 17 */ "SIGUSR2",
1925  /* 18 */ "SIGCHLD",
1926  /* 19 */ "SIGPWR",
1927  /* 20 */ "SIGWINCH",
1928  /* 21 */ "SIGURG",
1929  /* 22 */ "SIGPOLL",
1930  /* 23 */ "SIGSTOP",
1931  /* 24 */ "SIGTSTP",
1932  /* 25 */ "SIGCONT",
1933  /* 26 */ "SIGTTIN",
1934  /* 27 */ "SIGTTOU",
1935  /* 28 */ "SIGVTALRM",
1936  /* 29 */ "SIGPROF",
1937  /* 30 */ "SIGXCPU",
1938  /* 31 */ "SIGXFSZ",
1939  /* 32 */ "SIGWAITING",
1940  /* 33 */ "SIGLWP",
1941  /* 34 */ "SIGFREEZE",
1942  /* 35 */ "SIGTHAW",
1943  /* 36 */ "SIGCANCEL",
1944};
1945
1946static emul_syscall emul_solaris_syscalls = {
1947  solaris_descriptors,
1948  ARRAY_SIZE (solaris_descriptors),
1949  solaris_error_names,
1950  ARRAY_SIZE (solaris_error_names),
1951  solaris_signal_names,
1952  ARRAY_SIZE (solaris_signal_names),
1953};
1954
1955
1956/* Solaris's os_emul interface, most are just passed on to the generic
1957   syscall stuff */
1958
1959static os_emul_data *
1960emul_solaris_create(device *root,
1961		    bfd *image,
1962		    const char *name)
1963{
1964  /* check that this emulation is really for us */
1965  if (name != NULL && strcmp(name, "solaris") != 0)
1966    return NULL;
1967
1968  if (image == NULL)
1969    return NULL;
1970
1971  return emul_unix_create(root, image, "solaris", &emul_solaris_syscalls);
1972}
1973
1974static void
1975emul_solaris_init(os_emul_data *emul_data,
1976		  int nr_cpus)
1977{
1978  fd_closed[0] = 0;
1979  fd_closed[1] = 0;
1980  fd_closed[2] = 0;
1981}
1982
1983static void
1984emul_solaris_system_call(cpu *processor,
1985			 unsigned_word cia,
1986			 os_emul_data *emul_data)
1987{
1988  emul_do_system_call(emul_data,
1989		      emul_data->syscalls,
1990		      cpu_registers(processor)->gpr[0],
1991		      3, /*r3 contains arg0*/
1992		      processor,
1993		      cia);
1994}
1995
1996const os_emul emul_solaris = {
1997  "solaris",
1998  emul_solaris_create,
1999  emul_solaris_init,
2000  emul_solaris_system_call,
2001  0, /*instruction_call*/
2002  0  /*data*/
2003};
2004
2005
2006/* EMULATION
2007
2008   Linux - Emulation of user programs for Linux/PPC
2009
2010   DESCRIPTION
2011
2012   */
2013
2014
2015/* Linux specific implementation */
2016
2017typedef unsigned32	linux_dev_t;
2018typedef unsigned32	linux_ino_t;
2019typedef unsigned32	linux_mode_t;
2020typedef unsigned16	linux_nlink_t;
2021typedef signed32	linux_off_t;
2022typedef signed32	linux_pid_t;
2023typedef unsigned32	linux_uid_t;
2024typedef unsigned32	linux_gid_t;
2025typedef unsigned32	linux_size_t;
2026typedef signed32	linux_ssize_t;
2027typedef signed32	linux_ptrdiff_t;
2028typedef signed32	linux_time_t;
2029typedef signed32	linux_clock_t;
2030typedef signed32	linux_daddr_t;
2031
2032#ifdef HAVE_SYS_STAT_H
2033/* For the PowerPC, don't both with the 'old' stat structure, since there
2034   should be no extant binaries with that structure.  */
2035
2036struct linux_stat {
2037	linux_dev_t	st_dev;
2038	linux_ino_t	st_ino;
2039	linux_mode_t	st_mode;
2040	linux_nlink_t	st_nlink;
2041	linux_uid_t 	st_uid;
2042	linux_gid_t 	st_gid;
2043	linux_dev_t	st_rdev;
2044	linux_off_t	st_size;
2045	unsigned32  	st_blksize;
2046	unsigned32  	st_blocks;
2047	unsigned32  	st_atimx;	/* don't use st_{a,c,m}time, that might a macro */
2048	unsigned32  	__unused1;	/* defined by the host's stat.h */
2049	unsigned32  	st_mtimx;
2050	unsigned32  	__unused2;
2051	unsigned32  	st_ctimx;
2052	unsigned32  	__unused3;
2053	unsigned32  	__unused4;
2054	unsigned32  	__unused5;
2055};
2056
2057/* Convert from host stat structure to solaris stat structure */
2058STATIC_INLINE_EMUL_UNIX void
2059convert_to_linux_stat(unsigned_word addr,
2060		      struct stat *host,
2061		      cpu *processor,
2062		      unsigned_word cia)
2063{
2064  struct linux_stat target;
2065
2066  target.st_dev   = H2T_4(host->st_dev);
2067  target.st_ino   = H2T_4(host->st_ino);
2068  target.st_mode  = H2T_4(host->st_mode);
2069  target.st_nlink = H2T_2(host->st_nlink);
2070  target.st_uid   = H2T_4(host->st_uid);
2071  target.st_gid   = H2T_4(host->st_gid);
2072  target.st_size  = H2T_4(host->st_size);
2073
2074#ifdef HAVE_ST_RDEV
2075  target.st_rdev  = H2T_4(host->st_rdev);
2076#else
2077  target.st_rdev  = 0;
2078#endif
2079
2080#ifdef HAVE_ST_BLKSIZE
2081  target.st_blksize = H2T_4(host->st_blksize);
2082#else
2083  target.st_blksize = 0;
2084#endif
2085
2086#ifdef HAVE_ST_BLOCKS
2087  target.st_blocks  = H2T_4(host->st_blocks);
2088#else
2089  target.st_blocks  = 0;
2090#endif
2091
2092  target.st_atimx   = H2T_4(host->st_atime);
2093  target.st_ctimx   = H2T_4(host->st_ctime);
2094  target.st_mtimx   = H2T_4(host->st_mtime);
2095  target.__unused1  = 0;
2096  target.__unused2  = 0;
2097  target.__unused3  = 0;
2098  target.__unused4  = 0;
2099  target.__unused5  = 0;
2100
2101  emul_write_buffer(&target, addr, sizeof(target), processor, cia);
2102}
2103#endif /* HAVE_SYS_STAT_H */
2104
2105#ifndef HAVE_STAT
2106#define do_linux_stat 0
2107#else
2108static void
2109do_linux_stat(os_emul_data *emul,
2110	      unsigned call,
2111	      const int arg0,
2112	      cpu *processor,
2113	      unsigned_word cia)
2114{
2115  unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
2116  unsigned_word stat_pkt = cpu_registers(processor)->gpr[arg0+1];
2117  char path_buf[PATH_MAX];
2118  struct stat buf;
2119  char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
2120  int status;
2121
2122  if (WITH_TRACE && ppc_trace[trace_os_emul])
2123    printf_filtered ("0x%lx [%s], 0x%lx", (long)path_addr, path, (long)stat_pkt);
2124
2125  status = stat (path, &buf);
2126  if (status == 0)
2127    convert_to_linux_stat (stat_pkt, &buf, processor, cia);
2128
2129  emul_write_status(processor, status, errno);
2130}
2131#endif
2132
2133#ifndef HAVE_LSTAT
2134#define do_linux_lstat 0
2135#else
2136static void
2137do_linux_lstat(os_emul_data *emul,
2138	       unsigned call,
2139	       const int arg0,
2140	       cpu *processor,
2141	       unsigned_word cia)
2142{
2143  unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
2144  unsigned_word stat_pkt = cpu_registers(processor)->gpr[arg0+1];
2145  char path_buf[PATH_MAX];
2146  struct stat buf;
2147  char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
2148  int status;
2149
2150  if (WITH_TRACE && ppc_trace[trace_os_emul])
2151    printf_filtered ("0x%lx [%s], 0x%lx", (long)path_addr, path, (long)stat_pkt);
2152
2153  status = lstat (path, &buf);
2154  if (status == 0)
2155    convert_to_linux_stat (stat_pkt, &buf, processor, cia);
2156
2157  emul_write_status(processor, status, errno);
2158}
2159#endif
2160
2161#ifndef HAVE_FSTAT
2162#define do_linux_fstat 0
2163#else
2164static void
2165do_linux_fstat(os_emul_data *emul,
2166	       unsigned call,
2167	       const int arg0,
2168	       cpu *processor,
2169	       unsigned_word cia)
2170{
2171  int fildes = (int)cpu_registers(processor)->gpr[arg0];
2172  unsigned_word stat_pkt = cpu_registers(processor)->gpr[arg0+1];
2173  struct stat buf;
2174  int status;
2175
2176  if (WITH_TRACE && ppc_trace[trace_os_emul])
2177    printf_filtered ("%d, 0x%lx", fildes, (long)stat_pkt);
2178
2179  status = fdbad (fildes);
2180  if (status == 0)
2181    status = fstat (fildes, &buf);
2182  if (status == 0)
2183    convert_to_linux_stat (stat_pkt, &buf, processor, cia);
2184
2185  emul_write_status(processor, status, errno);
2186}
2187#endif
2188
2189#if defined(HAVE_TERMIO_STRUCTURE) || defined(HAVE_TERMIOS_STRUCTURE)
2190#define LINUX_NCC		10
2191#define LINUX_NCCS		19
2192
2193#define	LINUX_VINTR		 0
2194#define	LINUX_VQUIT		 1
2195#define	LINUX_VERASE		 2
2196#define	LINUX_VKILL		 3
2197#define	LINUX_VEOF		 4
2198#define LINUX_VMIN		 5
2199#define	LINUX_VEOL		 6
2200#define	LINUX_VTIME		 7
2201#define LINUX_VEOL2		 8
2202#define LINUX_VSWTC		 9
2203#define LINUX_VWERASE 		10
2204#define LINUX_VREPRINT		11
2205#define LINUX_VSUSP 		12
2206#define LINUX_VSTART		13
2207#define LINUX_VSTOP		14
2208#define LINUX_VLNEXT		15
2209#define LINUX_VDISCARD		16
2210
2211#define LINUX_IOC_NRBITS	 8
2212#define LINUX_IOC_TYPEBITS	 8
2213#define LINUX_IOC_SIZEBITS	13
2214#define LINUX_IOC_DIRBITS	 3
2215
2216#define LINUX_IOC_NRMASK	((1 << LINUX_IOC_NRBITS)-1)
2217#define LINUX_IOC_TYPEMASK	((1 << LINUX_IOC_TYPEBITS)-1)
2218#define LINUX_IOC_SIZEMASK	((1 << LINUX_IOC_SIZEBITS)-1)
2219#define LINUX_IOC_DIRMASK	((1 << LINUX_IOC_DIRBITS)-1)
2220
2221#define LINUX_IOC_NRSHIFT	0
2222#define LINUX_IOC_TYPESHIFT	(LINUX_IOC_NRSHIFT+LINUX_IOC_NRBITS)
2223#define LINUX_IOC_SIZESHIFT	(LINUX_IOC_TYPESHIFT+LINUX_IOC_TYPEBITS)
2224#define LINUX_IOC_DIRSHIFT	(LINUX_IOC_SIZESHIFT+LINUX_IOC_SIZEBITS)
2225
2226/*
2227 * Direction bits _IOC_NONE could be 0, but OSF/1 gives it a bit.
2228 * And this turns out useful to catch old ioctl numbers in header
2229 * files for us.
2230 */
2231#define LINUX_IOC_NONE		1U
2232#define LINUX_IOC_READ		2U
2233#define LINUX_IOC_WRITE		4U
2234
2235#define LINUX_IOC(dir,type,nr,size) \
2236	(((dir)  << LINUX_IOC_DIRSHIFT) | \
2237	 ((type) << LINUX_IOC_TYPESHIFT) | \
2238	 ((nr)   << LINUX_IOC_NRSHIFT) | \
2239	 ((size) << LINUX_IOC_SIZESHIFT))
2240
2241/* used to create numbers */
2242#define LINUX_IO(type,nr)	 LINUX_IOC(LINUX_IOC_NONE,(type),(nr),0)
2243#define LINUX_IOR(type,nr,size)	 LINUX_IOC(LINUX_IOC_READ,(type),(nr),sizeof(size))
2244#define LINUX_IOW(type,nr,size)	 LINUX_IOC(LINUX_IOC_WRITE,(type),(nr),sizeof(size))
2245#define LINUX_IOWR(type,nr,size) LINUX_IOC(LINUX_IOC_READ|LINUX_IOC_WRITE,(type),(nr),sizeof(size))
2246#endif
2247
2248#if defined(HAVE_TERMIO_STRUCTURE) || defined(HAVE_TERMIOS_STRUCTURE)
2249/* Convert to/from host termio structure */
2250
2251struct linux_termio {
2252	unsigned16	c_iflag;		/* input modes */
2253	unsigned16	c_oflag;		/* output modes */
2254	unsigned16	c_cflag;		/* control modes */
2255	unsigned16	c_lflag;		/* line discipline modes */
2256	unsigned8	c_line;			/* line discipline */
2257	unsigned8	c_cc[LINUX_NCC];	/* control chars */
2258};
2259
2260STATIC_INLINE_EMUL_UNIX void
2261convert_to_linux_termio(unsigned_word addr,
2262			struct termio *host,
2263			cpu *processor,
2264			unsigned_word cia)
2265{
2266  struct linux_termio target;
2267  int i;
2268
2269  target.c_iflag = H2T_2 (host->c_iflag);
2270  target.c_oflag = H2T_2 (host->c_oflag);
2271  target.c_cflag = H2T_2 (host->c_cflag);
2272  target.c_lflag = H2T_2 (host->c_lflag);
2273
2274#if defined(HAVE_TERMIO_CLINE) || defined(HAVE_TERMIOS_CLINE)
2275  target.c_line  = host->c_line;
2276#else
2277  target.c_line  = 0;
2278#endif
2279
2280  for (i = 0; i < LINUX_NCC; i++)
2281    target.c_cc[i] = 0;
2282
2283#ifdef VINTR
2284  target.c_cc[LINUX_VINTR] = host->c_cc[VINTR];
2285#endif
2286
2287#ifdef VQUIT
2288  target.c_cc[LINUX_VQUIT] = host->c_cc[VQUIT];
2289#endif
2290
2291#ifdef VERASE
2292  target.c_cc[LINUX_VERASE] = host->c_cc[VERASE];
2293#endif
2294
2295#ifdef VKILL
2296  target.c_cc[LINUX_VKILL] = host->c_cc[VKILL];
2297#endif
2298
2299#ifdef VEOF
2300  target.c_cc[LINUX_VEOF] = host->c_cc[VEOF];
2301#endif
2302
2303#ifdef VMIN
2304  target.c_cc[LINUX_VMIN] = host->c_cc[VMIN];
2305#endif
2306
2307#ifdef VEOL
2308  target.c_cc[LINUX_VEOL] = host->c_cc[VEOL];
2309#endif
2310
2311#ifdef VTIME
2312  target.c_cc[LINUX_VTIME] = host->c_cc[VTIME];
2313#endif
2314
2315#ifdef VEOL2
2316  target.c_cc[LINUX_VEOL2] = host->c_cc[VEOL2];
2317#endif
2318
2319#ifdef VSWTC
2320  target.c_cc[LINUX_VSWTC] = host->c_cc[VSWTC];
2321#endif
2322
2323#ifdef VSWTCH
2324  target.c_cc[LINUX_VSWTC] = host->c_cc[VSWTCH];
2325#endif
2326
2327  emul_write_buffer(&target, addr, sizeof(target), processor, cia);
2328}
2329#endif /* HAVE_TERMIO_STRUCTURE */
2330
2331#ifdef HAVE_TERMIOS_STRUCTURE
2332/* Convert to/from host termios structure */
2333
2334typedef unsigned32 linux_tcflag_t;
2335typedef unsigned8  linux_cc_t;
2336typedef unsigned32 linux_speed_t;
2337
2338struct linux_termios {
2339  linux_tcflag_t	c_iflag;
2340  linux_tcflag_t	c_oflag;
2341  linux_tcflag_t	c_cflag;
2342  linux_tcflag_t	c_lflag;
2343  linux_cc_t		c_cc[LINUX_NCCS];
2344  linux_cc_t		c_line;
2345  signed32		c_ispeed;
2346  signed32		c_ospeed;
2347};
2348
2349STATIC_INLINE_EMUL_UNIX void
2350convert_to_linux_termios(unsigned_word addr,
2351			 struct termios *host,
2352			 cpu *processor,
2353			 unsigned_word cia)
2354{
2355  struct linux_termios target;
2356  int i;
2357
2358  target.c_iflag = H2T_4 (host->c_iflag);
2359  target.c_oflag = H2T_4 (host->c_oflag);
2360  target.c_cflag = H2T_4 (host->c_cflag);
2361  target.c_lflag = H2T_4 (host->c_lflag);
2362
2363  for (i = 0; i < LINUX_NCCS; i++)
2364    target.c_cc[i] = 0;
2365
2366#ifdef VINTR
2367  target.c_cc[LINUX_VINTR] = host->c_cc[VINTR];
2368#endif
2369
2370#ifdef VQUIT
2371  target.c_cc[LINUX_VQUIT] = host->c_cc[VQUIT];
2372#endif
2373
2374#ifdef VERASE
2375  target.c_cc[LINUX_VERASE] = host->c_cc[VERASE];
2376#endif
2377
2378#ifdef VKILL
2379  target.c_cc[LINUX_VKILL] = host->c_cc[VKILL];
2380#endif
2381
2382#ifdef VEOF
2383  target.c_cc[LINUX_VEOF] = host->c_cc[VEOF];
2384#endif
2385
2386#ifdef VEOL
2387  target.c_cc[LINUX_VEOL] = host->c_cc[VEOL];
2388#endif
2389
2390#ifdef VEOL2
2391  target.c_cc[LINUX_VEOL2] = host->c_cc[VEOL2];
2392#endif
2393
2394#ifdef VSWTCH
2395  target.c_cc[LINUX_VSWTC] = host->c_cc[VSWTCH];
2396#endif
2397
2398#ifdef HAVE_TERMIOS_CLINE
2399  target.c_line   = host->c_line;
2400#else
2401  target.c_line   = 0;
2402#endif
2403
2404#ifdef HAVE_CFGETISPEED
2405  target.c_ispeed = cfgetispeed (host);
2406#else
2407  target.c_ispeed = 0;
2408#endif
2409
2410#ifdef HAVE_CFGETOSPEED
2411  target.c_ospeed = cfgetospeed (host);
2412#else
2413  target.c_ospeed = 0;
2414#endif
2415
2416  emul_write_buffer(&target, addr, sizeof(target), processor, cia);
2417}
2418#endif /* HAVE_TERMIOS_STRUCTURE */
2419
2420#ifndef HAVE_IOCTL
2421#define do_linux_ioctl 0
2422#else
2423static void
2424do_linux_ioctl(os_emul_data *emul,
2425	       unsigned call,
2426	       const int arg0,
2427	       cpu *processor,
2428	       unsigned_word cia)
2429{
2430  int fildes = cpu_registers(processor)->gpr[arg0];
2431  unsigned request = cpu_registers(processor)->gpr[arg0+1];
2432  unsigned_word argp_addr = cpu_registers(processor)->gpr[arg0+2];
2433  int status = 0;
2434  const char *name = "<unknown>";
2435
2436#ifdef HAVE_TERMIOS_STRUCTURE
2437  struct termios host_termio;
2438
2439#else
2440#ifdef HAVE_TERMIO_STRUCTURE
2441  struct termio host_termio;
2442#endif
2443#endif
2444
2445  status = fdbad (fildes);
2446  if (status != 0)
2447    goto done;
2448
2449  switch (request)
2450    {
2451    case 0:					/* make sure we have at least one case */
2452    default:
2453      status = -1;
2454      errno = EINVAL;
2455      break;
2456
2457#if defined(HAVE_TERMIO_STRUCTURE) || defined(HAVE_TERMIOS_STRUCTURE)
2458#if defined(TCGETA) || defined(TCGETS) || defined(HAVE_TCGETATTR)
2459    case LINUX_IOR('t', 23, struct linux_termio):	/* TCGETA */
2460      name = "TCGETA";
2461#ifdef HAVE_TCGETATTR
2462      status = tcgetattr(fildes, &host_termio);
2463#elif defined(TCGETS)
2464      status = ioctl (fildes, TCGETS, &host_termio);
2465#else
2466      status = ioctl (fildes, TCGETA, &host_termio);
2467#endif
2468      if (status == 0)
2469	convert_to_linux_termio (argp_addr, &host_termio, processor, cia);
2470      break;
2471#endif /* TCGETA */
2472#endif /* HAVE_TERMIO_STRUCTURE */
2473
2474#ifdef HAVE_TERMIOS_STRUCTURE
2475#if defined(TCGETS) || defined(HAVE_TCGETATTR)
2476    case LINUX_IOR('t', 19, struct linux_termios):	/* TCGETS */
2477      name = "TCGETS";
2478#ifdef HAVE_TCGETATTR
2479      status = tcgetattr(fildes, &host_termio);
2480#else
2481      status = ioctl (fildes, TCGETS, &host_termio);
2482#endif
2483      if (status == 0)
2484	convert_to_linux_termios (argp_addr, &host_termio, processor, cia);
2485      break;
2486#endif /* TCGETS */
2487#endif /* HAVE_TERMIOS_STRUCTURE */
2488    }
2489
2490done:
2491  emul_write_status(processor, status, errno);
2492
2493  if (WITH_TRACE && ppc_trace[trace_os_emul])
2494    printf_filtered ("%d, 0x%x [%s], 0x%lx", fildes, request, name, (long)argp_addr);
2495}
2496#endif /* HAVE_IOCTL */
2497
2498static emul_syscall_descriptor linux_descriptors[] = {
2499  /*   0 */ { 0, "setup" },
2500  /*   1 */ { do_unix_exit, "exit" },
2501  /*   2 */ { 0, "fork" },
2502  /*   3 */ { do_unix_read, "read" },
2503  /*   4 */ { do_unix_write, "write" },
2504  /*   5 */ { do_unix_open, "open" },
2505  /*   6 */ { do_unix_close, "close" },
2506  /*   7 */ { 0, "waitpid" },
2507  /*   8 */ { 0, "creat" },
2508  /*   9 */ { do_unix_link, "link" },
2509  /*  10 */ { do_unix_unlink, "unlink" },
2510  /*  11 */ { 0, "execve" },
2511  /*  12 */ { do_unix_chdir, "chdir" },
2512  /*  13 */ { do_unix_time, "time" },
2513  /*  14 */ { 0, "mknod" },
2514  /*  15 */ { 0, "chmod" },
2515  /*  16 */ { 0, "chown" },
2516  /*  17 */ { 0, "break" },
2517  /*  18 */ { 0, "stat" },
2518  /*  19 */ { do_unix_lseek, "lseek" },
2519  /*  20 */ { do_unix_getpid, "getpid" },
2520  /*  21 */ { 0, "mount" },
2521  /*  22 */ { 0, "umount" },
2522  /*  23 */ { 0, "setuid" },
2523  /*  24 */ { do_unix_getuid, "getuid" },
2524  /*  25 */ { 0, "stime" },
2525  /*  26 */ { 0, "ptrace" },
2526  /*  27 */ { 0, "alarm" },
2527  /*  28 */ { 0, "fstat" },
2528  /*  29 */ { 0, "pause" },
2529  /*  30 */ { 0, "utime" },
2530  /*  31 */ { 0, "stty" },
2531  /*  32 */ { 0, "gtty" },
2532  /*  33 */ { do_unix_access, "access" },
2533  /*  34 */ { 0, "nice" },
2534  /*  35 */ { 0, "ftime" },
2535  /*  36 */ { 0, "sync" },
2536  /*  37 */ { 0, "kill" },
2537  /*  38 */ { 0, "rename" },
2538  /*  39 */ { do_unix_mkdir, "mkdir" },
2539  /*  40 */ { do_unix_rmdir, "rmdir" },
2540  /*  41 */ { do_unix_dup, "dup" },
2541  /*  42 */ { 0, "pipe" },
2542  /*  43 */ { 0, "times" },
2543  /*  44 */ { 0, "prof" },
2544  /*  45 */ { do_unix_break, "brk" },
2545  /*  46 */ { 0, "setgid" },
2546  /*  47 */ { do_unix_getgid, "getgid" },
2547  /*  48 */ { 0, "signal" },
2548  /*  49 */ { do_unix_geteuid, "geteuid" },
2549  /*  50 */ { do_unix_getegid, "getegid" },
2550  /*  51 */ { 0, "acct" },
2551  /*  52 */ { 0, "phys" },
2552  /*  53 */ { 0, "lock" },
2553  /*  54 */ { do_linux_ioctl, "ioctl" },
2554  /*  55 */ { 0, "fcntl" },
2555  /*  56 */ { 0, "mpx" },
2556  /*  57 */ { 0, "setpgid" },
2557  /*  58 */ { 0, "ulimit" },
2558  /*  59 */ { 0, "olduname" },
2559  /*  60 */ { do_unix_umask, "umask" },
2560  /*  61 */ { 0, "chroot" },
2561  /*  62 */ { 0, "ustat" },
2562  /*  63 */ { do_unix_dup2, "dup2" },
2563  /*  64 */ { do_unix_getppid, "getppid" },
2564  /*  65 */ { 0, "getpgrp" },
2565  /*  66 */ { 0, "setsid" },
2566  /*  67 */ { 0, "sigaction" },
2567  /*  68 */ { 0, "sgetmask" },
2568  /*  69 */ { 0, "ssetmask" },
2569  /*  70 */ { 0, "setreuid" },
2570  /*  71 */ { 0, "setregid" },
2571  /*  72 */ { 0, "sigsuspend" },
2572  /*  73 */ { 0, "sigpending" },
2573  /*  74 */ { 0, "sethostname" },
2574  /*  75 */ { 0, "setrlimit" },
2575  /*  76 */ { 0, "getrlimit" },
2576  /*  77 */ { do_unix_getrusage, "getrusage" },
2577  /*  78 */ { do_unix_gettimeofday, "gettimeofday" },
2578  /*  79 */ { 0, "settimeofday" },
2579  /*  80 */ { 0, "getgroups" },
2580  /*  81 */ { 0, "setgroups" },
2581  /*  82 */ { 0, "select" },
2582  /*  83 */ { do_unix_symlink, "symlink" },
2583  /*  84 */ { 0, "lstat" },
2584  /*  85 */ { 0, "readlink" },
2585  /*  86 */ { 0, "uselib" },
2586  /*  87 */ { 0, "swapon" },
2587  /*  88 */ { 0, "reboot" },
2588  /*  89 */ { 0, "readdir" },
2589  /*  90 */ { 0, "mmap" },
2590  /*  91 */ { 0, "munmap" },
2591  /*  92 */ { 0, "truncate" },
2592  /*  93 */ { 0, "ftruncate" },
2593  /*  94 */ { 0, "fchmod" },
2594  /*  95 */ { 0, "fchown" },
2595  /*  96 */ { 0, "getpriority" },
2596  /*  97 */ { 0, "setpriority" },
2597  /*  98 */ { 0, "profil" },
2598  /*  99 */ { 0, "statfs" },
2599  /* 100 */ { 0, "fstatfs" },
2600  /* 101 */ { 0, "ioperm" },
2601  /* 102 */ { 0, "socketcall" },
2602  /* 103 */ { 0, "syslog" },
2603  /* 104 */ { 0, "setitimer" },
2604  /* 105 */ { 0, "getitimer" },
2605  /* 106 */ { do_linux_stat, "newstat" },
2606  /* 107 */ { do_linux_lstat, "newlstat" },
2607  /* 108 */ { do_linux_fstat, "newfstat" },
2608  /* 109 */ { 0, "uname" },
2609  /* 110 */ { 0, "iopl" },
2610  /* 111 */ { 0, "vhangup" },
2611  /* 112 */ { 0, "idle" },
2612  /* 113 */ { 0, "vm86" },
2613  /* 114 */ { 0, "wait4" },
2614  /* 115 */ { 0, "swapoff" },
2615  /* 116 */ { 0, "sysinfo" },
2616  /* 117 */ { 0, "ipc" },
2617  /* 118 */ { 0, "fsync" },
2618  /* 119 */ { 0, "sigreturn" },
2619  /* 120 */ { 0, "clone" },
2620  /* 121 */ { 0, "setdomainname" },
2621  /* 122 */ { 0, "newuname" },
2622  /* 123 */ { 0, "modify_ldt" },
2623  /* 124 */ { 0, "adjtimex" },
2624  /* 125 */ { 0, "mprotect" },
2625  /* 126 */ { 0, "sigprocmask" },
2626  /* 127 */ { 0, "create_module" },
2627  /* 128 */ { 0, "init_module" },
2628  /* 129 */ { 0, "delete_module" },
2629  /* 130 */ { 0, "get_kernel_syms" },
2630  /* 131 */ { 0, "quotactl" },
2631  /* 132 */ { 0, "getpgid" },
2632  /* 133 */ { 0, "fchdir" },
2633  /* 134 */ { 0, "bdflush" },
2634  /* 135 */ { 0, "sysfs" },
2635  /* 136 */ { 0, "personality" },
2636  /* 137 */ { 0, "afs_syscall" },
2637  /* 138 */ { 0, "setfsuid" },
2638  /* 139 */ { 0, "setfsgid" },
2639  /* 140 */ { 0, "llseek" },
2640  /* 141 */ { 0, "getdents" },
2641  /* 142 */ { 0, "newselect" },
2642  /* 143 */ { 0, "flock" },
2643  /* 144 */ { 0, "msync" },
2644  /* 145 */ { 0, "readv" },
2645  /* 146 */ { 0, "writev" },
2646  /* 147 */ { 0, "getsid" },
2647  /* 148 */ { 0, "fdatasync" },
2648  /* 149 */ { 0, "sysctl" },
2649  /* 150 */ { 0, "mlock" },
2650  /* 151 */ { 0, "munlock" },
2651  /* 152 */ { 0, "mlockall" },
2652  /* 153 */ { 0, "munlockall" },
2653  /* 154 */ { 0, "sched_setparam" },
2654  /* 155 */ { 0, "sched_getparam" },
2655  /* 156 */ { 0, "sched_setscheduler" },
2656  /* 157 */ { 0, "sched_getscheduler" },
2657  /* 158 */ { 0, "sched_yield" },
2658  /* 159 */ { 0, "sched_get_priority_max" },
2659  /* 160 */ { 0, "sched_get_priority_min" },
2660  /* 161 */ { 0, "sched_rr_get_interval" },
2661};
2662
2663static char *(linux_error_names[]) = {
2664  /*   0 */ "ESUCCESS",
2665  /*   1 */ "EPERM",
2666  /*   2 */ "ENOENT",
2667  /*   3 */ "ESRCH",
2668  /*   4 */ "EINTR",
2669  /*   5 */ "EIO",
2670  /*   6 */ "ENXIO",
2671  /*   7 */ "E2BIG",
2672  /*   8 */ "ENOEXEC",
2673  /*   9 */ "EBADF",
2674  /*  10 */ "ECHILD",
2675  /*  11 */ "EAGAIN",
2676  /*  12 */ "ENOMEM",
2677  /*  13 */ "EACCES",
2678  /*  14 */ "EFAULT",
2679  /*  15 */ "ENOTBLK",
2680  /*  16 */ "EBUSY",
2681  /*  17 */ "EEXIST",
2682  /*  18 */ "EXDEV",
2683  /*  19 */ "ENODEV",
2684  /*  20 */ "ENOTDIR",
2685  /*  21 */ "EISDIR",
2686  /*  22 */ "EINVAL",
2687  /*  23 */ "ENFILE",
2688  /*  24 */ "EMFILE",
2689  /*  25 */ "ENOTTY",
2690  /*  26 */ "ETXTBSY",
2691  /*  27 */ "EFBIG",
2692  /*  28 */ "ENOSPC",
2693  /*  29 */ "ESPIPE",
2694  /*  30 */ "EROFS",
2695  /*  31 */ "EMLINK",
2696  /*  32 */ "EPIPE",
2697  /*  33 */ "EDOM",
2698  /*  34 */ "ERANGE",
2699  /*  35 */ "EDEADLK",
2700  /*  36 */ "ENAMETOOLONG",
2701  /*  37 */ "ENOLCK",
2702  /*  38 */ "ENOSYS",
2703  /*  39 */ "ENOTEMPTY",
2704  /*  40 */ "ELOOP",
2705  /*  41 */ 0,
2706  /*  42 */ "ENOMSG",
2707  /*  43 */ "EIDRM",
2708  /*  44 */ "ECHRNG",
2709  /*  45 */ "EL2NSYNC",
2710  /*  46 */ "EL3HLT",
2711  /*  47 */ "EL3RST",
2712  /*  48 */ "ELNRNG",
2713  /*  49 */ "EUNATCH",
2714  /*  50 */ "ENOCSI",
2715  /*  51 */ "EL2HLT",
2716  /*  52 */ "EBADE",
2717  /*  53 */ "EBADR",
2718  /*  54 */ "EXFULL",
2719  /*  55 */ "ENOANO",
2720  /*  56 */ "EBADRQC",
2721  /*  57 */ "EBADSLT",
2722  /*  58 */ "EDEADLOCK",
2723  /*  59 */ "EBFONT",
2724  /*  60 */ "ENOSTR",
2725  /*  61 */ "ENODATA",
2726  /*  62 */ "ETIME",
2727  /*  63 */ "ENOSR",
2728  /*  64 */ "ENONET",
2729  /*  65 */ "ENOPKG",
2730  /*  66 */ "EREMOTE",
2731  /*  67 */ "ENOLINK",
2732  /*  68 */ "EADV",
2733  /*  69 */ "ESRMNT",
2734  /*  70 */ "ECOMM",
2735  /*  71 */ "EPROTO",
2736  /*  72 */ "EMULTIHOP",
2737  /*  73 */ "EDOTDOT",
2738  /*  74 */ "EBADMSG",
2739  /*  75 */ "EOVERFLOW",
2740  /*  76 */ "ENOTUNIQ",
2741  /*  77 */ "EBADFD",
2742  /*  78 */ "EREMCHG",
2743  /*  79 */ "ELIBACC",
2744  /*  80 */ "ELIBBAD",
2745  /*  81 */ "ELIBSCN",
2746  /*  82 */ "ELIBMAX",
2747  /*  83 */ "ELIBEXEC",
2748  /*  84 */ "EILSEQ",
2749  /*  85 */ "ERESTART",
2750  /*  86 */ "ESTRPIPE",
2751  /*  87 */ "EUSERS",
2752  /*  88 */ "ENOTSOCK",
2753  /*  89 */ "EDESTADDRREQ",
2754  /*  90 */ "EMSGSIZE",
2755  /*  91 */ "EPROTOTYPE",
2756  /*  92 */ "ENOPROTOOPT",
2757  /*  93 */ "EPROTONOSUPPORT",
2758  /*  94 */ "ESOCKTNOSUPPORT",
2759  /*  95 */ "EOPNOTSUPP",
2760  /*  96 */ "EPFNOSUPPORT",
2761  /*  97 */ "EAFNOSUPPORT",
2762  /*  98 */ "EADDRINUSE",
2763  /*  99 */ "EADDRNOTAVAIL",
2764  /* 100 */ "ENETDOWN",
2765  /* 101 */ "ENETUNREACH",
2766  /* 102 */ "ENETRESET",
2767  /* 103 */ "ECONNABORTED",
2768  /* 104 */ "ECONNRESET",
2769  /* 105 */ "ENOBUFS",
2770  /* 106 */ "EISCONN",
2771  /* 107 */ "ENOTCONN",
2772  /* 108 */ "ESHUTDOWN",
2773  /* 109 */ "ETOOMANYREFS",
2774  /* 110 */ "ETIMEDOUT",
2775  /* 111 */ "ECONNREFUSED",
2776  /* 112 */ "EHOSTDOWN",
2777  /* 113 */ "EHOSTUNREACH",
2778  /* 114 */ "EALREADY",
2779  /* 115 */ "EINPROGRESS",
2780  /* 116 */ "ESTALE",
2781  /* 117 */ "EUCLEAN",
2782  /* 118 */ "ENOTNAM",
2783  /* 119 */ "ENAVAIL",
2784  /* 120 */ "EISNAM",
2785  /* 121 */ "EREMOTEIO",
2786  /* 122 */ "EDQUOT",
2787};
2788
2789static char *(linux_signal_names[]) = {
2790  /*  0 */ 0,
2791  /*  1 */ "SIGHUP",
2792  /*  2 */ "SIGINT",
2793  /*  3 */ "SIGQUIT",
2794  /*  4 */ "SIGILL",
2795  /*  5 */ "SIGTRAP",
2796  /*  6 */ "SIGABRT",
2797  /*  6 */ "SIGIOT",
2798  /*  7 */ "SIGBUS",
2799  /*  8 */ "SIGFPE",
2800  /*  9 */ "SIGKILL",
2801  /* 10 */ "SIGUSR1",
2802  /* 11 */ "SIGSEGV",
2803  /* 12 */ "SIGUSR2",
2804  /* 13 */ "SIGPIPE",
2805  /* 14 */ "SIGALRM",
2806  /* 15 */ "SIGTERM",
2807  /* 16 */ "SIGSTKFLT",
2808  /* 17 */ "SIGCHLD",
2809  /* 18 */ "SIGCONT",
2810  /* 19 */ "SIGSTOP",
2811  /* 20 */ "SIGTSTP",
2812  /* 21 */ "SIGTTIN",
2813  /* 22 */ "SIGTTOU",
2814  /* 23 */ "SIGURG",
2815  /* 24 */ "SIGXCPU",
2816  /* 25 */ "SIGXFSZ",
2817  /* 26 */ "SIGVTALRM",
2818  /* 27 */ "SIGPROF",
2819  /* 28 */ "SIGWINCH",
2820  /* 29 */ "SIGIO",
2821  /* 30 */ "SIGPWR",
2822  /* 31 */ "SIGUNUSED",
2823};
2824
2825static emul_syscall emul_linux_syscalls = {
2826  linux_descriptors,
2827  ARRAY_SIZE (linux_descriptors),
2828  linux_error_names,
2829  ARRAY_SIZE (linux_error_names),
2830  linux_signal_names,
2831  ARRAY_SIZE (linux_signal_names),
2832};
2833
2834
2835/* Linux's os_emul interface, most are just passed on to the generic
2836   syscall stuff */
2837
2838static os_emul_data *
2839emul_linux_create(device *root,
2840		  bfd *image,
2841		  const char *name)
2842{
2843  /* check that this emulation is really for us */
2844  if (name != NULL && strcmp(name, "linux") != 0)
2845    return NULL;
2846
2847  if (image == NULL)
2848    return NULL;
2849
2850  return emul_unix_create(root, image, "linux", &emul_linux_syscalls);
2851}
2852
2853static void
2854emul_linux_init(os_emul_data *emul_data,
2855		int nr_cpus)
2856{
2857  fd_closed[0] = 0;
2858  fd_closed[1] = 0;
2859  fd_closed[2] = 0;
2860}
2861
2862static void
2863emul_linux_system_call(cpu *processor,
2864		       unsigned_word cia,
2865		       os_emul_data *emul_data)
2866{
2867  emul_do_system_call(emul_data,
2868		      emul_data->syscalls,
2869		      cpu_registers(processor)->gpr[0],
2870		      3, /*r3 contains arg0*/
2871		      processor,
2872		      cia);
2873}
2874
2875const os_emul emul_linux = {
2876  "linux",
2877  emul_linux_create,
2878  emul_linux_init,
2879  emul_linux_system_call,
2880  0, /*instruction_call*/
2881  0  /*data*/
2882};
2883
2884#endif /* _EMUL_UNIX_C_ */
2885