[PATCH 2/7] Introduce target_fileio_set_fs

Gary Benson
2015-04-16T12:20:01Z

This commit introduces a new target method target_fileio_set_fs
and adds calls to it in various places. This allows support to
be added for targets where processes do not share a common
filesystem.

gdb/ChangeLog:

* target.h (struct inferior): New forward declaration.
(struct target_ops) <to_fileio_set_fs>: New field.
(target_fileio_set_fs): New declaration.
* target-delegates.c: Regenerate.
* target.c (target_fileio_set_fs): New function.
* exec.c (exec_file_attach): Call target_fileio_set_fs.
* gdb_bfd.c (inferior.h): New include.
(gdb_bfd_iovec_fileio_open): Rename argument. Call
target_fileio_set_fs.
(gdb_bfd_open): Call target_fileio_set_fs. Pass current
inferior as argument to gdb_bfd_iovec_fileio_open.
* linux-tdep.c (linux_info_proc): Call target_fileio_set_fs.
(linux_find_memory_regions_full): Likewise.
(linux_fill_prpsinfo): Likewise.
* solib.c (solib_find_1): Likewise.
---
gdb/ChangeLog | 18 ++++++++++++++++++
gdb/exec.c | 2 ++
gdb/gdb_bfd.c | 10 ++++++++--
gdb/linux-tdep.c | 9 +++++++++
gdb/solib.c | 9 +++++++--
gdb/target-delegates.c | 28 ++++++++++++++++++++++++++++
gdb/target.c | 23 +++++++++++++++++++++++
gdb/target.h | 23 +++++++++++++++++++++++
8 files changed, 118 insertions(+), 4 deletions(-)

diff --git a/gdb/exec.c b/gdb/exec.c
index 872b86c..e97793a 100644
--- a/gdb/exec.c
+++ b/gdb/exec.c
@@ -231,6 +231,8 @@ exec_file_attach (const char *filename, int from_tty)

if (is_target_filename (filename))
{
+ target_fileio_set_fs (current_inferior ());
+
if (target_filesystem_is_local ())
filename += strlen (TARGET_SYSROOT_PREFIX);
else
diff --git a/gdb/gdb_bfd.c b/gdb/gdb_bfd.c
index 3d5d23f..bdcf985 100644
--- a/gdb/gdb_bfd.c
+++ b/gdb/gdb_bfd.c
@@ -32,6 +32,7 @@
#endif
#include "target.h"
#include "gdb/fileio.h"
+#include "inferior.h"

typedef bfd *bfdp;
DEF_VEC_P (bfdp);
@@ -213,7 +214,7 @@ fileio_errno_to_host (int errnum)
OPEN_CLOSURE is unused. */

static void *
-gdb_bfd_iovec_fileio_open (struct bfd *abfd, void *open_closure)
+gdb_bfd_iovec_fileio_open (struct bfd *abfd, void *inferior)
{
const char *filename = bfd_get_filename (abfd);
int fd, target_errno;
@@ -221,6 +222,8 @@ gdb_bfd_iovec_fileio_open (struct bfd *abfd, void *open_closure)

gdb_assert (is_target_filename (filename));

+ target_fileio_set_fs ((struct inferior *) inferior);
+
fd = target_fileio_open (filename + strlen (TARGET_SYSROOT_PREFIX),
FILEIO_O_RDONLY, 0,
&target_errno);
@@ -322,12 +325,15 @@ gdb_bfd_open (const char *name, const char *target, int fd)

if (is_target_filename (name))
{
+ target_fileio_set_fs (current_inferior ());
+
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_open,
+ current_inferior (),
gdb_bfd_iovec_fileio_pread,
gdb_bfd_iovec_fileio_close,
gdb_bfd_iovec_fileio_fstat);
diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
index 9d75b66..44b2970 100644
--- a/gdb/linux-tdep.c
+++ b/gdb/linux-tdep.c
@@ -715,6 +715,9 @@ linux_info_proc (struct gdbarch *gdbarch, const char *args,
if (args && args[0])
error (_("Too many parameters: %s"), args);

+ /* Access /proc/ from our filesystem. */
+ target_fileio_set_fs (NULL);
+
printf_filtered (_("process %ld\n"), pid);
if (cmdline_f)
{
@@ -1130,6 +1133,9 @@ linux_find_memory_regions_full (struct gdbarch *gdbarch,

pid = current_inferior ()->pid;

+ /* Access /proc/ from our filesystem. */
+ target_fileio_set_fs (NULL);
+
if (use_coredump_filter)
{
xsnprintf (coredumpfilter_name, sizeof (coredumpfilter_name),
@@ -1752,6 +1758,9 @@ linux_fill_prpsinfo (struct elf_internal_linux_prpsinfo *p)

gdb_assert (p != NULL);

+ /* Access /proc/ from our filesystem. */
+ target_fileio_set_fs (NULL);
+
/* Obtaining PID and filename. */
pid = ptid_get_pid (inferior_ptid);
xsnprintf (filename, sizeof (filename), "/proc/%d/cmdline", (int) pid);
diff --git a/gdb/solib.c b/gdb/solib.c
index 2466235..f1e694f 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -167,8 +167,13 @@ solib_find_1 (char *in_pathname, int *fd, int is_solib)
ensures that the same search algorithm is used for
all local files regardless of whether a "target:"
prefix was used. */
- if (is_target_filename (sysroot) && target_filesystem_is_local ())
- sysroot += strlen (TARGET_SYSROOT_PREFIX);
+ if (is_target_filename (sysroot))
+ {
+ target_fileio_set_fs (current_inferior ());
+
+ if (target_filesystem_is_local ())
+ sysroot += strlen (TARGET_SYSROOT_PREFIX);
+ }

if (*sysroot == '\0')
sysroot = NULL;
diff --git a/gdb/target-delegates.c b/gdb/target-delegates.c
index 36eacbf..0c16f9e 100644
--- a/gdb/target-delegates.c
+++ b/gdb/target-delegates.c
@@ -2343,6 +2343,30 @@ debug_thread_address_space (struct target_ops *self, ptid_t arg1)
return result;
}

+static void
+delegate_fileio_set_fs (struct target_ops *self, int arg1)
+{
+ self = self->beneath;
+ self->to_fileio_set_fs (self, arg1);
+}
+
+static void
+tdefault_fileio_set_fs (struct target_ops *self, int arg1)
+{
+}
+
+static void
+debug_fileio_set_fs (struct target_ops *self, int arg1)
+{
+ fprintf_unfiltered (gdb_stdlog, "-> %s->to_fileio_set_fs (...)\n", debug_target.to_shortname);
+ debug_target.to_fileio_set_fs (&debug_target, arg1);
+ fprintf_unfiltered (gdb_stdlog, "<- %s->to_fileio_set_fs (", debug_target.to_shortname);
+ target_debug_print_struct_target_ops_p (&debug_target);
+ fputs_unfiltered (", ", gdb_stdlog);
+ target_debug_print_int (arg1);
+ fputs_unfiltered (")\n", gdb_stdlog);
+}
+
static int
delegate_filesystem_is_local (struct target_ops *self)
{
@@ -4049,6 +4073,8 @@ install_delegators (struct target_ops *ops)
ops->to_thread_architecture = delegate_thread_architecture;
if (ops->to_thread_address_space == NULL)
ops->to_thread_address_space = delegate_thread_address_space;
+ if (ops->to_fileio_set_fs == NULL)
+ ops->to_fileio_set_fs = delegate_fileio_set_fs;
if (ops->to_filesystem_is_local == NULL)
ops->to_filesystem_is_local = delegate_filesystem_is_local;
if (ops->to_trace_init == NULL)
@@ -4254,6 +4280,7 @@ install_dummy_methods (struct target_ops *ops)
ops->to_can_run_breakpoint_commands = tdefault_can_run_breakpoint_commands;
ops->to_thread_architecture = default_thread_architecture;
ops->to_thread_address_space = default_thread_address_space;
+ ops->to_fileio_set_fs = tdefault_fileio_set_fs;
ops->to_filesystem_is_local = tdefault_filesystem_is_local;
ops->to_trace_init = tdefault_trace_init;
ops->to_download_tracepoint = tdefault_download_tracepoint;
@@ -4402,6 +4429,7 @@ init_debug_target (struct target_ops *ops)
ops->to_can_run_breakpoint_commands = debug_can_run_breakpoint_commands;
ops->to_thread_architecture = debug_thread_architecture;
ops->to_thread_address_space = debug_thread_address_space;
+ ops->to_fileio_set_fs = debug_fileio_set_fs;
ops->to_filesystem_is_local = debug_filesystem_is_local;
ops->to_trace_init = debug_trace_init;
ops->to_download_tracepoint = debug_download_tracepoint;
diff --git a/gdb/target.c b/gdb/target.c
index 306c21d..0b78512 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -2684,6 +2684,29 @@ default_fileio_target (void)
return find_default_run_target ("file I/O");
}

+/* See target.h. */
+
+void
+target_fileio_set_fs (struct inferior *inf)
+{
+ struct target_ops *t;
+ int pid = (inf == NULL || inf->fake_pid_p) ? 0 : inf->pid;
+
+ for (t = default_fileio_target (); t != NULL; t = t->beneath)
+ {
+ if (t->to_fileio_set_fs != NULL)
+ {
+ t->to_fileio_set_fs (t, pid);
+
+ if (targetdebug)
+ fprintf_unfiltered (gdb_stdlog,
+ "target_fileio_set_fs (%d)\n", pid);
+
+ break;
+ }
+ }
+}
+
/* File handle for target file operations. */

typedef struct
diff --git a/gdb/target.h b/gdb/target.h
index 66bf91e..0472237 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -38,6 +38,7 @@ struct static_tracepoint_marker;
struct traceframe_info;
struct expression;
struct dcache_struct;
+struct inferior;

#include "infrun.h" /* For enum exec_direction_kind. */

@@ -830,6 +831,15 @@ struct target_ops

/* Target file operations. */

+ /* Set the filesystem accessed by target_filesystem_is_local and
+ target_fileio_* methods that take FILENAME arguments to the
+ filesystem as seen by process PID on the target system. If
+ PID is zero, set the filesystem to that seen by the GDB, or,
+ for remote targets, the remote stub. See the comment on
+ target_fileio_set_fs for more details. */
+ void (*to_fileio_set_fs) (struct target_ops *, int pid)
+ TARGET_DEFAULT_IGNORE ();
+
/* Return nonzero if the filesystem accessed by the
target_fileio_* methods is the local filesystem,
zero otherwise. */
@@ -1932,6 +1942,19 @@ extern int target_search_memory (CORE_ADDR start_addr,

/* Target file operations. */

+/* Set the filesystem accessed by target_filesystem_is_local and
+ target_fileio_* methods that take FILENAME arguments to the
+ filesystem as seen by INF iff INF is non-NULL and refers to
+ a running process with a non-faked PID. Set the filesystem
+ to that seen by the debugger (GDB or the remote stub) in all
+ other cases. All callers of target_filesystem_is_local and
+ target_fileio_* methods with FILENAME arguments should call
+ target_fileio_set_fs to ensure the correct filesystem is used.
+ File descriptors returned by target_fileio_open should continue
+ to reference the filesystem in which they were opened across
+ calls to target_fileio_set_fs. */
+extern void target_fileio_set_fs (struct inferior *inf);
+
/* Return nonzero if the filesystem accessed by the target_fileio_*
methods is the local filesystem, zero otherwise. */
#define target_filesystem_is_local() \
--
1.7.1