/* This file is part of the program psim.
- Copyright (C) 1996, Andrew Cagney <cagney@highland.com.au>
+ 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 2 of the License, or
+ 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,
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, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <sys/time.h>
#endif
-#ifdef HAVE_SYS_TERMIOS_H
+#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
-#ifdef HAVE_SYS_TERMIO_H
+#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
int getrusage();
#endif
-#if HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-
-#if HAVE_SYS_MOUNT_H
-#include <sys/mount.h>
-#endif
-
#if HAVE_DIRENT_H
# include <dirent.h>
# define NAMLEN(dirent) strlen((dirent)->d_name)
emul_syscall *syscalls;
};
-
+\f
/* 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,
/* check if buffer exists by reading it */
emul_read_buffer(scratch_buffer, buf, nbytes, processor, cia);
+ status = fdbad (d);
/* read */
- status = read (d, scratch_buffer, nbytes);
+ 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);
- zfree(scratch_buffer);
+ free(scratch_buffer);
}
unsigned_word cia)
{
void *scratch_buffer = NULL;
- int nr_moved;
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];
scratch_buffer = zalloc(nbytes); /* FIXME - nbytes == 0 */
/* copy in */
- nr_moved = vm_data_map_read_buffer(cpu_data_map(processor),
- scratch_buffer,
- buf,
- nbytes);
- if (nr_moved != nbytes) {
- /* FIXME - should handle better */
- error("system_call()write copy failed (nr_moved=%d != nbytes=%d)\n",
- nr_moved, nbytes);
- }
+ emul_read_buffer(scratch_buffer, buf, nbytes,
+ processor, cia);
+ status = fdbad (d);
/* write */
- status = write(d, scratch_buffer, nbytes);
+ if (status == 0)
+ status = write(d, scratch_buffer, nbytes);
emul_write_status(processor, status, errno);
- zfree(scratch_buffer);
+ free(scratch_buffer);
flush_stdoutput();
}
if (WITH_TRACE && ppc_trace[trace_os_emul])
printf_filtered ("%d", d);
- status = close(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);
}
unsigned_word cia)
{
/* just pass this onto the `vm' device */
- psim *system = cpu_system(processor);
unsigned_word new_break = cpu_registers(processor)->gpr[arg0];
int status;
printf_filtered ("0x%lx", (long)cpu_registers(processor)->gpr[arg0]);
status = device_ioctl(emul->vm,
- system,
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
cpu *processor,
unsigned_word cia)
{
- int status = (int)getpid();
- emul_write_status(processor, status, errno);
+ pid_t status = getpid();
+ emul_write_status(processor, (int)status, errno);
}
#endif
cpu *processor,
unsigned_word cia)
{
- int status = (int)getppid();
- emul_write_status(processor, status, errno);
+ pid_t status = getppid();
+ emul_write_status(processor, (int)status, errno);
}
#endif
cpu *processor,
unsigned_word cia)
{
- int uid = (int)getuid();
- int euid = (int)geteuid();
- emul_write2_status(processor, uid, euid, errno);
+ uid_t uid = getuid();
+ uid_t euid = geteuid();
+ emul_write2_status(processor, (int)uid, (int)euid, errno);
}
#endif
cpu *processor,
unsigned_word cia)
{
- int status = (int)getuid();
- emul_write_status(processor, status, errno);
+ uid_t status = getuid();
+ emul_write_status(processor, (int)status, errno);
}
#endif
cpu *processor,
unsigned_word cia)
{
- int status = (int)geteuid();
- emul_write_status(processor, status, errno);
+ uid_t status = geteuid();
+ emul_write_status(processor, (int)status, errno);
}
#endif
unsigned_word cia)
{
int oldd = cpu_registers(processor)->gpr[arg0];
- int status = dup(oldd);
+ int status = (fdbad (oldd) < 0) ? -1 : dup(oldd);
int err = errno;
if (WITH_TRACE && ppc_trace[trace_os_emul])
{
int oldd = cpu_registers(processor)->gpr[arg0];
int newd = cpu_registers(processor)->gpr[arg0+1];
- int status = dup2(oldd, newd);
+ int status = (fdbad (oldd) < 0) ? -1 : dup2(oldd, newd);
int err = errno;
if (WITH_TRACE && ppc_trace[trace_os_emul])
cpu *processor,
unsigned_word cia)
{
- int fildes = cpu_registers(processor)->gpr[arg0];
- off_t offset = emul_read_gpr64(processor, arg0+2);
- int whence = cpu_registers(processor)->gpr[arg0+4];
+ 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);
- if (status == -1)
- emul_write_status(processor, -1, errno);
- else {
- emul_write_status(processor, 0, 0); /* success */
- emul_write_gpr64(processor, 3, status);
- }
+ status = fdbad (fildes);
+ if (status == 0)
+ status = lseek(fildes, offset, whence);
+ emul_write_status(processor, (int)status, errno);
}
#endif
cpu *processor,
unsigned_word cia)
{
- int gid = (int)getgid();
- int egid = (int)getegid();
- emul_write2_status(processor, gid, egid, errno);
+ gid_t gid = getgid();
+ gid_t egid = getegid();
+ emul_write2_status(processor, (int)gid, (int)egid, errno);
}
#endif
cpu *processor,
unsigned_word cia)
{
- int status = (int)getgid();
- emul_write_status(processor, status, 0);
+ gid_t status = getgid();
+ emul_write_status(processor, (int)status, errno);
}
#endif
cpu *processor,
unsigned_word cia)
{
- int status = (int)getegid();
- emul_write_status(processor, status, errno);
+ gid_t status = getegid();
+ emul_write_status(processor, (int)status, errno);
}
#endif
cpu *processor,
unsigned_word cia)
{
- int mask = cpu_registers(processor)->gpr[arg0];
+ 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", mask);
+ printf_filtered ("0%o", (unsigned int)mask);
emul_write_status(processor, status, errno);
}
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
}
#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);
+}
+
\f
/* Common code for initializing the system call stuff */
int elf_binary;
os_emul_data *data;
device *vm;
+ char *filename;
/* merge any emulation specific entries into the device tree */
0 /*oea-interrupt-prefix*/);
/* virtual memory - handles growth of stack/heap */
- vm = device_tree_add_parsed(root, "/openprom/vm@0x%lx",
- (unsigned long)(top_of_stack - stack_size));
- device_tree_add_parsed(vm, "./stack-base 0x%lx",
- (unsigned long)(top_of_stack - stack_size));
- device_tree_add_parsed(vm, "./nr-bytes 0x%x", stack_size);
+ 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);
- device_tree_add_parsed(root, "/openprom/vm/map-binary/file-name %s",
- bfd_get_filename(image));
+ filename = tree_quote_property (bfd_get_filename(image));
+ tree_parse(root, "/openprom/vm/map-binary/file-name %s",
+ filename);
+ free (filename);
/* finish the init */
- device_tree_add_parsed(root, "/openprom/init/register/pc 0x%lx",
- (unsigned long)bfd_get_start_address(image));
- device_tree_add_parsed(root, "/openprom/init/register/sp 0x%lx",
- (unsigned long)top_of_stack);
- device_tree_add_parsed(root, "/openprom/init/register/msr 0x%x", msr_little_endian_mode);
- device_tree_add_parsed(root, "/openprom/init/stack/stack-type %s",
- (elf_binary ? "elf" : "xcoff"));
+ 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);
}
\f
+/* EMULATION
+
+ Solaris - Emulation of user programs for Solaris/PPC
+
+ DESCRIPTION
+
+ */
+
+
/* Solaris specific implementation */
typedef signed32 solaris_uid_t;
#ifdef HAVE_SYS_STAT_H
#define SOLARIS_ST_FSTYPSZ 16 /* array size for file system type name */
-typedef struct {
- solaris_time_t tv_sec;
- signed32 tv_usec;
-} solaris_timestruc_t;
+/* 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_pad2[2];
solaris_off_t st_size;
signed32 st_pad3; /* future off_t expansion */
- solaris_timestruc_t st_atim;
- solaris_timestruc_t st_mtim;
- solaris_timestruc_t st_ctim;
+ 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];
if (WITH_TRACE && ppc_trace[trace_os_emul])
printf_filtered ("%d, 0x%lx", fildes, (long)stat_pkt);
- status = fstat (fildes, &buf);
+ status = fdbad (fildes);
+ if (status == 0)
+ status = fstat (fildes, &buf);
if (status == 0)
convert_to_solaris_stat (stat_pkt, &buf, processor, cia);
}
#endif
-#if defined(HAVE_SYS_TERMIO_H) || defined(HAVE_SYS_TERMIOS_H)
+#if defined(HAVE_TERMIO_STRUCTURE) || defined(HAVE_TERMIOS_STRUCTURE)
#define SOLARIS_TIOC ('T'<<8)
#define SOLARIS_NCC 8
#define SOLARIS_NCCS 19
#define SOLARIS_VLNEXT 15
#endif
-#ifdef HAVE_SYS_TERMIO_H
+#if defined(HAVE_TERMIO_STRUCTURE) || defined(HAVE_TERMIOS_STRUCTURE)
/* Convert to/from host termio structure */
struct solaris_termio {
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;
emul_write_buffer(&target, addr, sizeof(target), processor, cia);
}
-#endif /* HAVE_SYS_TERMIO_H */
+#endif /* HAVE_TERMIO_STRUCTURE || HAVE_TERMIOS_STRUCTURE */
-#ifdef HAVE_SYS_TERMIOS_H
+#ifdef HAVE_TERMIOS_STRUCTURE
/* Convert to/from host termios structure */
typedef unsigned32 solaris_tcflag_t;
emul_write_buffer(&target, addr, sizeof(target), processor, cia);
}
-#endif /* HAVE_SYS_TERMIOS_H */
+#endif /* HAVE_TERMIOS_STRUCTURE */
#ifndef HAVE_IOCTL
#define do_solaris_ioctl 0
int status = 0;
const char *name = "<unknown>";
-#ifdef HAVE_SYS_TERMIO_H
+#ifdef HAVE_TERMIOS_STRUCTURE
+ struct termios host_termio;
+
+#else
+#ifdef HAVE_TERMIO_STRUCTURE
struct termio host_termio;
#endif
-
-#ifdef HAVE_SYS_TERMIOS_H
- struct termios host_termios;
#endif
+ status = fdbad (fildes);
+ if (status != 0)
+ goto done;
+
switch (request)
{
case 0: /* make sure we have at least one case */
errno = EINVAL;
break;
-#ifdef HAVE_SYS_TERMIO_H
-#ifdef TCGETA
+#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_SYS_TERMIO_H */
+#endif /* HAVE_TERMIO_STRUCTURE */
-#ifdef HAVE_SYS_TERMIOS_H
+#ifdef HAVE_TERMIOS_STRUCTURE
#if defined(TCGETS) || defined(HAVE_TCGETATTR)
case SOLARIS_TIOC | 13: /* TCGETS */
name = "TCGETS";
#ifdef HAVE_TCGETATTR
- status = tcgetattr(fildes, &host_termios);
+ status = tcgetattr(fildes, &host_termio);
#else
- status = ioctl (fildes, TCGETS, &host_termios);
+ status = ioctl (fildes, TCGETS, &host_termio);
#endif
if (status == 0)
- convert_to_solaris_termios (argp_addr, &host_termios, processor, cia);
+ convert_to_solaris_termios (argp_addr, &host_termio, processor, cia);
break;
#endif /* TCGETS */
-#endif /* HAVE_SYS_TERMIOS_H */
+#endif /* HAVE_TERMIOS_STRUCTURE */
}
+done:
emul_write_status(processor, status, errno);
if (WITH_TRACE && ppc_trace[trace_os_emul])
/* 10 */ { do_unix_unlink, "unlink" },
/* 11 */ { 0, "exec" },
/* 12 */ { do_unix_chdir, "chdir" },
- /* 13 */ { 0, "time" },
+ /* 13 */ { do_unix_time, "time" },
/* 14 */ { 0, "mknod" },
/* 15 */ { 0, "chmod" },
/* 16 */ { 0, "chown" },
/* 30 */ { 0, "utime" },
/* 31 */ { 0, "stty" },
/* 32 */ { 0, "gtty" },
- /* 33 */ { 0, "access" },
+ /* 33 */ { do_unix_access, "access" },
/* 34 */ { 0, "nice" },
/* 35 */ { 0, "statfs" },
/* 36 */ { 0, "sync" },
/* 94 */ { 0, "fchown" },
/* 95 */ { 0, "sigprocmask" },
/* 96 */ { 0, "sigsuspend" },
- /* 97 */ { 0, "sigaltstack" },
- /* 98 */ { 0, "sigaction" },
+ /* 97 */ { do_unix_nop, "sigaltstack" },
+ /* 98 */ { do_unix_nop, "sigaction" },
/* 99 */ { 0, "sigpending" },
/* 100 */ { 0, "context" },
/* 101 */ { 0, "evsys" },
/* 153 */ { 0, "fchroot" },
/* 154 */ { 0, "utimes" },
/* 155 */ { 0, "vhangup" },
- /* 156 */ { 0, "gettimeofday" },
+ /* 156 */ { do_unix_gettimeofday, "gettimeofday" },
/* 157 */ { 0, "getitimer" },
/* 158 */ { 0, "setitimer" },
/* 159 */ { 0, "lwp_create" },
return emul_unix_create(root, image, "solaris", &emul_solaris_syscalls);
}
-
+
static void
emul_solaris_init(os_emul_data *emul_data,
int nr_cpus)
{
- /* nothing yet */
+ fd_closed[0] = 0;
+ fd_closed[1] = 0;
+ fd_closed[2] = 0;
}
static void
};
\f
+/* EMULATION
+
+ Linux - Emulation of user programs for Linux/PPC
+
+ DESCRIPTION
+
+ */
+
+
/* Linux specific implementation */
typedef unsigned32 linux_dev_t;
if (WITH_TRACE && ppc_trace[trace_os_emul])
printf_filtered ("%d, 0x%lx", fildes, (long)stat_pkt);
- status = fstat (fildes, &buf);
+ status = fdbad (fildes);
+ if (status == 0)
+ status = fstat (fildes, &buf);
if (status == 0)
convert_to_linux_stat (stat_pkt, &buf, processor, cia);
}
#endif
-#if defined(HAVE_SYS_TERMIO_H) || defined(HAVE_SYS_TERMIOS_H)
+#if defined(HAVE_TERMIO_STRUCTURE) || defined(HAVE_TERMIOS_STRUCTURE)
#define LINUX_NCC 10
#define LINUX_NCCS 19
#define LINUX_IOWR(type,nr,size) LINUX_IOC(LINUX_IOC_READ|LINUX_IOC_WRITE,(type),(nr),sizeof(size))
#endif
-#ifdef HAVE_SYS_TERMIO_H
+#if defined(HAVE_TERMIO_STRUCTURE) || defined(HAVE_TERMIOS_STRUCTURE)
/* Convert to/from host termio structure */
struct linux_termio {
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;
emul_write_buffer(&target, addr, sizeof(target), processor, cia);
}
-#endif /* HAVE_SYS_TERMIO_H */
+#endif /* HAVE_TERMIO_STRUCTURE */
-#ifdef HAVE_SYS_TERMIOS_H
+#ifdef HAVE_TERMIOS_STRUCTURE
/* Convert to/from host termios structure */
typedef unsigned32 linux_tcflag_t;
#endif
#ifdef VSWTCH
- target.c_cc[LINUX_VSWTCH] = host->c_cc[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);
emul_write_buffer(&target, addr, sizeof(target), processor, cia);
}
-#endif /* HAVE_SYS_TERMIOS_H */
+#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)
+ 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];
int status = 0;
const char *name = "<unknown>";
-#ifdef HAVE_SYS_TERMIO_H
+#ifdef HAVE_TERMIOS_STRUCTURE
+ struct termios host_termio;
+
+#else
+#ifdef HAVE_TERMIO_STRUCTURE
struct termio host_termio;
#endif
-
-#ifdef HAVE_SYS_TERMIOS_H
- struct termios host_termios;
#endif
+ status = fdbad (fildes);
+ if (status != 0)
+ goto done;
+
switch (request)
{
case 0: /* make sure we have at least one case */
errno = EINVAL;
break;
-#ifdef HAVE_SYS_TERMIO_H
-#ifdef TCGETA
+#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_SYS_TERMIO_H */
+#endif /* HAVE_TERMIO_STRUCTURE */
-#ifdef HAVE_SYS_TERMIOS_H
+#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_termios);
+ status = tcgetattr(fildes, &host_termio);
#else
- status = ioctl (fildes, TCGETS, &host_termios);
+ status = ioctl (fildes, TCGETS, &host_termio);
#endif
if (status == 0)
- convert_to_linux_termios (argp_addr, &host_termios, processor, cia);
+ convert_to_linux_termios (argp_addr, &host_termio, processor, cia);
break;
#endif /* TCGETS */
-#endif /* HAVE_SYS_TERMIOS_H */
+#endif /* HAVE_TERMIOS_STRUCTURE */
}
+done:
emul_write_status(processor, status, errno);
if (WITH_TRACE && ppc_trace[trace_os_emul])
/* 10 */ { do_unix_unlink, "unlink" },
/* 11 */ { 0, "execve" },
/* 12 */ { do_unix_chdir, "chdir" },
- /* 13 */ { 0, "time" },
+ /* 13 */ { do_unix_time, "time" },
/* 14 */ { 0, "mknod" },
/* 15 */ { 0, "chmod" },
/* 16 */ { 0, "chown" },
/* 30 */ { 0, "utime" },
/* 31 */ { 0, "stty" },
/* 32 */ { 0, "gtty" },
- /* 33 */ { 0, "access" },
+ /* 33 */ { do_unix_access, "access" },
/* 34 */ { 0, "nice" },
/* 35 */ { 0, "ftime" },
/* 36 */ { 0, "sync" },
/* 74 */ { 0, "sethostname" },
/* 75 */ { 0, "setrlimit" },
/* 76 */ { 0, "getrlimit" },
- /* 77 */ { 0, "getrusage" },
- /* 78 */ { 0, "gettimeofday" },
+ /* 77 */ { do_unix_getrusage, "getrusage" },
+ /* 78 */ { do_unix_gettimeofday, "gettimeofday" },
/* 79 */ { 0, "settimeofday" },
/* 80 */ { 0, "getgroups" },
/* 81 */ { 0, "setgroups" },
static os_emul_data *
emul_linux_create(device *root,
- bfd *image,
- const char *name)
+ bfd *image,
+ const char *name)
{
/* check that this emulation is really for us */
if (name != NULL && strcmp(name, "linux") != 0)
static void
emul_linux_init(os_emul_data *emul_data,
- int nr_cpus)
+ int nr_cpus)
{
- /* nothing yet */
+ 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)
+ unsigned_word cia,
+ os_emul_data *emul_data)
{
emul_do_system_call(emul_data,
emul_data->syscalls,