From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 12209 invoked by alias); 14 Aug 2008 20:24:13 -0000 Received: (qmail 12196 invoked by uid 22791); 14 Aug 2008 20:24:10 -0000 X-Spam-Check-By: sourceware.org Received: from mtagate2.de.ibm.com (HELO mtagate2.de.ibm.com) (195.212.29.151) by sourceware.org (qpsmtpd/0.31) with ESMTP; Thu, 14 Aug 2008 20:23:28 +0000 Received: from d12nrmr1607.megacenter.de.ibm.com (d12nrmr1607.megacenter.de.ibm.com [9.149.167.49]) by mtagate2.de.ibm.com (8.13.8/8.13.8) with ESMTP id m7EKNKYq143748 for ; Thu, 14 Aug 2008 20:23:20 GMT Received: from d12av02.megacenter.de.ibm.com (d12av02.megacenter.de.ibm.com [9.149.165.228]) by d12nrmr1607.megacenter.de.ibm.com (8.13.8/8.13.8/NCO v9.0) with ESMTP id m7EKNK3v1876074 for ; Thu, 14 Aug 2008 22:23:20 +0200 Received: from d12av02.megacenter.de.ibm.com (loopback [127.0.0.1]) by d12av02.megacenter.de.ibm.com (8.12.11.20060308/8.13.3) with ESMTP id m7EKNJcF013290 for ; Thu, 14 Aug 2008 22:23:20 +0200 Received: from tuxmaker.boeblingen.de.ibm.com (tuxmaker.boeblingen.de.ibm.com [9.152.85.9]) by d12av02.megacenter.de.ibm.com (8.12.11.20060308/8.12.11) with SMTP id m7EKNJ0W013287; Thu, 14 Aug 2008 22:23:19 +0200 Message-Id: <200808142023.m7EKNJ0W013287@d12av02.megacenter.de.ibm.com> Received: by tuxmaker.boeblingen.de.ibm.com (sSMTP sendmail emulation); Thu, 14 Aug 2008 22:23:19 +0200 Subject: Re: [rfc/rfa] Retrieve libraries from remote target To: eliz@gnu.org Date: Thu, 14 Aug 2008 20:24:00 -0000 From: "Ulrich Weigand" Cc: gdb-patches@sourceware.org, drow@false.org In-Reply-To: from "Eli Zaretskii" at Aug 14, 2008 10:35:36 PM X-Mailer: ELM [version 2.5 PL2] MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2008-08/txt/msg00385.txt.bz2 Eli Zaretskii wrote: > As written, the sentence in effect says that it's GDB who uses the > `remote:' prefix, which is probably not what you mean. Indeed, thanks for catching this! > Other than that, the doco patches are approved. Thanks! Here's an updated version including those changes. Bye, Ulrich 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". diff -urNp gdb-orig/gdb/doc/gdb.texinfo gdb-head/gdb/doc/gdb.texinfo --- gdb-orig/gdb/doc/gdb.texinfo 2008-08-14 17:55:46.556444105 +0200 +++ gdb-head/gdb/doc/gdb.texinfo 2008-08-14 22:16:37.951684794 +0200 @@ -12595,8 +12595,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. @@ -12620,6 +12623,16 @@ libraries, they need to be laid out in t 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 -urNp gdb-orig/gdb/NEWS gdb-head/gdb/NEWS --- gdb-orig/gdb/NEWS 2008-08-14 17:55:46.584440094 +0200 +++ gdb-head/gdb/NEWS 2008-08-14 22:17:40.809110194 +0200 @@ -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 -urNp gdb-orig/gdb/remote.c gdb-head/gdb/remote.c --- gdb-orig/gdb/remote.c 2008-08-14 22:09:22.693026189 +0200 +++ gdb-head/gdb/remote.c 2008-08-14 22:09:06.573811367 +0200 @@ -6695,7 +6695,8 @@ remote_hostio_send_command (int command_ 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; @@ -6959,6 +6960,97 @@ remote_hostio_close_cleanup (void *opaqu 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 -urNp gdb-orig/gdb/remote.h gdb-head/gdb/remote.h --- gdb-orig/gdb/remote.h 2008-08-14 17:55:46.634432932 +0200 +++ gdb-head/gdb/remote.h 2008-08-14 22:09:06.580810364 +0200 @@ -73,4 +73,8 @@ void remote_file_get (const char *remote 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 -urNp gdb-orig/gdb/solib.c gdb-head/gdb/solib.c --- gdb-orig/gdb/solib.c 2008-08-14 22:09:22.706024326 +0200 +++ gdb-head/gdb/solib.c 2008-08-14 22:09:06.592808644 +0200 @@ -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 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 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 **fo 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 **fo 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 -urNp gdb-orig/gdb/solib-frv.c gdb-head/gdb/solib-frv.c --- gdb-orig/gdb/solib-frv.c 2008-08-14 22:09:22.718022606 +0200 +++ gdb-head/gdb/solib-frv.c 2008-08-14 22:09:06.604806924 +0200 @@ -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 -urNp gdb-orig/gdb/solib-svr4.c gdb-head/gdb/solib-svr4.c --- gdb-orig/gdb/solib-svr4.c 2008-08-14 22:09:22.741019309 +0200 +++ gdb-head/gdb/solib-svr4.c 2008-08-14 22:09:06.619804774 +0200 @@ -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 -urNp gdb-orig/gdb/solist.h gdb-head/gdb/solist.h --- gdb-orig/gdb/solist.h 2008-08-14 17:55:46.791410442 +0200 +++ gdb-head/gdb/solist.h 2008-08-14 22:09:06.626803770 +0200 @@ -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 -urNp gdb-orig/gdb/symfile.c gdb-head/gdb/symfile.c --- gdb-orig/gdb/symfile.c 2008-08-14 17:55:46.827405285 +0200 +++ gdb-head/gdb/symfile.c 2008-08-14 22:09:06.652800043 +0200 @@ -53,6 +53,7 @@ #include "varobj.h" #include "elf-bfd.h" #include "solib.h" +#include "remote.h" #include #include @@ -1266,7 +1267,10 @@ build_id_verify (const char *filename, s 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; @@ -1357,18 +1361,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; } @@ -1614,6 +1622,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. */ @@ -1644,7 +1674,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); @@ -1656,7 +1686,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 ())); } @@ -2357,7 +2387,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. */ -- Dr. Ulrich Weigand GNU Toolchain for Linux on System z and Cell BE Ulrich.Weigand@de.ibm.com