#ifndef _EMUL_UNIX_C_
#define _EMUL_UNIX_C_
#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>
#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
#include <unistd.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#if defined(BSD) && !defined(errno) && (BSD < 199306)
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
struct _os_emul_data {
device *vm;
emul_syscall *syscalls;
};
struct unix_timeval {
signed32 tv_sec;
signed32 tv_usec;
};
struct unix_timezone {
signed32 tz_minuteswest;
signed32 tz_dsttime;
};
#define UNIX_RUSAGE_SELF 0
#define UNIX_RUSAGE_CHILDREN (-1)
#define UNIX_RUSAGE_BOTH (-2)
struct unix_rusage {
struct unix_timeval ru_utime;
struct unix_timeval ru_stime;
signed32 ru_maxrss;
signed32 ru_ixrss;
signed32 ru_idrss;
signed32 ru_isrss;
signed32 ru_minflt;
signed32 ru_majflt;
signed32 ru_nswap;
signed32 ru_inblock;
signed32 ru_oublock;
signed32 ru_msgsnd;
signed32 ru_msgrcv;
signed32 ru_nsignals;
signed32 ru_nvcsw;
signed32 ru_nivcsw;
};
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);
scratch_buffer = zalloc(nbytes);
emul_read_buffer(scratch_buffer, buf, nbytes, processor, cia);
status = read (d, scratch_buffer, nbytes);
emul_write_status(processor, status, errno);
if (status > 0)
emul_write_buffer(scratch_buffer, buf, status, processor, cia);
zfree(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);
scratch_buffer = zalloc(nbytes);
emul_read_buffer(scratch_buffer, buf, nbytes,
processor, cia);
status = write(d, scratch_buffer, nbytes);
emul_write_status(processor, status, errno);
zfree(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 = 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)
{
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);
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 = 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 = 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 = 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);
status = mkdir(path, mode);
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);
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);
}
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;
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;
}
emul_add_tree_options(root, image, name,
(WITH_ENVIRONMENT == USER_ENVIRONMENT
? "user" : "virtual"),
0 );
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);
tree_parse(root, "/openprom/vm/map-binary/file-name %s",
bfd_get_filename(image));
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"));
data = ZALLOC(os_emul_data);
data->vm = vm;
data->syscalls = syscall;
return data;
}
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
struct solaris_stat {
solaris_dev_t st_dev;
signed32 st_pad1[3];
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;
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];
};
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 < sizeof (target.st_pad1) / sizeof (target.st_pad1[0]); i++)
target.st_pad1[i] = 0;
for (i = 0; i < sizeof (target.st_pad2) / sizeof (target.st_pad2[0]); i++)
target.st_pad2[i] = 0;
target.st_pad3 = 0;
for (i = 0; i < sizeof (target.st_pad4) / sizeof (target.st_pad4[0]); i++)
target.st_pad4[i] = 0;
strcpy (target.st_fstype, "ufs");
emul_write_buffer(&target, addr, sizeof(target), processor, cia);
}
#endif
#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 = 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)
struct solaris_termio {
unsigned16 c_iflag;
unsigned16 c_oflag;
unsigned16 c_cflag;
unsigned16 c_lflag;
unsigned8 c_line;
unsigned8 c_cc[SOLARIS_NCC];
};
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
#ifdef HAVE_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
#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
switch (request)
{
case 0:
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:
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
#endif
#ifdef HAVE_TERMIOS_STRUCTURE
#if defined(TCGETS) || defined(HAVE_TCGETATTR)
case SOLARIS_TIOC | 13:
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
#endif
}
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
static emul_syscall_descriptor solaris_descriptors[] = {
{ 0, "syscall" },
{ do_unix_exit, "exit" },
{ 0, "fork" },
{ do_unix_read, "read" },
{ do_unix_write, "write" },
{ do_unix_open, "open" },
{ do_unix_close, "close" },
{ 0, "wait" },
{ 0, "creat" },
{ do_unix_link, "link" },
{ do_unix_unlink, "unlink" },
{ 0, "exec" },
{ do_unix_chdir, "chdir" },
{ do_unix_time, "time" },
{ 0, "mknod" },
{ 0, "chmod" },
{ 0, "chown" },
{ do_unix_break, "brk" },
{ do_solaris_stat, "stat" },
{ do_unix_lseek, "lseek" },
{ do_unix_getpid2, "getpid" },
{ 0, "mount" },
{ 0, "umount" },
{ 0, "setuid" },
{ do_unix_getuid2, "getuid" },
{ 0, "stime" },
{ 0, "ptrace" },
{ 0, "alarm" },
{ do_solaris_fstat, "fstat" },
{ 0, "pause" },
{ 0, "utime" },
{ 0, "stty" },
{ 0, "gtty" },
{ do_unix_access, "access" },
{ 0, "nice" },
{ 0, "statfs" },
{ 0, "sync" },
{ 0, "kill" },
{ 0, "fstatfs" },
{ 0, "pgrpsys" },
{ 0, "xenix" },
{ do_unix_dup, "dup" },
{ 0, "pipe" },
{ 0, "times" },
{ 0, "profil" },
{ 0, "plock" },
{ 0, "setgid" },
{ do_unix_getgid2, "getgid" },
{ 0, "signal" },
{ 0, "msgsys" },
{ 0, "syssun" },
{ 0, "acct" },
{ 0, "shmsys" },
{ 0, "semsys" },
{ do_solaris_ioctl, "ioctl" },
{ 0, "uadmin" },
{ 0, 0 },
{ 0, "utssys" },
{ 0, "fdsync" },
{ 0, "execve" },
{ do_unix_umask, "umask" },
{ 0, "chroot" },
{ 0, "fcntl" },
{ 0, "ulimit" },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ do_unix_rmdir, "rmdir" },
{ do_unix_mkdir, "mkdir" },
{ 0, "getdents" },
{ 0, 0 },
{ 0, 0 },
{ 0, "sysfs" },
{ 0, "getmsg" },
{ 0, "putmsg" },
{ 0, "poll" },
{ do_solaris_lstat, "lstat" },
{ do_unix_symlink, "symlink" },
{ 0, "readlink" },
{ 0, "setgroups" },
{ 0, "getgroups" },
{ 0, "fchmod" },
{ 0, "fchown" },
{ 0, "sigprocmask" },
{ 0, "sigsuspend" },
{ do_unix_nop, "sigaltstack" },
{ do_unix_nop, "sigaction" },
{ 0, "sigpending" },
{ 0, "context" },
{ 0, "evsys" },
{ 0, "evtrapret" },
{ 0, "statvfs" },
{ 0, "fstatvfs" },
{ 0, 0 },
{ 0, "nfssys" },
{ 0, "waitsys" },
{ 0, "sigsendsys" },
{ 0, "hrtsys" },
{ 0, "acancel" },
{ 0, "async" },
{ 0, "priocntlsys" },
{ 0, "pathconf" },
{ 0, "mincore" },
{ 0, "mmap" },
{ 0, "mprotect" },
{ 0, "munmap" },
{ 0, "fpathconf" },
{ 0, "vfork" },
{ 0, "fchdir" },
{ 0, "readv" },
{ 0, "writev" },
{ 0, "xstat" },
{ 0, "lxstat" },
{ 0, "fxstat" },
{ 0, "xmknod" },
{ 0, "clocal" },
{ 0, "setrlimit" },
{ 0, "getrlimit" },
{ 0, "lchown" },
{ 0, "memcntl" },
{ 0, "getpmsg" },
{ 0, "putpmsg" },
{ 0, "rename" },
{ 0, "uname" },
{ 0, "setegid" },
{ 0, "sysconfig" },
{ 0, "adjtime" },
{ 0, "systeminfo" },
{ 0, 0 },
{ 0, "seteuid" },
{ 0, "vtrace" },
{ 0, "fork1" },
{ 0, "sigtimedwait" },
{ 0, "lwp_info" },
{ 0, "yield" },
{ 0, "lwp_sema_wait" },
{ 0, "lwp_sema_post" },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, "modctl" },
{ 0, "fchroot" },
{ 0, "utimes" },
{ 0, "vhangup" },
{ do_unix_gettimeofday, "gettimeofday" },
{ 0, "getitimer" },
{ 0, "setitimer" },
{ 0, "lwp_create" },
{ 0, "lwp_exit" },
{ 0, "lwp_suspend" },
{ 0, "lwp_continue" },
{ 0, "lwp_kill" },
{ 0, "lwp_self" },
{ 0, "lwp_setprivate" },
{ 0, "lwp_getprivate" },
{ 0, "lwp_wait" },
{ 0, "lwp_mutex_unlock" },
{ 0, "lwp_mutex_lock" },
{ 0, "lwp_cond_wait" },
{ 0, "lwp_cond_signal" },
{ 0, "lwp_cond_broadcast" },
{ 0, "pread" },
{ 0, "pwrite" },
{ 0, "llseek" },
{ 0, "inst_sync" },
{ 0, 0 },
{ 0, "kaio" },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, "tsolsys" },
{ 0, "acl" },
{ 0, "auditsys" },
{ 0, "processor_bind" },
{ 0, "processor_info" },
{ 0, "p_online" },
{ 0, "sigqueue" },
{ 0, "clock_gettime" },
{ 0, "clock_settime" },
{ 0, "clock_getres" },
{ 0, "timer_create" },
{ 0, "timer_delete" },
{ 0, "timer_settime" },
{ 0, "timer_gettime" },
{ 0, "timer_getoverrun" },
{ 0, "nanosleep" },
{ 0, "facl" },
{ 0, "door" },
{ 0, "setreuid" },
{ 0, "setregid" },
{ 0, "install_utrap" },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
{ 0, "signotifywait" },
{ 0, "lwp_sigredirect" },
{ 0, "lwp_alarm" },
};
static char *(solaris_error_names[]) = {
"ESUCCESS",
"EPERM",
"ENOENT",
"ESRCH",
"EINTR",
"EIO",
"ENXIO",
"E2BIG",
"ENOEXEC",
"EBADF",
"ECHILD",
"EAGAIN",
"ENOMEM",
"EACCES",
"EFAULT",
"ENOTBLK",
"EBUSY",
"EEXIST",
"EXDEV",
"ENODEV",
"ENOTDIR",
"EISDIR",
"EINVAL",
"ENFILE",
"EMFILE",
"ENOTTY",
"ETXTBSY",
"EFBIG",
"ENOSPC",
"ESPIPE",
"EROFS",
"EMLINK",
"EPIPE",
"EDOM",
"ERANGE",
"ENOMSG",
"EIDRM",
"ECHRNG",
"EL2NSYNC",
"EL3HLT",
"EL3RST",
"ELNRNG",
"EUNATCH",
"ENOCSI",
"EL2HLT",
"EDEADLK",
"ENOLCK",
"ECANCELED",
"ENOTSUP",
"EDQUOT",
"EBADE",
"EBADR",
"EXFULL",
"ENOANO",
"EBADRQC",
"EBADSLT",
"EDEADLOCK",
"EBFONT",
"Error code 58",
"Error code 59",
"ENOSTR",
"ENODATA",
"ETIME",
"ENOSR",
"ENONET",
"ENOPKG",
"EREMOTE",
"ENOLINK",
"EADV",
"ESRMNT",
"ECOMM",
"EPROTO",
"Error code 72",
"Error code 73",
"EMULTIHOP",
"Error code 75",
"Error code 76",
"EBADMSG",
"ENAMETOOLONG",
"EOVERFLOW",
"ENOTUNIQ",
"EBADFD",
"EREMCHG",
"ELIBACC",
"ELIBBAD",
"ELIBSCN",
"ELIBMAX",
"ELIBEXEC",
"EILSEQ",
"ENOSYS",
"ELOOP",
"ERESTART",
"ESTRPIPE",
"ENOTEMPTY",
"EUSERS",
"ENOTSOCK",
"EDESTADDRREQ",
"EMSGSIZE",
"EPROTOTYPE",
"ENOPROTOOPT",
"Error code 100",
"Error code 101",
"Error code 102",
"Error code 103",
"Error code 104",
"Error code 105",
"Error code 106",
"Error code 107",
"Error code 108",
"Error code 109",
"Error code 110",
"Error code 111",
"Error code 112",
"Error code 113",
"Error code 114",
"Error code 115",
"Error code 116",
"Error code 117",
"Error code 118",
"Error code 119",
"EPROTONOSUPPORT",
"ESOCKTNOSUPPORT",
"EOPNOTSUPP",
"EPFNOSUPPORT",
"EAFNOSUPPORT",
"EADDRINUSE",
"EADDRNOTAVAIL",
"ENETDOWN",
"ENETUNREACH",
"ENETRESET",
"ECONNABORTED",
"ECONNRESET",
"ENOBUFS",
"EISCONN",
"ENOTCONN",
"Error code 135",
"Error code 136",
"Error code 137",
"Error code 138",
"Error code 139",
"Error code 140",
"Error code 141",
"Error code 142",
"ESHUTDOWN",
"ETOOMANYREFS",
"ETIMEDOUT",
"ECONNREFUSED",
"EHOSTDOWN",
"EHOSTUNREACH",
"EALREADY",
"EINPROGRESS",
"ESTALE",
};
static char *(solaris_signal_names[]) = {
0,
"SIGHUP",
"SIGINT",
"SIGQUIT",
"SIGILL",
"SIGTRAP",
"SIGABRT",
"SIGEMT",
"SIGFPE",
"SIGKILL",
"SIGBUS",
"SIGSEGV",
"SIGSYS",
"SIGPIPE",
"SIGALRM",
"SIGTERM",
"SIGUSR1",
"SIGUSR2",
"SIGCHLD",
"SIGPWR",
"SIGWINCH",
"SIGURG",
"SIGPOLL",
"SIGSTOP",
"SIGTSTP",
"SIGCONT",
"SIGTTIN",
"SIGTTOU",
"SIGVTALRM",
"SIGPROF",
"SIGXCPU",
"SIGXFSZ",
"SIGWAITING",
"SIGLWP",
"SIGFREEZE",
"SIGTHAW",
"SIGCANCEL",
};
static emul_syscall emul_solaris_syscalls = {
solaris_descriptors,
sizeof(solaris_descriptors) / sizeof(solaris_descriptors[0]),
solaris_error_names,
sizeof(solaris_error_names) / sizeof(solaris_error_names[0]),
solaris_signal_names,
sizeof(solaris_signal_names) / sizeof(solaris_signal_names[0]),
};
static os_emul_data *
emul_solaris_create(device *root,
bfd *image,
const char *name)
{
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)
{
}
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,
processor,
cia);
}
const os_emul emul_solaris = {
"solaris",
emul_solaris_create,
emul_solaris_init,
emul_solaris_system_call,
0,
0
};
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
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;
unsigned32 __unused1;
unsigned32 st_mtimx;
unsigned32 __unused2;
unsigned32 st_ctimx;
unsigned32 __unused3;
unsigned32 __unused4;
unsigned32 __unused5;
};
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
#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 = 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)
#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))
#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)
struct linux_termio {
unsigned16 c_iflag;
unsigned16 c_oflag;
unsigned16 c_cflag;
unsigned16 c_lflag;
unsigned8 c_line;
unsigned8 c_cc[LINUX_NCC];
};
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
#ifdef HAVE_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
#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
switch (request)
{
case 0:
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):
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
#endif
#ifdef HAVE_TERMIOS_STRUCTURE
#if defined(TCGETS) || defined(HAVE_TCGETATTR)
case LINUX_IOR('t', 19, struct linux_termios):
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
#endif
}
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
static emul_syscall_descriptor linux_descriptors[] = {
{ 0, "setup" },
{ do_unix_exit, "exit" },
{ 0, "fork" },
{ do_unix_read, "read" },
{ do_unix_write, "write" },
{ do_unix_open, "open" },
{ do_unix_close, "close" },
{ 0, "waitpid" },
{ 0, "creat" },
{ do_unix_link, "link" },
{ do_unix_unlink, "unlink" },
{ 0, "execve" },
{ do_unix_chdir, "chdir" },
{ do_unix_time, "time" },
{ 0, "mknod" },
{ 0, "chmod" },
{ 0, "chown" },
{ 0, "break" },
{ 0, "stat" },
{ do_unix_lseek, "lseek" },
{ do_unix_getpid, "getpid" },
{ 0, "mount" },
{ 0, "umount" },
{ 0, "setuid" },
{ do_unix_getuid, "getuid" },
{ 0, "stime" },
{ 0, "ptrace" },
{ 0, "alarm" },
{ 0, "fstat" },
{ 0, "pause" },
{ 0, "utime" },
{ 0, "stty" },
{ 0, "gtty" },
{ do_unix_access, "access" },
{ 0, "nice" },
{ 0, "ftime" },
{ 0, "sync" },
{ 0, "kill" },
{ 0, "rename" },
{ do_unix_mkdir, "mkdir" },
{ do_unix_rmdir, "rmdir" },
{ do_unix_dup, "dup" },
{ 0, "pipe" },
{ 0, "times" },
{ 0, "prof" },
{ do_unix_break, "brk" },
{ 0, "setgid" },
{ do_unix_getgid, "getgid" },
{ 0, "signal" },
{ do_unix_geteuid, "geteuid" },
{ do_unix_getegid, "getegid" },
{ 0, "acct" },
{ 0, "phys" },
{ 0, "lock" },
{ do_linux_ioctl, "ioctl" },
{ 0, "fcntl" },
{ 0, "mpx" },
{ 0, "setpgid" },
{ 0, "ulimit" },
{ 0, "olduname" },
{ do_unix_umask, "umask" },
{ 0, "chroot" },
{ 0, "ustat" },
{ do_unix_dup2, "dup2" },
{ do_unix_getppid, "getppid" },
{ 0, "getpgrp" },
{ 0, "setsid" },
{ 0, "sigaction" },
{ 0, "sgetmask" },
{ 0, "ssetmask" },
{ 0, "setreuid" },
{ 0, "setregid" },
{ 0, "sigsuspend" },
{ 0, "sigpending" },
{ 0, "sethostname" },
{ 0, "setrlimit" },
{ 0, "getrlimit" },
{ do_unix_getrusage, "getrusage" },
{ do_unix_gettimeofday, "gettimeofday" },
{ 0, "settimeofday" },
{ 0, "getgroups" },
{ 0, "setgroups" },
{ 0, "select" },
{ do_unix_symlink, "symlink" },
{ 0, "lstat" },
{ 0, "readlink" },
{ 0, "uselib" },
{ 0, "swapon" },
{ 0, "reboot" },
{ 0, "readdir" },
{ 0, "mmap" },
{ 0, "munmap" },
{ 0, "truncate" },
{ 0, "ftruncate" },
{ 0, "fchmod" },
{ 0, "fchown" },
{ 0, "getpriority" },
{ 0, "setpriority" },
{ 0, "profil" },
{ 0, "statfs" },
{ 0, "fstatfs" },
{ 0, "ioperm" },
{ 0, "socketcall" },
{ 0, "syslog" },
{ 0, "setitimer" },
{ 0, "getitimer" },
{ do_linux_stat, "newstat" },
{ do_linux_lstat, "newlstat" },
{ do_linux_fstat, "newfstat" },
{ 0, "uname" },
{ 0, "iopl" },
{ 0, "vhangup" },
{ 0, "idle" },
{ 0, "vm86" },
{ 0, "wait4" },
{ 0, "swapoff" },
{ 0, "sysinfo" },
{ 0, "ipc" },
{ 0, "fsync" },
{ 0, "sigreturn" },
{ 0, "clone" },
{ 0, "setdomainname" },
{ 0, "newuname" },
{ 0, "modify_ldt" },
{ 0, "adjtimex" },
{ 0, "mprotect" },
{ 0, "sigprocmask" },
{ 0, "create_module" },
{ 0, "init_module" },
{ 0, "delete_module" },
{ 0, "get_kernel_syms" },
{ 0, "quotactl" },
{ 0, "getpgid" },
{ 0, "fchdir" },
{ 0, "bdflush" },
{ 0, "sysfs" },
{ 0, "personality" },
{ 0, "afs_syscall" },
{ 0, "setfsuid" },
{ 0, "setfsgid" },
{ 0, "llseek" },
{ 0, "getdents" },
{ 0, "newselect" },
{ 0, "flock" },
{ 0, "msync" },
{ 0, "readv" },
{ 0, "writev" },
{ 0, "getsid" },
{ 0, "fdatasync" },
{ 0, "sysctl" },
{ 0, "mlock" },
{ 0, "munlock" },
{ 0, "mlockall" },
{ 0, "munlockall" },
{ 0, "sched_setparam" },
{ 0, "sched_getparam" },
{ 0, "sched_setscheduler" },
{ 0, "sched_getscheduler" },
{ 0, "sched_yield" },
{ 0, "sched_get_priority_max" },
{ 0, "sched_get_priority_min" },
{ 0, "sched_rr_get_interval" },
};
static char *(linux_error_names[]) = {
"ESUCCESS",
"EPERM",
"ENOENT",
"ESRCH",
"EINTR",
"EIO",
"ENXIO",
"E2BIG",
"ENOEXEC",
"EBADF",
"ECHILD",
"EAGAIN",
"ENOMEM",
"EACCES",
"EFAULT",
"ENOTBLK",
"EBUSY",
"EEXIST",
"EXDEV",
"ENODEV",
"ENOTDIR",
"EISDIR",
"EINVAL",
"ENFILE",
"EMFILE",
"ENOTTY",
"ETXTBSY",
"EFBIG",
"ENOSPC",
"ESPIPE",
"EROFS",
"EMLINK",
"EPIPE",
"EDOM",
"ERANGE",
"EDEADLK",
"ENAMETOOLONG",
"ENOLCK",
"ENOSYS",
"ENOTEMPTY",
"ELOOP",
0,
"ENOMSG",
"EIDRM",
"ECHRNG",
"EL2NSYNC",
"EL3HLT",
"EL3RST",
"ELNRNG",
"EUNATCH",
"ENOCSI",
"EL2HLT",
"EBADE",
"EBADR",
"EXFULL",
"ENOANO",
"EBADRQC",
"EBADSLT",
"EDEADLOCK",
"EBFONT",
"ENOSTR",
"ENODATA",
"ETIME",
"ENOSR",
"ENONET",
"ENOPKG",
"EREMOTE",
"ENOLINK",
"EADV",
"ESRMNT",
"ECOMM",
"EPROTO",
"EMULTIHOP",
"EDOTDOT",
"EBADMSG",
"EOVERFLOW",
"ENOTUNIQ",
"EBADFD",
"EREMCHG",
"ELIBACC",
"ELIBBAD",
"ELIBSCN",
"ELIBMAX",
"ELIBEXEC",
"EILSEQ",
"ERESTART",
"ESTRPIPE",
"EUSERS",
"ENOTSOCK",
"EDESTADDRREQ",
"EMSGSIZE",
"EPROTOTYPE",
"ENOPROTOOPT",
"EPROTONOSUPPORT",
"ESOCKTNOSUPPORT",
"EOPNOTSUPP",
"EPFNOSUPPORT",
"EAFNOSUPPORT",
"EADDRINUSE",
"EADDRNOTAVAIL",
"ENETDOWN",
"ENETUNREACH",
"ENETRESET",
"ECONNABORTED",
"ECONNRESET",
"ENOBUFS",
"EISCONN",
"ENOTCONN",
"ESHUTDOWN",
"ETOOMANYREFS",
"ETIMEDOUT",
"ECONNREFUSED",
"EHOSTDOWN",
"EHOSTUNREACH",
"EALREADY",
"EINPROGRESS",
"ESTALE",
"EUCLEAN",
"ENOTNAM",
"ENAVAIL",
"EISNAM",
"EREMOTEIO",
"EDQUOT",
};
static char *(linux_signal_names[]) = {
0,
"SIGHUP",
"SIGINT",
"SIGQUIT",
"SIGILL",
"SIGTRAP",
"SIGABRT",
"SIGIOT",
"SIGBUS",
"SIGFPE",
"SIGKILL",
"SIGUSR1",
"SIGSEGV",
"SIGUSR2",
"SIGPIPE",
"SIGALRM",
"SIGTERM",
"SIGSTKFLT",
"SIGCHLD",
"SIGCONT",
"SIGSTOP",
"SIGTSTP",
"SIGTTIN",
"SIGTTOU",
"SIGURG",
"SIGXCPU",
"SIGXFSZ",
"SIGVTALRM",
"SIGPROF",
"SIGWINCH",
"SIGIO",
"SIGPWR",
"SIGUNUSED",
};
static emul_syscall emul_linux_syscalls = {
linux_descriptors,
sizeof(linux_descriptors) / sizeof(linux_descriptors[0]),
linux_error_names,
sizeof(linux_error_names) / sizeof(linux_error_names[0]),
linux_signal_names,
sizeof(linux_signal_names) / sizeof(linux_signal_names[0]),
};
static os_emul_data *
emul_linux_create(device *root,
bfd *image,
const char *name)
{
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)
{
}
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,
processor,
cia);
}
const os_emul emul_linux = {
"linux",
emul_linux_create,
emul_linux_init,
emul_linux_system_call,
0,
0
};
#endif