From f1838a98418d9912df59591058ca560f2de5cf14 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Tue, 26 Aug 2008 17:30:35 +0000 Subject: [PATCH] ChangeLog: * remote.h (remote_filename_p, remote_bfd_open): Add prototypes. * remote.c (remote_bfd_iovec_open, remote_bfd_iovec_close, remote_bfd_iovec_pread, remote_bfd_iovec_stat, remote_filename_p, remote_bfd_open): New functions. (remote_hostio_send_command): Fail safely if remote connection is not set up. * solist.h (solib_open): Remove prototype. (solib_bfd_open): Add prototype. * solib.c: Include "remote.h". (solib_open): Remove, replace by ... (solib_bfd_open): ... this new function. Handle remote BFDs. (solib_map_sections): Replace solib_open by solib_bfd_open. * solib-frv.c: Include "exceptions.h". (enable_break2): Replace solib_open by solib_bfd_open. * solib-svr4.c: Include "exceptions.h". (enable_break): Replace solib_open by solib_bfd_open. * symfile.c: Include "remote.h". (build_id_verify): Handle remote BFDs. (separate_debug_file_exists): Use BFD to access file. Handle remote BFDs. (symfile_bfd_open): Handle remote BFDs. (reread_symbols): Handle remote BFDs. * NEWS: Mention "remote:" argument prefix to "set sysroot". doc/ChangeLog: * gdb.texinfo (Commands to Specify Files): Document "remote:" argument prefix to "set sysroot". --- gdb/ChangeLog | 29 +++++++++++++ gdb/NEWS | 5 +++ gdb/doc/ChangeLog | 5 +++ gdb/doc/gdb.texinfo | 17 +++++++- gdb/remote.c | 94 ++++++++++++++++++++++++++++++++++++++++- gdb/remote.h | 4 ++ gdb/solib-frv.c | 21 +++------- gdb/solib-svr4.c | 21 +++------- gdb/solib.c | 100 +++++++++++++++++++++++++------------------- gdb/solist.h | 2 +- gdb/symfile.c | 51 ++++++++++++++++++---- 11 files changed, 263 insertions(+), 86 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 0ab3596d1d..cdc4c77088 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,32 @@ +2008-08-26 Ulrich Weigand + + * remote.h (remote_filename_p, remote_bfd_open): Add prototypes. + * remote.c (remote_bfd_iovec_open, remote_bfd_iovec_close, + remote_bfd_iovec_pread, remote_bfd_iovec_stat, remote_filename_p, + remote_bfd_open): New functions. + (remote_hostio_send_command): Fail safely if remote connection + is not set up. + + * solist.h (solib_open): Remove prototype. + (solib_bfd_open): Add prototype. + * solib.c: Include "remote.h". + (solib_open): Remove, replace by ... + (solib_bfd_open): ... this new function. Handle remote BFDs. + (solib_map_sections): Replace solib_open by solib_bfd_open. + * solib-frv.c: Include "exceptions.h". + (enable_break2): Replace solib_open by solib_bfd_open. + * solib-svr4.c: Include "exceptions.h". + (enable_break): Replace solib_open by solib_bfd_open. + + * symfile.c: Include "remote.h". + (build_id_verify): Handle remote BFDs. + (separate_debug_file_exists): Use BFD to access file. Handle + remote BFDs. + (symfile_bfd_open): Handle remote BFDs. + (reread_symbols): Handle remote BFDs. + + * NEWS: Mention "remote:" argument prefix to "set sysroot". + 2008-08-26 Ulrich Weigand * gdbarch.sh (target_gdbarch): New global variable. diff --git a/gdb/NEWS b/gdb/NEWS index 46d143829a..4c9af8295a 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -3,6 +3,11 @@ *** Changes since GDB 6.8 +* GDB now supports automatic retrieval of shared library files from +remote targets. To use this feature, specify a system root that begins +with the `remote:' prefix, either via the `set sysroot' command or via +the `--with-sysroot' configure-time option. + * Commands `set debug-file-directory', `set solib-search-path' and `set args' now complete on file names. diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 7e837706d9..bb1ac1f0c2 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,8 @@ +2008-08-26 Ulrich Weigand + + * gdb.texinfo (Commands to Specify Files): Document "remote:" + argument prefix to "set sysroot". + 2008-08-21 Paul N. Hilfinger * gdb.texinfo (Omissions from Ada): Describe new treatment of True diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 6760b71940..60fc4b96c6 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -12605,8 +12605,11 @@ library events happen. @end table Shared libraries are also supported in many cross or remote debugging -configurations. A copy of the target's libraries need to be present on the -host system; they need to be the same as the target libraries, although the +configurations. @value{GDBN} needs to have access to the target's libraries; +this can be accomplished either by providing copies of the libraries +on the host system, or by asking @value{GDBN} to automatically retrieve the +libraries from the target. If copies of the target libraries are +provided, they need to be the same as the target libraries, although the copies on the target can be stripped as long as the copies on the host are not. @@ -12630,6 +12633,16 @@ libraries, they need to be laid out in the same way that they are on the target, with e.g.@: a @file{/lib} and @file{/usr/lib} hierarchy under @var{path}. +If @var{path} starts with the sequence @file{remote:}, @value{GDBN} will +retrieve the target libraries from the remote system. This is only +supported when using a remote target that supports the @code{remote get} +command (@pxref{File Transfer,,Sending files to a remote system}). +The part of @var{path} following the initial @file{remote:} +(if present) is used as system root prefix on the remote file system. +@footnote{If you want to specify a local system root using a directory +that happens to be named @file{remote:}, you need to use some equivalent +variant of the name like @file{./remote:}.} + The @code{set solib-absolute-prefix} command is an alias for @code{set sysroot}. diff --git a/gdb/remote.c b/gdb/remote.c index 0847d67602..1d972ec87f 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -6668,7 +6668,8 @@ remote_hostio_send_command (int command_bytes, int which_packet, int ret, bytes_read; char *attachment_tmp; - if (remote_protocol_packets[which_packet].support == PACKET_DISABLE) + if (!remote_desc + || remote_protocol_packets[which_packet].support == PACKET_DISABLE) { *remote_errno = FILEIO_ENOSYS; return -1; @@ -6932,6 +6933,97 @@ remote_hostio_close_cleanup (void *opaque) remote_hostio_close (fd, &remote_errno); } + +static void * +remote_bfd_iovec_open (struct bfd *abfd, void *open_closure) +{ + const char *filename = bfd_get_filename (abfd); + int fd, remote_errno; + int *stream; + + gdb_assert (remote_filename_p (filename)); + + fd = remote_hostio_open (filename + 7, FILEIO_O_RDONLY, 0, &remote_errno); + if (fd == -1) + { + errno = remote_fileio_errno_to_host (remote_errno); + bfd_set_error (bfd_error_system_call); + return NULL; + } + + stream = xmalloc (sizeof (int)); + *stream = fd; + return stream; +} + +static int +remote_bfd_iovec_close (struct bfd *abfd, void *stream) +{ + int fd = *(int *)stream; + int remote_errno; + + xfree (stream); + + /* Ignore errors on close; these may happen if the remote + connection was already torn down. */ + remote_hostio_close (fd, &remote_errno); + + return 1; +} + +static file_ptr +remote_bfd_iovec_pread (struct bfd *abfd, void *stream, void *buf, + file_ptr nbytes, file_ptr offset) +{ + int fd = *(int *)stream; + int remote_errno; + file_ptr pos, bytes; + + pos = 0; + while (nbytes > pos) + { + bytes = remote_hostio_pread (fd, (char *)buf + pos, nbytes - pos, + offset + pos, &remote_errno); + if (bytes == 0) + /* Success, but no bytes, means end-of-file. */ + break; + if (bytes == -1) + { + errno = remote_fileio_errno_to_host (remote_errno); + bfd_set_error (bfd_error_system_call); + return -1; + } + + pos += bytes; + } + + return pos; +} + +static int +remote_bfd_iovec_stat (struct bfd *abfd, void *stream, struct stat *sb) +{ + /* FIXME: We should probably implement remote_hostio_stat. */ + sb->st_size = INT_MAX; + return 0; +} + +int +remote_filename_p (const char *filename) +{ + return strncmp (filename, "remote:", 7) == 0; +} + +bfd * +remote_bfd_open (const char *remote_file, const char *target) +{ + return bfd_openr_iovec (remote_file, target, + remote_bfd_iovec_open, NULL, + remote_bfd_iovec_pread, + remote_bfd_iovec_close, + remote_bfd_iovec_stat); +} + void remote_file_put (const char *local_file, const char *remote_file, int from_tty) { diff --git a/gdb/remote.h b/gdb/remote.h index 25fe82617b..e40a6c2ee9 100644 --- a/gdb/remote.h +++ b/gdb/remote.h @@ -73,4 +73,8 @@ void remote_file_get (const char *remote_file, const char *local_file, int from_tty); void remote_file_delete (const char *remote_file, int from_tty); +bfd *remote_bfd_open (const char *remote_file, const char *target); + +int remote_filename_p (const char *filename); + #endif diff --git a/gdb/solib-frv.c b/gdb/solib-frv.c index 6b6ff15fdd..189fbe0222 100644 --- a/gdb/solib-frv.c +++ b/gdb/solib-frv.c @@ -30,6 +30,7 @@ #include "command.h" #include "gdbcmd.h" #include "elf/frv.h" +#include "exceptions.h" /* Flag which indicates whether internal debug messages should be printed. */ static int solib_frv_debug; @@ -645,12 +646,11 @@ enable_break2 (void) unsigned int interp_sect_size; gdb_byte *buf; bfd *tmp_bfd = NULL; - int tmp_fd = -1; - char *tmp_pathname = NULL; int status; CORE_ADDR addr, interp_loadmap_addr; gdb_byte addr_buf[FRV_PTR_SIZE]; struct int_elf32_fdpic_loadmap *ldm; + volatile struct gdb_exception ex; /* Read the contents of the .interp section into a local buffer; the contents specify the dynamic linker this program uses. */ @@ -668,25 +668,16 @@ enable_break2 (void) be trivial on GNU/Linux). Therefore, we have to try an alternate mechanism to find the dynamic linker's base address. */ - tmp_fd = solib_open (buf, &tmp_pathname); - if (tmp_fd >= 0) - tmp_bfd = bfd_fopen (tmp_pathname, gnutarget, FOPEN_RB, tmp_fd); - + TRY_CATCH (ex, RETURN_MASK_ALL) + { + tmp_bfd = solib_bfd_open (buf); + } if (tmp_bfd == NULL) { enable_break_failure_warning (); return 0; } - /* Make sure the dynamic linker is really a useful object. */ - if (!bfd_check_format (tmp_bfd, bfd_object)) - { - warning (_("Unable to grok dynamic linker %s as an object file"), buf); - enable_break_failure_warning (); - bfd_close (tmp_bfd); - return 0; - } - status = frv_fdpic_loadmap_addresses (target_gdbarch, &interp_loadmap_addr, 0); if (status < 0) diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c index 654c90687e..4aff3831a0 100644 --- a/gdb/solib-svr4.c +++ b/gdb/solib-svr4.c @@ -42,6 +42,7 @@ #include "elf-bfd.h" #include "exec.h" #include "auxv.h" +#include "exceptions.h" static struct link_map_offsets *svr4_fetch_link_map_offsets (void); static int svr4_have_link_map_offsets (void); @@ -1038,8 +1039,7 @@ enable_break (void) struct so_list *so; bfd *tmp_bfd = NULL; struct target_ops *tmp_bfd_target; - int tmp_fd = -1; - char *tmp_pathname = NULL; + volatile struct gdb_exception ex; /* Read the contents of the .interp section into a local buffer; the contents specify the dynamic linker this program uses. */ @@ -1058,21 +1058,13 @@ enable_break (void) be trivial on GNU/Linux). Therefore, we have to try an alternate mechanism to find the dynamic linker's base address. */ - tmp_fd = solib_open (buf, &tmp_pathname); - if (tmp_fd >= 0) - tmp_bfd = bfd_fopen (tmp_pathname, gnutarget, FOPEN_RB, tmp_fd); - + TRY_CATCH (ex, RETURN_MASK_ALL) + { + tmp_bfd = solib_bfd_open (buf); + } if (tmp_bfd == NULL) goto bkpt_at_symbol; - /* Make sure the dynamic linker's really a useful object. */ - if (!bfd_check_format (tmp_bfd, bfd_object)) - { - warning (_("Unable to grok dynamic linker %s as an object file"), buf); - bfd_close (tmp_bfd); - goto bkpt_at_symbol; - } - /* Now convert the TMP_BFD into a target. That way target, as well as BFD operations can be used. Note that closing the target will also close the underlying bfd. */ @@ -1166,7 +1158,6 @@ enable_break (void) /* For whatever reason we couldn't set a breakpoint in the dynamic linker. Warn and drop into the old code. */ bkpt_at_symbol: - xfree (tmp_pathname); warning (_("Unable to find dynamic linker breakpoint function.\n" "GDB will be unable to debug shared library initializers\n" "and track explicitly loaded dynamic code.")); diff --git a/gdb/solib.c b/gdb/solib.c index 1812eada13..7ca3a42021 100644 --- a/gdb/solib.c +++ b/gdb/solib.c @@ -44,6 +44,7 @@ #include "solist.h" #include "observer.h" #include "readline/readline.h" +#include "remote.h" /* Architecture-specific operations. */ @@ -106,11 +107,11 @@ The search path for loading non-absolute shared library symbol files is %s.\n"), GLOBAL FUNCTION - solib_open -- Find a shared library file and open it. + solib_bfd_open -- Find a shared library file and open BFD for it. SYNOPSIS - int solib_open (char *in_patname, char **found_pathname); + struct bfd *solib_open (char *in_pathname); DESCRIPTION @@ -137,16 +138,17 @@ The search path for loading non-absolute shared library symbol files is %s.\n"), RETURNS - file handle for opened solib, or -1 for failure. */ + BFD file handle for opened solib; throws error on failure. */ -int -solib_open (char *in_pathname, char **found_pathname) +bfd * +solib_bfd_open (char *in_pathname) { struct target_so_ops *ops = solib_ops (target_gdbarch); int found_file = -1; char *temp_pathname = NULL; char *p = in_pathname; int gdb_sysroot_is_empty; + bfd *abfd; gdb_sysroot_is_empty = (gdb_sysroot == NULL || *gdb_sysroot == 0); @@ -168,6 +170,29 @@ solib_open (char *in_pathname, char **found_pathname) strcat (temp_pathname, in_pathname); } + /* Handle remote files. */ + if (remote_filename_p (temp_pathname)) + { + temp_pathname = xstrdup (temp_pathname); + abfd = remote_bfd_open (temp_pathname, gnutarget); + if (!abfd) + { + make_cleanup (xfree, temp_pathname); + error (_("Could not open `%s' as an executable file: %s"), + temp_pathname, bfd_errmsg (bfd_get_error ())); + } + + if (!bfd_check_format (abfd, bfd_object)) + { + bfd_close (abfd); + make_cleanup (xfree, temp_pathname); + error (_("`%s': not in executable format: %s"), + temp_pathname, bfd_errmsg (bfd_get_error ())); + } + + return abfd; + } + /* Now see if we can open it. */ found_file = open (temp_pathname, O_RDONLY | O_BINARY, 0); @@ -228,16 +253,30 @@ solib_open (char *in_pathname, char **found_pathname) OPF_TRY_CWD_FIRST, in_pathname, O_RDONLY | O_BINARY, 0, &temp_pathname); - /* Done. If not found, tough luck. Return found_file and - (optionally) found_pathname. */ - if (temp_pathname) + /* Done. If still not found, error. */ + if (found_file < 0) + perror_with_name (in_pathname); + + /* Leave temp_pathname allocated. abfd->name will point to it. */ + abfd = bfd_fopen (temp_pathname, gnutarget, FOPEN_RB, found_file); + if (!abfd) { - if (found_pathname != NULL) - *found_pathname = temp_pathname; - else - xfree (temp_pathname); + close (found_file); + make_cleanup (xfree, temp_pathname); + error (_("Could not open `%s' as an executable file: %s"), + temp_pathname, bfd_errmsg (bfd_get_error ())); + } + + if (!bfd_check_format (abfd, bfd_object)) + { + bfd_close (abfd); + make_cleanup (xfree, temp_pathname); + error (_("`%s': not in executable format: %s"), + temp_pathname, bfd_errmsg (bfd_get_error ())); } - return found_file; + + bfd_set_cacheable (abfd, 1); + return abfd; } @@ -273,46 +312,24 @@ solib_map_sections (void *arg) { struct so_list *so = (struct so_list *) arg; /* catch_errors bogon */ char *filename; - char *scratch_pathname; - int scratch_chan; struct section_table *p; struct cleanup *old_chain; bfd *abfd; filename = tilde_expand (so->so_name); - old_chain = make_cleanup (xfree, filename); - scratch_chan = solib_open (filename, &scratch_pathname); - - if (scratch_chan < 0) - { - perror_with_name (filename); - } - - /* Leave scratch_pathname allocated. abfd->name will point to it. */ - abfd = bfd_fopen (scratch_pathname, gnutarget, FOPEN_RB, scratch_chan); - if (!abfd) - { - close (scratch_chan); - error (_("Could not open `%s' as an executable file: %s"), - scratch_pathname, bfd_errmsg (bfd_get_error ())); - } + abfd = solib_bfd_open (filename); + do_cleanups (old_chain); /* Leave bfd open, core_xfer_memory and "info files" need it. */ so->abfd = abfd; - bfd_set_cacheable (abfd, 1); /* copy full path name into so_name, so that later symbol_file_add can find it */ - if (strlen (scratch_pathname) >= SO_NAME_MAX_PATH_SIZE) - error (_("Full path name length of shared library exceeds SO_NAME_MAX_PATH_SIZE in so_list structure.")); - strcpy (so->so_name, scratch_pathname); + if (strlen (bfd_get_filename (abfd)) >= SO_NAME_MAX_PATH_SIZE) + error (_("Shared library file name is too long.")); + strcpy (so->so_name, bfd_get_filename (abfd)); - if (!bfd_check_format (abfd, bfd_object)) - { - error (_("\"%s\": not in executable format: %s."), - scratch_pathname, bfd_errmsg (bfd_get_error ())); - } if (build_section_table (abfd, &so->sections, &so->sections_end)) { error (_("Can't find the file sections in `%s': %s"), @@ -339,9 +356,6 @@ solib_map_sections (void *arg) } } - /* Free the file names, close the file now. */ - do_cleanups (old_chain); - return (1); } diff --git a/gdb/solist.h b/gdb/solist.h index fb104b49db..4a40a2d191 100644 --- a/gdb/solist.h +++ b/gdb/solist.h @@ -127,7 +127,7 @@ void free_so (struct so_list *so); struct so_list *master_so_list (void); /* Find solib binary file and open it. */ -extern int solib_open (char *in_pathname, char **found_pathname); +extern bfd *solib_bfd_open (char *in_pathname); /* FIXME: gdbarch needs to control this variable */ extern struct target_so_ops *current_target_so_ops; diff --git a/gdb/symfile.c b/gdb/symfile.c index faa375b7e2..8d22005eda 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -53,6 +53,7 @@ #include "varobj.h" #include "elf-bfd.h" #include "solib.h" +#include "remote.h" #include #include @@ -1216,7 +1217,10 @@ build_id_verify (const char *filename, struct build_id *check) int retval = 0; /* We expect to be silent on the non-existing files. */ - abfd = bfd_openr (filename, gnutarget); + if (remote_filename_p (filename)) + abfd = remote_bfd_open (filename, gnutarget); + else + abfd = bfd_openr (filename, gnutarget); if (abfd == NULL) return 0; @@ -1307,18 +1311,22 @@ static int separate_debug_file_exists (const char *name, unsigned long crc) { unsigned long file_crc = 0; - int fd; + bfd *abfd; gdb_byte buffer[8*1024]; int count; - fd = open (name, O_RDONLY | O_BINARY); - if (fd < 0) + if (remote_filename_p (name)) + abfd = remote_bfd_open (name, gnutarget); + else + abfd = bfd_openr (name, gnutarget); + + if (!abfd) return 0; - while ((count = read (fd, buffer, sizeof (buffer))) > 0) + while ((count = bfd_bread (buffer, sizeof (buffer), abfd)) > 0) file_crc = gnu_debuglink_crc32 (file_crc, buffer, count); - close (fd); + bfd_close (abfd); return crc == file_crc; } @@ -1564,6 +1572,28 @@ symfile_bfd_open (char *name) int desc; char *absolute_name; + if (remote_filename_p (name)) + { + name = xstrdup (name); + sym_bfd = remote_bfd_open (name, gnutarget); + if (!sym_bfd) + { + make_cleanup (xfree, name); + error (_("`%s': can't open to read symbols: %s."), name, + bfd_errmsg (bfd_get_error ())); + } + + if (!bfd_check_format (sym_bfd, bfd_object)) + { + bfd_close (sym_bfd); + make_cleanup (xfree, name); + error (_("`%s': can't read symbols: %s."), name, + bfd_errmsg (bfd_get_error ())); + } + + return sym_bfd; + } + name = tilde_expand (name); /* Returns 1st new malloc'd copy. */ /* Look down path for it, allocate 2nd new malloc'd copy. */ @@ -1594,7 +1624,7 @@ symfile_bfd_open (char *name) { close (desc); make_cleanup (xfree, name); - error (_("\"%s\": can't open to read symbols: %s."), name, + error (_("`%s': can't open to read symbols: %s."), name, bfd_errmsg (bfd_get_error ())); } bfd_set_cacheable (sym_bfd, 1); @@ -1606,7 +1636,7 @@ symfile_bfd_open (char *name) with the bfd). */ bfd_close (sym_bfd); /* This also closes desc. */ make_cleanup (xfree, name); - error (_("\"%s\": can't read symbols: %s."), name, + error (_("`%s': can't read symbols: %s."), name, bfd_errmsg (bfd_get_error ())); } @@ -2307,7 +2337,10 @@ reread_symbols (void) if (!bfd_close (objfile->obfd)) error (_("Can't close BFD for %s: %s"), objfile->name, bfd_errmsg (bfd_get_error ())); - objfile->obfd = bfd_openr (obfd_filename, gnutarget); + if (remote_filename_p (obfd_filename)) + objfile->obfd = remote_bfd_open (obfd_filename, gnutarget); + else + objfile->obfd = bfd_openr (obfd_filename, gnutarget); if (objfile->obfd == NULL) error (_("Can't open %s to read symbols."), objfile->name); /* bfd_openr sets cacheable to true, which is what we want. */ -- 2.34.1