diff options
author | Ulrich Weigand <uweigand@de.ibm.com> | 2012-01-20 09:45:51 +0000 |
---|---|---|
committer | Ulrich Weigand <uweigand@de.ibm.com> | 2012-01-20 09:45:51 +0000 |
commit | 7313baad7c73664bed62b87481cbb078d71e84f4 (patch) | |
tree | 6b2214e0bc33bb629ea6abd5e4502ec494cc50b2 /gdb/target.c | |
parent | 901f991244d02f62d4e7a9c903de9f05175de2ac (diff) | |
download | gdb-7313baad7c73664bed62b87481cbb078d71e84f4.zip gdb-7313baad7c73664bed62b87481cbb078d71e84f4.tar.gz gdb-7313baad7c73664bed62b87481cbb078d71e84f4.tar.bz2 |
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.c | 288 |
1 files changed, 283 insertions, 5 deletions
diff --git a/gdb/target.c b/gdb/target.c index 6af4620..595c2ce 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) { |