📄 emul_netbsd.c
字号:
/* This file is part of the program psim. Copyright (C) 1994-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 (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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#ifndef _EMUL_NETBSD_C_#define _EMUL_NETBSD_C_/* Note: this module is called via a table. There is no benefit in making it inline */#include "emul_generic.h"#include "emul_netbsd.h"#ifdef HAVE_STRING_H#include <string.h>#else#ifdef HAVE_STRINGS_H#include <strings.h>#endif#endif#include <sys/types.h>#include <sys/stat.h>#include <stdio.h>#include <signal.h>#include <fcntl.h>#include <errno.h>#include <sys/errno.h>#include <sys/param.h>#include <sys/time.h>#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_SYS_IOCTL_H#include <sys/ioctl.h>#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#define WITH_NetBSD_HOST (NetBSD >= 199306)#if WITH_NetBSD_HOST /* here NetBSD as that is what we're emulating */#include <sys/syscall.h> /* FIXME - should not be including this one */#include <sys/sysctl.h>#include <sys/mount.h>extern int getdirentries(int fd, char *buf, int nbytes, long *basep);/* NetBSD post 2.0 has the statfs system call (if COMPAT_20), but does not have struct statfs. In this case don't implement fstatfs. FIXME: Should implement fstatvfs. */#ifndef HAVE_STRUCT_STATFS#undef HAVE_FSTATFS#endif#else/* If this is not netbsd, don't allow fstatfs or getdirentries at this time */#undef HAVE_FSTATFS#undef HAVE_GETDIRENTRIES#endif#if (BSD < 199306) /* here BSD as just a bug */extern int errno;#endif#ifndef STATIC_INLINE_EMUL_NETBSD#define STATIC_INLINE_EMUL_NETBSD STATIC_INLINE#endif#if WITH_NetBSD_HOST#define SYS(X) ASSERT(call == (SYS_##X))#else#define SYS(X)#endif#if WITH_NetBSD_HOST && (PATH_MAX != 1024)#error "PATH_MAX not 1024"#elif !defined(PATH_MAX)#define PATH_MAX 1024#endif/* EMULATION NetBSD - Emulation of user programs for NetBSD/PPC DESCRIPTION *//* NetBSD's idea of what is needed to implement emulations */struct _os_emul_data { device *vm; emul_syscall *syscalls;};STATIC_INLINE_EMUL_NETBSD voidwrite_stat(unsigned_word addr, struct stat buf, cpu *processor, unsigned_word cia){ H2T(buf.st_dev); H2T(buf.st_ino); H2T(buf.st_mode); H2T(buf.st_nlink); H2T(buf.st_uid); H2T(buf.st_gid); H2T(buf.st_size); H2T(buf.st_atime); /* H2T(buf.st_spare1); */ H2T(buf.st_mtime); /* H2T(buf.st_spare2); */ H2T(buf.st_ctime); /* H2T(buf.st_spare3); */#ifdef AC_STRUCT_ST_RDEV H2T(buf.st_rdev);#endif#ifdef AC_STRUCT_ST_BLKSIZE H2T(buf.st_blksize);#endif#ifdef AC_STRUCT_ST_BLOCKS H2T(buf.st_blocks);#endif#if WITH_NetBSD_HOST H2T(buf.st_flags); H2T(buf.st_gen);#endif emul_write_buffer(&buf, addr, sizeof(buf), processor, cia);}#ifdef HAVE_FSTATFSSTATIC_INLINE_EMUL_NETBSD voidwrite_statfs(unsigned_word addr, struct statfs buf, cpu *processor, unsigned_word cia){ H2T(buf.f_type); H2T(buf.f_flags); H2T(buf.f_bsize); H2T(buf.f_iosize); H2T(buf.f_blocks); H2T(buf.f_bfree); H2T(buf.f_bavail); H2T(buf.f_files); H2T(buf.f_ffree); H2T(buf.f_fsid.val[0]); H2T(buf.f_fsid.val[1]); H2T(buf.f_owner); /* f_spare[4]; */ /* f_fstypename[MFSNAMELEN]; */ /* f_mntonname[MNAMELEN]; */ /* f_mntfromname[MNAMELEN]; */ emul_write_buffer(&buf, addr, sizeof(buf), processor, cia);}#endifSTATIC_INLINE_EMUL_NETBSD voidwrite_timeval(unsigned_word addr, struct timeval t, cpu *processor, unsigned_word cia){ H2T(t.tv_sec); H2T(t.tv_usec); emul_write_buffer(&t, addr, sizeof(t), processor, cia);}STATIC_INLINE_EMUL_NETBSD voidwrite_timezone(unsigned_word addr, struct timezone tz, cpu *processor, unsigned_word cia){ H2T(tz.tz_minuteswest); H2T(tz.tz_dsttime); emul_write_buffer(&tz, addr, sizeof(tz), processor, cia);}#ifdef HAVE_GETDIRENTRIESSTATIC_INLINE_EMUL_NETBSD voidwrite_direntries(unsigned_word addr, char *buf, int nbytes, cpu *processor, unsigned_word cia){ while (nbytes > 0) { struct dirent *out; struct dirent *in = (struct dirent*)buf; ASSERT(in->d_reclen <= nbytes); out = (struct dirent*)zalloc(in->d_reclen); memcpy(out/*dest*/, in/*src*/, in->d_reclen); H2T(out->d_fileno); H2T(out->d_reclen); H2T(out->d_type); H2T(out->d_namlen); emul_write_buffer(out, addr, in->d_reclen, processor, cia); nbytes -= in->d_reclen; addr += in->d_reclen; buf += in->d_reclen; zfree(out); }}#endif#ifdef HAVE_GETRUSAGESTATIC_INLINE_EMUL_NETBSD voidwrite_rusage(unsigned_word addr, struct rusage rusage, cpu *processor, unsigned_word cia){ H2T(rusage.ru_utime.tv_sec); /* user time used */ H2T(rusage.ru_utime.tv_usec); H2T(rusage.ru_stime.tv_sec); /* system time used */ H2T(rusage.ru_stime.tv_usec); H2T(rusage.ru_maxrss); /* integral max resident set size */ H2T(rusage.ru_ixrss); /* integral shared text memory size */ H2T(rusage.ru_idrss); /* integral unshared data size */ H2T(rusage.ru_isrss); /* integral unshared stack size */ H2T(rusage.ru_minflt); /* page reclaims */ H2T(rusage.ru_majflt); /* page faults */ H2T(rusage.ru_nswap); /* swaps */ H2T(rusage.ru_inblock); /* block input operations */ H2T(rusage.ru_oublock); /* block output operations */ H2T(rusage.ru_msgsnd); /* messages sent */ H2T(rusage.ru_msgrcv); /* messages received */ H2T(rusage.ru_nsignals); /* signals received */ H2T(rusage.ru_nvcsw); /* voluntary context switches */ H2T(rusage.ru_nivcsw); /* involuntary context switches */ emul_write_buffer(&rusage, addr, sizeof(rusage), processor, cia);}#endifstatic voiddo_exit(os_emul_data *emul, unsigned call, const int arg0, cpu *processor, unsigned_word cia){ int status = (int)cpu_registers(processor)->gpr[arg0]; SYS(exit); if (WITH_TRACE && ppc_trace[trace_os_emul]) printf_filtered ("%d)\n", status); cpu_halt(processor, cia, was_exited, status);}static voiddo_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; SYS(read); 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); /* read */#if 0 if (d == 0) { status = fread (scratch_buffer, 1, nbytes, stdin); if (status == 0 && ferror (stdin)) status = -1; }#endif 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 voiddo_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; SYS(write); 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); /* write */ status = write(d, scratch_buffer, nbytes); emul_write_status(processor, status, errno); zfree(scratch_buffer); flush_stdoutput();}static voiddo_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 hostflags; 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); SYS(open); /* Do some translation on 'flags' to match it to the host's version. */ /* These flag values were taken from the NetBSD 1.4 header files. */ if ((flags & 3) == 0) hostflags = O_RDONLY; else if ((flags & 3) == 1) hostflags = O_WRONLY; else hostflags = O_RDWR; if (flags & 0x00000008) hostflags |= O_APPEND; if (flags & 0x00000200) hostflags |= O_CREAT; if (flags & 0x00000400) hostflags |= O_TRUNC; if (flags & 0x00000800) hostflags |= O_EXCL; /* Can't combine these statements, cuz open sets errno. */ status = open(path, hostflags, mode); emul_write_status(processor, status, errno);}static voiddo_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); SYS(close); /* Can't combine these statements, cuz close sets errno. */ status = close(d); emul_write_status(processor, status, errno);}static voiddo_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]); SYS(break); status = device_ioctl(emul->vm, processor, cia, device_ioctl_break, new_break); /*ioctl-data*/ emul_write_status(processor, 0, status);}#ifndef HAVE_GETPID#define do_getpid 0#elsestatic voiddo_getpid(os_emul_data *emul, unsigned call, const int arg0, cpu *processor, unsigned_word cia){ SYS(getpid); emul_write_status(processor, (int)getpid(), 0);}#endif#ifndef HAVE_GETUID#define do_getuid 0#elsestatic void
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -