+2015-12-29 Kevin Buettner <kevinb@redhat.com>
+
+ * emul_netbsd.c (fd_closed): New static array.
+ (fdbad): New function.
+ (do_read, do_write, do_close, do_dup, do_ioctl, do_dup2, do_fcntl)
+ (do_fstatfs, do_fstat, do_lseek): Call `fdbad'.
+ (emul_netbsd_init): Initialize `fd_closed'.
+ * emul_unix.c (fd_closed): New static array.
+ (fdbad): New function.
+ (do_unix_read, do_unix_write, do_unix_close, do_unix_dup)
+ (do_unix_dup2, do_unix_lseek, do_solaris_fstat, do_solaris_ioctl)
+ (do_linux_fstat, do_linux_ioctl): Call `fdbad'.
+ (emul_solaris_init, emul_linux_init): Initialize `fd_closed'.
+
2015-12-26 Mike Frysinger <vapier@gentoo.org>
* Makefile.in (TCONFIG_H): Delete.
}
#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,
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)
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);
free(scratch_buffer);
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);
}
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])
|| 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
{
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])
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
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)
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);
}
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 {
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
};
+/* 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_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);
free(scratch_buffer);
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)
{
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])
if (WITH_TRACE && ppc_trace[trace_os_emul])
printf_filtered ("%d %ld %d", fildes, (long)offset, whence);
- status = lseek(fildes, offset, whence);
+ status = fdbad (fildes);
+ if (status == 0)
+ status = lseek(fildes, offset, whence);
emul_write_status(processor, (int)status, errno);
}
#endif
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
#endif
+ status = fdbad (fildes);
+ if (status != 0)
+ goto done;
+
switch (request)
{
case 0: /* make sure we have at least one case */
#endif /* HAVE_TERMIOS_STRUCTURE */
}
+done:
emul_write_status(processor, status, errno);
if (WITH_TRACE && ppc_trace[trace_os_emul])
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
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
#endif
+ status = fdbad (fildes);
+ if (status != 0)
+ goto done;
+
switch (request)
{
case 0: /* make sure we have at least one case */
#endif /* HAVE_TERMIOS_STRUCTURE */
}
+done:
emul_write_status(processor, status, errno);
if (WITH_TRACE && ppc_trace[trace_os_emul])
emul_linux_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