summaryrefslogtreecommitdiff
path: root/gdb/target.c
diff options
context:
space:
mode:
authorUlrich Weigand <uweigand@de.ibm.com>2012-01-20 09:45:49 +0000
committerUlrich Weigand <uweigand@de.ibm.com>2012-01-20 09:45:49 +0000
commite275619a2e8d64964b675b0e85bb7c69e2a7dad0 (patch)
tree623ae67bab63c8a8451ab63f4f172f08c690453b /gdb/target.c
parentf8cdeea569d34d96c29b22f12dcc0c82bef1bd5a (diff)
downloadgdb-e275619a2e8d64964b675b0e85bb7c69e2a7dad0.tar.gz
2012-01-20 Pedro Alves <palves@redhat.com>
Ulrich Weigand <ulrich.weigand@linaro.org> * configure.ac [AC_CHECK_FUNCS]: Check for pread and pwrite. * config.in, configure: Regenerate. * target.h (struct target_ops): Add to_fileio_open, to_fileio_pwrite, to_fileio_pread, to_fileio_close, to_fileio_unlink. (target_fileio_open): Add prototype. (target_fileio_pwrite): Likewise. (target_fileio_pread): Likewise. (target_fileio_close): Likewise. (target_fileio_unlink): Likewise. (target_fileio_read_alloc): Likewise. (target_fileio_read_stralloc): Likewise. * target.c: Include "gdb/fileio.h". (target_read_stralloc): Accept trailing, but not embedded NUL bytes. (default_fileio_target): New function. (target_fileio_open): Likewise. (target_fileio_pwrite): Likewise. (target_fileio_pread): Likewise. (target_fileio_close): Likewise. (target_fileio_unlink): Likewise. (target_fileio_close_cleanup): Likewise. (target_fileio_read_alloc_1): Likewise. (target_fileio_read_alloc): Likewise. (target_fileio_read_stralloc): Likewise. * inf-child.c: Include "gdb/fileio.h", <sys/types.h>, <sys/stat.h>, <fcntl.h>, and <unistd.h>. (inf_child_fileio_open_flags_to_host): New function. (inf_child_errno_to_fileio_error): Likewise. (inf_child_fileio_open): Likewise. (inf_child_fileio_pwrite): Likewise. (inf_child_fileio_pread): Likewise. (inf_child_fileio_close): Likewise. (inf_child_fileio_unlink): Likewise. (inf_child_target): Install to_fileio routines. * remote.c (init_remote_ops): Install to_fileio routines.
Diffstat (limited to 'gdb/target.c')
-rw-r--r--gdb/target.c288
1 files changed, 283 insertions, 5 deletions
diff --git a/gdb/target.c b/gdb/target.c
index 6af4620ddf7..595c2ced6c3 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -42,6 +42,7 @@
#include "exec.h"
#include "inline-frame.h"
#include "tracepoint.h"
+#include "gdb/fileio.h"
static void target_info (char *, int);
@@ -2344,7 +2345,7 @@ target_read_stralloc (struct target_ops *ops, enum target_object object,
const char *annex)
{
gdb_byte *buffer;
- LONGEST transferred;
+ LONGEST i, transferred;
transferred = target_read_alloc_1 (ops, object, annex, &buffer, 1);
@@ -2355,10 +2356,16 @@ target_read_stralloc (struct target_ops *ops, enum target_object object,
return xstrdup ("");
buffer[transferred] = 0;
- if (strlen (buffer) < transferred)
- warning (_("target object %d, annex %s, "
- "contained unexpected null characters"),
- (int) object, annex ? annex : "(none)");
+
+ /* Check for embedded NUL bytes; but allow trailing NULs. */
+ for (i = strlen (buffer); i < transferred; i++)
+ if (buffer[i] != 0)
+ {
+ warning (_("target object %d, annex %s, "
+ "contained unexpected null characters"),
+ (int) object, annex ? annex : "(none)");
+ break;
+ }
return (char *) buffer;
}
@@ -3159,6 +3166,277 @@ target_thread_address_space (ptid_t ptid)
return inf->aspace;
}
+
+/* Target file operations. */
+
+static struct target_ops *
+default_fileio_target (void)
+{
+ /* If we're already connected to something that can perform
+ file I/O, use it. Otherwise, try using the native target. */
+ if (current_target.to_stratum >= process_stratum)
+ return current_target.beneath;
+ else
+ return find_default_run_target ("file I/O");
+}
+
+/* Open FILENAME on the target, using FLAGS and MODE. Return a
+ target file descriptor, or -1 if an error occurs (and set
+ *TARGET_ERRNO). */
+int
+target_fileio_open (const char *filename, int flags, int mode,
+ int *target_errno)
+{
+ struct target_ops *t;
+
+ for (t = default_fileio_target (); t != NULL; t = t->beneath)
+ {
+ if (t->to_fileio_open != NULL)
+ {
+ int fd = t->to_fileio_open (filename, flags, mode, target_errno);
+
+ if (targetdebug)
+ fprintf_unfiltered (gdb_stdlog,
+ "target_fileio_open (%s,0x%x,0%o) = %d (%d)\n",
+ filename, flags, mode,
+ fd, fd != -1 ? 0 : *target_errno);
+ return fd;
+ }
+ }
+
+ *target_errno = FILEIO_ENOSYS;
+ return -1;
+}
+
+/* Write up to LEN bytes from WRITE_BUF to FD on the target.
+ Return the number of bytes written, or -1 if an error occurs
+ (and set *TARGET_ERRNO). */
+int
+target_fileio_pwrite (int fd, const gdb_byte *write_buf, int len,
+ ULONGEST offset, int *target_errno)
+{
+ struct target_ops *t;
+
+ for (t = default_fileio_target (); t != NULL; t = t->beneath)
+ {
+ if (t->to_fileio_pwrite != NULL)
+ {
+ int ret = t->to_fileio_pwrite (fd, write_buf, len, offset,
+ target_errno);
+
+ if (targetdebug)
+ fprintf_unfiltered (gdb_stdlog,
+ "target_fileio_pwrite (%d,%p,%d,%s) "
+ "= %d (%d)\n",
+ fd, write_buf, len, pulongest (offset),
+ ret, ret != -1 ? 0 : *target_errno);
+ return ret;
+ }
+ }
+
+ *target_errno = FILEIO_ENOSYS;
+ return -1;
+}
+
+/* Read up to LEN bytes FD on the target into READ_BUF.
+ Return the number of bytes read, or -1 if an error occurs
+ (and set *TARGET_ERRNO). */
+int
+target_fileio_pread (int fd, gdb_byte *read_buf, int len,
+ ULONGEST offset, int *target_errno)
+{
+ struct target_ops *t;
+
+ for (t = default_fileio_target (); t != NULL; t = t->beneath)
+ {
+ if (t->to_fileio_pread != NULL)
+ {
+ int ret = t->to_fileio_pread (fd, read_buf, len, offset,
+ target_errno);
+
+ if (targetdebug)
+ fprintf_unfiltered (gdb_stdlog,
+ "target_fileio_pread (%d,%p,%d,%s) "
+ "= %d (%d)\n",
+ fd, read_buf, len, pulongest (offset),
+ ret, ret != -1 ? 0 : *target_errno);
+ return ret;
+ }
+ }
+
+ *target_errno = FILEIO_ENOSYS;
+ return -1;
+}
+
+/* Close FD on the target. Return 0, or -1 if an error occurs
+ (and set *TARGET_ERRNO). */
+int
+target_fileio_close (int fd, int *target_errno)
+{
+ struct target_ops *t;
+
+ for (t = default_fileio_target (); t != NULL; t = t->beneath)
+ {
+ if (t->to_fileio_close != NULL)
+ {
+ int ret = t->to_fileio_close (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;
+ }
+ }
+
+ *target_errno = FILEIO_ENOSYS;
+ return -1;
+}
+
+/* Unlink FILENAME on the target. Return 0, or -1 if an error
+ occurs (and set *TARGET_ERRNO). */
+int
+target_fileio_unlink (const char *filename, int *target_errno)
+{
+ struct target_ops *t;
+
+ for (t = default_fileio_target (); t != NULL; t = t->beneath)
+ {
+ if (t->to_fileio_unlink != NULL)
+ {
+ int ret = t->to_fileio_unlink (filename, target_errno);
+
+ if (targetdebug)
+ fprintf_unfiltered (gdb_stdlog,
+ "target_fileio_unlink (%s) = %d (%d)\n",
+ filename, ret, ret != -1 ? 0 : *target_errno);
+ return ret;
+ }
+ }
+
+ *target_errno = FILEIO_ENOSYS;
+ return -1;
+}
+
+static void
+target_fileio_close_cleanup (void *opaque)
+{
+ int fd = *(int *) opaque;
+ int target_errno;
+
+ target_fileio_close (fd, &target_errno);
+}
+
+/* Read target file FILENAME. Store the result in *BUF_P and
+ return the size of the transferred data. PADDING additional bytes are
+ available in *BUF_P. This is a helper function for
+ target_fileio_read_alloc; see the declaration of that function for more
+ information. */
+
+static LONGEST
+target_fileio_read_alloc_1 (const char *filename,
+ gdb_byte **buf_p, int padding)
+{
+ struct cleanup *close_cleanup;
+ size_t buf_alloc, buf_pos;
+ gdb_byte *buf;
+ LONGEST n;
+ int fd;
+ int target_errno;
+
+ fd = target_fileio_open (filename, FILEIO_O_RDONLY, 0700, &target_errno);
+ if (fd == -1)
+ return -1;
+
+ close_cleanup = make_cleanup (target_fileio_close_cleanup, &fd);
+
+ /* Start by reading up to 4K at a time. The target will throttle
+ this number down if necessary. */
+ buf_alloc = 4096;
+ buf = xmalloc (buf_alloc);
+ buf_pos = 0;
+ while (1)
+ {
+ n = target_fileio_pread (fd, &buf[buf_pos],
+ buf_alloc - buf_pos - padding, buf_pos,
+ &target_errno);
+ if (n < 0)
+ {
+ /* An error occurred. */
+ do_cleanups (close_cleanup);
+ xfree (buf);
+ return -1;
+ }
+ else if (n == 0)
+ {
+ /* Read all there was. */
+ do_cleanups (close_cleanup);
+ if (buf_pos == 0)
+ xfree (buf);
+ else
+ *buf_p = buf;
+ return buf_pos;
+ }
+
+ buf_pos += n;
+
+ /* If the buffer is filling up, expand it. */
+ if (buf_alloc < buf_pos * 2)
+ {
+ buf_alloc *= 2;
+ buf = xrealloc (buf, buf_alloc);
+ }
+
+ QUIT;
+ }
+}
+
+/* Read target file FILENAME. Store the result in *BUF_P and return
+ the size of the transferred data. See the declaration in "target.h"
+ function for more information about the return value. */
+
+LONGEST
+target_fileio_read_alloc (const char *filename, gdb_byte **buf_p)
+{
+ return target_fileio_read_alloc_1 (filename, buf_p, 0);
+}
+
+/* Read target file FILENAME. The result is NUL-terminated and
+ returned as a string, allocated using xmalloc. If an error occurs
+ or the transfer is unsupported, NULL is returned. Empty objects
+ are returned as allocated but empty strings. A warning is issued
+ if the result contains any embedded NUL bytes. */
+
+char *
+target_fileio_read_stralloc (const char *filename)
+{
+ gdb_byte *buffer;
+ LONGEST i, transferred;
+
+ transferred = target_fileio_read_alloc_1 (filename, &buffer, 1);
+
+ if (transferred < 0)
+ return NULL;
+
+ if (transferred == 0)
+ return xstrdup ("");
+
+ buffer[transferred] = 0;
+
+ /* Check for embedded NUL bytes; but allow trailing NULs. */
+ for (i = strlen (buffer); i < transferred; i++)
+ if (buffer[i] != 0)
+ {
+ warning (_("target file %s "
+ "contained unexpected null characters"),
+ filename);
+ break;
+ }
+
+ return (char *) buffer;
+}
+
+
static int
default_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
{