diff options
Diffstat (limited to 'gdbserver')
-rw-r--r-- | gdbserver/hostio.cc | 62 | ||||
-rw-r--r-- | gdbserver/linux-low.cc | 10 | ||||
-rw-r--r-- | gdbserver/linux-low.h | 2 | ||||
-rw-r--r-- | gdbserver/target.cc | 7 | ||||
-rw-r--r-- | gdbserver/target.h | 7 |
5 files changed, 81 insertions, 7 deletions
diff --git a/gdbserver/hostio.cc b/gdbserver/hostio.cc index 17b6179..69729a8 100644 --- a/gdbserver/hostio.cc +++ b/gdbserver/hostio.cc @@ -89,12 +89,18 @@ require_filename (char **pp, char *filename) return 0; } +template <typename T> static int -require_int (char **pp, int *value) +require_int (char **pp, T *value) { + constexpr bool is_signed = std::is_signed<T>::value; + char *p; int count, firstdigit; + /* Max count of hexadecimal digits in T (1 hex digit is 4 bits). */ + int max_count = sizeof (T) * CHAR_BIT / 4; + p = *pp; *value = 0; count = 0; @@ -111,7 +117,8 @@ require_int (char **pp, int *value) firstdigit = nib; /* Don't allow overflow. */ - if (count >= 8 || (count == 7 && firstdigit >= 0x8)) + if (count >= max_count + || (is_signed && count == (max_count - 1) && firstdigit >= 0x8)) return -1; *value = *value * 16 + nib; @@ -343,7 +350,8 @@ handle_open (char *own_buf) static void handle_pread (char *own_buf, int *new_packet_len) { - int fd, ret, len, offset, bytes_sent; + int fd, ret, len, bytes_sent; + off_t offset; char *p, *data; static int max_reply_size = -1; @@ -410,7 +418,8 @@ handle_pread (char *own_buf, int *new_packet_len) static void handle_pwrite (char *own_buf, int packet_len) { - int fd, ret, len, offset; + int fd, ret, len; + off_t offset; char *p, *data; p = own_buf + strlen ("vFile:pwrite:"); @@ -504,7 +513,48 @@ handle_stat (char *own_buf, int *new_packet_len) return; } - if (lstat (filename, &st) == -1) + if (stat (filename, &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_lstat (char *own_buf, int *new_packet_len) +{ + int ret, bytes_sent; + char *p; + struct stat st; + struct fio_stat fst; + char filename[HOSTIO_PATH_MAX]; + + p = own_buf + strlen ("vFile:lstat:"); + + if (require_filename (&p, filename) + || require_end (p)) + { + hostio_packet_error (own_buf); + return; + } + + if (hostio_fs_pid != 0) + ret = the_target->multifs_lstat (hostio_fs_pid, filename, &st); + else + ret = lstat (filename, &st); + + if (ret == -1) { hostio_error (own_buf); return; @@ -641,6 +691,8 @@ handle_vFile (char *own_buf, int packet_len, int *new_packet_len) handle_fstat (own_buf, new_packet_len); else if (startswith (own_buf, "vFile:stat:")) handle_stat (own_buf, new_packet_len); + else if (startswith (own_buf, "vFile:lstat:")) + handle_lstat (own_buf, new_packet_len); else if (startswith (own_buf, "vFile:close:")) handle_close (own_buf); else if (startswith (own_buf, "vFile:unlink:")) diff --git a/gdbserver/linux-low.cc b/gdbserver/linux-low.cc index 1d223c1..3964270 100644 --- a/gdbserver/linux-low.cc +++ b/gdbserver/linux-low.cc @@ -751,7 +751,7 @@ linux_process_target::handle_extended_wait (lwp_info **orig_event_lwp, /* Set the event status. */ event_lwp->waitstatus.set_execd (make_unique_xstrdup - (linux_proc_pid_to_exec_file (event_thr->id.lwp ()))); + (pid_to_exec_file (event_thr->id.lwp ()))); /* Mark the exec status as pending. */ event_lwp->stopped = 1; @@ -6033,7 +6033,7 @@ linux_process_target::supports_pid_to_exec_file () const char * linux_process_target::pid_to_exec_file (int pid) { - return linux_proc_pid_to_exec_file (pid); + return linux_proc_pid_to_exec_file (pid, linux_ns_same (pid, LINUX_NS_MNT)); } bool @@ -6050,6 +6050,12 @@ linux_process_target::multifs_open (int pid, const char *filename, } int +linux_process_target::multifs_lstat (int pid, const char *filename, struct stat *sb) +{ + return linux_mntns_lstat (pid, filename, sb); +} + +int linux_process_target::multifs_unlink (int pid, const char *filename) { return linux_mntns_unlink (pid, filename); diff --git a/gdbserver/linux-low.h b/gdbserver/linux-low.h index 7d3e35f..e1c88ee 100644 --- a/gdbserver/linux-low.h +++ b/gdbserver/linux-low.h @@ -304,6 +304,8 @@ public: int multifs_open (int pid, const char *filename, int flags, mode_t mode) override; + int multifs_lstat (int pid, const char *filename, struct stat *st) override; + int multifs_unlink (int pid, const char *filename) override; ssize_t multifs_readlink (int pid, const char *filename, char *buf, diff --git a/gdbserver/target.cc b/gdbserver/target.cc index e812785..c400174c 100644 --- a/gdbserver/target.cc +++ b/gdbserver/target.cc @@ -773,6 +773,13 @@ process_stratum_target::multifs_open (int pid, const char *filename, } int +process_stratum_target::multifs_lstat (int pid, const char *filename, + struct stat *sb) +{ + return lstat (filename, sb); +} + +int process_stratum_target::multifs_unlink (int pid, const char *filename) { return unlink (filename); diff --git a/gdbserver/target.h b/gdbserver/target.h index af788e2..66ca72f 100644 --- a/gdbserver/target.h +++ b/gdbserver/target.h @@ -31,6 +31,7 @@ #include "gdbsupport/btrace-common.h" #include <vector> #include "gdbsupport/byte-vector.h" +#include <sys/stat.h> struct emit_ops; struct process_info; @@ -441,6 +442,12 @@ public: virtual int multifs_open (int pid, const char *filename, int flags, mode_t mode); + /* Multiple-filesystem-aware lstat. Like lstat(2), but operating in + the filesystem as it appears to process PID. Systems where all + processes share a common filesystem should not override this. + The default behavior is to use lstat(2). */ + virtual int multifs_lstat (int pid, const char *filename, struct stat *sb); + /* Multiple-filesystem-aware unlink. Like unlink(2), but operates in the filesystem as it appears to process PID. Systems where all processes share a common filesystem should not override this. |