X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=sim%2Fppc%2Femul_netbsd.c;h=9b80fc25dc812ab4317de3a7481b34a31199cc07;hb=7ef412cf72a197d68e532604cc1fa21351adc858;hp=13897face2dfeb9ad8db8e1149f8e561810008d2;hpb=c663138840a39a5c9aefc853f2b6e963ff0446bb;p=deliverable%2Fbinutils-gdb.git diff --git a/sim/ppc/emul_netbsd.c b/sim/ppc/emul_netbsd.c index 13897face2..9b80fc25dc 100644 --- a/sim/ppc/emul_netbsd.c +++ b/sim/ppc/emul_netbsd.c @@ -4,7 +4,7 @@ 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, @@ -13,8 +13,7 @@ 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 . */ @@ -43,7 +42,6 @@ #include #include #include -#include #include #include @@ -94,6 +92,14 @@ int getrusage(); #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 */ @@ -216,7 +222,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, @@ -227,7 +233,7 @@ write_timezone(unsigned_word addr, H2T(tz.tz_dsttime); emul_write_buffer(&tz, addr, sizeof(tz), processor, cia); } - +#endif #ifdef HAVE_GETDIRENTRIES STATIC_INLINE_EMUL_NETBSD void @@ -251,7 +257,7 @@ write_direntries(unsigned_word addr, nbytes -= in->d_reclen; addr += in->d_reclen; buf += in->d_reclen; - zfree(out); + free(out); } } #endif @@ -286,6 +292,31 @@ write_rusage(unsigned_word addr, } #endif + +/* 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_exit(os_emul_data *emul, unsigned call, @@ -333,13 +364,15 @@ do_read(os_emul_data *emul, status = -1; } #endif - status = read (d, scratch_buffer, nbytes); + status = fdbad (d); + 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); } @@ -368,9 +401,12 @@ do_write(os_emul_data *emul, processor, cia); /* write */ - status = write(d, scratch_buffer, nbytes); + status = fdbad (d); + if (status == 0) + status = write(d, scratch_buffer, nbytes); + emul_write_status(processor, status, errno); - zfree(scratch_buffer); + free(scratch_buffer); flush_stdoutput(); } @@ -434,8 +470,20 @@ do_close(os_emul_data *emul, SYS(close); - /* Can't combine these statements, cuz close sets errno. */ - 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); } @@ -543,7 +591,7 @@ do_dup(os_emul_data *emul, 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]) @@ -634,7 +682,9 @@ do_ioctl(os_emul_data *emul, || dir & IOC_OUT || !(dir & IOC_VOID)) error("do_ioctl() read or write of parameter not implemented\n"); - status = ioctl(d, request, NULL); + status = fdbad (d); + if (status == 0) + status = ioctl(d, request, NULL); emul_write_status(processor, status, errno); #endif @@ -675,7 +725,7 @@ 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 status = (fdbad (oldd) < 0) ? -1 : dup2(oldd, newd); int err = errno; if (WITH_TRACE && ppc_trace[trace_os_emul]) @@ -705,7 +755,9 @@ do_fcntl(os_emul_data *emul, printf_filtered ("%d, %d, %d", fd, cmd, arg); SYS(fcntl); - status = fcntl(fd, cmd, arg); + status = fdbad (fd); + if (status == 0) + status = fcntl(fd, cmd, arg); emul_write_status(processor, status, errno); } #endif @@ -790,7 +842,9 @@ do_fstatfs(os_emul_data *emul, printf_filtered ("%d, 0x%lx", fd, (long)buf_addr); SYS(fstatfs); - status = fstatfs(fd, (buf_addr == 0 ? NULL : &buf)); + status = fdbad (fd); + if (status == 0) + status = fstatfs(fd, (buf_addr == 0 ? NULL : &buf)); emul_write_status(processor, status, errno); if (status == 0) { if (buf_addr != 0) @@ -843,7 +897,9 @@ do_fstat(os_emul_data *emul, SYS(fstat); #endif /* Can't combine these statements, cuz fstat sets errno. */ - status = fstat(fd, &buf); + status = fdbad (fd); + if (status == 0) + status = fstat(fd, &buf); emul_write_status(processor, status, errno); write_stat(stat_buf_addr, buf, processor, cia); } @@ -909,7 +965,7 @@ do_getdirentries(os_emul_data *emul, if (status > 0) write_direntries(buf_addr, buf, status, processor, cia); if (buf != NULL) - zfree(buf); + free(buf); } #endif @@ -945,7 +1001,9 @@ do_lseek(os_emul_data *emul, int whence = cpu_registers(processor)->gpr[arg0+4]; off_t status; SYS(lseek); - status = lseek(fildes, offset, whence); + status = fdbad (fildes); + if (status == 0) + status = lseek(fildes, offset, whence); if (status == -1) emul_write_status(processor, -1, errno); else { @@ -1355,11 +1413,11 @@ static char *(netbsd_signal_names[]) = { static emul_syscall emul_netbsd_syscalls = { netbsd_descriptors, - sizeof(netbsd_descriptors) / sizeof(netbsd_descriptors[0]), + ARRAY_SIZE (netbsd_descriptors), netbsd_error_names, - sizeof(netbsd_error_names) / sizeof(netbsd_error_names[0]), + ARRAY_SIZE (netbsd_error_names), netbsd_signal_names, - sizeof(netbsd_signal_names) / sizeof(netbsd_signal_names[0]), + ARRAY_SIZE (netbsd_signal_names), }; @@ -1376,6 +1434,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) @@ -1410,8 +1469,10 @@ emul_netbsd_create(device *root, (unsigned long)(top_of_stack - stack_size)); tree_parse(vm, "./nr-bytes 0x%x", stack_size); + filename = tree_quote_property (bfd_get_filename(image)); tree_parse(root, "/openprom/vm/map-binary/file-name %s", - bfd_get_filename(image)); + filename); + free (filename); /* finish the init */ tree_parse(root, "/openprom/init/register/pc 0x%lx", @@ -1441,7 +1502,9 @@ static void emul_netbsd_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 @@ -1466,4 +1529,4 @@ const os_emul emul_netbsd = { 0 /*data*/ }; -#endif _EMUL_NETBSD_C_ +#endif /* _EMUL_NETBSD_C_ */