Adjust linux's "info proc" command to read the /proc files from the target. From: Pedro Alves Obviously not a complete patch. The command' implementation would need to move behind a gdbarch callback, and only one /proc file access has been adjusted. --- gdb/linux-nat.c | 203 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 195 insertions(+), 8 deletions(-) diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c index f6b36a2..d333c44 100644 --- a/gdb/linux-nat.c +++ b/gdb/linux-nat.c @@ -4830,13 +4830,190 @@ enum info_proc_what IP_ALL }; +#include "gdb/fileio.h" + +static int +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 +errno_to_fileio_error (int error) +{ + switch (error) + { + 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; +} + +static int +linux_nat_file_open (const char *filename, int flags, int mode, + int *target_errno) +{ + int nat_flags; + int fd; + + if (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 = errno_to_fileio_error (errno); + return fd; +} + +static int +linux_nat_file_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, offset); +#else + ret = lseek (fd, offset, SEEK_SET); + if (ret != -1) + ret = write (fd, write_buf, len); +#endif + + if (ret == -1) + *target_errno = errno_to_fileio_error (errno); + return ret; +} + +static int +linux_nat_file_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, offset); +#else + ret = lseek (fd, offset, SEEK_SET); + if (ret != -1) + ret = read (fd, read_buf, len); +#endif + + if (ret == -1) + *target_errno = errno_to_fileio_error (errno); + + return ret; +} + +static int +linux_nat_file_close (int fd, int *target_errno) +{ + int ret; + + ret = close (fd); + if (ret == -1) + *target_errno = errno_to_fileio_error (errno); + + return ret; +} + +static void +do_target_file_close (void *arg) +{ + int fd = *(int *) arg; + int target_errno; + + target_file_close (fd, &target_errno); + xfree (arg); +} + +static struct cleanup * +make_cleanup_target_file_close (int fd) +{ + int *fdp = XNEW (int); + + *fdp = fd; + return make_cleanup (do_target_file_close, fdp); +} + static void linux_nat_info_proc_cmd_1 (char *args, enum info_proc_what what, int from_tty) { /* A long is used for pid instead of an int to avoid a loss of precision compiler warning from the output of strtoul. */ long pid = PIDGET (inferior_ptid); - FILE *procfile; + int procfile; char buffer[MAXPATHLEN]; char fname1[MAXPATHLEN], fname2[MAXPATHLEN]; int cmdline_f = (what == IP_MINIMAL || what == IP_CMDLINE || what == IP_ALL); @@ -4846,6 +5023,7 @@ linux_nat_info_proc_cmd_1 (char *args, enum info_proc_what what, int from_tty) int status_f = (what == IP_STATUS || what == IP_ALL); int stat_f = (what == IP_STAT || what == IP_ALL); struct stat dummy; + int target_errno; if (args && isdigit (args[0])) pid = strtoul (args, &args, 10); @@ -4857,19 +5035,17 @@ linux_nat_info_proc_cmd_1 (char *args, enum info_proc_what what, int from_tty) if (pid == 0) error (_("No current process: you must name one.")); - sprintf (fname1, "/proc/%ld", pid); - if (stat (fname1, &dummy) != 0) - error (_("No /proc directory: '%s'"), fname1); - printf_filtered (_("process %ld\n"), pid); if (cmdline_f) { sprintf (fname1, "/proc/%ld/cmdline", pid); - if ((procfile = fopen (fname1, "r")) != NULL) + if ((procfile = target_file_open (fname1, FILEIO_O_RDONLY, + 0, &target_errno)) != -1) { - struct cleanup *cleanup = make_cleanup_fclose (procfile); + struct cleanup *cleanup = make_cleanup_target_file_close (procfile); - if (fgets (buffer, sizeof (buffer), procfile)) + if (target_file_pread (procfile, buffer, sizeof (buffer), + 0, &target_errno) != -1) printf_filtered ("cmdline = '%s'\n", buffer); else warning (_("unable to read '%s'"), fname1); @@ -4898,6 +5074,8 @@ linux_nat_info_proc_cmd_1 (char *args, enum info_proc_what what, int from_tty) } if (mappings_f) { + FILE *procfile; + sprintf (fname1, "/proc/%ld/maps", pid); if ((procfile = fopen (fname1, "r")) != NULL) { @@ -4960,6 +5138,8 @@ linux_nat_info_proc_cmd_1 (char *args, enum info_proc_what what, int from_tty) } if (status_f) { + FILE *procfile; + sprintf (fname1, "/proc/%ld/status", pid); if ((procfile = fopen (fname1, "r")) != NULL) { @@ -4974,6 +5154,8 @@ linux_nat_info_proc_cmd_1 (char *args, enum info_proc_what what, int from_tty) } if (stat_f) { + FILE *procfile; + sprintf (fname1, "/proc/%ld/stat", pid); if ((procfile = fopen (fname1, "r")) != NULL) { @@ -5880,6 +6062,11 @@ linux_nat_add_target (struct target_ops *t) t->to_core_of_thread = linux_nat_core_of_thread; + t->to_file_open = linux_nat_file_open; + t->to_file_pwrite = linux_nat_file_pwrite; + t->to_file_pread = linux_nat_file_pread; + t->to_file_close = linux_nat_file_close; + /* We don't change the stratum; this target will sit at process_stratum and thread_db will set at thread_stratum. This is a little strange, since this is a multi-threaded-capable