mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-01-24 12:35:55 +08:00
Add debuginfod support for objdump -S
Currently objdump -S is not able to make use files downloaded from debuginfod. This is due to bfd_find_nearest_line_discriminator being unable to locate any separate debuginfo files in the debuginfod cache. Additionally objdump lacked a call to debuginfod_find_source in order to download missing source files. 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. Co-authored-by: Nick Clifton <nickc@redhat.com>
This commit is contained in:
parent
6e7a29c7de
commit
d647c797b7
@ -1,3 +1,16 @@
|
||||
2022-09-02 Aaron Merey <amerey@redhat.com>
|
||||
|
||||
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 <nickc@redhat.com>
|
||||
|
||||
PR 29534
|
||||
|
@ -72,6 +72,10 @@
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBDEBUGINFOD
|
||||
#include <elfutils/debuginfod.h>
|
||||
#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;
|
||||
|
||||
#define SHOW_PRECEDING_CONTEXT_LINES (5)
|
||||
|
||||
/* 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 = (bfd *) data;
|
||||
const struct bfd_build_id * build_id;
|
||||
|
||||
build_id = abfd->build_id;
|
||||
if (build_id == NULL)
|
||||
return NULL;
|
||||
|
||||
build_id_str = malloc (build_id->size * 2 + 1);
|
||||
if (build_id_str == NULL)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < build_id->size; i++)
|
||||
sprintf (build_id_str + (i * 2), "%02x", build_id->data[i]);
|
||||
build_id_str[build_id->size * 2] = '\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 = abfd->build_id;
|
||||
separate_info * i = first_separate_info;
|
||||
|
||||
if (build_id == NULL || i == NULL)
|
||||
return NULL;
|
||||
|
||||
while (i != NULL)
|
||||
{
|
||||
const bfd * i_bfd = (bfd *) i->handle;
|
||||
|
||||
if (abfd != NULL && i_bfd->build_id != NULL)
|
||||
{
|
||||
const unsigned char * data = i_bfd->build_id->data;
|
||||
size_t size = i_bfd->build_id->size;
|
||||
|
||||
if (size == build_id->size
|
||||
&& memcmp (data, build_id->data, size) == 0)
|
||||
return (bfd *) i->handle;
|
||||
}
|
||||
|
||||
i = 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 = abfd->build_id;
|
||||
separate_info * i = first_separate_info;
|
||||
|
||||
if (i == NULL
|
||||
|| build_id == NULL
|
||||
|| !load_debug_section (gnu_debugaltlink, (void *) abfd))
|
||||
return NULL;
|
||||
|
||||
section = &debug_displays[gnu_debugaltlink].section;
|
||||
if (section == NULL)
|
||||
return NULL;
|
||||
|
||||
name = (const char *) section->start;
|
||||
namelen = strnlen (name, section->size) + 1;
|
||||
if (namelen == 1)
|
||||
return NULL;
|
||||
if (namelen >= section->size)
|
||||
return NULL;
|
||||
|
||||
id_len = 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 != NULL)
|
||||
{
|
||||
const bfd * i_bfd = (bfd *) i->handle;
|
||||
|
||||
if (i_bfd != NULL && i_bfd->build_id != NULL)
|
||||
{
|
||||
const unsigned char * data = i_bfd->build_id->data;
|
||||
size_t size = i_bfd->build_id->size;
|
||||
|
||||
if (id_len == size
|
||||
&& memcmp (section->start + namelen, data, size) == 0)
|
||||
return (bfd *) i->handle;
|
||||
}
|
||||
|
||||
i = i->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* HAVE_LIBDEBUGINFOD */
|
||||
|
||||
/* Reads the contents of file FN into memory. Returns a pointer to the buffer.
|
||||
Also returns the size of the buffer in SIZE_RETURN and a filled out
|
||||
stat structure in FST_RETURN. Returns NULL upon failure. */
|
||||
|
||||
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 = getpagesize ();
|
||||
int ps;
|
||||
size_t msize;
|
||||
#endif
|
||||
const char *map;
|
||||
int fd = open (fn, O_RDONLY | O_BINARY);
|
||||
int fd;
|
||||
|
||||
/* Paranoia. */
|
||||
if (fn == NULL || * fn == 0 || size_return == NULL || fst_return == NULL)
|
||||
return NULL;
|
||||
|
||||
fd = open (fn, O_RDONLY | O_BINARY);
|
||||
|
||||
#if HAVE_LIBDEBUGINFOD
|
||||
if (fd < 0 && use_debuginfod && fn[0] == '/' && abfd != NULL)
|
||||
{
|
||||
unsigned char * build_id;
|
||||
debuginfod_client * client;
|
||||
|
||||
client = debuginfod_begin ();
|
||||
if (client == NULL)
|
||||
return NULL;
|
||||
|
||||
build_id = get_build_id (abfd);
|
||||
fd = debuginfod_find_source (client, build_id, 0, fn, NULL);
|
||||
free (build_id);
|
||||
debuginfod_end (client);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (fd < 0)
|
||||
return NULL;
|
||||
if (fstat (fd, fst) < 0)
|
||||
|
||||
if (fstat (fd, fst_return) < 0)
|
||||
{
|
||||
close (fd);
|
||||
return NULL;
|
||||
}
|
||||
*size = fst->st_size;
|
||||
|
||||
*size_return = fst_return->st_size;
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
msize = (*size + ps - 1) & ~(ps - 1);
|
||||
ps = getpagesize ();
|
||||
msize = (*size_return + ps - 1) & ~(ps - 1);
|
||||
map = mmap (NULL, msize, PROT_READ, MAP_SHARED, fd, 0);
|
||||
if (map != (char *) -1L)
|
||||
{
|
||||
@ -1764,8 +1914,9 @@ slurp_file (const char *fn, size_t *size, struct stat *fst)
|
||||
return map;
|
||||
}
|
||||
#endif
|
||||
map = (const char *) malloc (*size);
|
||||
if (!map || (size_t) read (fd, (char *) map, *size) != *size)
|
||||
|
||||
map = (const char *) malloc (*size_return);
|
||||
if (!map || (size_t) read (fd, (char *) map, *size_return) != *size_return)
|
||||
{
|
||||
free ((void *) map);
|
||||
map = NULL;
|
||||
@ -1831,16 +1982,20 @@ index_file (const char *map, size_t size, unsigned int *maxline)
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
|
||||
static struct print_file_list *
|
||||
try_print_file_open (const char *origname, const char *modname, struct stat *fst)
|
||||
try_print_file_open (const char * origname,
|
||||
const char * modname,
|
||||
struct stat * fst_return,
|
||||
bfd * abfd)
|
||||
{
|
||||
struct print_file_list *p;
|
||||
|
||||
p = (struct print_file_list *) xmalloc (sizeof (struct print_file_list));
|
||||
|
||||
p->map = slurp_file (modname, &p->mapsize, fst);
|
||||
p->map = slurp_file (modname, &p->mapsize, fst_return, abfd);
|
||||
if (p->map == NULL)
|
||||
{
|
||||
free (p);
|
||||
@ -1870,7 +2025,7 @@ update_source_path (const char *filename, bfd *abfd)
|
||||
struct stat fst;
|
||||
int i;
|
||||
|
||||
p = try_print_file_open (filename, filename, &fst);
|
||||
p = try_print_file_open (filename, filename, &fst, abfd);
|
||||
if (p == NULL)
|
||||
{
|
||||
if (include_path_count == 0)
|
||||
@ -1886,7 +2041,7 @@ update_source_path (const char *filename, bfd *abfd)
|
||||
char *modname = concat (include_paths[i], "/", fname,
|
||||
(const char *) 0);
|
||||
|
||||
p = try_print_file_open (filename, modname, &fst);
|
||||
p = try_print_file_open (filename, modname, &fst, abfd);
|
||||
if (p)
|
||||
break;
|
||||
|
||||
@ -1956,10 +2111,52 @@ show_line (bfd *abfd, asection *section, bfd_vma addr_offset)
|
||||
if (! with_line_numbers && ! with_source_code)
|
||||
return;
|
||||
|
||||
#ifdef HAVE_LIBDEBUGINFOD
|
||||
{
|
||||
bfd *debug_bfd;
|
||||
const char *alt_filename = 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 = find_separate_debug (abfd);
|
||||
if (debug_bfd == NULL)
|
||||
debug_bfd = abfd;
|
||||
|
||||
alt_bfd = find_alt_debug (debug_bfd);
|
||||
if (alt_bfd != NULL)
|
||||
alt_filename = bfd_get_filename (alt_bfd);
|
||||
}
|
||||
else
|
||||
debug_bfd = 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 () == 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_offset,
|
||||
&filename, &functionname,
|
||||
&linenumber, &discriminator))
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (filename != NULL && *filename == '\0')
|
||||
filename = NULL;
|
||||
@ -4136,33 +4333,6 @@ open_debug_file (const char * pathname)
|
||||
return data;
|
||||
}
|
||||
|
||||
#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 = (bfd *) data;
|
||||
const struct bfd_build_id * build_id;
|
||||
|
||||
build_id = abfd->build_id;
|
||||
if (build_id == NULL)
|
||||
return NULL;
|
||||
|
||||
build_id_str = malloc (build_id->size * 2 + 1);
|
||||
if (build_id_str == NULL)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < build_id->size; i++)
|
||||
sprintf (build_id_str + (i * 2), "%02x", build_id->data[i]);
|
||||
build_id_str[build_id->size * 2] = '\0';
|
||||
|
||||
return (unsigned char *)build_id_str;
|
||||
}
|
||||
#endif /* HAVE_LIBDEBUGINFOD */
|
||||
|
||||
static void
|
||||
dump_dwarf_section (bfd *abfd, asection *section,
|
||||
void *arg)
|
||||
|
Loading…
Reference in New Issue
Block a user