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 +#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 #include +#include "build-id.h" +#ifdef HAVE_LIBDEBUGINFOD +#include +#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; }