|  | /*  This file is part of the program psim. | 
|  |  | 
|  | Copyright (C) 1996-1998, Andrew Cagney <cagney@highland.com.au> | 
|  |  | 
|  | This program is free software; you can redistribute it and/or modify | 
|  | it under the terms of the GNU General Public License as published by | 
|  | the Free Software Foundation; either version 3 of the License, or | 
|  | (at your option) any later version. | 
|  |  | 
|  | This program is distributed in the hope that it will be useful, | 
|  | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | GNU General Public License for more details. | 
|  |  | 
|  | You should have received a copy of the GNU General Public License | 
|  | along with this program; if not, see <http://www.gnu.org/licenses/>. | 
|  |  | 
|  | */ | 
|  |  | 
|  |  | 
|  | #ifndef _EMUL_UNIX_C_ | 
|  | #define _EMUL_UNIX_C_ | 
|  |  | 
|  |  | 
|  | /* Note: this module is called via a table.  There is no benefit in | 
|  | making it inline */ | 
|  |  | 
|  | #include "emul_generic.h" | 
|  | #include "emul_unix.h" | 
|  |  | 
|  | #ifdef HAVE_STRING_H | 
|  | #include <string.h> | 
|  | #else | 
|  | #ifdef HAVE_STRINGS_H | 
|  | #include <strings.h> | 
|  | #endif | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_SYS_TYPES_H | 
|  | #include <sys/types.h> | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_SYS_TYPES_H | 
|  | #include <sys/stat.h> | 
|  | #else | 
|  | #undef HAVE_STAT | 
|  | #undef HAVE_LSTAT | 
|  | #undef HAVE_FSTAT | 
|  | #endif | 
|  |  | 
|  | #include <stdio.h> | 
|  | #include <signal.h> | 
|  | #include <errno.h> | 
|  |  | 
|  | #ifdef HAVE_FCNTL_H | 
|  | #include <fcntl.h> | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_SYS_PARAM_H | 
|  | #include <sys/param.h> | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_SYS_TIME_H | 
|  | #include <sys/time.h> | 
|  | #endif | 
|  |  | 
|  | #ifndef HAVE_TERMIOS_STRUCTURE | 
|  | #undef HAVE_SYS_TERMIOS_H | 
|  | #undef HAVE_TCGETATTR | 
|  | #else | 
|  | #ifndef HAVE_SYS_TERMIOS_H | 
|  | #undef HAVE_TERMIOS_STRUCTURE | 
|  | #endif | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_TERMIOS_STRUCTURE | 
|  | #include <sys/termios.h> | 
|  |  | 
|  | /* If we have TERMIOS, use that for the termio structure, since some systems | 
|  | don't like including both sys/termios.h and sys/termio.h at the same | 
|  | time.  */ | 
|  | #undef	HAVE_TERMIO_STRUCTURE | 
|  | #undef	TCGETA | 
|  | #undef	termio | 
|  | #define termio termios | 
|  | #endif | 
|  |  | 
|  | #ifndef HAVE_TERMIO_STRUCTURE | 
|  | #undef HAVE_SYS_TERMIO_H | 
|  | #else | 
|  | #ifndef HAVE_SYS_TERMIO_H | 
|  | #undef HAVE_TERMIO_STRUCTURE | 
|  | #endif | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_TERMIO_STRUCTURE | 
|  | #include <sys/termio.h> | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_GETRUSAGE | 
|  | #ifndef HAVE_SYS_RESOURCE_H | 
|  | #undef HAVE_GETRUSAGE | 
|  | #endif | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_GETRUSAGE | 
|  | #include <sys/resource.h> | 
|  | int getrusage(); | 
|  | #endif | 
|  |  | 
|  | #if HAVE_DIRENT_H | 
|  | # include <dirent.h> | 
|  | # define NAMLEN(dirent) strlen((dirent)->d_name) | 
|  | #else | 
|  | # define dirent direct | 
|  | # define NAMLEN(dirent) (dirent)->d_namlen | 
|  | # if HAVE_SYS_NDIR_H | 
|  | #  include <sys/ndir.h> | 
|  | # endif | 
|  | # if HAVE_SYS_DIR_H | 
|  | #  include <sys/dir.h> | 
|  | # endif | 
|  | # if HAVE_NDIR_H | 
|  | #  include <ndir.h> | 
|  | # endif | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_UNISTD_H | 
|  | #undef MAXPATHLEN		/* sys/param.h might define this also */ | 
|  | #include <unistd.h> | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_STDLIB_H | 
|  | #include <stdlib.h> | 
|  | #endif | 
|  |  | 
|  | #if defined(BSD) && !defined(errno) && (BSD < 199306)	/* here BSD as just a bug */ | 
|  | extern int errno; | 
|  | #endif | 
|  |  | 
|  | #ifndef STATIC_INLINE_EMUL_UNIX | 
|  | #define STATIC_INLINE_EMUL_UNIX STATIC_INLINE | 
|  | #endif | 
|  |  | 
|  | #ifndef PATH_MAX | 
|  | #define PATH_MAX 1024 | 
|  | #endif | 
|  |  | 
|  | #ifndef EINVAL | 
|  | #define EINVAL -1 | 
|  | #endif | 
|  |  | 
|  | /* UNIX's idea of what is needed to implement emulations */ | 
|  |  | 
|  | struct _os_emul_data { | 
|  | device *vm; | 
|  | emul_syscall *syscalls; | 
|  | }; | 
|  |  | 
|  |  | 
|  | /* Emulation of simple UNIX system calls that are common on all systems.  */ | 
|  |  | 
|  | /* Structures that are common agmonst the UNIX varients */ | 
|  | struct unix_timeval { | 
|  | signed32 tv_sec;		/* seconds */ | 
|  | signed32 tv_usec;		/* microseconds */ | 
|  | }; | 
|  |  | 
|  | struct unix_timezone { | 
|  | signed32 tz_minuteswest;	/* minutes west of Greenwich */ | 
|  | signed32 tz_dsttime;		/* type of dst correction */ | 
|  | }; | 
|  |  | 
|  | #define	UNIX_RUSAGE_SELF	0 | 
|  | #define	UNIX_RUSAGE_CHILDREN	(-1) | 
|  | #define UNIX_RUSAGE_BOTH	(-2)	/* sys_wait4() uses this */ | 
|  |  | 
|  | struct	unix_rusage { | 
|  | struct unix_timeval ru_utime;	/* user time used */ | 
|  | struct unix_timeval ru_stime;	/* system time used */ | 
|  | signed32 ru_maxrss;		/* maximum resident set size */ | 
|  | signed32 ru_ixrss;		/* integral shared memory size */ | 
|  | signed32 ru_idrss;		/* integral unshared data size */ | 
|  | signed32 ru_isrss;		/* integral unshared stack size */ | 
|  | signed32 ru_minflt;		/* any page faults not requiring I/O */ | 
|  | signed32 ru_majflt;		/* any page faults requiring I/O */ | 
|  | signed32 ru_nswap;		/* swaps */ | 
|  | signed32 ru_inblock;		/* block input operations */ | 
|  | signed32 ru_oublock;		/* block output operations */ | 
|  | signed32 ru_msgsnd;		/* messages sent */ | 
|  | signed32 ru_msgrcv;		/* messages received */ | 
|  | signed32 ru_nsignals;		/* signals received */ | 
|  | signed32 ru_nvcsw;		/* voluntary context switches */ | 
|  | signed32 ru_nivcsw;		/* involuntary " */ | 
|  | }; | 
|  |  | 
|  |  | 
|  | /* File descriptors 0, 1, and 2 should not be closed.  fd_closed[] | 
|  | tracks whether these descriptors have been closed in do_close() | 
|  | below.  */ | 
|  |  | 
|  | static int fd_closed[3]; | 
|  |  | 
|  | /* Check for some occurrences of bad file descriptors.  We only check | 
|  | whether fd 0, 1, or 2 are "closed".  By "closed" we mean that these | 
|  | descriptors aren't actually closed, but are considered to be closed | 
|  | by this layer. | 
|  |  | 
|  | Other checks are performed by the underlying OS call.  */ | 
|  |  | 
|  | static int | 
|  | fdbad (int fd) | 
|  | { | 
|  | if (fd >=0 && fd <= 2 && fd_closed[fd]) | 
|  | { | 
|  | errno = EBADF; | 
|  | return -1; | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static void | 
|  | do_unix_exit(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | int status = (int)cpu_registers(processor)->gpr[arg0]; | 
|  | if (WITH_TRACE && ppc_trace[trace_os_emul]) | 
|  | printf_filtered ("%d)\n", status); | 
|  |  | 
|  | cpu_halt(processor, cia, was_exited, status); | 
|  | } | 
|  |  | 
|  |  | 
|  | static void | 
|  | do_unix_read(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | void *scratch_buffer; | 
|  | int d = (int)cpu_registers(processor)->gpr[arg0]; | 
|  | unsigned_word buf = cpu_registers(processor)->gpr[arg0+1]; | 
|  | int nbytes = cpu_registers(processor)->gpr[arg0+2]; | 
|  | int status; | 
|  |  | 
|  | if (WITH_TRACE && ppc_trace[trace_os_emul]) | 
|  | printf_filtered ("%d, 0x%lx, %d", d, (long)buf, nbytes); | 
|  |  | 
|  | /* get a tempoary bufer */ | 
|  | scratch_buffer = zalloc(nbytes); | 
|  |  | 
|  | /* check if buffer exists by reading it */ | 
|  | emul_read_buffer(scratch_buffer, buf, nbytes, processor, cia); | 
|  |  | 
|  | status = fdbad (d); | 
|  | /* read */ | 
|  | if (status == 0) | 
|  | status = read (d, scratch_buffer, nbytes); | 
|  |  | 
|  | emul_write_status(processor, status, errno); | 
|  | if (status > 0) | 
|  | emul_write_buffer(scratch_buffer, buf, status, processor, cia); | 
|  |  | 
|  | free(scratch_buffer); | 
|  | } | 
|  |  | 
|  |  | 
|  | static void | 
|  | do_unix_write(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | void *scratch_buffer = NULL; | 
|  | int d = (int)cpu_registers(processor)->gpr[arg0]; | 
|  | unsigned_word buf = cpu_registers(processor)->gpr[arg0+1]; | 
|  | int nbytes = cpu_registers(processor)->gpr[arg0+2]; | 
|  | int status; | 
|  |  | 
|  | if (WITH_TRACE && ppc_trace[trace_os_emul]) | 
|  | printf_filtered ("%d, 0x%lx, %d", d, (long)buf, nbytes); | 
|  |  | 
|  | /* get a tempoary bufer */ | 
|  | scratch_buffer = zalloc(nbytes); /* FIXME - nbytes == 0 */ | 
|  |  | 
|  | /* copy in */ | 
|  | emul_read_buffer(scratch_buffer, buf, nbytes, | 
|  | processor, cia); | 
|  |  | 
|  | status = fdbad (d); | 
|  | /* write */ | 
|  | if (status == 0) | 
|  | status = write(d, scratch_buffer, nbytes); | 
|  | emul_write_status(processor, status, errno); | 
|  | free(scratch_buffer); | 
|  |  | 
|  | flush_stdoutput(); | 
|  | } | 
|  |  | 
|  |  | 
|  | static void | 
|  | do_unix_open(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | unsigned_word path_addr = cpu_registers(processor)->gpr[arg0]; | 
|  | char path_buf[PATH_MAX]; | 
|  | char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia); | 
|  | int flags = (int)cpu_registers(processor)->gpr[arg0+1]; | 
|  | int mode = (int)cpu_registers(processor)->gpr[arg0+2]; | 
|  | int status; | 
|  |  | 
|  | if (WITH_TRACE && ppc_trace[trace_os_emul]) | 
|  | printf_filtered ("0x%lx [%s], 0x%x, 0x%x", (long)path_addr, path, flags, mode); | 
|  |  | 
|  | status = open(path, flags, mode); | 
|  | emul_write_status(processor, status, errno); | 
|  | } | 
|  |  | 
|  |  | 
|  | static void | 
|  | do_unix_close(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | int d = (int)cpu_registers(processor)->gpr[arg0]; | 
|  | int status; | 
|  |  | 
|  | if (WITH_TRACE && ppc_trace[trace_os_emul]) | 
|  | printf_filtered ("%d", d); | 
|  |  | 
|  | status = fdbad (d); | 
|  | if (status == 0) | 
|  | { | 
|  | /* Do not close stdin, stdout, or stderr. GDB may still need access to | 
|  | these descriptors.  */ | 
|  | if (d == 0 || d == 1 || d == 2) | 
|  | { | 
|  | fd_closed[d] = 1; | 
|  | status = 0; | 
|  | } | 
|  | else | 
|  | status = close(d); | 
|  | } | 
|  |  | 
|  | emul_write_status(processor, status, errno); | 
|  | } | 
|  |  | 
|  |  | 
|  | static void | 
|  | do_unix_break(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | /* just pass this onto the `vm' device */ | 
|  | unsigned_word new_break = cpu_registers(processor)->gpr[arg0]; | 
|  | int status; | 
|  |  | 
|  | if (WITH_TRACE && ppc_trace[trace_os_emul]) | 
|  | printf_filtered ("0x%lx", (long)cpu_registers(processor)->gpr[arg0]); | 
|  |  | 
|  | status = device_ioctl(emul->vm, | 
|  | processor, | 
|  | cia, | 
|  | device_ioctl_break, | 
|  | new_break); /*ioctl-data*/ | 
|  |  | 
|  | emul_write_status(processor, 0, status); | 
|  | } | 
|  |  | 
|  | #ifndef HAVE_ACCESS | 
|  | #define do_unix_access 0 | 
|  | #else | 
|  | static void | 
|  | do_unix_access(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | unsigned_word path_addr = cpu_registers(processor)->gpr[arg0]; | 
|  | char path_buf[PATH_MAX]; | 
|  | char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia); | 
|  | int mode = (int)cpu_registers(processor)->gpr[arg0+1]; | 
|  | int status; | 
|  |  | 
|  | if (WITH_TRACE && ppc_trace[trace_os_emul]) | 
|  | printf_filtered ("0x%lx [%s], 0x%x [0%o]", (long)path_addr, path, mode, mode); | 
|  |  | 
|  | status = access(path, mode); | 
|  | emul_write_status(processor, status, errno); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #ifndef HAVE_GETPID | 
|  | #define do_unix_getpid 0 | 
|  | #else | 
|  | static void | 
|  | do_unix_getpid(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | pid_t status = getpid(); | 
|  | emul_write_status(processor, (int)status, errno); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #ifndef HAVE_GETPPID | 
|  | #define do_unix_getppid 0 | 
|  | #else | 
|  | static void | 
|  | do_unix_getppid(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | pid_t status = getppid(); | 
|  | emul_write_status(processor, (int)status, errno); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #if !defined(HAVE_GETPID) || !defined(HAVE_GETPPID) | 
|  | #define do_unix_getpid2 0 | 
|  | #else | 
|  | static void | 
|  | do_unix_getpid2(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | int pid  = (int)getpid(); | 
|  | int ppid = (int)getppid(); | 
|  | emul_write2_status(processor, pid, ppid, errno); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #if !defined(HAVE_GETUID) || !defined(HAVE_GETEUID) | 
|  | #define do_unix_getuid2 0 | 
|  | #else | 
|  | static void | 
|  | do_unix_getuid2(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | uid_t uid  = getuid(); | 
|  | uid_t euid = geteuid(); | 
|  | emul_write2_status(processor, (int)uid, (int)euid, errno); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #ifndef HAVE_GETUID | 
|  | #define do_unix_getuid 0 | 
|  | #else | 
|  | static void | 
|  | do_unix_getuid(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | uid_t status = getuid(); | 
|  | emul_write_status(processor, (int)status, errno); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #ifndef HAVE_GETEUID | 
|  | #define do_unix_geteuid 0 | 
|  | #else | 
|  | static void | 
|  | do_unix_geteuid(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | uid_t status = geteuid(); | 
|  | emul_write_status(processor, (int)status, errno); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #if 0 | 
|  | #ifndef HAVE_KILL | 
|  | #define do_unix_kill 0 | 
|  | #else | 
|  | static void | 
|  | do_unix_kill(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | pid_t pid = cpu_registers(processor)->gpr[arg0]; | 
|  | int sig = cpu_registers(processor)->gpr[arg0+1]; | 
|  |  | 
|  | if (WITH_TRACE && ppc_trace[trace_os_emul]) | 
|  | printf_filtered ("%d, %d", (int)pid, sig); | 
|  |  | 
|  | printf_filtered("SYS_kill at 0x%lx - more to this than just being killed\n", | 
|  | (long)cia); | 
|  |  | 
|  | cpu_halt(processor, cia, was_signalled, sig); | 
|  | } | 
|  | #endif | 
|  | #endif | 
|  |  | 
|  | #ifndef HAVE_DUP | 
|  | #define do_unix_dup 0 | 
|  | #else | 
|  | static void | 
|  | do_unix_dup(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | int oldd = cpu_registers(processor)->gpr[arg0]; | 
|  | int status = (fdbad (oldd) < 0) ? -1 : dup(oldd); | 
|  | int err = errno; | 
|  |  | 
|  | if (WITH_TRACE && ppc_trace[trace_os_emul]) | 
|  | printf_filtered ("%d", oldd); | 
|  |  | 
|  | emul_write_status(processor, status, err); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #ifndef HAVE_DUP2 | 
|  | #define do_unix_dup2 0 | 
|  | #else | 
|  | static void | 
|  | do_unix_dup2(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | int oldd = cpu_registers(processor)->gpr[arg0]; | 
|  | int newd = cpu_registers(processor)->gpr[arg0+1]; | 
|  | int status = (fdbad (oldd) < 0) ? -1 : dup2(oldd, newd); | 
|  | int err = errno; | 
|  |  | 
|  | if (WITH_TRACE && ppc_trace[trace_os_emul]) | 
|  | printf_filtered ("%d, %d", oldd, newd); | 
|  |  | 
|  | emul_write_status(processor, status, err); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #ifndef HAVE_LSEEK | 
|  | #define do_unix_lseek 0 | 
|  | #else | 
|  | static void | 
|  | do_unix_lseek(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | int fildes   = (int)cpu_registers(processor)->gpr[arg0]; | 
|  | off_t offset = (off_t)cpu_registers(processor)->gpr[arg0+1]; | 
|  | int whence   = (int)cpu_registers(processor)->gpr[arg0+2]; | 
|  | off_t status; | 
|  |  | 
|  | if (WITH_TRACE && ppc_trace[trace_os_emul]) | 
|  | printf_filtered ("%d %ld %d", fildes, (long)offset, whence); | 
|  |  | 
|  | status = fdbad (fildes); | 
|  | if (status == 0) | 
|  | status = lseek(fildes, offset, whence); | 
|  | emul_write_status(processor, (int)status, errno); | 
|  | } | 
|  | #endif | 
|  |  | 
|  |  | 
|  | #if !defined(HAVE_GETGID) || !defined(HAVE_GETEGID) | 
|  | #define do_unix_getgid2 0 | 
|  | #else | 
|  | static void | 
|  | do_unix_getgid2(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | gid_t gid  = getgid(); | 
|  | gid_t egid = getegid(); | 
|  | emul_write2_status(processor, (int)gid, (int)egid, errno); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #ifndef HAVE_GETGID | 
|  | #define do_unix_getgid 0 | 
|  | #else | 
|  | static void | 
|  | do_unix_getgid(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | gid_t status = getgid(); | 
|  | emul_write_status(processor, (int)status, errno); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #ifndef HAVE_GETEGID | 
|  | #define do_unix_getegid 0 | 
|  | #else | 
|  | static void | 
|  | do_unix_getegid(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | gid_t status = getegid(); | 
|  | emul_write_status(processor, (int)status, errno); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #ifndef HAVE_UMASK | 
|  | #define do_unix_umask 0 | 
|  | #else | 
|  | static void | 
|  | do_unix_umask(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | mode_t mask = (mode_t)cpu_registers(processor)->gpr[arg0]; | 
|  | int status = umask(mask); | 
|  |  | 
|  | if (WITH_TRACE && ppc_trace[trace_os_emul]) | 
|  | printf_filtered ("0%o", (unsigned int)mask); | 
|  |  | 
|  | emul_write_status(processor, status, errno); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #ifndef HAVE_CHDIR | 
|  | #define do_unix_chdir 0 | 
|  | #else | 
|  | static void | 
|  | do_unix_chdir(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | unsigned_word path_addr = cpu_registers(processor)->gpr[arg0]; | 
|  | char path_buf[PATH_MAX]; | 
|  | char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia); | 
|  | int status; | 
|  |  | 
|  | if (WITH_TRACE && ppc_trace[trace_os_emul]) | 
|  | printf_filtered ("0x%lx [%s]", (long)path_addr, path); | 
|  |  | 
|  | status = chdir(path); | 
|  | emul_write_status(processor, status, errno); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #ifndef HAVE_LINK | 
|  | #define do_unix_link 0 | 
|  | #else | 
|  | static void | 
|  | do_unix_link(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | unsigned_word path1_addr = cpu_registers(processor)->gpr[arg0]; | 
|  | char path1_buf[PATH_MAX]; | 
|  | char *path1 = emul_read_string(path1_buf, path1_addr, PATH_MAX, processor, cia); | 
|  | unsigned_word path2_addr = cpu_registers(processor)->gpr[arg0+1]; | 
|  | char path2_buf[PATH_MAX]; | 
|  | char *path2 = emul_read_string(path2_buf, path2_addr, PATH_MAX, processor, cia); | 
|  | int status; | 
|  |  | 
|  | if (WITH_TRACE && ppc_trace[trace_os_emul]) | 
|  | printf_filtered ("0x%lx [%s], 0x%lx [%s]", (long)path1_addr, path1, (long)path2_addr, path2); | 
|  |  | 
|  | status = link(path1, path2); | 
|  | emul_write_status(processor, status, errno); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #ifndef HAVE_SYMLINK | 
|  | #define do_unix_symlink 0 | 
|  | #else | 
|  | static void | 
|  | do_unix_symlink(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | unsigned_word path1_addr = cpu_registers(processor)->gpr[arg0]; | 
|  | char path1_buf[PATH_MAX]; | 
|  | char *path1 = emul_read_string(path1_buf, path1_addr, PATH_MAX, processor, cia); | 
|  | unsigned_word path2_addr = cpu_registers(processor)->gpr[arg0+1]; | 
|  | char path2_buf[PATH_MAX]; | 
|  | char *path2 = emul_read_string(path2_buf, path2_addr, PATH_MAX, processor, cia); | 
|  | int status; | 
|  |  | 
|  | if (WITH_TRACE && ppc_trace[trace_os_emul]) | 
|  | printf_filtered ("0x%lx [%s], 0x%lx [%s]", (long)path1_addr, path1, (long)path2_addr, path2); | 
|  |  | 
|  | status = symlink(path1, path2); | 
|  | emul_write_status(processor, status, errno); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #ifndef HAVE_UNLINK | 
|  | #define do_unix_unlink 0 | 
|  | #else | 
|  | static void | 
|  | do_unix_unlink(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | unsigned_word path_addr = cpu_registers(processor)->gpr[arg0]; | 
|  | char path_buf[PATH_MAX]; | 
|  | char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia); | 
|  | int status; | 
|  |  | 
|  | if (WITH_TRACE && ppc_trace[trace_os_emul]) | 
|  | printf_filtered ("0x%lx [%s]", (long)path_addr, path); | 
|  |  | 
|  | status = unlink(path); | 
|  | emul_write_status(processor, status, errno); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #ifndef HAVE_MKDIR | 
|  | #define do_unix_mkdir 0 | 
|  | #else | 
|  | static void | 
|  | do_unix_mkdir(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | unsigned_word path_addr = cpu_registers(processor)->gpr[arg0]; | 
|  | char path_buf[PATH_MAX]; | 
|  | char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia); | 
|  | int mode = (int)cpu_registers(processor)->gpr[arg0+1]; | 
|  | int status; | 
|  |  | 
|  | if (WITH_TRACE && ppc_trace[trace_os_emul]) | 
|  | printf_filtered ("0x%lx [%s], 0%3o", (long)path_addr, path, mode); | 
|  |  | 
|  | #ifdef USE_WIN32API | 
|  | status = mkdir(path); | 
|  | #else | 
|  | status = mkdir(path, mode); | 
|  | #endif | 
|  | emul_write_status(processor, status, errno); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #ifndef HAVE_RMDIR | 
|  | #define do_unix_rmdir 0 | 
|  | #else | 
|  | static void | 
|  | do_unix_rmdir(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | unsigned_word path_addr = cpu_registers(processor)->gpr[arg0]; | 
|  | char path_buf[PATH_MAX]; | 
|  | char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia); | 
|  | int status; | 
|  |  | 
|  | if (WITH_TRACE && ppc_trace[trace_os_emul]) | 
|  | printf_filtered ("0x%lx [%s]", (long)path_addr, path); | 
|  |  | 
|  | status = rmdir(path); | 
|  | emul_write_status(processor, status, errno); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #ifndef HAVE_TIME | 
|  | #define do_unix_time 0 | 
|  | #else | 
|  | static void | 
|  | do_unix_time(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | unsigned_word tp = cpu_registers(processor)->gpr[arg0]; | 
|  | time_t now = time ((time_t *)0); | 
|  | unsigned_word status = H2T_4(now); | 
|  |  | 
|  | if (WITH_TRACE && ppc_trace[trace_os_emul]) | 
|  | printf_filtered ("0x%lx", (long)tp); | 
|  |  | 
|  | emul_write_status(processor, (int)status, errno); | 
|  |  | 
|  | if (tp) | 
|  | emul_write_buffer(&status, tp, sizeof(status), processor, cia); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #if !defined(HAVE_GETTIMEOFDAY) || !defined(HAVE_SYS_TIME_H) | 
|  | #define do_unix_gettimeofday 0 | 
|  | #else | 
|  | static void | 
|  | do_unix_gettimeofday(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | unsigned_word tv = cpu_registers(processor)->gpr[arg0]; | 
|  | unsigned_word tz = cpu_registers(processor)->gpr[arg0+1]; | 
|  | struct unix_timeval target_timeval; | 
|  | struct timeval host_timeval; | 
|  | struct unix_timezone target_timezone; | 
|  | struct timezone host_timezone; | 
|  | int status; | 
|  |  | 
|  | if (WITH_TRACE && ppc_trace[trace_os_emul]) | 
|  | printf_filtered ("0x%lx, 0x%lx", (long)tv, (long)tz); | 
|  |  | 
|  | /* Just in case the system doesn't set the timezone structure */ | 
|  | host_timezone.tz_minuteswest = 0; | 
|  | host_timezone.tz_dsttime = 0; | 
|  |  | 
|  | status = gettimeofday(&host_timeval, &host_timezone); | 
|  | if (status >= 0) { | 
|  | if (tv) { | 
|  | target_timeval.tv_sec = H2T_4(host_timeval.tv_sec); | 
|  | target_timeval.tv_usec = H2T_4(host_timeval.tv_usec); | 
|  | emul_write_buffer((void *) &target_timeval, tv, sizeof(target_timeval), processor, cia); | 
|  | } | 
|  |  | 
|  | if (tz) { | 
|  | target_timezone.tz_minuteswest = H2T_4(host_timezone.tz_minuteswest); | 
|  | target_timezone.tz_dsttime = H2T_4(host_timezone.tz_dsttime); | 
|  | emul_write_buffer((void *) &target_timezone, tv, sizeof(target_timezone), processor, cia); | 
|  | } | 
|  | } | 
|  |  | 
|  | emul_write_status(processor, (int)status, errno); | 
|  | } | 
|  | #endif | 
|  |  | 
|  |  | 
|  | #ifndef HAVE_GETRUSAGE | 
|  | #define do_unix_getrusage 0 | 
|  | #else | 
|  | static void | 
|  | do_unix_getrusage(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | signed_word who = (signed_word)cpu_registers(processor)->gpr[arg0]; | 
|  | unsigned_word usage = cpu_registers(processor)->gpr[arg0+1]; | 
|  | struct rusage host_rusage, host_rusage2; | 
|  | struct unix_rusage target_rusage; | 
|  | int status; | 
|  |  | 
|  | if (WITH_TRACE && ppc_trace[trace_os_emul]) | 
|  | printf_filtered ("%ld, 0x%lx", (long)who, (long)usage); | 
|  |  | 
|  | switch (who) { | 
|  | default: | 
|  | status = -1; | 
|  | errno = EINVAL; | 
|  | break; | 
|  |  | 
|  | case UNIX_RUSAGE_SELF: | 
|  | status = getrusage(RUSAGE_SELF, &host_rusage); | 
|  | break; | 
|  |  | 
|  | case UNIX_RUSAGE_CHILDREN: | 
|  | status = getrusage(RUSAGE_CHILDREN, &host_rusage); | 
|  | break; | 
|  |  | 
|  | case UNIX_RUSAGE_BOTH: | 
|  | status = getrusage(RUSAGE_SELF, &host_rusage); | 
|  | if (status >= 0) { | 
|  | status = getrusage(RUSAGE_CHILDREN, &host_rusage2); | 
|  | if (status >= 0) { | 
|  | host_rusage.ru_utime.tv_sec += host_rusage2.ru_utime.tv_sec; | 
|  | host_rusage.ru_utime.tv_usec += host_rusage2.ru_utime.tv_usec; | 
|  | host_rusage.ru_stime.tv_sec += host_rusage2.ru_stime.tv_sec; | 
|  | host_rusage.ru_stime.tv_usec += host_rusage2.ru_stime.tv_usec; | 
|  | host_rusage.ru_maxrss += host_rusage2.ru_maxrss; | 
|  | host_rusage.ru_ixrss += host_rusage2.ru_ixrss; | 
|  | host_rusage.ru_idrss += host_rusage2.ru_idrss; | 
|  | host_rusage.ru_isrss += host_rusage2.ru_isrss; | 
|  | host_rusage.ru_minflt += host_rusage2.ru_minflt; | 
|  | host_rusage.ru_majflt += host_rusage2.ru_majflt; | 
|  | host_rusage.ru_nswap += host_rusage2.ru_nswap; | 
|  | host_rusage.ru_inblock += host_rusage2.ru_inblock; | 
|  | host_rusage.ru_oublock += host_rusage2.ru_oublock; | 
|  | host_rusage.ru_msgsnd += host_rusage2.ru_msgsnd; | 
|  | host_rusage.ru_msgrcv += host_rusage2.ru_msgrcv; | 
|  | host_rusage.ru_nsignals += host_rusage2.ru_nsignals; | 
|  | host_rusage.ru_nvcsw += host_rusage2.ru_nvcsw; | 
|  | host_rusage.ru_nivcsw += host_rusage2.ru_nivcsw; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | if (status >= 0) { | 
|  | target_rusage.ru_utime.tv_sec = H2T_4(host_rusage2.ru_utime.tv_sec); | 
|  | target_rusage.ru_utime.tv_usec = H2T_4(host_rusage2.ru_utime.tv_usec); | 
|  | target_rusage.ru_stime.tv_sec = H2T_4(host_rusage2.ru_stime.tv_sec); | 
|  | target_rusage.ru_stime.tv_usec = H2T_4(host_rusage2.ru_stime.tv_usec); | 
|  | target_rusage.ru_maxrss = H2T_4(host_rusage2.ru_maxrss); | 
|  | target_rusage.ru_ixrss = H2T_4(host_rusage2.ru_ixrss); | 
|  | target_rusage.ru_idrss = H2T_4(host_rusage2.ru_idrss); | 
|  | target_rusage.ru_isrss = H2T_4(host_rusage2.ru_isrss); | 
|  | target_rusage.ru_minflt = H2T_4(host_rusage2.ru_minflt); | 
|  | target_rusage.ru_majflt = H2T_4(host_rusage2.ru_majflt); | 
|  | target_rusage.ru_nswap = H2T_4(host_rusage2.ru_nswap); | 
|  | target_rusage.ru_inblock = H2T_4(host_rusage2.ru_inblock); | 
|  | target_rusage.ru_oublock = H2T_4(host_rusage2.ru_oublock); | 
|  | target_rusage.ru_msgsnd = H2T_4(host_rusage2.ru_msgsnd); | 
|  | target_rusage.ru_msgrcv = H2T_4(host_rusage2.ru_msgrcv); | 
|  | target_rusage.ru_nsignals = H2T_4(host_rusage2.ru_nsignals); | 
|  | target_rusage.ru_nvcsw = H2T_4(host_rusage2.ru_nvcsw); | 
|  | target_rusage.ru_nivcsw = H2T_4(host_rusage2.ru_nivcsw); | 
|  | emul_write_buffer((void *) &target_rusage, usage, sizeof(target_rusage), processor, cia); | 
|  | } | 
|  |  | 
|  | emul_write_status(processor, status, errno); | 
|  | } | 
|  | #endif | 
|  |  | 
|  |  | 
|  | static void | 
|  | do_unix_nop(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | if (WITH_TRACE && ppc_trace[trace_os_emul]) | 
|  | printf_filtered ("0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx", | 
|  | (long)cpu_registers(processor)->gpr[arg0], | 
|  | (long)cpu_registers(processor)->gpr[arg0+1], | 
|  | (long)cpu_registers(processor)->gpr[arg0+2], | 
|  | (long)cpu_registers(processor)->gpr[arg0+3], | 
|  | (long)cpu_registers(processor)->gpr[arg0+4], | 
|  | (long)cpu_registers(processor)->gpr[arg0+5]); | 
|  |  | 
|  | emul_write_status(processor, 0, errno); | 
|  | } | 
|  |  | 
|  |  | 
|  | /* Common code for initializing the system call stuff */ | 
|  |  | 
|  | static os_emul_data * | 
|  | emul_unix_create(device *root, | 
|  | bfd *image, | 
|  | const char *name, | 
|  | emul_syscall *syscall) | 
|  | { | 
|  | unsigned_word top_of_stack; | 
|  | unsigned stack_size; | 
|  | int elf_binary; | 
|  | os_emul_data *data; | 
|  | device *vm; | 
|  | char *filename; | 
|  |  | 
|  | /* merge any emulation specific entries into the device tree */ | 
|  |  | 
|  | /* establish a few defaults */ | 
|  | if (image->xvec->flavour == bfd_target_elf_flavour) { | 
|  | elf_binary = 1; | 
|  | top_of_stack = 0xe0000000; | 
|  | stack_size =   0x00100000; | 
|  | } | 
|  | else { | 
|  | elf_binary = 0; | 
|  | top_of_stack = 0x20000000; | 
|  | stack_size =   0x00100000; | 
|  | } | 
|  |  | 
|  | /* options */ | 
|  | emul_add_tree_options(root, image, name, | 
|  | (WITH_ENVIRONMENT == USER_ENVIRONMENT | 
|  | ? "user" : "virtual"), | 
|  | 0 /*oea-interrupt-prefix*/); | 
|  |  | 
|  | /* virtual memory - handles growth of stack/heap */ | 
|  | vm = tree_parse(root, "/openprom/vm@0x%lx", | 
|  | (unsigned long)(top_of_stack - stack_size)); | 
|  | tree_parse(vm, "./stack-base 0x%lx", | 
|  | (unsigned long)(top_of_stack - stack_size)); | 
|  | tree_parse(vm, "./nr-bytes 0x%x", stack_size); | 
|  |  | 
|  | filename = tree_quote_property (bfd_get_filename(image)); | 
|  | tree_parse(root, "/openprom/vm/map-binary/file-name %s", | 
|  | filename); | 
|  | free (filename); | 
|  |  | 
|  | /* finish the init */ | 
|  | tree_parse(root, "/openprom/init/register/pc 0x%lx", | 
|  | (unsigned long)bfd_get_start_address(image)); | 
|  | tree_parse(root, "/openprom/init/register/sp 0x%lx", | 
|  | (unsigned long)top_of_stack); | 
|  | tree_parse(root, "/openprom/init/register/msr 0x%x", | 
|  | ((tree_find_boolean_property(root, "/options/little-endian?") | 
|  | ? msr_little_endian_mode | 
|  | : 0) | 
|  | | (tree_find_boolean_property(root, "/openprom/options/floating-point?") | 
|  | ? (msr_floating_point_available | 
|  | | msr_floating_point_exception_mode_0 | 
|  | | msr_floating_point_exception_mode_1) | 
|  | : 0))); | 
|  | tree_parse(root, "/openprom/init/stack/stack-type %s", | 
|  | (elf_binary ? "ppc-elf" : "ppc-xcoff")); | 
|  |  | 
|  | /* finally our emulation data */ | 
|  | data = ZALLOC(os_emul_data); | 
|  | data->vm = vm; | 
|  | data->syscalls = syscall; | 
|  | return data; | 
|  | } | 
|  |  | 
|  |  | 
|  | /* EMULATION | 
|  |  | 
|  | Solaris - Emulation of user programs for Solaris/PPC | 
|  |  | 
|  | DESCRIPTION | 
|  |  | 
|  | */ | 
|  |  | 
|  |  | 
|  | /* Solaris specific implementation */ | 
|  |  | 
|  | typedef	signed32	solaris_uid_t; | 
|  | typedef	signed32	solaris_gid_t; | 
|  | typedef signed32	solaris_off_t; | 
|  | typedef signed32	solaris_pid_t; | 
|  | typedef signed32	solaris_time_t; | 
|  | typedef unsigned32	solaris_dev_t; | 
|  | typedef unsigned32	solaris_ino_t; | 
|  | typedef unsigned32	solaris_mode_t; | 
|  | typedef	unsigned32	solaris_nlink_t; | 
|  |  | 
|  | #ifdef HAVE_SYS_STAT_H | 
|  | #define	SOLARIS_ST_FSTYPSZ 16		/* array size for file system type name */ | 
|  |  | 
|  | /* AIX 7.1 defines st_pad[123] to st_[amc]tim.tv_pad, respectively */ | 
|  | #undef st_pad1 | 
|  | #undef st_pad2 | 
|  | #undef st_pad3 | 
|  |  | 
|  | struct solaris_stat { | 
|  | solaris_dev_t		st_dev; | 
|  | signed32		st_pad1[3];	/* reserved for network id */ | 
|  | solaris_ino_t		st_ino; | 
|  | solaris_mode_t	st_mode; | 
|  | solaris_nlink_t 	st_nlink; | 
|  | solaris_uid_t 	st_uid; | 
|  | solaris_gid_t 	st_gid; | 
|  | solaris_dev_t		st_rdev; | 
|  | signed32		st_pad2[2]; | 
|  | solaris_off_t		st_size; | 
|  | signed32		st_pad3;	/* future off_t expansion */ | 
|  | struct unix_timeval	st_atim; | 
|  | struct unix_timeval	st_mtim; | 
|  | struct unix_timeval	st_ctim; | 
|  | signed32		st_blksize; | 
|  | signed32		st_blocks; | 
|  | char			st_fstype[SOLARIS_ST_FSTYPSZ]; | 
|  | signed32		st_pad4[8];	/* expansion area */ | 
|  | }; | 
|  |  | 
|  | /* Convert from host stat structure to solaris stat structure */ | 
|  | STATIC_INLINE_EMUL_UNIX void | 
|  | convert_to_solaris_stat(unsigned_word addr, | 
|  | struct stat *host, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | struct solaris_stat target; | 
|  | int i; | 
|  |  | 
|  | target.st_dev   = H2T_4(host->st_dev); | 
|  | target.st_ino   = H2T_4(host->st_ino); | 
|  | target.st_mode  = H2T_4(host->st_mode); | 
|  | target.st_nlink = H2T_4(host->st_nlink); | 
|  | target.st_uid   = H2T_4(host->st_uid); | 
|  | target.st_gid   = H2T_4(host->st_gid); | 
|  | target.st_size  = H2T_4(host->st_size); | 
|  |  | 
|  | #ifdef HAVE_ST_RDEV | 
|  | target.st_rdev  = H2T_4(host->st_rdev); | 
|  | #else | 
|  | target.st_rdev  = 0; | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_ST_BLKSIZE | 
|  | target.st_blksize = H2T_4(host->st_blksize); | 
|  | #else | 
|  | target.st_blksize = 0; | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_ST_BLOCKS | 
|  | target.st_blocks  = H2T_4(host->st_blocks); | 
|  | #else | 
|  | target.st_blocks  = 0; | 
|  | #endif | 
|  |  | 
|  | target.st_atim.tv_sec  = H2T_4(host->st_atime); | 
|  | target.st_atim.tv_usec = 0; | 
|  |  | 
|  | target.st_ctim.tv_sec  = H2T_4(host->st_ctime); | 
|  | target.st_ctim.tv_usec = 0; | 
|  |  | 
|  | target.st_mtim.tv_sec  = H2T_4(host->st_mtime); | 
|  | target.st_mtim.tv_usec = 0; | 
|  |  | 
|  | for (i = 0; i < ARRAY_SIZE (target.st_pad1); i++) | 
|  | target.st_pad1[i] = 0; | 
|  |  | 
|  | for (i = 0; i < ARRAY_SIZE (target.st_pad2); i++) | 
|  | target.st_pad2[i] = 0; | 
|  |  | 
|  | target.st_pad3 = 0; | 
|  |  | 
|  | for (i = 0; i < ARRAY_SIZE (target.st_pad4); i++) | 
|  | target.st_pad4[i] = 0; | 
|  |  | 
|  | /* For now, just punt and always say it is a ufs file */ | 
|  | strcpy (target.st_fstype, "ufs"); | 
|  |  | 
|  | emul_write_buffer(&target, addr, sizeof(target), processor, cia); | 
|  | } | 
|  | #endif /* HAVE_SYS_STAT_H */ | 
|  |  | 
|  | #ifndef HAVE_STAT | 
|  | #define do_solaris_stat 0 | 
|  | #else | 
|  | static void | 
|  | do_solaris_stat(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | unsigned_word path_addr = cpu_registers(processor)->gpr[arg0]; | 
|  | unsigned_word stat_pkt = cpu_registers(processor)->gpr[arg0+1]; | 
|  | char path_buf[PATH_MAX]; | 
|  | struct stat buf; | 
|  | char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia); | 
|  | int status; | 
|  |  | 
|  | if (WITH_TRACE && ppc_trace[trace_os_emul]) | 
|  | printf_filtered ("0x%lx [%s], 0x%lx", (long)path_addr, path, (long)stat_pkt); | 
|  |  | 
|  | status = stat (path, &buf); | 
|  | if (status == 0) | 
|  | convert_to_solaris_stat (stat_pkt, &buf, processor, cia); | 
|  |  | 
|  | emul_write_status(processor, status, errno); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #ifndef HAVE_LSTAT | 
|  | #define do_solaris_lstat 0 | 
|  | #else | 
|  | static void | 
|  | do_solaris_lstat(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | unsigned_word path_addr = cpu_registers(processor)->gpr[arg0]; | 
|  | unsigned_word stat_pkt = cpu_registers(processor)->gpr[arg0+1]; | 
|  | char path_buf[PATH_MAX]; | 
|  | struct stat buf; | 
|  | char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia); | 
|  | int status; | 
|  |  | 
|  | if (WITH_TRACE && ppc_trace[trace_os_emul]) | 
|  | printf_filtered ("0x%lx [%s], 0x%lx", (long)path_addr, path, (long)stat_pkt); | 
|  |  | 
|  | status = lstat (path, &buf); | 
|  | if (status == 0) | 
|  | convert_to_solaris_stat (stat_pkt, &buf, processor, cia); | 
|  |  | 
|  | emul_write_status(processor, status, errno); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #ifndef HAVE_FSTAT | 
|  | #define do_solaris_fstat 0 | 
|  | #else | 
|  | static void | 
|  | do_solaris_fstat(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | int fildes = (int)cpu_registers(processor)->gpr[arg0]; | 
|  | unsigned_word stat_pkt = cpu_registers(processor)->gpr[arg0+1]; | 
|  | struct stat buf; | 
|  | int status; | 
|  |  | 
|  | if (WITH_TRACE && ppc_trace[trace_os_emul]) | 
|  | printf_filtered ("%d, 0x%lx", fildes, (long)stat_pkt); | 
|  |  | 
|  | status = fdbad (fildes); | 
|  | if (status == 0) | 
|  | status = fstat (fildes, &buf); | 
|  | if (status == 0) | 
|  | convert_to_solaris_stat (stat_pkt, &buf, processor, cia); | 
|  |  | 
|  | emul_write_status(processor, status, errno); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #if defined(HAVE_TERMIO_STRUCTURE) || defined(HAVE_TERMIOS_STRUCTURE) | 
|  | #define	SOLARIS_TIOC	  ('T'<<8) | 
|  | #define SOLARIS_NCC	  8 | 
|  | #define SOLARIS_NCCS	  19 | 
|  |  | 
|  | #define	SOLARIS_VINTR	  0 | 
|  | #define	SOLARIS_VQUIT	  1 | 
|  | #define	SOLARIS_VERASE	  2 | 
|  | #define	SOLARIS_VKILL	  3 | 
|  | #define	SOLARIS_VEOF	  4 | 
|  | #define	SOLARIS_VEOL	  5 | 
|  | #define	SOLARIS_VEOL2	  6 | 
|  | #define	SOLARIS_VSWTCH	  7 | 
|  | #define	SOLARIS_VSTART	  8 | 
|  | #define	SOLARIS_VSTOP	  9 | 
|  | #define	SOLARIS_VSUSP	 10 | 
|  | #define	SOLARIS_VDSUSP	 11 | 
|  | #define	SOLARIS_VREPRINT 12 | 
|  | #define	SOLARIS_VDISCARD 13 | 
|  | #define	SOLARIS_VWERASE	 14 | 
|  | #define	SOLARIS_VLNEXT	 15 | 
|  | #endif | 
|  |  | 
|  | #if defined(HAVE_TERMIO_STRUCTURE) || defined(HAVE_TERMIOS_STRUCTURE) | 
|  | /* Convert to/from host termio structure */ | 
|  |  | 
|  | struct solaris_termio { | 
|  | unsigned16	c_iflag;		/* input modes */ | 
|  | unsigned16	c_oflag;		/* output modes */ | 
|  | unsigned16	c_cflag;		/* control modes */ | 
|  | unsigned16	c_lflag;		/* line discipline modes */ | 
|  | unsigned8	c_line;			/* line discipline */ | 
|  | unsigned8	c_cc[SOLARIS_NCC];	/* control chars */ | 
|  | }; | 
|  |  | 
|  | STATIC_INLINE_EMUL_UNIX void | 
|  | convert_to_solaris_termio(unsigned_word addr, | 
|  | struct termio *host, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | struct solaris_termio target; | 
|  | int i; | 
|  |  | 
|  | target.c_iflag = H2T_2 (host->c_iflag); | 
|  | target.c_oflag = H2T_2 (host->c_oflag); | 
|  | target.c_cflag = H2T_2 (host->c_cflag); | 
|  | target.c_lflag = H2T_2 (host->c_lflag); | 
|  |  | 
|  | #if defined(HAVE_TERMIO_CLINE) || defined(HAVE_TERMIOS_CLINE) | 
|  | target.c_line  = host->c_line; | 
|  | #else | 
|  | target.c_line  = 0; | 
|  | #endif | 
|  |  | 
|  | for (i = 0; i < SOLARIS_NCC; i++) | 
|  | target.c_cc[i] = 0; | 
|  |  | 
|  | #ifdef VINTR | 
|  | target.c_cc[SOLARIS_VINTR] = host->c_cc[VINTR]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VQUIT | 
|  | target.c_cc[SOLARIS_VQUIT] = host->c_cc[VQUIT]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VERASE | 
|  | target.c_cc[SOLARIS_VERASE] = host->c_cc[VERASE]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VKILL | 
|  | target.c_cc[SOLARIS_VKILL] = host->c_cc[VKILL]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VEOF | 
|  | target.c_cc[SOLARIS_VEOF] = host->c_cc[VEOF]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VEOL | 
|  | target.c_cc[SOLARIS_VEOL] = host->c_cc[VEOL]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VEOL2 | 
|  | target.c_cc[SOLARIS_VEOL2] = host->c_cc[VEOL2]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VSWTCH | 
|  | target.c_cc[SOLARIS_VSWTCH] = host->c_cc[VSWTCH]; | 
|  |  | 
|  | #else | 
|  | #ifdef VSWTC | 
|  | target.c_cc[SOLARIS_VSWTCH] = host->c_cc[VSWTC]; | 
|  | #endif | 
|  | #endif | 
|  |  | 
|  | emul_write_buffer(&target, addr, sizeof(target), processor, cia); | 
|  | } | 
|  | #endif /* HAVE_TERMIO_STRUCTURE || HAVE_TERMIOS_STRUCTURE */ | 
|  |  | 
|  | #ifdef HAVE_TERMIOS_STRUCTURE | 
|  | /* Convert to/from host termios structure */ | 
|  |  | 
|  | typedef unsigned32 solaris_tcflag_t; | 
|  | typedef unsigned8  solaris_cc_t; | 
|  | typedef unsigned32 solaris_speed_t; | 
|  |  | 
|  | struct solaris_termios { | 
|  | solaris_tcflag_t	c_iflag; | 
|  | solaris_tcflag_t	c_oflag; | 
|  | solaris_tcflag_t	c_cflag; | 
|  | solaris_tcflag_t	c_lflag; | 
|  | solaris_cc_t		c_cc[SOLARIS_NCCS]; | 
|  | }; | 
|  |  | 
|  | STATIC_INLINE_EMUL_UNIX void | 
|  | convert_to_solaris_termios(unsigned_word addr, | 
|  | struct termios *host, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | struct solaris_termios target; | 
|  | int i; | 
|  |  | 
|  | target.c_iflag = H2T_4 (host->c_iflag); | 
|  | target.c_oflag = H2T_4 (host->c_oflag); | 
|  | target.c_cflag = H2T_4 (host->c_cflag); | 
|  | target.c_lflag = H2T_4 (host->c_lflag); | 
|  |  | 
|  | for (i = 0; i < SOLARIS_NCCS; i++) | 
|  | target.c_cc[i] = 0; | 
|  |  | 
|  | #ifdef VINTR | 
|  | target.c_cc[SOLARIS_VINTR] = host->c_cc[VINTR]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VQUIT | 
|  | target.c_cc[SOLARIS_VQUIT] = host->c_cc[VQUIT]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VERASE | 
|  | target.c_cc[SOLARIS_VERASE] = host->c_cc[VERASE]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VKILL | 
|  | target.c_cc[SOLARIS_VKILL] = host->c_cc[VKILL]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VEOF | 
|  | target.c_cc[SOLARIS_VEOF] = host->c_cc[VEOF]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VEOL | 
|  | target.c_cc[SOLARIS_VEOL] = host->c_cc[VEOL]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VEOL2 | 
|  | target.c_cc[SOLARIS_VEOL2] = host->c_cc[VEOL2]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VSWTCH | 
|  | target.c_cc[SOLARIS_VSWTCH] = host->c_cc[VSWTCH]; | 
|  |  | 
|  | #else | 
|  | #ifdef VSWTC | 
|  | target.c_cc[SOLARIS_VSWTCH] = host->c_cc[VSWTC]; | 
|  | #endif | 
|  | #endif | 
|  |  | 
|  | #ifdef VSTART | 
|  | target.c_cc[SOLARIS_VSTART] = host->c_cc[VSTART]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VSTOP | 
|  | target.c_cc[SOLARIS_VSTOP] = host->c_cc[VSTOP]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VSUSP | 
|  | target.c_cc[SOLARIS_VSUSP] = host->c_cc[VSUSP]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VDSUSP | 
|  | target.c_cc[SOLARIS_VDSUSP] = host->c_cc[VDSUSP]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VREPRINT | 
|  | target.c_cc[SOLARIS_VREPRINT] = host->c_cc[VREPRINT]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VDISCARD | 
|  | target.c_cc[SOLARIS_VDISCARD] = host->c_cc[VDISCARD]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VWERASE | 
|  | target.c_cc[SOLARIS_VWERASE] = host->c_cc[VWERASE]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VLNEXT | 
|  | target.c_cc[SOLARIS_VLNEXT] = host->c_cc[VLNEXT]; | 
|  | #endif | 
|  |  | 
|  | emul_write_buffer(&target, addr, sizeof(target), processor, cia); | 
|  | } | 
|  | #endif /* HAVE_TERMIOS_STRUCTURE */ | 
|  |  | 
|  | #ifndef HAVE_IOCTL | 
|  | #define do_solaris_ioctl 0 | 
|  | #else | 
|  | static void | 
|  | do_solaris_ioctl(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | int fildes = cpu_registers(processor)->gpr[arg0]; | 
|  | unsigned request = cpu_registers(processor)->gpr[arg0+1]; | 
|  | unsigned_word argp_addr = cpu_registers(processor)->gpr[arg0+2]; | 
|  | int status = 0; | 
|  | const char *name = "<unknown>"; | 
|  |  | 
|  | #ifdef HAVE_TERMIOS_STRUCTURE | 
|  | struct termios host_termio; | 
|  |  | 
|  | #else | 
|  | #ifdef HAVE_TERMIO_STRUCTURE | 
|  | struct termio host_termio; | 
|  | #endif | 
|  | #endif | 
|  |  | 
|  | status = fdbad (fildes); | 
|  | if (status != 0) | 
|  | goto done; | 
|  |  | 
|  | switch (request) | 
|  | { | 
|  | case 0:					/* make sure we have at least one case */ | 
|  | default: | 
|  | status = -1; | 
|  | errno = EINVAL; | 
|  | break; | 
|  |  | 
|  | #if defined(HAVE_TERMIO_STRUCTURE) || defined(HAVE_TERMIOS_STRUCTURE) | 
|  | #if defined(TCGETA) || defined(TCGETS) || defined(HAVE_TCGETATTR) | 
|  | case SOLARIS_TIOC | 1:			/* TCGETA */ | 
|  | name = "TCGETA"; | 
|  | #ifdef HAVE_TCGETATTR | 
|  | status = tcgetattr(fildes, &host_termio); | 
|  | #elif defined(TCGETS) | 
|  | status = ioctl (fildes, TCGETS, &host_termio); | 
|  | #else | 
|  | status = ioctl (fildes, TCGETA, &host_termio); | 
|  | #endif | 
|  | if (status == 0) | 
|  | convert_to_solaris_termio (argp_addr, &host_termio, processor, cia); | 
|  | break; | 
|  | #endif /* TCGETA */ | 
|  | #endif /* HAVE_TERMIO_STRUCTURE */ | 
|  |  | 
|  | #ifdef HAVE_TERMIOS_STRUCTURE | 
|  | #if defined(TCGETS) || defined(HAVE_TCGETATTR) | 
|  | case SOLARIS_TIOC | 13:			/* TCGETS */ | 
|  | name = "TCGETS"; | 
|  | #ifdef HAVE_TCGETATTR | 
|  | status = tcgetattr(fildes, &host_termio); | 
|  | #else | 
|  | status = ioctl (fildes, TCGETS, &host_termio); | 
|  | #endif | 
|  | if (status == 0) | 
|  | convert_to_solaris_termios (argp_addr, &host_termio, processor, cia); | 
|  | break; | 
|  | #endif /* TCGETS */ | 
|  | #endif /* HAVE_TERMIOS_STRUCTURE */ | 
|  | } | 
|  |  | 
|  | done: | 
|  | emul_write_status(processor, status, errno); | 
|  |  | 
|  | if (WITH_TRACE && ppc_trace[trace_os_emul]) | 
|  | printf_filtered ("%d, 0x%x [%s], 0x%lx", fildes, request, name, (long)argp_addr); | 
|  | } | 
|  | #endif /* HAVE_IOCTL */ | 
|  |  | 
|  | static emul_syscall_descriptor solaris_descriptors[] = { | 
|  | /*   0 */ { 0, "syscall" }, | 
|  | /*   1 */ { do_unix_exit, "exit" }, | 
|  | /*   2 */ { 0, "fork" }, | 
|  | /*   3 */ { do_unix_read, "read" }, | 
|  | /*   4 */ { do_unix_write, "write" }, | 
|  | /*   5 */ { do_unix_open, "open" }, | 
|  | /*   6 */ { do_unix_close, "close" }, | 
|  | /*   7 */ { 0, "wait" }, | 
|  | /*   8 */ { 0, "creat" }, | 
|  | /*   9 */ { do_unix_link, "link" }, | 
|  | /*  10 */ { do_unix_unlink, "unlink" }, | 
|  | /*  11 */ { 0, "exec" }, | 
|  | /*  12 */ { do_unix_chdir, "chdir" }, | 
|  | /*  13 */ { do_unix_time, "time" }, | 
|  | /*  14 */ { 0, "mknod" }, | 
|  | /*  15 */ { 0, "chmod" }, | 
|  | /*  16 */ { 0, "chown" }, | 
|  | /*  17 */ { do_unix_break, "brk" }, | 
|  | /*  18 */ { do_solaris_stat, "stat" }, | 
|  | /*  19 */ { do_unix_lseek, "lseek" }, | 
|  | /*  20 */ { do_unix_getpid2, "getpid" }, | 
|  | /*  21 */ { 0, "mount" }, | 
|  | /*  22 */ { 0, "umount" }, | 
|  | /*  23 */ { 0, "setuid" }, | 
|  | /*  24 */ { do_unix_getuid2, "getuid" }, | 
|  | /*  25 */ { 0, "stime" }, | 
|  | /*  26 */ { 0, "ptrace" }, | 
|  | /*  27 */ { 0, "alarm" }, | 
|  | /*  28 */ { do_solaris_fstat, "fstat" }, | 
|  | /*  29 */ { 0, "pause" }, | 
|  | /*  30 */ { 0, "utime" }, | 
|  | /*  31 */ { 0, "stty" }, | 
|  | /*  32 */ { 0, "gtty" }, | 
|  | /*  33 */ { do_unix_access, "access" }, | 
|  | /*  34 */ { 0, "nice" }, | 
|  | /*  35 */ { 0, "statfs" }, | 
|  | /*  36 */ { 0, "sync" }, | 
|  | /*  37 */ { 0, "kill" }, | 
|  | /*  38 */ { 0, "fstatfs" }, | 
|  | /*  39 */ { 0, "pgrpsys" }, | 
|  | /*  40 */ { 0, "xenix" }, | 
|  | /*  41 */ { do_unix_dup, "dup" }, | 
|  | /*  42 */ { 0, "pipe" }, | 
|  | /*  43 */ { 0, "times" }, | 
|  | /*  44 */ { 0, "profil" }, | 
|  | /*  45 */ { 0, "plock" }, | 
|  | /*  46 */ { 0, "setgid" }, | 
|  | /*  47 */ { do_unix_getgid2, "getgid" }, | 
|  | /*  48 */ { 0, "signal" }, | 
|  | /*  49 */ { 0, "msgsys" }, | 
|  | /*  50 */ { 0, "syssun" }, | 
|  | /*  51 */ { 0, "acct" }, | 
|  | /*  52 */ { 0, "shmsys" }, | 
|  | /*  53 */ { 0, "semsys" }, | 
|  | /*  54 */ { do_solaris_ioctl, "ioctl" }, | 
|  | /*  55 */ { 0, "uadmin" }, | 
|  | /*  56 */ { 0, 0 /* reserved for exch */ }, | 
|  | /*  57 */ { 0, "utssys" }, | 
|  | /*  58 */ { 0, "fdsync" }, | 
|  | /*  59 */ { 0, "execve" }, | 
|  | /*  60 */ { do_unix_umask, "umask" }, | 
|  | /*  61 */ { 0, "chroot" }, | 
|  | /*  62 */ { 0, "fcntl" }, | 
|  | /*  63 */ { 0, "ulimit" }, | 
|  | /*  64 */ { 0, 0 /* reserved for UNIX PC */ }, | 
|  | /*  64 */ { 0, 0 /* reserved for UNIX PC */ }, | 
|  | /*  65 */ { 0, 0 /* reserved for UNIX PC */ }, | 
|  | /*  66 */ { 0, 0 /* reserved for UNIX PC */ }, | 
|  | /*  67 */ { 0, 0 /* reserved for UNIX PC */ }, | 
|  | /*  68 */ { 0, 0 /* reserved for UNIX PC */ }, | 
|  | /*  69 */ { 0, 0 /* reserved for UNIX PC */ }, | 
|  | /*  70 */ { 0, 0 /* was advfs */ }, | 
|  | /*  71 */ { 0, 0 /* was unadvfs */ }, | 
|  | /*  72 */ { 0, 0 /* was rmount */ }, | 
|  | /*  73 */ { 0, 0 /* was rumount */ }, | 
|  | /*  74 */ { 0, 0 /* was rfstart */ }, | 
|  | /*  75 */ { 0, 0 /* was sigret */ }, | 
|  | /*  76 */ { 0, 0 /* was rdebug */ }, | 
|  | /*  77 */ { 0, 0 /* was rfstop */ }, | 
|  | /*  78 */ { 0, 0 /* was rfsys */ }, | 
|  | /*  79 */ { do_unix_rmdir, "rmdir" }, | 
|  | /*  80 */ { do_unix_mkdir, "mkdir" }, | 
|  | /*  81 */ { 0, "getdents" }, | 
|  | /*  82 */ { 0, 0 /* was libattach */ }, | 
|  | /*  83 */ { 0, 0 /* was libdetach */ }, | 
|  | /*  84 */ { 0, "sysfs" }, | 
|  | /*  85 */ { 0, "getmsg" }, | 
|  | /*  86 */ { 0, "putmsg" }, | 
|  | /*  87 */ { 0, "poll" }, | 
|  | /*  88 */ { do_solaris_lstat, "lstat" }, | 
|  | /*  89 */ { do_unix_symlink, "symlink" }, | 
|  | /*  90 */ { 0, "readlink" }, | 
|  | /*  91 */ { 0, "setgroups" }, | 
|  | /*  92 */ { 0, "getgroups" }, | 
|  | /*  93 */ { 0, "fchmod" }, | 
|  | /*  94 */ { 0, "fchown" }, | 
|  | /*  95 */ { 0, "sigprocmask" }, | 
|  | /*  96 */ { 0, "sigsuspend" }, | 
|  | /*  97 */ { do_unix_nop, "sigaltstack" }, | 
|  | /*  98 */ { do_unix_nop, "sigaction" }, | 
|  | /*  99 */ { 0, "sigpending" }, | 
|  | /* 100 */ { 0, "context" }, | 
|  | /* 101 */ { 0, "evsys" }, | 
|  | /* 102 */ { 0, "evtrapret" }, | 
|  | /* 103 */ { 0, "statvfs" }, | 
|  | /* 104 */ { 0, "fstatvfs" }, | 
|  | /* 105 */ { 0, 0 /* reserved */ }, | 
|  | /* 106 */ { 0, "nfssys" }, | 
|  | /* 107 */ { 0, "waitsys" }, | 
|  | /* 108 */ { 0, "sigsendsys" }, | 
|  | /* 109 */ { 0, "hrtsys" }, | 
|  | /* 110 */ { 0, "acancel" }, | 
|  | /* 111 */ { 0, "async" }, | 
|  | /* 112 */ { 0, "priocntlsys" }, | 
|  | /* 113 */ { 0, "pathconf" }, | 
|  | /* 114 */ { 0, "mincore" }, | 
|  | /* 115 */ { 0, "mmap" }, | 
|  | /* 116 */ { 0, "mprotect" }, | 
|  | /* 117 */ { 0, "munmap" }, | 
|  | /* 118 */ { 0, "fpathconf" }, | 
|  | /* 119 */ { 0, "vfork" }, | 
|  | /* 120 */ { 0, "fchdir" }, | 
|  | /* 121 */ { 0, "readv" }, | 
|  | /* 122 */ { 0, "writev" }, | 
|  | /* 123 */ { 0, "xstat" }, | 
|  | /* 124 */ { 0, "lxstat" }, | 
|  | /* 125 */ { 0, "fxstat" }, | 
|  | /* 126 */ { 0, "xmknod" }, | 
|  | /* 127 */ { 0, "clocal" }, | 
|  | /* 128 */ { 0, "setrlimit" }, | 
|  | /* 129 */ { 0, "getrlimit" }, | 
|  | /* 130 */ { 0, "lchown" }, | 
|  | /* 131 */ { 0, "memcntl" }, | 
|  | /* 132 */ { 0, "getpmsg" }, | 
|  | /* 133 */ { 0, "putpmsg" }, | 
|  | /* 134 */ { 0, "rename" }, | 
|  | /* 135 */ { 0, "uname" }, | 
|  | /* 136 */ { 0, "setegid" }, | 
|  | /* 137 */ { 0, "sysconfig" }, | 
|  | /* 138 */ { 0, "adjtime" }, | 
|  | /* 139 */ { 0, "systeminfo" }, | 
|  | /* 140 */ { 0, 0 /* reserved */ }, | 
|  | /* 141 */ { 0, "seteuid" }, | 
|  | /* 142 */ { 0, "vtrace" }, | 
|  | /* 143 */ { 0, "fork1" }, | 
|  | /* 144 */ { 0, "sigtimedwait" }, | 
|  | /* 145 */ { 0, "lwp_info" }, | 
|  | /* 146 */ { 0, "yield" }, | 
|  | /* 147 */ { 0, "lwp_sema_wait" }, | 
|  | /* 148 */ { 0, "lwp_sema_post" }, | 
|  | /* 149 */ { 0, 0 /* reserved */ }, | 
|  | /* 150 */ { 0, 0 /* reserved */ }, | 
|  | /* 151 */ { 0, 0 /* reserved */ }, | 
|  | /* 152 */ { 0, "modctl" }, | 
|  | /* 153 */ { 0, "fchroot" }, | 
|  | /* 154 */ { 0, "utimes" }, | 
|  | /* 155 */ { 0, "vhangup" }, | 
|  | /* 156 */ { do_unix_gettimeofday, "gettimeofday" }, | 
|  | /* 157 */ { 0, "getitimer" }, | 
|  | /* 158 */ { 0, "setitimer" }, | 
|  | /* 159 */ { 0, "lwp_create" }, | 
|  | /* 160 */ { 0, "lwp_exit" }, | 
|  | /* 161 */ { 0, "lwp_suspend" }, | 
|  | /* 162 */ { 0, "lwp_continue" }, | 
|  | /* 163 */ { 0, "lwp_kill" }, | 
|  | /* 164 */ { 0, "lwp_self" }, | 
|  | /* 165 */ { 0, "lwp_setprivate" }, | 
|  | /* 166 */ { 0, "lwp_getprivate" }, | 
|  | /* 167 */ { 0, "lwp_wait" }, | 
|  | /* 168 */ { 0, "lwp_mutex_unlock" }, | 
|  | /* 169 */ { 0, "lwp_mutex_lock" }, | 
|  | /* 170 */ { 0, "lwp_cond_wait" }, | 
|  | /* 171 */ { 0, "lwp_cond_signal" }, | 
|  | /* 172 */ { 0, "lwp_cond_broadcast" }, | 
|  | /* 173 */ { 0, "pread" }, | 
|  | /* 174 */ { 0, "pwrite" }, | 
|  | /* 175 */ { 0, "llseek" }, | 
|  | /* 176 */ { 0, "inst_sync" }, | 
|  | /* 177 */ { 0, 0 /* reserved */ }, | 
|  | /* 178 */ { 0, "kaio" }, | 
|  | /* 179 */ { 0, 0 /* reserved */ }, | 
|  | /* 180 */ { 0, 0 /* reserved */ }, | 
|  | /* 181 */ { 0, 0 /* reserved */ }, | 
|  | /* 182 */ { 0, 0 /* reserved */ }, | 
|  | /* 183 */ { 0, 0 /* reserved */ }, | 
|  | /* 184 */ { 0, "tsolsys" }, | 
|  | /* 185 */ { 0, "acl" }, | 
|  | /* 186 */ { 0, "auditsys" }, | 
|  | /* 187 */ { 0, "processor_bind" }, | 
|  | /* 188 */ { 0, "processor_info" }, | 
|  | /* 189 */ { 0, "p_online" }, | 
|  | /* 190 */ { 0, "sigqueue" }, | 
|  | /* 191 */ { 0, "clock_gettime" }, | 
|  | /* 192 */ { 0, "clock_settime" }, | 
|  | /* 193 */ { 0, "clock_getres" }, | 
|  | /* 194 */ { 0, "timer_create" }, | 
|  | /* 195 */ { 0, "timer_delete" }, | 
|  | /* 196 */ { 0, "timer_settime" }, | 
|  | /* 197 */ { 0, "timer_gettime" }, | 
|  | /* 198 */ { 0, "timer_getoverrun" }, | 
|  | /* 199 */ { 0, "nanosleep" }, | 
|  | /* 200 */ { 0, "facl" }, | 
|  | /* 201 */ { 0, "door" }, | 
|  | /* 202 */ { 0, "setreuid" }, | 
|  | /* 203 */ { 0, "setregid" }, | 
|  | /* 204 */ { 0, "install_utrap" }, | 
|  | /* 205 */ { 0, 0 /* reserved */ }, | 
|  | /* 206 */ { 0, 0 /* reserved */ }, | 
|  | /* 207 */ { 0, 0 /* reserved */ }, | 
|  | /* 208 */ { 0, 0 /* reserved */ }, | 
|  | /* 209 */ { 0, 0 /* reserved */ }, | 
|  | /* 210 */ { 0, "signotifywait" }, | 
|  | /* 211 */ { 0, "lwp_sigredirect" }, | 
|  | /* 212 */ { 0, "lwp_alarm" }, | 
|  | }; | 
|  |  | 
|  | static char *(solaris_error_names[]) = { | 
|  | /*   0 */ "ESUCCESS", | 
|  | /*   1 */ "EPERM", | 
|  | /*   2 */ "ENOENT", | 
|  | /*   3 */ "ESRCH", | 
|  | /*   4 */ "EINTR", | 
|  | /*   5 */ "EIO", | 
|  | /*   6 */ "ENXIO", | 
|  | /*   7 */ "E2BIG", | 
|  | /*   8 */ "ENOEXEC", | 
|  | /*   9 */ "EBADF", | 
|  | /*  10 */ "ECHILD", | 
|  | /*  11 */ "EAGAIN", | 
|  | /*  12 */ "ENOMEM", | 
|  | /*  13 */ "EACCES", | 
|  | /*  14 */ "EFAULT", | 
|  | /*  15 */ "ENOTBLK", | 
|  | /*  16 */ "EBUSY", | 
|  | /*  17 */ "EEXIST", | 
|  | /*  18 */ "EXDEV", | 
|  | /*  19 */ "ENODEV", | 
|  | /*  20 */ "ENOTDIR", | 
|  | /*  21 */ "EISDIR", | 
|  | /*  22 */ "EINVAL", | 
|  | /*  23 */ "ENFILE", | 
|  | /*  24 */ "EMFILE", | 
|  | /*  25 */ "ENOTTY", | 
|  | /*  26 */ "ETXTBSY", | 
|  | /*  27 */ "EFBIG", | 
|  | /*  28 */ "ENOSPC", | 
|  | /*  29 */ "ESPIPE", | 
|  | /*  30 */ "EROFS", | 
|  | /*  31 */ "EMLINK", | 
|  | /*  32 */ "EPIPE", | 
|  | /*  33 */ "EDOM", | 
|  | /*  34 */ "ERANGE", | 
|  | /*  35 */ "ENOMSG", | 
|  | /*  36 */ "EIDRM", | 
|  | /*  37 */ "ECHRNG", | 
|  | /*  38 */ "EL2NSYNC", | 
|  | /*  39 */ "EL3HLT", | 
|  | /*  40 */ "EL3RST", | 
|  | /*  41 */ "ELNRNG", | 
|  | /*  42 */ "EUNATCH", | 
|  | /*  43 */ "ENOCSI", | 
|  | /*  44 */ "EL2HLT", | 
|  | /*  45 */ "EDEADLK", | 
|  | /*  46 */ "ENOLCK", | 
|  | /*  47 */ "ECANCELED", | 
|  | /*  48 */ "ENOTSUP", | 
|  | /*  49 */ "EDQUOT", | 
|  | /*  50 */ "EBADE", | 
|  | /*  51 */ "EBADR", | 
|  | /*  52 */ "EXFULL", | 
|  | /*  53 */ "ENOANO", | 
|  | /*  54 */ "EBADRQC", | 
|  | /*  55 */ "EBADSLT", | 
|  | /*  56 */ "EDEADLOCK", | 
|  | /*  57 */ "EBFONT", | 
|  | /*  58 */ "Error code 58", | 
|  | /*  59 */ "Error code 59", | 
|  | /*  60 */ "ENOSTR", | 
|  | /*  61 */ "ENODATA", | 
|  | /*  62 */ "ETIME", | 
|  | /*  63 */ "ENOSR", | 
|  | /*  64 */ "ENONET", | 
|  | /*  65 */ "ENOPKG", | 
|  | /*  66 */ "EREMOTE", | 
|  | /*  67 */ "ENOLINK", | 
|  | /*  68 */ "EADV", | 
|  | /*  69 */ "ESRMNT", | 
|  | /*  70 */ "ECOMM", | 
|  | /*  71 */ "EPROTO", | 
|  | /*  72 */ "Error code 72", | 
|  | /*  73 */ "Error code 73", | 
|  | /*  74 */ "EMULTIHOP", | 
|  | /*  75 */ "Error code 75", | 
|  | /*  76 */ "Error code 76", | 
|  | /*  77 */ "EBADMSG", | 
|  | /*  78 */ "ENAMETOOLONG", | 
|  | /*  79 */ "EOVERFLOW", | 
|  | /*  80 */ "ENOTUNIQ", | 
|  | /*  81 */ "EBADFD", | 
|  | /*  82 */ "EREMCHG", | 
|  | /*  83 */ "ELIBACC", | 
|  | /*  84 */ "ELIBBAD", | 
|  | /*  85 */ "ELIBSCN", | 
|  | /*  86 */ "ELIBMAX", | 
|  | /*  87 */ "ELIBEXEC", | 
|  | /*  88 */ "EILSEQ", | 
|  | /*  89 */ "ENOSYS", | 
|  | /*  90 */ "ELOOP", | 
|  | /*  91 */ "ERESTART", | 
|  | /*  92 */ "ESTRPIPE", | 
|  | /*  93 */ "ENOTEMPTY", | 
|  | /*  94 */ "EUSERS", | 
|  | /*  95 */ "ENOTSOCK", | 
|  | /*  96 */ "EDESTADDRREQ", | 
|  | /*  97 */ "EMSGSIZE", | 
|  | /*  98 */ "EPROTOTYPE", | 
|  | /*  99 */ "ENOPROTOOPT", | 
|  | /* 100 */ "Error code 100", | 
|  | /* 101 */ "Error code 101", | 
|  | /* 102 */ "Error code 102", | 
|  | /* 103 */ "Error code 103", | 
|  | /* 104 */ "Error code 104", | 
|  | /* 105 */ "Error code 105", | 
|  | /* 106 */ "Error code 106", | 
|  | /* 107 */ "Error code 107", | 
|  | /* 108 */ "Error code 108", | 
|  | /* 109 */ "Error code 109", | 
|  | /* 110 */ "Error code 110", | 
|  | /* 111 */ "Error code 111", | 
|  | /* 112 */ "Error code 112", | 
|  | /* 113 */ "Error code 113", | 
|  | /* 114 */ "Error code 114", | 
|  | /* 115 */ "Error code 115", | 
|  | /* 116 */ "Error code 116", | 
|  | /* 117 */ "Error code 117", | 
|  | /* 118 */ "Error code 118", | 
|  | /* 119 */ "Error code 119", | 
|  | /* 120 */ "EPROTONOSUPPORT", | 
|  | /* 121 */ "ESOCKTNOSUPPORT", | 
|  | /* 122 */ "EOPNOTSUPP", | 
|  | /* 123 */ "EPFNOSUPPORT", | 
|  | /* 124 */ "EAFNOSUPPORT", | 
|  | /* 125 */ "EADDRINUSE", | 
|  | /* 126 */ "EADDRNOTAVAIL", | 
|  | /* 127 */ "ENETDOWN", | 
|  | /* 128 */ "ENETUNREACH", | 
|  | /* 129 */ "ENETRESET", | 
|  | /* 130 */ "ECONNABORTED", | 
|  | /* 131 */ "ECONNRESET", | 
|  | /* 132 */ "ENOBUFS", | 
|  | /* 133 */ "EISCONN", | 
|  | /* 134 */ "ENOTCONN", | 
|  | /* 135 */ "Error code 135",	/* XENIX has 135 - 142 */ | 
|  | /* 136 */ "Error code 136", | 
|  | /* 137 */ "Error code 137", | 
|  | /* 138 */ "Error code 138", | 
|  | /* 139 */ "Error code 139", | 
|  | /* 140 */ "Error code 140", | 
|  | /* 141 */ "Error code 141", | 
|  | /* 142 */ "Error code 142", | 
|  | /* 143 */ "ESHUTDOWN", | 
|  | /* 144 */ "ETOOMANYREFS", | 
|  | /* 145 */ "ETIMEDOUT", | 
|  | /* 146 */ "ECONNREFUSED", | 
|  | /* 147 */ "EHOSTDOWN", | 
|  | /* 148 */ "EHOSTUNREACH", | 
|  | /* 149 */ "EALREADY", | 
|  | /* 150 */ "EINPROGRESS", | 
|  | /* 151 */ "ESTALE", | 
|  | }; | 
|  |  | 
|  | static char *(solaris_signal_names[]) = { | 
|  | /*  0 */ 0, | 
|  | /*  1 */ "SIGHUP", | 
|  | /*  2 */ "SIGINT", | 
|  | /*  3 */ "SIGQUIT", | 
|  | /*  4 */ "SIGILL", | 
|  | /*  5 */ "SIGTRAP", | 
|  | /*  6 */ "SIGABRT", | 
|  | /*  7 */ "SIGEMT", | 
|  | /*  8 */ "SIGFPE", | 
|  | /*  9 */ "SIGKILL", | 
|  | /* 10 */ "SIGBUS", | 
|  | /* 11 */ "SIGSEGV", | 
|  | /* 12 */ "SIGSYS", | 
|  | /* 13 */ "SIGPIPE", | 
|  | /* 14 */ "SIGALRM", | 
|  | /* 15 */ "SIGTERM", | 
|  | /* 16 */ "SIGUSR1", | 
|  | /* 17 */ "SIGUSR2", | 
|  | /* 18 */ "SIGCHLD", | 
|  | /* 19 */ "SIGPWR", | 
|  | /* 20 */ "SIGWINCH", | 
|  | /* 21 */ "SIGURG", | 
|  | /* 22 */ "SIGPOLL", | 
|  | /* 23 */ "SIGSTOP", | 
|  | /* 24 */ "SIGTSTP", | 
|  | /* 25 */ "SIGCONT", | 
|  | /* 26 */ "SIGTTIN", | 
|  | /* 27 */ "SIGTTOU", | 
|  | /* 28 */ "SIGVTALRM", | 
|  | /* 29 */ "SIGPROF", | 
|  | /* 30 */ "SIGXCPU", | 
|  | /* 31 */ "SIGXFSZ", | 
|  | /* 32 */ "SIGWAITING", | 
|  | /* 33 */ "SIGLWP", | 
|  | /* 34 */ "SIGFREEZE", | 
|  | /* 35 */ "SIGTHAW", | 
|  | /* 36 */ "SIGCANCEL", | 
|  | }; | 
|  |  | 
|  | static emul_syscall emul_solaris_syscalls = { | 
|  | solaris_descriptors, | 
|  | ARRAY_SIZE (solaris_descriptors), | 
|  | solaris_error_names, | 
|  | ARRAY_SIZE (solaris_error_names), | 
|  | solaris_signal_names, | 
|  | ARRAY_SIZE (solaris_signal_names), | 
|  | }; | 
|  |  | 
|  |  | 
|  | /* Solaris's os_emul interface, most are just passed on to the generic | 
|  | syscall stuff */ | 
|  |  | 
|  | static os_emul_data * | 
|  | emul_solaris_create(device *root, | 
|  | bfd *image, | 
|  | const char *name) | 
|  | { | 
|  | /* check that this emulation is really for us */ | 
|  | if (name != NULL && strcmp(name, "solaris") != 0) | 
|  | return NULL; | 
|  |  | 
|  | if (image == NULL) | 
|  | return NULL; | 
|  |  | 
|  | return emul_unix_create(root, image, "solaris", &emul_solaris_syscalls); | 
|  | } | 
|  |  | 
|  | static void | 
|  | emul_solaris_init(os_emul_data *emul_data, | 
|  | int nr_cpus) | 
|  | { | 
|  | fd_closed[0] = 0; | 
|  | fd_closed[1] = 0; | 
|  | fd_closed[2] = 0; | 
|  | } | 
|  |  | 
|  | static void | 
|  | emul_solaris_system_call(cpu *processor, | 
|  | unsigned_word cia, | 
|  | os_emul_data *emul_data) | 
|  | { | 
|  | emul_do_system_call(emul_data, | 
|  | emul_data->syscalls, | 
|  | cpu_registers(processor)->gpr[0], | 
|  | 3, /*r3 contains arg0*/ | 
|  | processor, | 
|  | cia); | 
|  | } | 
|  |  | 
|  | const os_emul emul_solaris = { | 
|  | "solaris", | 
|  | emul_solaris_create, | 
|  | emul_solaris_init, | 
|  | emul_solaris_system_call, | 
|  | 0, /*instruction_call*/ | 
|  | 0  /*data*/ | 
|  | }; | 
|  |  | 
|  |  | 
|  | /* EMULATION | 
|  |  | 
|  | Linux - Emulation of user programs for Linux/PPC | 
|  |  | 
|  | DESCRIPTION | 
|  |  | 
|  | */ | 
|  |  | 
|  |  | 
|  | /* Linux specific implementation */ | 
|  |  | 
|  | typedef unsigned32	linux_dev_t; | 
|  | typedef unsigned32	linux_ino_t; | 
|  | typedef unsigned32	linux_mode_t; | 
|  | typedef unsigned16	linux_nlink_t; | 
|  | typedef signed32	linux_off_t; | 
|  | typedef signed32	linux_pid_t; | 
|  | typedef unsigned32	linux_uid_t; | 
|  | typedef unsigned32	linux_gid_t; | 
|  | typedef unsigned32	linux_size_t; | 
|  | typedef signed32	linux_ssize_t; | 
|  | typedef signed32	linux_ptrdiff_t; | 
|  | typedef signed32	linux_time_t; | 
|  | typedef signed32	linux_clock_t; | 
|  | typedef signed32	linux_daddr_t; | 
|  |  | 
|  | #ifdef HAVE_SYS_STAT_H | 
|  | /* For the PowerPC, don't both with the 'old' stat structure, since there | 
|  | should be no extant binaries with that structure.  */ | 
|  |  | 
|  | struct linux_stat { | 
|  | linux_dev_t	st_dev; | 
|  | linux_ino_t	st_ino; | 
|  | linux_mode_t	st_mode; | 
|  | linux_nlink_t	st_nlink; | 
|  | linux_uid_t 	st_uid; | 
|  | linux_gid_t 	st_gid; | 
|  | linux_dev_t	st_rdev; | 
|  | linux_off_t	st_size; | 
|  | unsigned32  	st_blksize; | 
|  | unsigned32  	st_blocks; | 
|  | unsigned32  	st_atimx;	/* don't use st_{a,c,m}time, that might a macro */ | 
|  | unsigned32  	__unused1;	/* defined by the host's stat.h */ | 
|  | unsigned32  	st_mtimx; | 
|  | unsigned32  	__unused2; | 
|  | unsigned32  	st_ctimx; | 
|  | unsigned32  	__unused3; | 
|  | unsigned32  	__unused4; | 
|  | unsigned32  	__unused5; | 
|  | }; | 
|  |  | 
|  | /* Convert from host stat structure to solaris stat structure */ | 
|  | STATIC_INLINE_EMUL_UNIX void | 
|  | convert_to_linux_stat(unsigned_word addr, | 
|  | struct stat *host, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | struct linux_stat target; | 
|  |  | 
|  | target.st_dev   = H2T_4(host->st_dev); | 
|  | target.st_ino   = H2T_4(host->st_ino); | 
|  | target.st_mode  = H2T_4(host->st_mode); | 
|  | target.st_nlink = H2T_2(host->st_nlink); | 
|  | target.st_uid   = H2T_4(host->st_uid); | 
|  | target.st_gid   = H2T_4(host->st_gid); | 
|  | target.st_size  = H2T_4(host->st_size); | 
|  |  | 
|  | #ifdef HAVE_ST_RDEV | 
|  | target.st_rdev  = H2T_4(host->st_rdev); | 
|  | #else | 
|  | target.st_rdev  = 0; | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_ST_BLKSIZE | 
|  | target.st_blksize = H2T_4(host->st_blksize); | 
|  | #else | 
|  | target.st_blksize = 0; | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_ST_BLOCKS | 
|  | target.st_blocks  = H2T_4(host->st_blocks); | 
|  | #else | 
|  | target.st_blocks  = 0; | 
|  | #endif | 
|  |  | 
|  | target.st_atimx   = H2T_4(host->st_atime); | 
|  | target.st_ctimx   = H2T_4(host->st_ctime); | 
|  | target.st_mtimx   = H2T_4(host->st_mtime); | 
|  | target.__unused1  = 0; | 
|  | target.__unused2  = 0; | 
|  | target.__unused3  = 0; | 
|  | target.__unused4  = 0; | 
|  | target.__unused5  = 0; | 
|  |  | 
|  | emul_write_buffer(&target, addr, sizeof(target), processor, cia); | 
|  | } | 
|  | #endif /* HAVE_SYS_STAT_H */ | 
|  |  | 
|  | #ifndef HAVE_STAT | 
|  | #define do_linux_stat 0 | 
|  | #else | 
|  | static void | 
|  | do_linux_stat(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | unsigned_word path_addr = cpu_registers(processor)->gpr[arg0]; | 
|  | unsigned_word stat_pkt = cpu_registers(processor)->gpr[arg0+1]; | 
|  | char path_buf[PATH_MAX]; | 
|  | struct stat buf; | 
|  | char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia); | 
|  | int status; | 
|  |  | 
|  | if (WITH_TRACE && ppc_trace[trace_os_emul]) | 
|  | printf_filtered ("0x%lx [%s], 0x%lx", (long)path_addr, path, (long)stat_pkt); | 
|  |  | 
|  | status = stat (path, &buf); | 
|  | if (status == 0) | 
|  | convert_to_linux_stat (stat_pkt, &buf, processor, cia); | 
|  |  | 
|  | emul_write_status(processor, status, errno); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #ifndef HAVE_LSTAT | 
|  | #define do_linux_lstat 0 | 
|  | #else | 
|  | static void | 
|  | do_linux_lstat(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | unsigned_word path_addr = cpu_registers(processor)->gpr[arg0]; | 
|  | unsigned_word stat_pkt = cpu_registers(processor)->gpr[arg0+1]; | 
|  | char path_buf[PATH_MAX]; | 
|  | struct stat buf; | 
|  | char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia); | 
|  | int status; | 
|  |  | 
|  | if (WITH_TRACE && ppc_trace[trace_os_emul]) | 
|  | printf_filtered ("0x%lx [%s], 0x%lx", (long)path_addr, path, (long)stat_pkt); | 
|  |  | 
|  | status = lstat (path, &buf); | 
|  | if (status == 0) | 
|  | convert_to_linux_stat (stat_pkt, &buf, processor, cia); | 
|  |  | 
|  | emul_write_status(processor, status, errno); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #ifndef HAVE_FSTAT | 
|  | #define do_linux_fstat 0 | 
|  | #else | 
|  | static void | 
|  | do_linux_fstat(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | int fildes = (int)cpu_registers(processor)->gpr[arg0]; | 
|  | unsigned_word stat_pkt = cpu_registers(processor)->gpr[arg0+1]; | 
|  | struct stat buf; | 
|  | int status; | 
|  |  | 
|  | if (WITH_TRACE && ppc_trace[trace_os_emul]) | 
|  | printf_filtered ("%d, 0x%lx", fildes, (long)stat_pkt); | 
|  |  | 
|  | status = fdbad (fildes); | 
|  | if (status == 0) | 
|  | status = fstat (fildes, &buf); | 
|  | if (status == 0) | 
|  | convert_to_linux_stat (stat_pkt, &buf, processor, cia); | 
|  |  | 
|  | emul_write_status(processor, status, errno); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #if defined(HAVE_TERMIO_STRUCTURE) || defined(HAVE_TERMIOS_STRUCTURE) | 
|  | #define LINUX_NCC		10 | 
|  | #define LINUX_NCCS		19 | 
|  |  | 
|  | #define	LINUX_VINTR		 0 | 
|  | #define	LINUX_VQUIT		 1 | 
|  | #define	LINUX_VERASE		 2 | 
|  | #define	LINUX_VKILL		 3 | 
|  | #define	LINUX_VEOF		 4 | 
|  | #define LINUX_VMIN		 5 | 
|  | #define	LINUX_VEOL		 6 | 
|  | #define	LINUX_VTIME		 7 | 
|  | #define LINUX_VEOL2		 8 | 
|  | #define LINUX_VSWTC		 9 | 
|  | #define LINUX_VWERASE 		10 | 
|  | #define LINUX_VREPRINT		11 | 
|  | #define LINUX_VSUSP 		12 | 
|  | #define LINUX_VSTART		13 | 
|  | #define LINUX_VSTOP		14 | 
|  | #define LINUX_VLNEXT		15 | 
|  | #define LINUX_VDISCARD		16 | 
|  |  | 
|  | #define LINUX_IOC_NRBITS	 8 | 
|  | #define LINUX_IOC_TYPEBITS	 8 | 
|  | #define LINUX_IOC_SIZEBITS	13 | 
|  | #define LINUX_IOC_DIRBITS	 3 | 
|  |  | 
|  | #define LINUX_IOC_NRMASK	((1 << LINUX_IOC_NRBITS)-1) | 
|  | #define LINUX_IOC_TYPEMASK	((1 << LINUX_IOC_TYPEBITS)-1) | 
|  | #define LINUX_IOC_SIZEMASK	((1 << LINUX_IOC_SIZEBITS)-1) | 
|  | #define LINUX_IOC_DIRMASK	((1 << LINUX_IOC_DIRBITS)-1) | 
|  |  | 
|  | #define LINUX_IOC_NRSHIFT	0 | 
|  | #define LINUX_IOC_TYPESHIFT	(LINUX_IOC_NRSHIFT+LINUX_IOC_NRBITS) | 
|  | #define LINUX_IOC_SIZESHIFT	(LINUX_IOC_TYPESHIFT+LINUX_IOC_TYPEBITS) | 
|  | #define LINUX_IOC_DIRSHIFT	(LINUX_IOC_SIZESHIFT+LINUX_IOC_SIZEBITS) | 
|  |  | 
|  | /* | 
|  | * Direction bits _IOC_NONE could be 0, but OSF/1 gives it a bit. | 
|  | * And this turns out useful to catch old ioctl numbers in header | 
|  | * files for us. | 
|  | */ | 
|  | #define LINUX_IOC_NONE		1U | 
|  | #define LINUX_IOC_READ		2U | 
|  | #define LINUX_IOC_WRITE		4U | 
|  |  | 
|  | #define LINUX_IOC(dir,type,nr,size) \ | 
|  | (((dir)  << LINUX_IOC_DIRSHIFT) | \ | 
|  | ((type) << LINUX_IOC_TYPESHIFT) | \ | 
|  | ((nr)   << LINUX_IOC_NRSHIFT) | \ | 
|  | ((size) << LINUX_IOC_SIZESHIFT)) | 
|  |  | 
|  | /* used to create numbers */ | 
|  | #define LINUX_IO(type,nr)	 LINUX_IOC(LINUX_IOC_NONE,(type),(nr),0) | 
|  | #define LINUX_IOR(type,nr,size)	 LINUX_IOC(LINUX_IOC_READ,(type),(nr),sizeof(size)) | 
|  | #define LINUX_IOW(type,nr,size)	 LINUX_IOC(LINUX_IOC_WRITE,(type),(nr),sizeof(size)) | 
|  | #define LINUX_IOWR(type,nr,size) LINUX_IOC(LINUX_IOC_READ|LINUX_IOC_WRITE,(type),(nr),sizeof(size)) | 
|  | #endif | 
|  |  | 
|  | #if defined(HAVE_TERMIO_STRUCTURE) || defined(HAVE_TERMIOS_STRUCTURE) | 
|  | /* Convert to/from host termio structure */ | 
|  |  | 
|  | struct linux_termio { | 
|  | unsigned16	c_iflag;		/* input modes */ | 
|  | unsigned16	c_oflag;		/* output modes */ | 
|  | unsigned16	c_cflag;		/* control modes */ | 
|  | unsigned16	c_lflag;		/* line discipline modes */ | 
|  | unsigned8	c_line;			/* line discipline */ | 
|  | unsigned8	c_cc[LINUX_NCC];	/* control chars */ | 
|  | }; | 
|  |  | 
|  | STATIC_INLINE_EMUL_UNIX void | 
|  | convert_to_linux_termio(unsigned_word addr, | 
|  | struct termio *host, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | struct linux_termio target; | 
|  | int i; | 
|  |  | 
|  | target.c_iflag = H2T_2 (host->c_iflag); | 
|  | target.c_oflag = H2T_2 (host->c_oflag); | 
|  | target.c_cflag = H2T_2 (host->c_cflag); | 
|  | target.c_lflag = H2T_2 (host->c_lflag); | 
|  |  | 
|  | #if defined(HAVE_TERMIO_CLINE) || defined(HAVE_TERMIOS_CLINE) | 
|  | target.c_line  = host->c_line; | 
|  | #else | 
|  | target.c_line  = 0; | 
|  | #endif | 
|  |  | 
|  | for (i = 0; i < LINUX_NCC; i++) | 
|  | target.c_cc[i] = 0; | 
|  |  | 
|  | #ifdef VINTR | 
|  | target.c_cc[LINUX_VINTR] = host->c_cc[VINTR]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VQUIT | 
|  | target.c_cc[LINUX_VQUIT] = host->c_cc[VQUIT]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VERASE | 
|  | target.c_cc[LINUX_VERASE] = host->c_cc[VERASE]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VKILL | 
|  | target.c_cc[LINUX_VKILL] = host->c_cc[VKILL]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VEOF | 
|  | target.c_cc[LINUX_VEOF] = host->c_cc[VEOF]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VMIN | 
|  | target.c_cc[LINUX_VMIN] = host->c_cc[VMIN]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VEOL | 
|  | target.c_cc[LINUX_VEOL] = host->c_cc[VEOL]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VTIME | 
|  | target.c_cc[LINUX_VTIME] = host->c_cc[VTIME]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VEOL2 | 
|  | target.c_cc[LINUX_VEOL2] = host->c_cc[VEOL2]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VSWTC | 
|  | target.c_cc[LINUX_VSWTC] = host->c_cc[VSWTC]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VSWTCH | 
|  | target.c_cc[LINUX_VSWTC] = host->c_cc[VSWTCH]; | 
|  | #endif | 
|  |  | 
|  | emul_write_buffer(&target, addr, sizeof(target), processor, cia); | 
|  | } | 
|  | #endif /* HAVE_TERMIO_STRUCTURE */ | 
|  |  | 
|  | #ifdef HAVE_TERMIOS_STRUCTURE | 
|  | /* Convert to/from host termios structure */ | 
|  |  | 
|  | typedef unsigned32 linux_tcflag_t; | 
|  | typedef unsigned8  linux_cc_t; | 
|  | typedef unsigned32 linux_speed_t; | 
|  |  | 
|  | struct linux_termios { | 
|  | linux_tcflag_t	c_iflag; | 
|  | linux_tcflag_t	c_oflag; | 
|  | linux_tcflag_t	c_cflag; | 
|  | linux_tcflag_t	c_lflag; | 
|  | linux_cc_t		c_cc[LINUX_NCCS]; | 
|  | linux_cc_t		c_line; | 
|  | signed32		c_ispeed; | 
|  | signed32		c_ospeed; | 
|  | }; | 
|  |  | 
|  | STATIC_INLINE_EMUL_UNIX void | 
|  | convert_to_linux_termios(unsigned_word addr, | 
|  | struct termios *host, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | struct linux_termios target; | 
|  | int i; | 
|  |  | 
|  | target.c_iflag = H2T_4 (host->c_iflag); | 
|  | target.c_oflag = H2T_4 (host->c_oflag); | 
|  | target.c_cflag = H2T_4 (host->c_cflag); | 
|  | target.c_lflag = H2T_4 (host->c_lflag); | 
|  |  | 
|  | for (i = 0; i < LINUX_NCCS; i++) | 
|  | target.c_cc[i] = 0; | 
|  |  | 
|  | #ifdef VINTR | 
|  | target.c_cc[LINUX_VINTR] = host->c_cc[VINTR]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VQUIT | 
|  | target.c_cc[LINUX_VQUIT] = host->c_cc[VQUIT]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VERASE | 
|  | target.c_cc[LINUX_VERASE] = host->c_cc[VERASE]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VKILL | 
|  | target.c_cc[LINUX_VKILL] = host->c_cc[VKILL]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VEOF | 
|  | target.c_cc[LINUX_VEOF] = host->c_cc[VEOF]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VEOL | 
|  | target.c_cc[LINUX_VEOL] = host->c_cc[VEOL]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VEOL2 | 
|  | target.c_cc[LINUX_VEOL2] = host->c_cc[VEOL2]; | 
|  | #endif | 
|  |  | 
|  | #ifdef VSWTCH | 
|  | target.c_cc[LINUX_VSWTC] = host->c_cc[VSWTCH]; | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_TERMIOS_CLINE | 
|  | target.c_line   = host->c_line; | 
|  | #else | 
|  | target.c_line   = 0; | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_CFGETISPEED | 
|  | target.c_ispeed = cfgetispeed (host); | 
|  | #else | 
|  | target.c_ispeed = 0; | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_CFGETOSPEED | 
|  | target.c_ospeed = cfgetospeed (host); | 
|  | #else | 
|  | target.c_ospeed = 0; | 
|  | #endif | 
|  |  | 
|  | emul_write_buffer(&target, addr, sizeof(target), processor, cia); | 
|  | } | 
|  | #endif /* HAVE_TERMIOS_STRUCTURE */ | 
|  |  | 
|  | #ifndef HAVE_IOCTL | 
|  | #define do_linux_ioctl 0 | 
|  | #else | 
|  | static void | 
|  | do_linux_ioctl(os_emul_data *emul, | 
|  | unsigned call, | 
|  | const int arg0, | 
|  | cpu *processor, | 
|  | unsigned_word cia) | 
|  | { | 
|  | int fildes = cpu_registers(processor)->gpr[arg0]; | 
|  | unsigned request = cpu_registers(processor)->gpr[arg0+1]; | 
|  | unsigned_word argp_addr = cpu_registers(processor)->gpr[arg0+2]; | 
|  | int status = 0; | 
|  | const char *name = "<unknown>"; | 
|  |  | 
|  | #ifdef HAVE_TERMIOS_STRUCTURE | 
|  | struct termios host_termio; | 
|  |  | 
|  | #else | 
|  | #ifdef HAVE_TERMIO_STRUCTURE | 
|  | struct termio host_termio; | 
|  | #endif | 
|  | #endif | 
|  |  | 
|  | status = fdbad (fildes); | 
|  | if (status != 0) | 
|  | goto done; | 
|  |  | 
|  | switch (request) | 
|  | { | 
|  | case 0:					/* make sure we have at least one case */ | 
|  | default: | 
|  | status = -1; | 
|  | errno = EINVAL; | 
|  | break; | 
|  |  | 
|  | #if defined(HAVE_TERMIO_STRUCTURE) || defined(HAVE_TERMIOS_STRUCTURE) | 
|  | #if defined(TCGETA) || defined(TCGETS) || defined(HAVE_TCGETATTR) | 
|  | case LINUX_IOR('t', 23, struct linux_termio):	/* TCGETA */ | 
|  | name = "TCGETA"; | 
|  | #ifdef HAVE_TCGETATTR | 
|  | status = tcgetattr(fildes, &host_termio); | 
|  | #elif defined(TCGETS) | 
|  | status = ioctl (fildes, TCGETS, &host_termio); | 
|  | #else | 
|  | status = ioctl (fildes, TCGETA, &host_termio); | 
|  | #endif | 
|  | if (status == 0) | 
|  | convert_to_linux_termio (argp_addr, &host_termio, processor, cia); | 
|  | break; | 
|  | #endif /* TCGETA */ | 
|  | #endif /* HAVE_TERMIO_STRUCTURE */ | 
|  |  | 
|  | #ifdef HAVE_TERMIOS_STRUCTURE | 
|  | #if defined(TCGETS) || defined(HAVE_TCGETATTR) | 
|  | case LINUX_IOR('t', 19, struct linux_termios):	/* TCGETS */ | 
|  | name = "TCGETS"; | 
|  | #ifdef HAVE_TCGETATTR | 
|  | status = tcgetattr(fildes, &host_termio); | 
|  | #else | 
|  | status = ioctl (fildes, TCGETS, &host_termio); | 
|  | #endif | 
|  | if (status == 0) | 
|  | convert_to_linux_termios (argp_addr, &host_termio, processor, cia); | 
|  | break; | 
|  | #endif /* TCGETS */ | 
|  | #endif /* HAVE_TERMIOS_STRUCTURE */ | 
|  | } | 
|  |  | 
|  | done: | 
|  | emul_write_status(processor, status, errno); | 
|  |  | 
|  | if (WITH_TRACE && ppc_trace[trace_os_emul]) | 
|  | printf_filtered ("%d, 0x%x [%s], 0x%lx", fildes, request, name, (long)argp_addr); | 
|  | } | 
|  | #endif /* HAVE_IOCTL */ | 
|  |  | 
|  | static emul_syscall_descriptor linux_descriptors[] = { | 
|  | /*   0 */ { 0, "setup" }, | 
|  | /*   1 */ { do_unix_exit, "exit" }, | 
|  | /*   2 */ { 0, "fork" }, | 
|  | /*   3 */ { do_unix_read, "read" }, | 
|  | /*   4 */ { do_unix_write, "write" }, | 
|  | /*   5 */ { do_unix_open, "open" }, | 
|  | /*   6 */ { do_unix_close, "close" }, | 
|  | /*   7 */ { 0, "waitpid" }, | 
|  | /*   8 */ { 0, "creat" }, | 
|  | /*   9 */ { do_unix_link, "link" }, | 
|  | /*  10 */ { do_unix_unlink, "unlink" }, | 
|  | /*  11 */ { 0, "execve" }, | 
|  | /*  12 */ { do_unix_chdir, "chdir" }, | 
|  | /*  13 */ { do_unix_time, "time" }, | 
|  | /*  14 */ { 0, "mknod" }, | 
|  | /*  15 */ { 0, "chmod" }, | 
|  | /*  16 */ { 0, "chown" }, | 
|  | /*  17 */ { 0, "break" }, | 
|  | /*  18 */ { 0, "stat" }, | 
|  | /*  19 */ { do_unix_lseek, "lseek" }, | 
|  | /*  20 */ { do_unix_getpid, "getpid" }, | 
|  | /*  21 */ { 0, "mount" }, | 
|  | /*  22 */ { 0, "umount" }, | 
|  | /*  23 */ { 0, "setuid" }, | 
|  | /*  24 */ { do_unix_getuid, "getuid" }, | 
|  | /*  25 */ { 0, "stime" }, | 
|  | /*  26 */ { 0, "ptrace" }, | 
|  | /*  27 */ { 0, "alarm" }, | 
|  | /*  28 */ { 0, "fstat" }, | 
|  | /*  29 */ { 0, "pause" }, | 
|  | /*  30 */ { 0, "utime" }, | 
|  | /*  31 */ { 0, "stty" }, | 
|  | /*  32 */ { 0, "gtty" }, | 
|  | /*  33 */ { do_unix_access, "access" }, | 
|  | /*  34 */ { 0, "nice" }, | 
|  | /*  35 */ { 0, "ftime" }, | 
|  | /*  36 */ { 0, "sync" }, | 
|  | /*  37 */ { 0, "kill" }, | 
|  | /*  38 */ { 0, "rename" }, | 
|  | /*  39 */ { do_unix_mkdir, "mkdir" }, | 
|  | /*  40 */ { do_unix_rmdir, "rmdir" }, | 
|  | /*  41 */ { do_unix_dup, "dup" }, | 
|  | /*  42 */ { 0, "pipe" }, | 
|  | /*  43 */ { 0, "times" }, | 
|  | /*  44 */ { 0, "prof" }, | 
|  | /*  45 */ { do_unix_break, "brk" }, | 
|  | /*  46 */ { 0, "setgid" }, | 
|  | /*  47 */ { do_unix_getgid, "getgid" }, | 
|  | /*  48 */ { 0, "signal" }, | 
|  | /*  49 */ { do_unix_geteuid, "geteuid" }, | 
|  | /*  50 */ { do_unix_getegid, "getegid" }, | 
|  | /*  51 */ { 0, "acct" }, | 
|  | /*  52 */ { 0, "phys" }, | 
|  | /*  53 */ { 0, "lock" }, | 
|  | /*  54 */ { do_linux_ioctl, "ioctl" }, | 
|  | /*  55 */ { 0, "fcntl" }, | 
|  | /*  56 */ { 0, "mpx" }, | 
|  | /*  57 */ { 0, "setpgid" }, | 
|  | /*  58 */ { 0, "ulimit" }, | 
|  | /*  59 */ { 0, "olduname" }, | 
|  | /*  60 */ { do_unix_umask, "umask" }, | 
|  | /*  61 */ { 0, "chroot" }, | 
|  | /*  62 */ { 0, "ustat" }, | 
|  | /*  63 */ { do_unix_dup2, "dup2" }, | 
|  | /*  64 */ { do_unix_getppid, "getppid" }, | 
|  | /*  65 */ { 0, "getpgrp" }, | 
|  | /*  66 */ { 0, "setsid" }, | 
|  | /*  67 */ { 0, "sigaction" }, | 
|  | /*  68 */ { 0, "sgetmask" }, | 
|  | /*  69 */ { 0, "ssetmask" }, | 
|  | /*  70 */ { 0, "setreuid" }, | 
|  | /*  71 */ { 0, "setregid" }, | 
|  | /*  72 */ { 0, "sigsuspend" }, | 
|  | /*  73 */ { 0, "sigpending" }, | 
|  | /*  74 */ { 0, "sethostname" }, | 
|  | /*  75 */ { 0, "setrlimit" }, | 
|  | /*  76 */ { 0, "getrlimit" }, | 
|  | /*  77 */ { do_unix_getrusage, "getrusage" }, | 
|  | /*  78 */ { do_unix_gettimeofday, "gettimeofday" }, | 
|  | /*  79 */ { 0, "settimeofday" }, | 
|  | /*  80 */ { 0, "getgroups" }, | 
|  | /*  81 */ { 0, "setgroups" }, | 
|  | /*  82 */ { 0, "select" }, | 
|  | /*  83 */ { do_unix_symlink, "symlink" }, | 
|  | /*  84 */ { 0, "lstat" }, | 
|  | /*  85 */ { 0, "readlink" }, | 
|  | /*  86 */ { 0, "uselib" }, | 
|  | /*  87 */ { 0, "swapon" }, | 
|  | /*  88 */ { 0, "reboot" }, | 
|  | /*  89 */ { 0, "readdir" }, | 
|  | /*  90 */ { 0, "mmap" }, | 
|  | /*  91 */ { 0, "munmap" }, | 
|  | /*  92 */ { 0, "truncate" }, | 
|  | /*  93 */ { 0, "ftruncate" }, | 
|  | /*  94 */ { 0, "fchmod" }, | 
|  | /*  95 */ { 0, "fchown" }, | 
|  | /*  96 */ { 0, "getpriority" }, | 
|  | /*  97 */ { 0, "setpriority" }, | 
|  | /*  98 */ { 0, "profil" }, | 
|  | /*  99 */ { 0, "statfs" }, | 
|  | /* 100 */ { 0, "fstatfs" }, | 
|  | /* 101 */ { 0, "ioperm" }, | 
|  | /* 102 */ { 0, "socketcall" }, | 
|  | /* 103 */ { 0, "syslog" }, | 
|  | /* 104 */ { 0, "setitimer" }, | 
|  | /* 105 */ { 0, "getitimer" }, | 
|  | /* 106 */ { do_linux_stat, "newstat" }, | 
|  | /* 107 */ { do_linux_lstat, "newlstat" }, | 
|  | /* 108 */ { do_linux_fstat, "newfstat" }, | 
|  | /* 109 */ { 0, "uname" }, | 
|  | /* 110 */ { 0, "iopl" }, | 
|  | /* 111 */ { 0, "vhangup" }, | 
|  | /* 112 */ { 0, "idle" }, | 
|  | /* 113 */ { 0, "vm86" }, | 
|  | /* 114 */ { 0, "wait4" }, | 
|  | /* 115 */ { 0, "swapoff" }, | 
|  | /* 116 */ { 0, "sysinfo" }, | 
|  | /* 117 */ { 0, "ipc" }, | 
|  | /* 118 */ { 0, "fsync" }, | 
|  | /* 119 */ { 0, "sigreturn" }, | 
|  | /* 120 */ { 0, "clone" }, | 
|  | /* 121 */ { 0, "setdomainname" }, | 
|  | /* 122 */ { 0, "newuname" }, | 
|  | /* 123 */ { 0, "modify_ldt" }, | 
|  | /* 124 */ { 0, "adjtimex" }, | 
|  | /* 125 */ { 0, "mprotect" }, | 
|  | /* 126 */ { 0, "sigprocmask" }, | 
|  | /* 127 */ { 0, "create_module" }, | 
|  | /* 128 */ { 0, "init_module" }, | 
|  | /* 129 */ { 0, "delete_module" }, | 
|  | /* 130 */ { 0, "get_kernel_syms" }, | 
|  | /* 131 */ { 0, "quotactl" }, | 
|  | /* 132 */ { 0, "getpgid" }, | 
|  | /* 133 */ { 0, "fchdir" }, | 
|  | /* 134 */ { 0, "bdflush" }, | 
|  | /* 135 */ { 0, "sysfs" }, | 
|  | /* 136 */ { 0, "personality" }, | 
|  | /* 137 */ { 0, "afs_syscall" }, | 
|  | /* 138 */ { 0, "setfsuid" }, | 
|  | /* 139 */ { 0, "setfsgid" }, | 
|  | /* 140 */ { 0, "llseek" }, | 
|  | /* 141 */ { 0, "getdents" }, | 
|  | /* 142 */ { 0, "newselect" }, | 
|  | /* 143 */ { 0, "flock" }, | 
|  | /* 144 */ { 0, "msync" }, | 
|  | /* 145 */ { 0, "readv" }, | 
|  | /* 146 */ { 0, "writev" }, | 
|  | /* 147 */ { 0, "getsid" }, | 
|  | /* 148 */ { 0, "fdatasync" }, | 
|  | /* 149 */ { 0, "sysctl" }, | 
|  | /* 150 */ { 0, "mlock" }, | 
|  | /* 151 */ { 0, "munlock" }, | 
|  | /* 152 */ { 0, "mlockall" }, | 
|  | /* 153 */ { 0, "munlockall" }, | 
|  | /* 154 */ { 0, "sched_setparam" }, | 
|  | /* 155 */ { 0, "sched_getparam" }, | 
|  | /* 156 */ { 0, "sched_setscheduler" }, | 
|  | /* 157 */ { 0, "sched_getscheduler" }, | 
|  | /* 158 */ { 0, "sched_yield" }, | 
|  | /* 159 */ { 0, "sched_get_priority_max" }, | 
|  | /* 160 */ { 0, "sched_get_priority_min" }, | 
|  | /* 161 */ { 0, "sched_rr_get_interval" }, | 
|  | }; | 
|  |  | 
|  | static char *(linux_error_names[]) = { | 
|  | /*   0 */ "ESUCCESS", | 
|  | /*   1 */ "EPERM", | 
|  | /*   2 */ "ENOENT", | 
|  | /*   3 */ "ESRCH", | 
|  | /*   4 */ "EINTR", | 
|  | /*   5 */ "EIO", | 
|  | /*   6 */ "ENXIO", | 
|  | /*   7 */ "E2BIG", | 
|  | /*   8 */ "ENOEXEC", | 
|  | /*   9 */ "EBADF", | 
|  | /*  10 */ "ECHILD", | 
|  | /*  11 */ "EAGAIN", | 
|  | /*  12 */ "ENOMEM", | 
|  | /*  13 */ "EACCES", | 
|  | /*  14 */ "EFAULT", | 
|  | /*  15 */ "ENOTBLK", | 
|  | /*  16 */ "EBUSY", | 
|  | /*  17 */ "EEXIST", | 
|  | /*  18 */ "EXDEV", | 
|  | /*  19 */ "ENODEV", | 
|  | /*  20 */ "ENOTDIR", | 
|  | /*  21 */ "EISDIR", | 
|  | /*  22 */ "EINVAL", | 
|  | /*  23 */ "ENFILE", | 
|  | /*  24 */ "EMFILE", | 
|  | /*  25 */ "ENOTTY", | 
|  | /*  26 */ "ETXTBSY", | 
|  | /*  27 */ "EFBIG", | 
|  | /*  28 */ "ENOSPC", | 
|  | /*  29 */ "ESPIPE", | 
|  | /*  30 */ "EROFS", | 
|  | /*  31 */ "EMLINK", | 
|  | /*  32 */ "EPIPE", | 
|  | /*  33 */ "EDOM", | 
|  | /*  34 */ "ERANGE", | 
|  | /*  35 */ "EDEADLK", | 
|  | /*  36 */ "ENAMETOOLONG", | 
|  | /*  37 */ "ENOLCK", | 
|  | /*  38 */ "ENOSYS", | 
|  | /*  39 */ "ENOTEMPTY", | 
|  | /*  40 */ "ELOOP", | 
|  | /*  41 */ 0, | 
|  | /*  42 */ "ENOMSG", | 
|  | /*  43 */ "EIDRM", | 
|  | /*  44 */ "ECHRNG", | 
|  | /*  45 */ "EL2NSYNC", | 
|  | /*  46 */ "EL3HLT", | 
|  | /*  47 */ "EL3RST", | 
|  | /*  48 */ "ELNRNG", | 
|  | /*  49 */ "EUNATCH", | 
|  | /*  50 */ "ENOCSI", | 
|  | /*  51 */ "EL2HLT", | 
|  | /*  52 */ "EBADE", | 
|  | /*  53 */ "EBADR", | 
|  | /*  54 */ "EXFULL", | 
|  | /*  55 */ "ENOANO", | 
|  | /*  56 */ "EBADRQC", | 
|  | /*  57 */ "EBADSLT", | 
|  | /*  58 */ "EDEADLOCK", | 
|  | /*  59 */ "EBFONT", | 
|  | /*  60 */ "ENOSTR", | 
|  | /*  61 */ "ENODATA", | 
|  | /*  62 */ "ETIME", | 
|  | /*  63 */ "ENOSR", | 
|  | /*  64 */ "ENONET", | 
|  | /*  65 */ "ENOPKG", | 
|  | /*  66 */ "EREMOTE", | 
|  | /*  67 */ "ENOLINK", | 
|  | /*  68 */ "EADV", | 
|  | /*  69 */ "ESRMNT", | 
|  | /*  70 */ "ECOMM", | 
|  | /*  71 */ "EPROTO", | 
|  | /*  72 */ "EMULTIHOP", | 
|  | /*  73 */ "EDOTDOT", | 
|  | /*  74 */ "EBADMSG", | 
|  | /*  75 */ "EOVERFLOW", | 
|  | /*  76 */ "ENOTUNIQ", | 
|  | /*  77 */ "EBADFD", | 
|  | /*  78 */ "EREMCHG", | 
|  | /*  79 */ "ELIBACC", | 
|  | /*  80 */ "ELIBBAD", | 
|  | /*  81 */ "ELIBSCN", | 
|  | /*  82 */ "ELIBMAX", | 
|  | /*  83 */ "ELIBEXEC", | 
|  | /*  84 */ "EILSEQ", | 
|  | /*  85 */ "ERESTART", | 
|  | /*  86 */ "ESTRPIPE", | 
|  | /*  87 */ "EUSERS", | 
|  | /*  88 */ "ENOTSOCK", | 
|  | /*  89 */ "EDESTADDRREQ", | 
|  | /*  90 */ "EMSGSIZE", | 
|  | /*  91 */ "EPROTOTYPE", | 
|  | /*  92 */ "ENOPROTOOPT", | 
|  | /*  93 */ "EPROTONOSUPPORT", | 
|  | /*  94 */ "ESOCKTNOSUPPORT", | 
|  | /*  95 */ "EOPNOTSUPP", | 
|  | /*  96 */ "EPFNOSUPPORT", | 
|  | /*  97 */ "EAFNOSUPPORT", | 
|  | /*  98 */ "EADDRINUSE", | 
|  | /*  99 */ "EADDRNOTAVAIL", | 
|  | /* 100 */ "ENETDOWN", | 
|  | /* 101 */ "ENETUNREACH", | 
|  | /* 102 */ "ENETRESET", | 
|  | /* 103 */ "ECONNABORTED", | 
|  | /* 104 */ "ECONNRESET", | 
|  | /* 105 */ "ENOBUFS", | 
|  | /* 106 */ "EISCONN", | 
|  | /* 107 */ "ENOTCONN", | 
|  | /* 108 */ "ESHUTDOWN", | 
|  | /* 109 */ "ETOOMANYREFS", | 
|  | /* 110 */ "ETIMEDOUT", | 
|  | /* 111 */ "ECONNREFUSED", | 
|  | /* 112 */ "EHOSTDOWN", | 
|  | /* 113 */ "EHOSTUNREACH", | 
|  | /* 114 */ "EALREADY", | 
|  | /* 115 */ "EINPROGRESS", | 
|  | /* 116 */ "ESTALE", | 
|  | /* 117 */ "EUCLEAN", | 
|  | /* 118 */ "ENOTNAM", | 
|  | /* 119 */ "ENAVAIL", | 
|  | /* 120 */ "EISNAM", | 
|  | /* 121 */ "EREMOTEIO", | 
|  | /* 122 */ "EDQUOT", | 
|  | }; | 
|  |  | 
|  | static char *(linux_signal_names[]) = { | 
|  | /*  0 */ 0, | 
|  | /*  1 */ "SIGHUP", | 
|  | /*  2 */ "SIGINT", | 
|  | /*  3 */ "SIGQUIT", | 
|  | /*  4 */ "SIGILL", | 
|  | /*  5 */ "SIGTRAP", | 
|  | /*  6 */ "SIGABRT", | 
|  | /*  6 */ "SIGIOT", | 
|  | /*  7 */ "SIGBUS", | 
|  | /*  8 */ "SIGFPE", | 
|  | /*  9 */ "SIGKILL", | 
|  | /* 10 */ "SIGUSR1", | 
|  | /* 11 */ "SIGSEGV", | 
|  | /* 12 */ "SIGUSR2", | 
|  | /* 13 */ "SIGPIPE", | 
|  | /* 14 */ "SIGALRM", | 
|  | /* 15 */ "SIGTERM", | 
|  | /* 16 */ "SIGSTKFLT", | 
|  | /* 17 */ "SIGCHLD", | 
|  | /* 18 */ "SIGCONT", | 
|  | /* 19 */ "SIGSTOP", | 
|  | /* 20 */ "SIGTSTP", | 
|  | /* 21 */ "SIGTTIN", | 
|  | /* 22 */ "SIGTTOU", | 
|  | /* 23 */ "SIGURG", | 
|  | /* 24 */ "SIGXCPU", | 
|  | /* 25 */ "SIGXFSZ", | 
|  | /* 26 */ "SIGVTALRM", | 
|  | /* 27 */ "SIGPROF", | 
|  | /* 28 */ "SIGWINCH", | 
|  | /* 29 */ "SIGIO", | 
|  | /* 30 */ "SIGPWR", | 
|  | /* 31 */ "SIGUNUSED", | 
|  | }; | 
|  |  | 
|  | static emul_syscall emul_linux_syscalls = { | 
|  | linux_descriptors, | 
|  | ARRAY_SIZE (linux_descriptors), | 
|  | linux_error_names, | 
|  | ARRAY_SIZE (linux_error_names), | 
|  | linux_signal_names, | 
|  | ARRAY_SIZE (linux_signal_names), | 
|  | }; | 
|  |  | 
|  |  | 
|  | /* Linux's os_emul interface, most are just passed on to the generic | 
|  | syscall stuff */ | 
|  |  | 
|  | static os_emul_data * | 
|  | emul_linux_create(device *root, | 
|  | bfd *image, | 
|  | const char *name) | 
|  | { | 
|  | /* check that this emulation is really for us */ | 
|  | if (name != NULL && strcmp(name, "linux") != 0) | 
|  | return NULL; | 
|  |  | 
|  | if (image == NULL) | 
|  | return NULL; | 
|  |  | 
|  | return emul_unix_create(root, image, "linux", &emul_linux_syscalls); | 
|  | } | 
|  |  | 
|  | static void | 
|  | emul_linux_init(os_emul_data *emul_data, | 
|  | int nr_cpus) | 
|  | { | 
|  | fd_closed[0] = 0; | 
|  | fd_closed[1] = 0; | 
|  | fd_closed[2] = 0; | 
|  | } | 
|  |  | 
|  | static void | 
|  | emul_linux_system_call(cpu *processor, | 
|  | unsigned_word cia, | 
|  | os_emul_data *emul_data) | 
|  | { | 
|  | emul_do_system_call(emul_data, | 
|  | emul_data->syscalls, | 
|  | cpu_registers(processor)->gpr[0], | 
|  | 3, /*r3 contains arg0*/ | 
|  | processor, | 
|  | cia); | 
|  | } | 
|  |  | 
|  | const os_emul emul_linux = { | 
|  | "linux", | 
|  | emul_linux_create, | 
|  | emul_linux_init, | 
|  | emul_linux_system_call, | 
|  | 0, /*instruction_call*/ | 
|  | 0  /*data*/ | 
|  | }; | 
|  |  | 
|  | #endif /* _EMUL_UNIX_C_ */ |