X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fgdbserver%2Fhostio.c;h=b38a6bd05649a79677f0b0f8cdd89967c5daab04;hb=14d2069a321cdd2b06f1982e6832c8c5661febf4;hp=e89e100c6729ad95d7c8c12d00ca5591895002b2;hpb=0270a750ba588a8ad521e68be851772bac9c44f1;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/gdbserver/hostio.c b/gdb/gdbserver/hostio.c index e89e100c67..b38a6bd056 100644 --- a/gdb/gdbserver/hostio.c +++ b/gdb/gdbserver/hostio.c @@ -1,5 +1,5 @@ /* Host file transfer support for gdbserver. - Copyright (C) 2007-2012 Free Software Foundation, Inc. + Copyright (C) 2007-2015 Free Software Foundation, Inc. Contributed by CodeSourcery. @@ -20,10 +20,14 @@ #include "server.h" #include "gdb/fileio.h" +#include "hostio.h" #include #include #include +#include +#include +#include "fileio.h" extern int remote_debug; @@ -50,6 +54,14 @@ safe_fromhex (char a, int *nibble) return 0; } +/* Filenames are hex encoded, so the maximum we can handle is half the + packet buffer size. Cap to PATH_MAX, if it is shorter. */ +#if !defined (PATH_MAX) || (PATH_MAX > (PBUFSIZ / 2 + 1)) +# define HOSTIO_PATH_MAX (PBUFSIZ / 2 + 1) +#else +# define HOSTIO_PATH_MAX PATH_MAX +#endif + static int require_filename (char **pp, char *filename) { @@ -64,7 +76,7 @@ require_filename (char **pp, char *filename) int nib1, nib2; /* Don't allow overflow. */ - if (count >= PATH_MAX - 1) + if (count >= HOSTIO_PATH_MAX - 1) return -1; if (safe_fromhex (p[0], &nib1) @@ -231,44 +243,62 @@ hostio_reply_with_data (char *own_buf, char *buffer, int len, return input_index; } -static int -fileio_open_flags_to_host (int fileio_open_flags, int *open_flags_p) +/* 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; + +/* See hostio.h. */ + +void +hostio_handle_new_gdb_connection (void) { - int open_flags = 0; + hostio_fs_pid = 0; +} - if (fileio_open_flags & ~FILEIO_O_SUPPORTED) - return -1; +/* Handle a "vFile:setfs:" packet. */ - 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 +static void +handle_setfs (char *own_buf) +{ + char *p; + int pid; + + /* If the target doesn't have any of the in-filesystem-of methods + then there's no point in GDB sending "vFile:setfs:" packets. We + reply with an empty packet (i.e. we pretend we don't understand + "vFile:setfs:") and that should stop GDB sending any more. */ + if (the_target->multifs_open == NULL + && the_target->multifs_unlink == NULL + && the_target->multifs_readlink == NULL) + { + own_buf[0] = '\0'; + return; + } - *open_flags_p = open_flags; - return 0; + 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); } static void handle_open (char *own_buf) { - char filename[PATH_MAX]; + char filename[HOSTIO_PATH_MAX]; char *p; - int fileio_flags, mode, flags, fd; + int fileio_flags, fileio_mode, flags, fd; + mode_t mode; struct fd_list *new_fd; p = own_buf + strlen ("vFile:open:"); @@ -277,9 +307,10 @@ handle_open (char *own_buf) || require_comma (&p) || require_int (&p, &fileio_flags) || require_comma (&p) - || require_int (&p, &mode) + || require_int (&p, &fileio_mode) || require_end (p) - || fileio_open_flags_to_host (fileio_flags, &flags)) + || fileio_to_host_openflags (fileio_flags, &flags) + || fileio_to_host_mode (fileio_mode, &mode)) { hostio_packet_error (own_buf); return; @@ -287,7 +318,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 (hostio_fs_pid != 0 && the_target->multifs_open != NULL) + fd = the_target->multifs_open (hostio_fs_pid, filename, + flags, mode); + else + fd = open (filename, flags, mode); if (fd == -1) { @@ -402,6 +437,42 @@ handle_pwrite (char *own_buf, int packet_len) free (data); } +static void +handle_fstat (char *own_buf, int *new_packet_len) +{ + int fd, bytes_sent; + char *p; + struct stat st; + struct fio_stat fst; + + p = own_buf + strlen ("vFile:fstat:"); + + if (require_int (&p, &fd) + || require_valid_fd (fd) + || require_end (p)) + { + hostio_packet_error (own_buf); + return; + } + + if (fstat (fd, &st) == -1) + { + hostio_error (own_buf); + return; + } + + host_to_fileio_stat (&st, &fst); + + bytes_sent = hostio_reply_with_data (own_buf, + (char *) &fst, sizeof (fst), + new_packet_len); + + /* If the response does not fit into a single packet, do not attempt + to return a partial response, but simply fail. */ + if (bytes_sent < sizeof (fst)) + write_enn (own_buf); +} + static void handle_close (char *own_buf) { @@ -442,7 +513,7 @@ handle_close (char *own_buf) static void handle_unlink (char *own_buf) { - char filename[PATH_MAX]; + char filename[HOSTIO_PATH_MAX]; char *p; int ret; @@ -455,7 +526,10 @@ handle_unlink (char *own_buf) return; } - ret = unlink (filename); + if (hostio_fs_pid != 0 && the_target->multifs_unlink != NULL) + ret = the_target->multifs_unlink (hostio_fs_pid, filename); + else + ret = unlink (filename); if (ret == -1) { @@ -469,8 +543,7 @@ handle_unlink (char *own_buf) static void handle_readlink (char *own_buf, int *new_packet_len) { -#if defined (HAVE_READLINK) - char filename[PATH_MAX], linkname[PATH_MAX]; + char filename[HOSTIO_PATH_MAX], linkname[HOSTIO_PATH_MAX]; char *p; int ret, bytes_sent; @@ -483,7 +556,13 @@ handle_readlink (char *own_buf, int *new_packet_len) return; } - ret = readlink (filename, linkname, sizeof (linkname) - 1); + if (hostio_fs_pid != 0 && the_target->multifs_readlink != NULL) + ret = the_target->multifs_readlink (hostio_fs_pid, filename, + linkname, + sizeof (linkname) - 1); + else + ret = readlink (filename, linkname, sizeof (linkname) - 1); + if (ret == -1) { hostio_error (own_buf); @@ -496,9 +575,6 @@ handle_readlink (char *own_buf, int *new_packet_len) to return a partial response, but simply fail. */ if (bytes_sent < ret) sprintf (own_buf, "F-1,%x", FILEIO_ENAMETOOLONG); -#else /* ! HAVE_READLINK */ - sprintf (own_buf, "F-1,%x", FILEIO_ENOSYS); -#endif } /* Handle all the 'F' file transfer packets. */ @@ -506,18 +582,22 @@ handle_readlink (char *own_buf, int *new_packet_len) int handle_vFile (char *own_buf, int packet_len, int *new_packet_len) { - if (strncmp (own_buf, "vFile:open:", 11) == 0) + if (startswith (own_buf, "vFile:open:")) handle_open (own_buf); - else if (strncmp (own_buf, "vFile:pread:", 11) == 0) + else if (startswith (own_buf, "vFile:pread:")) handle_pread (own_buf, new_packet_len); - else if (strncmp (own_buf, "vFile:pwrite:", 12) == 0) + else if (startswith (own_buf, "vFile:pwrite:")) handle_pwrite (own_buf, packet_len); - else if (strncmp (own_buf, "vFile:close:", 12) == 0) + else if (startswith (own_buf, "vFile:fstat:")) + handle_fstat (own_buf, new_packet_len); + else if (startswith (own_buf, "vFile:close:")) handle_close (own_buf); - else if (strncmp (own_buf, "vFile:unlink:", 13) == 0) + else if (startswith (own_buf, "vFile:unlink:")) handle_unlink (own_buf); - else if (strncmp (own_buf, "vFile:readlink:", 15) == 0) + else if (startswith (own_buf, "vFile:readlink:")) handle_readlink (own_buf, new_packet_len); + else if (startswith (own_buf, "vFile:setfs:")) + handle_setfs (own_buf); else return 0;