aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
Diffstat (limited to 'gdb')
-rw-r--r--gdb/ChangeLog15
-rw-r--r--gdb/target.c169
2 files changed, 132 insertions, 52 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index a5abe28..591a114 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,18 @@
+2015-03-25 Gary Benson <gbenson@redhat.com>
+ Pedro Alves <palves@redhat.com>
+
+ * target.c (fileio_ft_t): New typedef, define object vector.
+ (fileio_fhandles): New static variable.
+ (is_closed_fileio_fh): New macro.
+ (lowest_closed_fd): New static variable.
+ (acquire_fileio_fd): New function.
+ (release_fileio_fd): Likewise.
+ (fileio_fd_to_fh): New macro.
+ (target_fileio_open): Wrap the file descriptor on success.
+ (target_fileio_pwrite): Updated to use wrapped file descriptor.
+ (target_fileio_pread): Likewise.
+ (target_fileio_close): Likewise.
+
2015-03-24 Pedro Alves <palves@redhat.com>
* thread.c (thread_apply_all_command): Take exited threads into
diff --git a/gdb/target.c b/gdb/target.c
index af94f48..6f6029b 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -2684,6 +2684,78 @@ default_fileio_target (void)
return find_default_run_target ("file I/O");
}
+/* File handle for target file operations. */
+
+typedef struct
+{
+ /* The target on which this file is open. */
+ struct target_ops *t;
+
+ /* The file descriptor on the target. */
+ int fd;
+} fileio_fh_t;
+
+DEF_VEC_O (fileio_fh_t);
+
+/* Vector of currently open file handles. The value returned by
+ target_fileio_open and passed as the FD argument to other
+ target_fileio_* functions is an index into this vector. This
+ vector's entries are never freed; instead, files are marked as
+ closed, and the handle becomes available for reuse. */
+static VEC (fileio_fh_t) *fileio_fhandles;
+
+/* Macro to check whether a fileio_fh_t represents a closed file. */
+#define is_closed_fileio_fh(fd) ((fd) < 0)
+
+/* Index into fileio_fhandles of the lowest handle that might be
+ closed. This permits handle reuse without searching the whole
+ list each time a new file is opened. */
+static int lowest_closed_fd;
+
+/* Acquire a target fileio file descriptor. */
+
+static int
+acquire_fileio_fd (struct target_ops *t, int fd)
+{
+ fileio_fh_t *fh, buf;
+
+ gdb_assert (!is_closed_fileio_fh (fd));
+
+ /* Search for closed handles to reuse. */
+ for (;
+ VEC_iterate (fileio_fh_t, fileio_fhandles,
+ lowest_closed_fd, fh);
+ lowest_closed_fd++)
+ if (is_closed_fileio_fh (fh->fd))
+ break;
+
+ /* Push a new handle if no closed handles were found. */
+ if (lowest_closed_fd == VEC_length (fileio_fh_t, fileio_fhandles))
+ fh = VEC_safe_push (fileio_fh_t, fileio_fhandles, NULL);
+
+ /* Fill in the handle. */
+ fh->t = t;
+ fh->fd = fd;
+
+ /* Return its index, and start the next lookup at
+ the next index. */
+ return lowest_closed_fd++;
+}
+
+/* Release a target fileio file descriptor. */
+
+static void
+release_fileio_fd (int fd, fileio_fh_t *fh)
+{
+ fh->fd = -1;
+ lowest_closed_fd = min (lowest_closed_fd, fd);
+}
+
+/* Return a pointer to the fileio_fhandle_t corresponding to FD. */
+
+#define fileio_fd_to_fh(fd) \
+ VEC_index (fileio_fh_t, fileio_fhandles, (fd))
+
/* Open FILENAME on the target, using FLAGS and MODE. Return a
target file descriptor, or -1 if an error occurs (and set
*TARGET_ERRNO). */
@@ -2699,6 +2771,11 @@ target_fileio_open (const char *filename, int flags, int mode,
{
int fd = t->to_fileio_open (t, filename, flags, mode, target_errno);
+ if (fd < 0)
+ fd = -1;
+ else
+ fd = acquire_fileio_fd (t, fd);
+
if (targetdebug)
fprintf_unfiltered (gdb_stdlog,
"target_fileio_open (%s,0x%x,0%o) = %d (%d)\n",
@@ -2719,27 +2796,22 @@ int
target_fileio_pwrite (int fd, const gdb_byte *write_buf, int len,
ULONGEST offset, int *target_errno)
{
- struct target_ops *t;
+ fileio_fh_t *fh = fileio_fd_to_fh (fd);
+ int ret = -1;
- for (t = default_fileio_target (); t != NULL; t = t->beneath)
- {
- if (t->to_fileio_pwrite != NULL)
- {
- int ret = t->to_fileio_pwrite (t, fd, write_buf, len, offset,
- target_errno);
-
- if (targetdebug)
- fprintf_unfiltered (gdb_stdlog,
- "target_fileio_pwrite (%d,...,%d,%s) "
- "= %d (%d)\n",
- fd, len, pulongest (offset),
- ret, ret != -1 ? 0 : *target_errno);
- return ret;
- }
- }
+ if (is_closed_fileio_fh (fh->fd))
+ *target_errno = EBADF;
+ else
+ ret = fh->t->to_fileio_pwrite (fh->t, fh->fd, write_buf,
+ len, offset, target_errno);
- *target_errno = FILEIO_ENOSYS;
- return -1;
+ if (targetdebug)
+ fprintf_unfiltered (gdb_stdlog,
+ "target_fileio_pwrite (%d,...,%d,%s) "
+ "= %d (%d)\n",
+ fd, len, pulongest (offset),
+ ret, ret != -1 ? 0 : *target_errno);
+ return ret;
}
/* Read up to LEN bytes FD on the target into READ_BUF.
@@ -2749,27 +2821,22 @@ int
target_fileio_pread (int fd, gdb_byte *read_buf, int len,
ULONGEST offset, int *target_errno)
{
- struct target_ops *t;
+ fileio_fh_t *fh = fileio_fd_to_fh (fd);
+ int ret = -1;
- for (t = default_fileio_target (); t != NULL; t = t->beneath)
- {
- if (t->to_fileio_pread != NULL)
- {
- int ret = t->to_fileio_pread (t, fd, read_buf, len, offset,
- target_errno);
-
- if (targetdebug)
- fprintf_unfiltered (gdb_stdlog,
- "target_fileio_pread (%d,...,%d,%s) "
- "= %d (%d)\n",
- fd, len, pulongest (offset),
- ret, ret != -1 ? 0 : *target_errno);
- return ret;
- }
- }
+ if (is_closed_fileio_fh (fh->fd))
+ *target_errno = EBADF;
+ else
+ ret = fh->t->to_fileio_pread (fh->t, fh->fd, read_buf,
+ len, offset, target_errno);
- *target_errno = FILEIO_ENOSYS;
- return -1;
+ if (targetdebug)
+ fprintf_unfiltered (gdb_stdlog,
+ "target_fileio_pread (%d,...,%d,%s) "
+ "= %d (%d)\n",
+ fd, len, pulongest (offset),
+ ret, ret != -1 ? 0 : *target_errno);
+ return ret;
}
/* Close FD on the target. Return 0, or -1 if an error occurs
@@ -2777,24 +2844,22 @@ target_fileio_pread (int fd, gdb_byte *read_buf, int len,
int
target_fileio_close (int fd, int *target_errno)
{
- struct target_ops *t;
+ fileio_fh_t *fh = fileio_fd_to_fh (fd);
+ int ret = -1;
- for (t = default_fileio_target (); t != NULL; t = t->beneath)
+ if (is_closed_fileio_fh (fh->fd))
+ *target_errno = EBADF;
+ else
{
- if (t->to_fileio_close != NULL)
- {
- int ret = t->to_fileio_close (t, fd, target_errno);
-
- if (targetdebug)
- fprintf_unfiltered (gdb_stdlog,
- "target_fileio_close (%d) = %d (%d)\n",
- fd, ret, ret != -1 ? 0 : *target_errno);
- return ret;
- }
+ ret = fh->t->to_fileio_close (fh->t, fh->fd, target_errno);
+ release_fileio_fd (fd, fh);
}
- *target_errno = FILEIO_ENOSYS;
- return -1;
+ if (targetdebug)
+ fprintf_unfiltered (gdb_stdlog,
+ "target_fileio_close (%d) = %d (%d)\n",
+ fd, ret, ret != -1 ? 0 : *target_errno);
+ return ret;
}
/* Unlink FILENAME on the target. Return 0, or -1 if an error