Re: [RFC PATCH] Support debuginfo and source file fetching via debuginfo server

Aaron Merey
2019-11-05T01:59:18Z

[-- Attachment #1: Type: text/plain, Size: 744 bytes --]

On Mon, Nov 4, 2019 at 11:26 AM Frank Ch. Eigler <fche@redhat.com> wrote:
>
> Hi -
>
> > I haven't followed this thread closely, so it might be an obvious "no", but
> > I was wondering if the library could offer to install a callback that is call
> > relatively often, allowing GDB to interrupt the operation [...]
>
> That could also work, at the cost of extending the API. Will play with it.
>
> - FChE

Attached is the updated debuginfo and source lookup code, using the
callback idea that Simon suggested. Downloads are now cancelled upon
SIGINT and the callback can be modified with code that prints progress
messages (the a and b parameters in the callback represent the
numerator and denominator of the download's completion fraction).

[-- Attachment #2: debuginfo_and_source_lookups.patch --]
[-- Type: text/x-patch, Size: 3913 bytes --]

gdb/elfread.c | 36 +++++++++++++++++++++++++++++++++++-
gdb/source.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 82 insertions(+), 1 deletion(-)

diff --git a/gdb/elfread.c b/gdb/elfread.c
index 226e3f09d3..e24bca610f 100644
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -48,7 +48,11 @@
#include "auxv.h"
#include "mdebugread.h"
#include "ctfread.h"
+#include "gdbsupport/scoped_fd.h"
#include "gdbsupport/gdb_string_view.h"
+#if HAVE_LIBDEBUGINFOD
+#include <elfutils/debuginfod.h>
+#endif

/* Forward declarations. */
extern const struct sym_fns elf_sym_fns_gdb_index;
@@ -1311,8 +1315,38 @@ elf_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
symbol_file_add_separate (debug_bfd.get (), debugfile.c_str (),
symfile_flags, objfile);
}
- else
+ else
+ {
has_dwarf2 = false;
+
+#if HAVE_LIBDEBUGINFOD
+ const struct bfd_build_id *build_id;
+ char *symfile_path;
+
+ build_id = build_id_bfd_get (objfile->obfd);
+
+ /* Allow debuginfod to abort the download if SIGINT is raised. */
+ debuginfod_set_progressfn (
+ [] (long a, long b) { return 1 ? check_quit_flag () : 0; }
+ );
+
+ /* Query debuginfod servers for symfile. */
+ scoped_fd fd (debuginfod_find_debuginfo (build_id->data,
+ build_id->size,
+ &symfile_path));
+
+ if (fd.get () >= 0)
+ {
+ /* file successfully retrieved from server. */
+ gdb_bfd_ref_ptr debug_bfd (symfile_bfd_open (symfile_path));
+
+ symbol_file_add_separate (debug_bfd.get (), symfile_path,
+ symfile_flags, objfile);
+ xfree (symfile_path);
+ has_dwarf2 = true;
+ }
+#endif /* LIBDEBUGINFOD */
+ }
}

/* Read the CTF section only if there is no DWARF info. */
diff --git a/gdb/source.c b/gdb/source.c
index 9f53d654f3..4e8a6558b7 100644
--- a/gdb/source.c
+++ b/gdb/source.c
@@ -30,6 +30,10 @@

#include <sys/types.h>
#include <fcntl.h>
+#include "build-id.h"
+#ifdef HAVE_LIBDEBUGINFOD
+#include <elfutils/debuginfod.h>
+#endif
#include "gdbcore.h"
#include "gdb_regex.h"
#include "symfile.h"
@@ -1127,6 +1131,49 @@ open_source_file (struct symtab *s)
s->fullname = NULL;
scoped_fd fd = find_and_open_source (s->filename, SYMTAB_DIRNAME (s),
&fullname);
+
+#if HAVE_LIBDEBUGINFOD
+ if (fd.get () < 0 && SYMTAB_COMPUNIT (s) != NULL)
+ {
+ const struct bfd_build_id *build_id;
+ const objfile *ofp = COMPUNIT_OBJFILE (SYMTAB_COMPUNIT (s));
+
+ std::string srcpath;
+ if (IS_DIR_SEPARATOR (s->filename[0]))
+ srcpath = s->filename;
+ else
+ {
+ srcpath = SYMTAB_DIRNAME (s);
+ srcpath += SLASH_STRING;
+ srcpath += s->filename;
+ }
+
+ build_id = build_id_bfd_get (ofp->obfd);
+
+ /* Query debuginfod for the source file. */
+ if (build_id != NULL)
+ {
+ char *name_in_cache;
+
+ /* Allow debuginfod to abort the download if SIGINT is raised. */
+ debuginfod_set_progressfn (
+ [] (long a, long b) { return 1 ? check_quit_flag () : 0; }
+ );
+
+ scoped_fd src_fd (debuginfod_find_source (build_id->data,
+ build_id->size,
+ srcpath.c_str (),
+ &name_in_cache));
+
+ if (src_fd.get () >= 0)
+ fullname.reset (name_in_cache);
+
+ s->fullname = fullname.release ();
+ return src_fd;
+ }
+ }
+#endif /* HAVE_LIBDEBUGINFOD */
+
s->fullname = fullname.release ();
return fd;
}