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