From patchwork Thu Apr 16 12:19:51 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gary Benson X-Patchwork-Id: 6258 Received: (qmail 130498 invoked by alias); 16 Apr 2015 12:54:43 -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 130482 invoked by uid 89); 16 Apr 2015 12:54:42 -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; Thu, 16 Apr 2015 12:54:40 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id t3GCJuuA014275 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL) for ; Thu, 16 Apr 2015 08:19:56 -0400 Received: from blade.nx (ovpn-116-95.ams2.redhat.com [10.36.116.95]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t3GCJtoM027749 for ; Thu, 16 Apr 2015 08:19:56 -0400 Received: from blade.nx (localhost [127.0.0.1]) by blade.nx (Postfix) with ESMTP id 64418264114 for ; Thu, 16 Apr 2015 13:19:54 +0100 (BST) From: Gary Benson To: gdb-patches@sourceware.org Subject: [PATCH 7/7] Implement vFile:setfs in gdbserver Date: Thu, 16 Apr 2015 13:19:51 +0100 Message-Id: <1429186791-6867-8-git-send-email-gbenson@redhat.com> In-Reply-To: <1429186791-6867-1-git-send-email-gbenson@redhat.com> References: <1429186791-6867-1-git-send-email-gbenson@redhat.com> X-IsSubscribed: yes gdb/gdbserver/ChangeLog: * target.h (struct target_ops) : New field. * linux-low.c (nat/linux-namespaces.h): New include. (linux_low_call_with_fs_of): New function. * linux-low.c (linux_target_ops): Initialize call_with_fs_of. * hostio.c (hostio_fs_pid): New static variable. (handle_setfs): New function. (enter_filesystem): Likewise. (open_closure): New structure. (handle_open_1): New function. (handle_open): Update to use enter_filesystem. (unlink_closure): New structure. (handle_unlink_1): New function. (handle_unlink): Update to use enter_filesystem. (readlink_closure): New structure. (handle_readlink_1): New function. (handle_readlink): Update to use enter_filesystem. (handle_vFile): Handle vFile:setfs packets. --- gdb/gdbserver/ChangeLog | 20 ++++++ gdb/gdbserver/hostio.c | 152 ++++++++++++++++++++++++++++++++++++++++---- gdb/gdbserver/linux-low.c | 10 +++ gdb/gdbserver/target.h | 6 ++ 4 files changed, 174 insertions(+), 14 deletions(-) diff --git a/gdb/gdbserver/hostio.c b/gdb/gdbserver/hostio.c index b03b5ad..9a1e443 100644 --- a/gdb/gdbserver/hostio.c +++ b/gdb/gdbserver/hostio.c @@ -243,6 +243,51 @@ hostio_reply_with_data (char *own_buf, char *buffer, int len, return input_index; } +/* Process ID of inferior whose filesystem hostio functions + that take FILENAME arguments will use. Zero means to use + our own filesystem. */ + +static int hostio_fs_pid = 0; + +/* Handle a "vFile:setfs:" packet. */ + +static void +handle_setfs (char *own_buf) +{ + char *p; + int pid; + + p = own_buf + strlen ("vFile:setfs:"); + + if (require_int (&p, &pid) + || pid < 0 + || require_end (p)) + { + hostio_packet_error (own_buf); + return; + } + + hostio_fs_pid = pid; + + hostio_reply (own_buf, 0); +} + +/* Cause the filesystem to appear as it does to the process specified + by the most recent valid "vFile:setfs:" packet and call FUNC with + argument ARG, restoring the filesystem to its original state + afterwards. Return nonzero if FUNC was called, zero otherwise (and + set ERRNO). */ + +static int +enter_filesystem (void (*func) (void *), void *arg) +{ + if (hostio_fs_pid != 0 && the_target->call_with_fs_of != NULL) + return the_target->call_with_fs_of (hostio_fs_pid, func, arg); + + func (arg); + return 1; +} + static int fileio_open_flags_to_host (int fileio_open_flags, int *open_flags_p) { @@ -275,23 +320,45 @@ fileio_open_flags_to_host (int fileio_open_flags, int *open_flags_p) return 0; } +/* Arguments and return value of open(2). */ + +struct open_closure +{ + char filename[HOSTIO_PATH_MAX]; + int flags; + int mode; + int return_value; +}; + +/* Helper for handle_open. */ + +static void +handle_open_1 (void *arg) +{ + struct open_closure *clo = (struct open_closure *) arg; + + clo->return_value = open (clo->filename, clo->flags, clo->mode); +} + +/* Handle a "vFile:open:" packet. */ + static void handle_open (char *own_buf) { - char filename[HOSTIO_PATH_MAX]; char *p; - int fileio_flags, mode, flags, fd; + int fileio_flags, fd; struct fd_list *new_fd; + struct open_closure clo; p = own_buf + strlen ("vFile:open:"); - if (require_filename (&p, filename) + if (require_filename (&p, clo.filename) || require_comma (&p) || require_int (&p, &fileio_flags) || require_comma (&p) - || require_int (&p, &mode) + || require_int (&p, &clo.mode) || require_end (p) - || fileio_open_flags_to_host (fileio_flags, &flags)) + || fileio_open_flags_to_host (fileio_flags, &clo.flags)) { hostio_packet_error (own_buf); return; @@ -299,7 +366,11 @@ handle_open (char *own_buf) /* We do not need to convert MODE, since the fileio protocol uses the standard values. */ - fd = open (filename, flags, mode); + + if (enter_filesystem (handle_open_1, &clo)) + fd = clo.return_value; + else + fd = -1; if (fd == -1) { @@ -487,23 +558,46 @@ handle_close (char *own_buf) hostio_reply (own_buf, ret); } +/* Arguments and return value of unlink(2). */ + +struct unlink_closure +{ + char filename[HOSTIO_PATH_MAX]; + int return_value; +}; + +/* Helper for handle_unlink. */ + +static void +handle_unlink_1 (void *arg) +{ + struct unlink_closure *clo = (struct unlink_closure *) arg; + + clo->return_value = unlink (clo->filename); +} + +/* Handle a "vFile:unlink:" packet. */ + static void handle_unlink (char *own_buf) { - char filename[HOSTIO_PATH_MAX]; + struct unlink_closure clo; char *p; int ret; p = own_buf + strlen ("vFile:unlink:"); - if (require_filename (&p, filename) + if (require_filename (&p, clo.filename) || require_end (p)) { hostio_packet_error (own_buf); return; } - ret = unlink (filename); + if (enter_filesystem (handle_unlink_1, &clo)) + ret = clo.return_value; + else + ret = -1; if (ret == -1) { @@ -514,30 +608,57 @@ handle_unlink (char *own_buf) hostio_reply (own_buf, ret); } +/* Arguments and return value of readlink(2). */ + +struct readlink_closure +{ + char filename[HOSTIO_PATH_MAX]; + char linkname[HOSTIO_PATH_MAX]; + int return_value; +}; + +/* Helper for handle_readlink. */ + +static void +handle_readlink_1 (void *arg) +{ + struct readlink_closure *clo = (struct readlink_closure *) arg; + + clo->return_value = readlink (clo->filename, clo->linkname, + sizeof (clo->linkname) - 1); +} + +/* Handle a "vFile:readlink:" packet. */ + static void handle_readlink (char *own_buf, int *new_packet_len) { - char filename[HOSTIO_PATH_MAX], linkname[HOSTIO_PATH_MAX]; + struct readlink_closure clo; char *p; int ret, bytes_sent; p = own_buf + strlen ("vFile:readlink:"); - if (require_filename (&p, filename) + if (require_filename (&p, clo.filename) || require_end (p)) { hostio_packet_error (own_buf); return; } - ret = readlink (filename, linkname, sizeof (linkname) - 1); + if (enter_filesystem (handle_readlink_1, &clo)) + ret = clo.return_value; + else + ret = -1; + if (ret == -1) { hostio_error (own_buf); return; } - bytes_sent = hostio_reply_with_data (own_buf, linkname, ret, new_packet_len); + bytes_sent = hostio_reply_with_data (own_buf, clo.linkname, + ret, new_packet_len); /* If the response does not fit into a single packet, do not attempt to return a partial response, but simply fail. */ @@ -550,7 +671,10 @@ handle_readlink (char *own_buf, int *new_packet_len) int handle_vFile (char *own_buf, int packet_len, int *new_packet_len) { - if (startswith (own_buf, "vFile:open:")) + if (the_target->call_with_fs_of != NULL + && startswith (own_buf, "vFile:setfs:")) + handle_setfs (own_buf); + else if (startswith (own_buf, "vFile:open:")) handle_open (own_buf); else if (startswith (own_buf, "vFile:pread:")) handle_pread (own_buf, new_packet_len); diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index 74f754d..4f01dbd 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -51,6 +51,7 @@ definition of elf_fpregset_t. */ #include #endif +#include "nat/linux-namespaces.h" #ifndef SPUFS_MAGIC #define SPUFS_MAGIC 0x23c9b64e @@ -6349,6 +6350,14 @@ current_lwp_ptid (void) return ptid_of (current_thread); } +/* Implementation of target_ops->call_with_fs_of. */ + +static int +linux_low_call_with_fs_of (int pid, void (*func) (void *), void *arg) +{ + return linux_ns_enter (pid, LINUX_NS_MNT, func, arg); +} + static struct target_ops linux_target_ops = { linux_create_inferior, linux_attach, @@ -6434,6 +6443,7 @@ static struct target_ops linux_target_ops = { #endif linux_supports_range_stepping, linux_proc_pid_to_exec_file, + linux_low_call_with_fs_of, }; static void diff --git a/gdb/gdbserver/target.h b/gdb/gdbserver/target.h index 6280c26..c766a2c 100644 --- a/gdb/gdbserver/target.h +++ b/gdb/gdbserver/target.h @@ -402,6 +402,12 @@ struct target_ops string should be copied into a buffer by the client if the string will not be immediately used, or if it must persist. */ char *(*pid_to_exec_file) (int pid); + + /* Cause the filesystem to appear as it does to process PID and + call FUNC with argument ARG, restoring the filesystem to its + original state afterwards. Return nonzero if FUNC was called, + zero otherwise (and set ERRNO). */ + int (*call_with_fs_of) (int pid, void (*func) (void *), void *arg); }; extern struct target_ops *the_target;