X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=sim%2Fppc%2Femul_netbsd.c;h=f81c9cb250330033d77bd12b4f56b1411f655183;hb=7206a0ee43e8c1bc26e7ddc8c589018e75783225;hp=3fc64bcaeb3e43c5b33c31d03ec23c9623711991;hpb=262faa5417cda51e88583546bb1f1d22eec6ec77;p=deliverable%2Fbinutils-gdb.git diff --git a/sim/ppc/emul_netbsd.c b/sim/ppc/emul_netbsd.c index 3fc64bcaeb..f81c9cb250 100644 --- a/sim/ppc/emul_netbsd.c +++ b/sim/ppc/emul_netbsd.c @@ -1,6 +1,6 @@ /* This file is part of the program psim. - Copyright (C) 1994-1996, Andrew Cagney + Copyright (C) 1994-1998, Andrew Cagney 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 @@ -11,11 +11,11 @@ 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. - + */ @@ -42,7 +42,7 @@ #include #include #include -#include +#include #include #include @@ -57,8 +57,9 @@ int getrusage(); #endif +#if HAVE_SYS_IOCTL_H #include -#include +#endif #if HAVE_DIRENT_H # include @@ -78,6 +79,7 @@ int getrusage(); #endif #ifdef HAVE_UNISTD_H +#undef MAXPATHLEN /* sys/param.h might define this also */ #include #endif @@ -89,7 +91,21 @@ int getrusage(); #if WITH_NetBSD_HOST /* here NetBSD as that is what we're emulating */ #include /* FIXME - should not be including this one */ #include +#include 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 */ @@ -114,6 +130,15 @@ extern int errno; #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 { @@ -135,7 +160,6 @@ write_stat(unsigned_word addr, H2T(buf.st_nlink); H2T(buf.st_uid); H2T(buf.st_gid); - H2T(buf.st_rdev); H2T(buf.st_size); H2T(buf.st_atime); /* H2T(buf.st_spare1); */ @@ -143,8 +167,15 @@ write_stat(unsigned_word addr, /* 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); @@ -152,8 +183,8 @@ write_stat(unsigned_word addr, emul_write_buffer(&buf, addr, sizeof(buf), processor, cia); } - -#if NetBSD + +#ifdef HAVE_FSTATFS STATIC_INLINE_EMUL_NETBSD void write_statfs(unsigned_word addr, struct statfs buf, @@ -180,7 +211,7 @@ write_statfs(unsigned_word addr, } #endif - + STATIC_INLINE_EMUL_NETBSD void write_timeval(unsigned_word addr, struct timeval t, @@ -192,7 +223,7 @@ write_timeval(unsigned_word addr, emul_write_buffer(&t, addr, sizeof(t), processor, cia); } - +#ifdef HAVE_GETTIMEOFDAY STATIC_INLINE_EMUL_NETBSD void write_timezone(unsigned_word addr, struct timezone tz, @@ -203,9 +234,9 @@ write_timezone(unsigned_word addr, H2T(tz.tz_dsttime); emul_write_buffer(&tz, addr, sizeof(tz), processor, cia); } +#endif - -#if WITH_NetBSD_HOST +#ifdef HAVE_GETDIRENTRIES STATIC_INLINE_EMUL_NETBSD void write_direntries(unsigned_word addr, char *buf, @@ -261,7 +292,7 @@ write_rusage(unsigned_word addr, emul_write_buffer(&rusage, addr, sizeof(rusage), processor, cia); } #endif - + static void do_exit(os_emul_data *emul, unsigned call, @@ -291,16 +322,16 @@ do_read(os_emul_data *emul, 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) { @@ -310,16 +341,11 @@ do_read(os_emul_data *emul, } #endif status = read (d, scratch_buffer, nbytes); - - if (status == -1) { - cpu_registers(processor)->gpr[0] = errno; - } else { - cpu_registers(processor)->gpr[3] = status; - - if (status > 0) - emul_write_buffer(scratch_buffer, buf, status, processor, cia); - } - + + emul_write_status(processor, status, errno); + if (status > 0) + emul_write_buffer(scratch_buffer, buf, status, processor, cia); + zfree(scratch_buffer); } @@ -332,30 +358,22 @@ do_write(os_emul_data *emul, 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]; 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 */ - 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); + /* write */ status = write(d, scratch_buffer, nbytes); emul_write_status(processor, status, errno); @@ -377,12 +395,34 @@ do_open(os_emul_data *emul, 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); - emul_write_status(processor, open(path, flags, mode), errno); + + /* 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); } @@ -394,12 +434,16 @@ do_close(os_emul_data *emul, 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); - emul_write_status(processor, close(d), errno); + + /* Can't combine these statements, cuz close sets errno. */ + status = close(d); + emul_write_status(processor, status, errno); } @@ -411,21 +455,25 @@ do_break(os_emul_data *emul, 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; if (WITH_TRACE && ppc_trace[trace_os_emul]) printf_filtered ("0x%lx", (long)cpu_registers(processor)->gpr[arg0]); SYS(break); - device_ioctl(emul->vm, - system, - processor, - cia, - 0, /*ioctl*/ - NULL); /*ioctl-data*/ + 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 +#else static void do_getpid(os_emul_data *emul, unsigned call, @@ -434,10 +482,13 @@ do_getpid(os_emul_data *emul, unsigned_word cia) { SYS(getpid); - cpu_registers(processor)->gpr[3] = (int)getpid(); + emul_write_status(processor, (int)getpid(), 0); } +#endif - +#ifndef HAVE_GETUID +#define do_getuid 0 +#else static void do_getuid(os_emul_data *emul, unsigned call, @@ -446,10 +497,13 @@ do_getuid(os_emul_data *emul, unsigned_word cia) { SYS(getuid); - cpu_registers(processor)->gpr[3] = (int)getuid(); + emul_write_status(processor, (int)getuid(), 0); } +#endif - +#ifndef HAVE_GETEUID +#define do_geteuid 0 +#else static void do_geteuid(os_emul_data *emul, unsigned call, @@ -458,10 +512,13 @@ do_geteuid(os_emul_data *emul, unsigned_word cia) { SYS(geteuid); - cpu_registers(processor)->gpr[3] = (int)geteuid(); + emul_write_status(processor, (int)geteuid(), 0); } +#endif - +#ifndef HAVE_KILL +#define do_kill 0 +#else static void do_kill(os_emul_data *emul, unsigned call, @@ -480,8 +537,11 @@ do_kill(os_emul_data *emul, (long)cia); cpu_halt(processor, cia, was_signalled, sig); } +#endif - +#ifndef HAVE_DUP +#define do_dup 0 +#else static void do_dup(os_emul_data *emul, unsigned call, @@ -491,15 +551,19 @@ do_dup(os_emul_data *emul, { 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); SYS(dup); - emul_write_status(processor, status, errno); + emul_write_status(processor, status, err); } +#endif - +#ifndef HAVE_GETEGID +#define do_getegid 0 +#else static void do_getegid(os_emul_data *emul, unsigned call, @@ -508,10 +572,13 @@ do_getegid(os_emul_data *emul, unsigned_word cia) { SYS(getegid); - cpu_registers(processor)->gpr[3] = (int)getegid(); + emul_write_status(processor, (int)getegid(), 0); } +#endif - +#ifndef HAVE_GETGID +#define do_getgid 0 +#else static void do_getgid(os_emul_data *emul, unsigned call, @@ -520,10 +587,13 @@ do_getgid(os_emul_data *emul, unsigned_word cia) { SYS(getgid); - cpu_registers(processor)->gpr[3] = (int)getgid(); + emul_write_status(processor, (int)getgid(), 0); } +#endif - +#ifndef HAVE_SIGPROCMASK +#define do_sigprocmask 0 +#else static void do_sigprocmask(os_emul_data *emul, unsigned call, @@ -534,16 +604,21 @@ do_sigprocmask(os_emul_data *emul, natural_word how = cpu_registers(processor)->gpr[arg0]; unsigned_word set = cpu_registers(processor)->gpr[arg0+1]; unsigned_word oset = cpu_registers(processor)->gpr[arg0+2]; +#ifdef SYS_sigprocmask SYS(sigprocmask); +#endif if (WITH_TRACE && ppc_trace[trace_os_emul]) printf_filtered ("%ld, 0x%ld, 0x%ld", (long)how, (long)set, (long)oset); - cpu_registers(processor)->gpr[3] = 0; + emul_write_status(processor, 0, 0); cpu_registers(processor)->gpr[4] = set; } +#endif - +#ifndef HAVE_IOCTL +#define do_ioctl 0 +#else static void do_ioctl(os_emul_data *emul, unsigned call, @@ -573,8 +648,11 @@ do_ioctl(os_emul_data *emul, if (WITH_TRACE && ppc_trace[trace_os_emul]) printf_filtered ("%d, 0x%x, 0x%lx", d, request, (long)argp_addr); } +#endif - +#ifndef HAVE_UMASK +#define do_umask 0 +#else static void do_umask(os_emul_data *emul, unsigned call, @@ -588,10 +666,13 @@ do_umask(os_emul_data *emul, printf_filtered ("0%o", mask); SYS(umask); - cpu_registers(processor)->gpr[3] = umask(mask); + emul_write_status(processor, umask(mask), 0); } +#endif - +#ifndef HAVE_DUP2 +#define do_dup2 0 +#else static void do_dup2(os_emul_data *emul, unsigned call, @@ -602,15 +683,19 @@ do_dup2(os_emul_data *emul, 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); SYS(dup2); - emul_write_status(processor, status, errno); + emul_write_status(processor, status, err); } +#endif - +#ifndef HAVE_FCNTL +#define do_fcntl 0 +#else static void do_fcntl(os_emul_data *emul, unsigned call, @@ -630,8 +715,11 @@ do_fcntl(os_emul_data *emul, status = fcntl(fd, cmd, arg); emul_write_status(processor, status, errno); } +#endif - +#ifndef HAVE_GETTIMEOFDAY +#define do_gettimeofday 0 +#else static void do_gettimeofday(os_emul_data *emul, unsigned call, @@ -645,12 +733,13 @@ do_gettimeofday(os_emul_data *emul, struct timezone tz; int status = gettimeofday((t_addr != 0 ? &t : NULL), (tz_addr != 0 ? &tz : NULL)); + int err = errno; if (WITH_TRACE && ppc_trace[trace_os_emul]) printf_filtered ("0x%lx, 0x%lx", (long)t_addr, (long)tz_addr); SYS(gettimeofday); - emul_write_status(processor, status, errno); + emul_write_status(processor, status, err); if (status == 0) { if (t_addr != 0) write_timeval(t_addr, t, processor, cia); @@ -658,7 +747,7 @@ do_gettimeofday(os_emul_data *emul, write_timezone(tz_addr, tz, processor, cia); } } - +#endif #ifndef HAVE_GETRUSAGE #define do_getrusage 0 @@ -674,12 +763,13 @@ do_getrusage(os_emul_data *emul, unsigned_word rusage_addr = cpu_registers(processor)->gpr[arg0+1]; struct rusage rusage; int status = getrusage(who, (rusage_addr != 0 ? &rusage : NULL)); + int err = errno; if (WITH_TRACE && ppc_trace[trace_os_emul]) printf_filtered ("%d, 0x%lx", who, (long)rusage_addr); SYS(getrusage); - emul_write_status(processor, status, errno); + emul_write_status(processor, status, err); if (status == 0) { if (rusage_addr != 0) write_rusage(rusage_addr, rusage, processor, cia); @@ -688,7 +778,7 @@ do_getrusage(os_emul_data *emul, #endif -#if !WITH_NetBSD_HOST +#ifndef HAVE_FSTATFS #define do_fstatfs 0 #else static void @@ -716,7 +806,9 @@ do_fstatfs(os_emul_data *emul, } #endif - +#ifndef HAVE_STAT +#define do_stat 0 +#else static void do_stat(os_emul_data *emul, unsigned call, @@ -730,14 +822,19 @@ do_stat(os_emul_data *emul, char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia); struct stat buf; int status; +#ifdef SYS_stat SYS(stat); +#endif status = stat(path, &buf); emul_write_status(processor, status, errno); if (status == 0) write_stat(stat_buf_addr, buf, processor, cia); } +#endif - +#ifndef HAVE_FSTAT +#define do_fstat 0 +#else static void do_fstat(os_emul_data *emul, unsigned call, @@ -748,12 +845,20 @@ do_fstat(os_emul_data *emul, int fd = cpu_registers(processor)->gpr[arg0]; unsigned_word stat_buf_addr = cpu_registers(processor)->gpr[arg0+1]; struct stat buf; + int status; +#ifdef SYS_fstat SYS(fstat); - emul_write_status(processor, fstat(fd, &buf), errno); +#endif + /* Can't combine these statements, cuz fstat sets errno. */ + status = fstat(fd, &buf); + emul_write_status(processor, status, errno); write_stat(stat_buf_addr, buf, processor, cia); } +#endif - +#ifndef HAVE_LSTAT +#define do_lstat 0 +#else static void do_lstat(os_emul_data *emul, unsigned call, @@ -766,13 +871,18 @@ do_lstat(os_emul_data *emul, char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia); unsigned_word stat_buf_addr = cpu_registers(processor)->gpr[arg0+1]; struct stat buf; + int status; +#ifdef SYS_lstat SYS(lstat); - emul_write_status(processor, stat(path, &buf), errno); +#endif + /* Can't combine these statements, cuz lstat sets errno. */ + status = lstat(path, &buf); + emul_write_status(processor, status, errno); write_stat(stat_buf_addr, buf, processor, cia); } +#endif - -#if !WITH_NetBSD_HOST +#ifndef HAVE_GETDIRENTRIES #define do_getdirentries 0 #else static void @@ -789,7 +899,9 @@ do_getdirentries(os_emul_data *emul, unsigned_word basep_addr = cpu_registers(processor)->gpr[arg0+3]; long basep; int status; +#ifdef SYS_getdirentries SYS(getdirentries); +#endif if (buf_addr != 0 && nbytes >= 0) buf = zalloc(nbytes); else @@ -825,7 +937,9 @@ do___syscall(os_emul_data *emul, cia); } - +#ifndef HAVE_LSEEK +#define do_lseek 0 +#else static void do_lseek(os_emul_data *emul, unsigned call, @@ -842,10 +956,11 @@ do_lseek(os_emul_data *emul, if (status == -1) emul_write_status(processor, -1, errno); else { + emul_write_status(processor, 0, 0); /* success */ emul_write_gpr64(processor, 3, status); } } - +#endif static void do___sysctl(os_emul_data *emul, @@ -872,7 +987,7 @@ do___sysctl(os_emul_data *emul, processor, cia); name += sizeof(mib); - + /* see what to do with it ... */ switch ((int)mib) { case 6/*CTL_HW*/: @@ -911,7 +1026,7 @@ do___sysctl(os_emul_data *emul, error("sysctl() name[0]=%d unknown\n", (int)mib); break; } - cpu_registers(processor)->gpr[3] = 0; + emul_write_status(processor, 0, 0); /* always succeed */ } @@ -919,7 +1034,7 @@ do___sysctl(os_emul_data *emul, static emul_syscall_descriptor netbsd_descriptors[] = { /* 0 */ { 0, "syscall" }, /* 1 */ { do_exit, "exit" }, - /* 2 */ { 0, "fork" }, + /* 2 */ { 0, "fork" }, /* 3 */ { do_read, "read" }, /* 4 */ { do_write, "write" }, /* 5 */ { do_open, "open" }, @@ -1123,7 +1238,7 @@ static emul_syscall_descriptor netbsd_descriptors[] = { /* 203 */ { 0, "mlock" }, /* 204 */ { 0, "munlock" }, }; - + static char *(netbsd_error_names[]) = { /* 0 */ "ESUCCESS", /* 1 */ "EPERM", @@ -1268,6 +1383,7 @@ emul_netbsd_create(device *root, int elf_binary; os_emul_data *bsd_data; device *vm; + char *filename; /* check that this emulation is really for us */ if (name != NULL && strcmp(name, "netbsd") != 0) @@ -1297,26 +1413,32 @@ emul_netbsd_create(device *root, 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"); + 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", - (device_find_boolean_property(root, "/options/little-endian?") - ? msr_little_endian_mode - : 0)); - 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 */ bsd_data = ZALLOC(os_emul_data); @@ -1354,4 +1476,4 @@ const os_emul emul_netbsd = { 0 /*data*/ }; -#endif _EMUL_NETBSD_C_ +#endif /* _EMUL_NETBSD_C_ */