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.
This commit is contained in:
Ulrich Weigand 2012-01-20 09:45:51 +00:00
parent 901f991244
commit 7313baad7c
8 changed files with 616 additions and 9 deletions

View file

@ -1,3 +1,45 @@
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.
2012-01-20 Pedro Alves <palves@redhat.com>
Ulrich Weigand <ulrich.weigand@linaro.org>

View file

@ -324,6 +324,9 @@
/* Define to 1 if you have the `posix_madvise' function. */
#undef HAVE_POSIX_MADVISE
/* Define to 1 if you have the `pread' function. */
#undef HAVE_PREAD
/* Define to 1 if you have the `pread64' function. */
#undef HAVE_PREAD64
@ -381,6 +384,9 @@
/* Define if sys/ptrace.h defines the PT_GETXMMREGS request. */
#undef HAVE_PT_GETXMMREGS
/* Define to 1 if you have the `pwrite' function. */
#undef HAVE_PWRITE
/* Define if Python interpreter is being linked in. */
#undef HAVE_PYTHON

5
gdb/configure vendored
View file

@ -12931,8 +12931,9 @@ $as_echo "#define HAVE_WORKING_FORK 1" >>confdefs.h
fi
for ac_func in canonicalize_file_name realpath getrusage getuid \
getgid pipe poll pread64 resize_term sbrk setpgid setpgrp setsid \
for ac_func in canonicalize_file_name realpath getrusage getuid getgid \
pipe poll pread pread64 pwrite resize_term \
sbrk setpgid setpgrp setsid \
sigaction sigprocmask sigsetmask socketpair syscall \
ttrace wborder wresize setlocale iconvlist libiconvlist btowc \
setrlimit getrlimit posix_madvise waitpid lstat

View file

@ -1063,8 +1063,9 @@ AC_C_BIGENDIAN
AC_FUNC_ALLOCA
AC_FUNC_MMAP
AC_FUNC_VFORK
AC_CHECK_FUNCS([canonicalize_file_name realpath getrusage getuid \
getgid pipe poll pread64 resize_term sbrk setpgid setpgrp setsid \
AC_CHECK_FUNCS([canonicalize_file_name realpath getrusage getuid getgid \
pipe poll pread pread64 pwrite resize_term \
sbrk setpgid setpgrp setsid \
sigaction sigprocmask sigsetmask socketpair syscall \
ttrace wborder wresize setlocale iconvlist libiconvlist btowc \
setrlimit getrlimit posix_madvise waitpid lstat])

View file

@ -27,6 +27,12 @@
#include "inferior.h"
#include "gdb_string.h"
#include "inf-child.h"
#include "gdb/fileio.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
for all registers. */
@ -108,6 +114,192 @@ inf_child_pid_to_exec_file (int pid)
return NULL;
}
/* Target file operations. */
static int
inf_child_fileio_open_flags_to_host (int fileio_open_flags, int *open_flags_p)
{
int open_flags = 0;
if (fileio_open_flags & ~FILEIO_O_SUPPORTED)
return -1;
if (fileio_open_flags & FILEIO_O_CREAT)
open_flags |= O_CREAT;
if (fileio_open_flags & FILEIO_O_EXCL)
open_flags |= O_EXCL;
if (fileio_open_flags & FILEIO_O_TRUNC)
open_flags |= O_TRUNC;
if (fileio_open_flags & FILEIO_O_APPEND)
open_flags |= O_APPEND;
if (fileio_open_flags & FILEIO_O_RDONLY)
open_flags |= O_RDONLY;
if (fileio_open_flags & FILEIO_O_WRONLY)
open_flags |= O_WRONLY;
if (fileio_open_flags & FILEIO_O_RDWR)
open_flags |= O_RDWR;
/* On systems supporting binary and text mode, always open files in
binary mode. */
#ifdef O_BINARY
open_flags |= O_BINARY;
#endif
*open_flags_p = open_flags;
return 0;
}
static int
inf_child_errno_to_fileio_error (int errnum)
{
switch (errnum)
{
case EPERM:
return FILEIO_EPERM;
case ENOENT:
return FILEIO_ENOENT;
case EINTR:
return FILEIO_EINTR;
case EIO:
return FILEIO_EIO;
case EBADF:
return FILEIO_EBADF;
case EACCES:
return FILEIO_EACCES;
case EFAULT:
return FILEIO_EFAULT;
case EBUSY:
return FILEIO_EBUSY;
case EEXIST:
return FILEIO_EEXIST;
case ENODEV:
return FILEIO_ENODEV;
case ENOTDIR:
return FILEIO_ENOTDIR;
case EISDIR:
return FILEIO_EISDIR;
case EINVAL:
return FILEIO_EINVAL;
case ENFILE:
return FILEIO_ENFILE;
case EMFILE:
return FILEIO_EMFILE;
case EFBIG:
return FILEIO_EFBIG;
case ENOSPC:
return FILEIO_ENOSPC;
case ESPIPE:
return FILEIO_ESPIPE;
case EROFS:
return FILEIO_EROFS;
case ENOSYS:
return FILEIO_ENOSYS;
case ENAMETOOLONG:
return FILEIO_ENAMETOOLONG;
}
return FILEIO_EUNKNOWN;
}
/* Open FILENAME on the target, using FLAGS and MODE. Return a
target file descriptor, or -1 if an error occurs (and set
*TARGET_ERRNO). */
static int
inf_child_fileio_open (const char *filename, int flags, int mode,
int *target_errno)
{
int nat_flags;
int fd;
if (inf_child_fileio_open_flags_to_host (flags, &nat_flags) == -1)
{
*target_errno = FILEIO_EINVAL;
return -1;
}
/* We do not need to convert MODE, since the fileio protocol uses
the standard values. */
fd = open (filename, nat_flags, mode);
if (fd == -1)
*target_errno = inf_child_errno_to_fileio_error (errno);
return fd;
}
/* 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). */
static int
inf_child_fileio_pwrite (int fd, const gdb_byte *write_buf, int len,
ULONGEST offset, int *target_errno)
{
int ret;
#ifdef HAVE_PWRITE
ret = pwrite (fd, write_buf, len, (long) offset);
#else
ret = lseek (fd, (long) offset, SEEK_SET);
if (ret != -1)
ret = write (fd, write_buf, len);
#endif
if (ret == -1)
*target_errno = inf_child_errno_to_fileio_error (errno);
return ret;
}
/* 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). */
static int
inf_child_fileio_pread (int fd, gdb_byte *read_buf, int len,
ULONGEST offset, int *target_errno)
{
int ret;
#ifdef HAVE_PREAD
ret = pread (fd, read_buf, len, (long) offset);
#else
ret = lseek (fd, (long) offset, SEEK_SET);
if (ret != -1)
ret = read (fd, read_buf, len);
#endif
if (ret == -1)
*target_errno = inf_child_errno_to_fileio_error (errno);
return ret;
}
/* Close FD on the target. Return 0, or -1 if an error occurs
(and set *TARGET_ERRNO). */
static int
inf_child_fileio_close (int fd, int *target_errno)
{
int ret;
ret = close (fd);
if (ret == -1)
*target_errno = inf_child_errno_to_fileio_error (errno);
return ret;
}
/* Unlink FILENAME on the target. Return 0, or -1 if an error
occurs (and set *TARGET_ERRNO). */
static int
inf_child_fileio_unlink (const char *filename, int *target_errno)
{
int ret;
ret = unlink (filename);
if (ret == -1)
*target_errno = inf_child_errno_to_fileio_error (errno);
return ret;
}
struct target_ops *
inf_child_target (void)
{
@ -139,6 +331,11 @@ inf_child_target (void)
t->to_has_stack = default_child_has_stack;
t->to_has_registers = default_child_has_registers;
t->to_has_execution = default_child_has_execution;
t->to_fileio_open = inf_child_fileio_open;
t->to_fileio_pwrite = inf_child_fileio_pwrite;
t->to_fileio_pread = inf_child_fileio_pread;
t->to_fileio_close = inf_child_fileio_close;
t->to_fileio_unlink = inf_child_fileio_unlink;
t->to_magic = OPS_MAGIC;
return t;
}

View file

@ -10674,6 +10674,11 @@ Specify the serial device it is connected to\n\
remote_ops.to_supports_multi_process = remote_supports_multi_process;
remote_ops.to_supports_disable_randomization
= remote_supports_disable_randomization;
remote_ops.to_fileio_open = remote_hostio_open;
remote_ops.to_fileio_pwrite = remote_hostio_pwrite;
remote_ops.to_fileio_pread = remote_hostio_pread;
remote_ops.to_fileio_close = remote_hostio_close;
remote_ops.to_fileio_unlink = remote_hostio_unlink;
remote_ops.to_supports_enable_disable_tracepoint = remote_supports_enable_disable_tracepoint;
remote_ops.to_supports_string_tracing = remote_supports_string_tracing;
remote_ops.to_trace_init = remote_trace_init;

View file

@ -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)
{

View file

@ -681,6 +681,35 @@ struct target_ops
struct address_space *(*to_thread_address_space) (struct target_ops *,
ptid_t);
/* Target file operations. */
/* 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 (*to_fileio_open) (const char *filename, int flags, int mode,
int *target_errno);
/* 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 (*to_fileio_pwrite) (int fd, const gdb_byte *write_buf, int len,
ULONGEST offset, int *target_errno);
/* 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 (*to_fileio_pread) (int fd, gdb_byte *read_buf, int len,
ULONGEST offset, int *target_errno);
/* Close FD on the target. Return 0, or -1 if an error occurs
(and set *TARGET_ERRNO). */
int (*to_fileio_close) (int fd, int *target_errno);
/* Unlink FILENAME on the target. Return 0, or -1 if an error
occurs (and set *TARGET_ERRNO). */
int (*to_fileio_unlink) (const char *filename, int *target_errno);
/* Tracepoint-related operations. */
/* Prepare the target for a tracing run. */
@ -1489,6 +1518,54 @@ extern int target_search_memory (CORE_ADDR start_addr,
ULONGEST pattern_len,
CORE_ADDR *found_addrp);
/* Target file operations. */
/* Open FILENAME on the target, using FLAGS and MODE. Return a
target file descriptor, or -1 if an error occurs (and set
*TARGET_ERRNO). */
extern int target_fileio_open (const char *filename, int flags, int mode,
int *target_errno);
/* 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). */
extern int target_fileio_pwrite (int fd, const gdb_byte *write_buf, int len,
ULONGEST offset, int *target_errno);
/* 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). */
extern int target_fileio_pread (int fd, gdb_byte *read_buf, int len,
ULONGEST offset, int *target_errno);
/* Close FD on the target. Return 0, or -1 if an error occurs
(and set *TARGET_ERRNO). */
extern int target_fileio_close (int fd, int *target_errno);
/* Unlink FILENAME on the target. Return 0, or -1 if an error
occurs (and set *TARGET_ERRNO). */
extern int target_fileio_unlink (const char *filename, int *target_errno);
/* Read target file FILENAME. The return value will be -1 if the transfer
fails or is not supported; 0 if the object is empty; or the length
of the object otherwise. If a positive value is returned, a
sufficiently large buffer will be allocated using xmalloc and
returned in *BUF_P containing the contents of the object.
This method should be used for objects sufficiently small to store
in a single xmalloc'd buffer, when no fixed bound on the object's
size is known in advance. */
extern LONGEST target_fileio_read_alloc (const char *filename,
gdb_byte **buf_p);
/* 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. */
extern char *target_fileio_read_stralloc (const char *filename);
/* Tracepoint-related operations. */
#define target_trace_init() \