From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2009) id DC0D33851A9D; Tue, 6 Sep 2022 14:54:12 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org DC0D33851A9D Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Aaron Merey To: bfd-cvs@sourceware.org Subject: [binutils-gdb] Add debuginfod support for objdump -S X-Act-Checkin: binutils-gdb X-Git-Author: Aaron Merey X-Git-Refname: refs/heads/master X-Git-Oldrev: 6e7a29c7de4e1df679f2b6f6449b20474fbbcfdf X-Git-Newrev: d647c797b7386dcaca5984a3fbe9fba469771737 Message-Id: <20220906145412.DC0D33851A9D@sourceware.org> Date: Tue, 6 Sep 2022 14:54:12 +0000 (GMT) X-BeenThere: binutils-cvs@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Binutils-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 06 Sep 2022 14:54:13 -0000 https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3Dd647c797b738= 6dcaca5984a3fbe9fba469771737 commit d647c797b7386dcaca5984a3fbe9fba469771737 Author: Aaron Merey Date: Fri Sep 2 19:01:56 2022 -0400 Add debuginfod support for objdump -S =20 Currently objdump -S is not able to make use files downloaded from debu= ginfod. This is due to bfd_find_nearest_line_discriminator being unable to loca= te any separate debuginfo files in the debuginfod cache. Additionally objdump = lacked a call to debuginfod_find_source in order to download missing source fi= les. =20 Fix this by using bfd_find_nearest_line_with_alt instead of bfd_find_nearest_line_discriminator. Also add a call to debuginfod_find_source in order to download missing source files. =20 Co-authored-by: Nick Clifton Diff: --- binutils/ChangeLog | 13 +++ binutils/objdump.c | 252 ++++++++++++++++++++++++++++++++++++++++++++-----= ---- 2 files changed, 224 insertions(+), 41 deletions(-) diff --git a/binutils/ChangeLog b/binutils/ChangeLog index b5711097d50..cfb6417b55e 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,16 @@ +2022-09-02 Aaron Merey + + PR 29075 + * objdump.c (find_separate_debug): New function. Finds the bfd + corresponding to the separate debuginfod of a given bfd. + (find_alt_debug): New function. Finds the bfd corresponding to the + .gnu_debugaltlink of a given bfd. + (slurp_file): Add bfd parameter. If a source file cannot be found + attempt to download it from debuginfod, if enabled. + (try_print_file_open): Add bfd parameter and pass it to slurp_file. + (show_line): If debuginfod is enabled, call + bfd_find_nearest_line_with_alt instead of bfd_find_nearest_line. + 2022-09-01 Nick Clifton =20 PR 29534 diff --git a/binutils/objdump.c b/binutils/objdump.c index b34df5392b9..d34f269b406 100644 --- a/binutils/objdump.c +++ b/binutils/objdump.c @@ -72,6 +72,10 @@ #include #endif =20 +#ifdef HAVE_LIBDEBUGINFOD +#include +#endif + /* Internal headers for the ELF .stab-dump code - sorry. */ #define BYTES_IN_WORD 32 #include "aout/aout64.h" @@ -1735,28 +1739,174 @@ static struct print_file_list *print_files; =20 #define SHOW_PRECEDING_CONTEXT_LINES (5) =20 -/* Read a complete file into memory. */ +#if HAVE_LIBDEBUGINFOD +/* Return a hex string represention of the build-id. */ + +unsigned char * +get_build_id (void * data) +{ + unsigned i; + char * build_id_str; + bfd * abfd =3D (bfd *) data; + const struct bfd_build_id * build_id; + + build_id =3D abfd->build_id; + if (build_id =3D=3D NULL) + return NULL; + + build_id_str =3D malloc (build_id->size * 2 + 1); + if (build_id_str =3D=3D NULL) + return NULL; + + for (i =3D 0; i < build_id->size; i++) + sprintf (build_id_str + (i * 2), "%02x", build_id->data[i]); + build_id_str[build_id->size * 2] =3D '\0'; + + return (unsigned char *) build_id_str; +} + +/* Search for a separate debug file matching ABFD's build-id. */ + +static bfd * +find_separate_debug (const bfd * abfd) +{ + const struct bfd_build_id * build_id =3D abfd->build_id; + separate_info * i =3D first_separate_info; + + if (build_id =3D=3D NULL || i =3D=3D NULL) + return NULL; + + while (i !=3D NULL) + { + const bfd * i_bfd =3D (bfd *) i->handle; + + if (abfd !=3D NULL && i_bfd->build_id !=3D NULL) + { + const unsigned char * data =3D i_bfd->build_id->data; + size_t size =3D i_bfd->build_id->size; + + if (size =3D=3D build_id->size + && memcmp (data, build_id->data, size) =3D=3D 0) + return (bfd *) i->handle; + } + + i =3D i->next; + } + + return NULL; +} + +/* Search for a separate debug file matching ABFD's .gnu_debugaltlink + build-id. */ + +static bfd * +find_alt_debug (const bfd * abfd) +{ + size_t namelen; + size_t id_len; + const char * name; + struct dwarf_section * section; + const struct bfd_build_id * build_id =3D abfd->build_id; + separate_info * i =3D first_separate_info; + + if (i =3D=3D NULL + || build_id =3D=3D NULL + || !load_debug_section (gnu_debugaltlink, (void *) abfd)) + return NULL; + + section =3D &debug_displays[gnu_debugaltlink].section; + if (section =3D=3D NULL) + return NULL; + + name =3D (const char *) section->start; + namelen =3D strnlen (name, section->size) + 1; + if (namelen =3D=3D 1) + return NULL; + if (namelen >=3D section->size) + return NULL; + + id_len =3D section->size - namelen; + if (id_len < 0x14) + return NULL; + + /* Compare the .gnu_debugaltlink build-id with the build-ids of the + known separate_info files. */ + while (i !=3D NULL) + { + const bfd * i_bfd =3D (bfd *) i->handle; + + if (i_bfd !=3D NULL && i_bfd->build_id !=3D NULL) + { + const unsigned char * data =3D i_bfd->build_id->data; + size_t size =3D i_bfd->build_id->size; + + if (id_len =3D=3D size + && memcmp (section->start + namelen, data, size) =3D=3D 0) + return (bfd *) i->handle; + } + + i =3D i->next; + } + + return NULL; +} + +#endif /* HAVE_LIBDEBUGINFOD */ + +/* Reads the contents of file FN into memory. Returns a pointer to the bu= ffer. + Also returns the size of the buffer in SIZE_RETURN and a filled out + stat structure in FST_RETURN. Returns NULL upon failure. */ =20 static const char * -slurp_file (const char *fn, size_t *size, struct stat *fst) +slurp_file (const char * fn, + size_t * size_return, + struct stat * fst_return, + bfd * abfd ATTRIBUTE_UNUSED) { #ifdef HAVE_MMAP - int ps =3D getpagesize (); + int ps; size_t msize; #endif const char *map; - int fd =3D open (fn, O_RDONLY | O_BINARY); + int fd; + + /* Paranoia. */ + if (fn =3D=3D NULL || * fn =3D=3D 0 || size_return =3D=3D NULL || fst_re= turn =3D=3D NULL) + return NULL; + + fd =3D open (fn, O_RDONLY | O_BINARY); + +#if HAVE_LIBDEBUGINFOD + if (fd < 0 && use_debuginfod && fn[0] =3D=3D '/' && abfd !=3D NULL) + { + unsigned char * build_id; + debuginfod_client * client; + + client =3D debuginfod_begin (); + if (client =3D=3D NULL) + return NULL; + + build_id =3D get_build_id (abfd); + fd =3D debuginfod_find_source (client, build_id, 0, fn, NULL); + free (build_id); + debuginfod_end (client); + } +#endif =20 if (fd < 0) return NULL; - if (fstat (fd, fst) < 0) + + if (fstat (fd, fst_return) < 0) { close (fd); return NULL; } - *size =3D fst->st_size; + + *size_return =3D fst_return->st_size; + #ifdef HAVE_MMAP - msize =3D (*size + ps - 1) & ~(ps - 1); + ps =3D getpagesize (); + msize =3D (*size_return + ps - 1) & ~(ps - 1); map =3D mmap (NULL, msize, PROT_READ, MAP_SHARED, fd, 0); if (map !=3D (char *) -1L) { @@ -1764,8 +1914,9 @@ slurp_file (const char *fn, size_t *size, struct stat= *fst) return map; } #endif - map =3D (const char *) malloc (*size); - if (!map || (size_t) read (fd, (char *) map, *size) !=3D *size) + + map =3D (const char *) malloc (*size_return); + if (!map || (size_t) read (fd, (char *) map, *size_return) !=3D *size_re= turn) { free ((void *) map); map =3D NULL; @@ -1831,16 +1982,20 @@ index_file (const char *map, size_t size, unsigned = int *maxline) } =20 /* Tries to open MODNAME, and if successful adds a node to print_files - linked list and returns that node. Returns NULL on failure. */ + linked list and returns that node. Also fills in the stat structure + pointed to by FST_RETURN. Returns NULL on failure. */ =20 static struct print_file_list * -try_print_file_open (const char *origname, const char *modname, struct sta= t *fst) +try_print_file_open (const char * origname, + const char * modname, + struct stat * fst_return, + bfd * abfd) { struct print_file_list *p; =20 p =3D (struct print_file_list *) xmalloc (sizeof (struct print_file_list= )); =20 - p->map =3D slurp_file (modname, &p->mapsize, fst); + p->map =3D slurp_file (modname, &p->mapsize, fst_return, abfd); if (p->map =3D=3D NULL) { free (p); @@ -1870,7 +2025,7 @@ update_source_path (const char *filename, bfd *abfd) struct stat fst; int i; =20 - p =3D try_print_file_open (filename, filename, &fst); + p =3D try_print_file_open (filename, filename, &fst, abfd); if (p =3D=3D NULL) { if (include_path_count =3D=3D 0) @@ -1886,7 +2041,7 @@ update_source_path (const char *filename, bfd *abfd) char *modname =3D concat (include_paths[i], "/", fname, (const char *) 0); =20 - p =3D try_print_file_open (filename, modname, &fst); + p =3D try_print_file_open (filename, modname, &fst, abfd); if (p) break; =20 @@ -1956,10 +2111,52 @@ show_line (bfd *abfd, asection *section, bfd_vma ad= dr_offset) if (! with_line_numbers && ! with_source_code) return; =20 +#ifdef HAVE_LIBDEBUGINFOD + { + bfd *debug_bfd; + const char *alt_filename =3D NULL; + + if (use_debuginfod) + { + bfd *alt_bfd; + + /* PR 29075: Check for separate debuginfo and .gnu_debugaltlink files. + They need to be passed to bfd_find_nearest_line_with_alt in case they + were downloaded from debuginfod. Otherwise libbfd will attempt to + search for them and fail to locate them. */ + debug_bfd =3D find_separate_debug (abfd); + if (debug_bfd =3D=3D NULL) + debug_bfd =3D abfd; + + alt_bfd =3D find_alt_debug (debug_bfd); + if (alt_bfd !=3D NULL) + alt_filename =3D bfd_get_filename (alt_bfd); + } + else + debug_bfd =3D abfd; + + bfd_set_error (bfd_error_no_error); + if (! bfd_find_nearest_line_with_alt (debug_bfd, alt_filename, + section, syms, + addr_offset, &filename, + &functionname, &linenumber, + &discriminator)) + { + if (bfd_get_error () =3D=3D bfd_error_no_error) + return; + if (! bfd_find_nearest_line_discriminator (abfd, section, syms, + addr_offset, &filename, + &functionname, &linenumber, + &discriminator)) + return; + } + } +#else if (! bfd_find_nearest_line_discriminator (abfd, section, syms, addr_off= set, &filename, &functionname, &linenumber, &discriminator)) return; +#endif =20 if (filename !=3D NULL && *filename =3D=3D '\0') filename =3D NULL; @@ -4136,33 +4333,6 @@ open_debug_file (const char * pathname) return data; } =20 -#if HAVE_LIBDEBUGINFOD -/* Return a hex string represention of the build-id. */ - -unsigned char * -get_build_id (void * data) -{ - unsigned i; - char * build_id_str; - bfd * abfd =3D (bfd *) data; - const struct bfd_build_id * build_id; - - build_id =3D abfd->build_id; - if (build_id =3D=3D NULL) - return NULL; - - build_id_str =3D malloc (build_id->size * 2 + 1); - if (build_id_str =3D=3D NULL) - return NULL; - - for (i =3D 0; i < build_id->size; i++) - sprintf (build_id_str + (i * 2), "%02x", build_id->data[i]); - build_id_str[build_id->size * 2] =3D '\0'; - - return (unsigned char *)build_id_str; -} -#endif /* HAVE_LIBDEBUGINFOD */ - static void dump_dwarf_section (bfd *abfd, asection *section, void *arg)