From patchwork Fri Mar 20 16:48:01 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gary Benson X-Patchwork-Id: 5739 Received: (qmail 24708 invoked by alias); 20 Mar 2015 17:47:02 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 24554 invoked by uid 89); 20 Mar 2015 17:47:00 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.1 required=5.0 tests=AWL, BAYES_00, SPF_HELO_PASS, SPF_PASS, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Fri, 20 Mar 2015 17:46:59 +0000 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id t2KGmB9e019255 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL) for ; Fri, 20 Mar 2015 12:48:13 -0400 Received: from blade.nx (ovpn-116-93.ams2.redhat.com [10.36.116.93]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t2KGmAbF007917 for ; Fri, 20 Mar 2015 12:48:11 -0400 Received: from blade.nx (localhost [127.0.0.1]) by blade.nx (Postfix) with ESMTP id 3B5C2264109 for ; Fri, 20 Mar 2015 16:48:10 +0000 (GMT) From: Gary Benson To: gdb-patches@sourceware.org Subject: [PATCH 3/9] Make gdb_bfd_open able to open BFDs using target fileio Date: Fri, 20 Mar 2015 16:48:01 +0000 Message-Id: <1426870087-32654-4-git-send-email-gbenson@redhat.com> In-Reply-To: <1426870087-32654-1-git-send-email-gbenson@redhat.com> References: <1426870087-32654-1-git-send-email-gbenson@redhat.com> X-IsSubscribed: yes This commit updates gdb_bfd_open to access files using target fileio functions if the supplied path starts with "target:" and if the local and target filesystems are not the same. This allows users to specify "set sysroot target:" and have GDB access files locally or from the remote as appropriate. The new functions in gdb_bfd.c are copies of functions from remote.c. This duplication is intentional and will be removed by the next commit in this series. gdb/ChangeLog: * gdb/gdb_bfd.h (TARGET_SYSROOT_PREFIX): New definition. (is_target_filename): New declaration. (gdb_bfd_has_target_filename): Likewise. (gdb_bfd_open): Update documentation comment. * gdb_bfd.c (target.h): New include. (gdb/fileio.h): Likewise. (is_target_filename): New function. (gdb_bfd_has_target_filename): Likewise. (fileio_errno_to_host): Likewise. (gdb_bfd_iovec_fileio_open): Likewise. (gdb_bfd_iovec_fileio_pread): Likewise. (gdb_bfd_iovec_fileio_close): Likewise. (gdb_bfd_iovec_fileio_fstat): Likewise. (gdb_bfd_open): Use target fileio to access paths prefixed with "target:" where necessary. --- gdb/ChangeLog | 18 +++++ gdb/gdb_bfd.c | 203 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ gdb/gdb_bfd.h | 29 +++++++- 3 files changed, 246 insertions(+), 4 deletions(-) diff --git a/gdb/gdb_bfd.c b/gdb/gdb_bfd.c index 7543dae..43bd328 100644 --- a/gdb/gdb_bfd.c +++ b/gdb/gdb_bfd.c @@ -33,6 +33,8 @@ #define MAP_FAILED ((void *) -1) #endif #endif +#include "target.h" +#include "gdb/fileio.h" typedef bfd *bfdp; DEF_VEC_P (bfdp); @@ -141,6 +143,177 @@ eq_bfd (const void *a, const void *b) /* See gdb_bfd.h. */ +int +is_target_filename (const char *name) +{ + return startswith (name, TARGET_SYSROOT_PREFIX); +} + +/* See gdb_bfd.h. */ + +int +gdb_bfd_has_target_filename (struct bfd *abfd) +{ + return is_target_filename (bfd_get_filename (abfd)); +} + + +/* Return the system error number corresponding to ERRNUM. */ + +static int +fileio_errno_to_host (int errnum) +{ + switch (errnum) + { + case FILEIO_EPERM: + return EPERM; + case FILEIO_ENOENT: + return ENOENT; + case FILEIO_EINTR: + return EINTR; + case FILEIO_EIO: + return EIO; + case FILEIO_EBADF: + return EBADF; + case FILEIO_EACCES: + return EACCES; + case FILEIO_EFAULT: + return EFAULT; + case FILEIO_EBUSY: + return EBUSY; + case FILEIO_EEXIST: + return EEXIST; + case FILEIO_ENODEV: + return ENODEV; + case FILEIO_ENOTDIR: + return ENOTDIR; + case FILEIO_EISDIR: + return EISDIR; + case FILEIO_EINVAL: + return EINVAL; + case FILEIO_ENFILE: + return ENFILE; + case FILEIO_EMFILE: + return EMFILE; + case FILEIO_EFBIG: + return EFBIG; + case FILEIO_ENOSPC: + return ENOSPC; + case FILEIO_ESPIPE: + return ESPIPE; + case FILEIO_EROFS: + return EROFS; + case FILEIO_ENOSYS: + return ENOSYS; + case FILEIO_ENAMETOOLONG: + return ENAMETOOLONG; + } + return -1; +} + +/* Wrapper for target_fileio_open suitable for passing as the + OPEN_FUNC argument to gdb_bfd_openr_iovec. The supplied + OPEN_CLOSURE is unused. */ + +static void * +gdb_bfd_iovec_fileio_open (struct bfd *abfd, void *open_closure) +{ + const char *filename = bfd_get_filename (abfd); + int fd, target_errno; + int *stream; + + gdb_assert (is_target_filename (filename)); + + fd = target_fileio_open (filename + strlen (TARGET_SYSROOT_PREFIX), + FILEIO_O_RDONLY, 0, + &target_errno); + if (fd == -1) + { + errno = fileio_errno_to_host (target_errno); + bfd_set_error (bfd_error_system_call); + return NULL; + } + + stream = XCNEW (int); + *stream = fd; + return stream; +} + +/* Wrapper for target_fileio_pread suitable for passing as the + PREAD_FUNC argument to gdb_bfd_openr_iovec. */ + +static file_ptr +gdb_bfd_iovec_fileio_pread (struct bfd *abfd, void *stream, void *buf, + file_ptr nbytes, file_ptr offset) +{ + int fd = *(int *) stream; + int target_errno; + file_ptr pos, bytes; + + pos = 0; + while (nbytes > pos) + { + bytes = target_fileio_pread (fd, (gdb_byte *) buf + pos, + nbytes - pos, offset + pos, + &target_errno); + if (bytes == 0) + /* Success, but no bytes, means end-of-file. */ + break; + if (bytes == -1) + { + errno = fileio_errno_to_host (target_errno); + bfd_set_error (bfd_error_system_call); + return -1; + } + + pos += bytes; + } + + return pos; +} + +/* Wrapper for target_fileio_close suitable for passing as the + CLOSE_FUNC argument to gdb_bfd_openr_iovec. */ + +static int +gdb_bfd_iovec_fileio_close (struct bfd *abfd, void *stream) +{ + int fd = *(int *) stream; + int target_errno; + + xfree (stream); + + /* Ignore errors on close. These may happen with remote + targets if the connection has already been torn down. */ + target_fileio_close (fd, &target_errno); + + /* Zero means success. */ + return 0; +} + +/* Wrapper for target_fileio_fstat suitable for passing as the + STAT_FUNC argument to gdb_bfd_openr_iovec. */ + +static int +gdb_bfd_iovec_fileio_fstat (struct bfd *abfd, void *stream, + struct stat *sb) +{ + int fd = *(int *) stream; + int target_errno; + int result; + + result = target_fileio_fstat (fd, sb, &target_errno); + if (result == -1) + { + errno = fileio_errno_to_host (target_errno); + bfd_set_error (bfd_error_system_call); + } + + return result; +} + +/* See gdb_bfd.h. */ + struct bfd * gdb_bfd_open (const char *name, const char *target, int fd) { @@ -150,6 +323,36 @@ gdb_bfd_open (const char *name, const char *target, int fd) struct gdb_bfd_cache_search search; struct stat st; + if (is_target_filename (name)) + { + if (!target_filesystem_is_local) + { + gdb_assert (fd == -1); + + abfd = gdb_bfd_openr_iovec (name, target, + gdb_bfd_iovec_fileio_open, NULL, + gdb_bfd_iovec_fileio_pread, + gdb_bfd_iovec_fileio_close, + gdb_bfd_iovec_fileio_fstat); + + if (abfd != NULL || errno != ENOSYS) + return abfd; + + /* gdb_bfd_iovec_fileio_open failed with ENOSYS. This can + happen, for example, with vgdb (Valgrind GDB), which + presents itself as a remote target but works on the local + filesystem: it does not implement remote get and users + are not expected to set gdb_sysroot. To handle this case + we fall back to trying the local filesystem iff + gdb_sysroot is exactly TARGET_SYSROOT_PREFIX. */ + if (gdb_sysroot == NULL + || strcmp (gdb_sysroot, TARGET_SYSROOT_PREFIX) != 0) + return NULL; + } + + name += strlen (TARGET_SYSROOT_PREFIX); + } + if (gdb_bfd_cache == NULL) gdb_bfd_cache = htab_create_alloc (1, hash_bfd, eq_bfd, NULL, xcalloc, xfree); diff --git a/gdb/gdb_bfd.h b/gdb/gdb_bfd.h index 05b6870..8fbdf36 100644 --- a/gdb/gdb_bfd.h +++ b/gdb/gdb_bfd.h @@ -24,11 +24,32 @@ DECLARE_REGISTRY (bfd); +/* If supplied a path starting with this sequence, gdb_bfd_open will + open BFDs using target fileio operations. */ + +#define TARGET_SYSROOT_PREFIX "target:" + +/* Returns nonzero if NAME starts with TARGET_SYSROOT_PREFIX, zero + otherwise. */ + +int is_target_filename (const char *name); + +/* Returns nonzero if the filename associated with ABFD starts with + TARGET_SYSROOT_PREFIX, zero otherwise. */ + +int gdb_bfd_has_target_filename (struct bfd *abfd); + /* Open a read-only (FOPEN_RB) BFD given arguments like bfd_fopen. - Returns NULL on error. On success, returns a new reference to the - BFD, which must be freed with gdb_bfd_unref. BFDs returned by this - call are shared among all callers opening the same file. If FD is - not -1, then after this call it is owned by BFD. */ + If NAME starts with TARGET_SYSROOT_PREFIX then the BFD will be + opened using target fileio operations if necessary. Returns NULL + on error. On success, returns a new reference to the BFD, which + must be freed with gdb_bfd_unref. BFDs returned by this call are + shared among all callers opening the same file. If FD is not -1, + then after this call it is owned by BFD. If the BFD was not + accessed using target fileio operations then the filename + associated with the BFD and accessible with bfd_get_filename will + not be exactly NAME but rather NAME with TARGET_SYSROOT_PREFIX + stripped. */ struct bfd *gdb_bfd_open (const char *name, const char *target, int fd);