]> git.pld-linux.org Git - packages/gdb.git/blob - gdb-6.6-buildid-locate.patch
- updated to 14.1 + rebased Fedora buildid patches set
[packages/gdb.git] / gdb-6.6-buildid-locate.patch
1 From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
2 From: Fedora GDB patches <invalid@email.com>
3 Date: Fri, 27 Oct 2017 21:07:50 +0200
4 Subject: gdb-6.6-buildid-locate.patch
5
6 ;; New locating of the matching binaries from the pure core file (build-id).
7 ;;=push+jan
8
9 diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h
10 --- a/bfd/libbfd-in.h
11 +++ b/bfd/libbfd-in.h
12 @@ -115,7 +115,7 @@ static inline char *
13  bfd_strdup (const char *str)
14  {
15    size_t len = strlen (str) + 1;
16 -  char *buf = bfd_malloc (len);
17 +  char *buf = (char *) bfd_malloc (len);
18    if (buf != NULL)
19      memcpy (buf, str, len);
20    return buf;
21 diff --git a/bfd/libbfd.h b/bfd/libbfd.h
22 --- a/bfd/libbfd.h
23 +++ b/bfd/libbfd.h
24 @@ -120,7 +120,7 @@ static inline char *
25  bfd_strdup (const char *str)
26  {
27    size_t len = strlen (str) + 1;
28 -  char *buf = bfd_malloc (len);
29 +  char *buf = (char *) bfd_malloc (len);
30    if (buf != NULL)
31      memcpy (buf, str, len);
32    return buf;
33 diff --git a/gdb/build-id.c b/gdb/build-id.c
34 --- a/gdb/build-id.c
35 +++ b/gdb/build-id.c
36 @@ -24,13 +24,71 @@
37  #include "gdbsupport/gdb_vecs.h"
38  #include "symfile.h"
39  #include "objfiles.h"
40 +#include <sys/stat.h>
41 +#include "elf-bfd.h"
42 +#include "elf/common.h"
43 +#include "elf/external.h"
44 +#include "elf/internal.h"
45  #include "filenames.h"
46 +#include "gdb_bfd.h"
47 +#include "gdbcmd.h"
48  #include "gdbcore.h"
49 +#include "inferior.h"
50 +#include "objfiles.h"
51 +#include "observable.h"
52 +#include "symfile.h"
53 +
54 +#define BUILD_ID_VERBOSE_NONE 0
55 +#define BUILD_ID_VERBOSE_FILENAMES 1
56 +#define BUILD_ID_VERBOSE_BINARY_PARSE 2
57 +static int build_id_verbose = BUILD_ID_VERBOSE_FILENAMES;
58 +static void
59 +show_build_id_verbose (struct ui_file *file, int from_tty,
60 +                      struct cmd_list_element *c, const char *value)
61 +{
62 +  fprintf_filtered (file, _("Verbosity level of the build-id locator is %s.\n"),
63 +                   value);
64 +}
65 +/* Locate NT_GNU_BUILD_ID and return its matching debug filename.
66 +   FIXME: NOTE decoding should be unified with the BFD core notes decoding.  */
67 +
68 +static struct bfd_build_id *
69 +build_id_buf_get (bfd *templ, gdb_byte *buf, bfd_size_type size)
70 +{
71 +  bfd_byte *p;
72 +
73 +  p = buf;
74 +  while (p < buf + size)
75 +    {
76 +      /* FIXME: bad alignment assumption.  */
77 +      Elf_External_Note *xnp = (Elf_External_Note *) p;
78 +      size_t namesz = H_GET_32 (templ, xnp->namesz);
79 +      size_t descsz = H_GET_32 (templ, xnp->descsz);
80 +      bfd_byte *descdata = (gdb_byte *) xnp->name + BFD_ALIGN (namesz, 4);
81 +
82 +      if (H_GET_32 (templ, xnp->type) == NT_GNU_BUILD_ID
83 +         && namesz == sizeof "GNU"
84 +         && memcmp (xnp->name, "GNU", sizeof "GNU") == 0)
85 +       {
86 +         size_t sz = descsz;
87 +         gdb_byte *data = (gdb_byte *) descdata;
88 +         struct bfd_build_id *retval;
89 +
90 +         retval = (struct bfd_build_id *) xmalloc (sizeof *retval - 1 + sz);
91 +         retval->size = sz;
92 +         memcpy (retval->data, data, sz);
93 +
94 +         return retval;
95 +       }
96 +      p = descdata + BFD_ALIGN (descsz, 4);
97 +    }
98 +  return NULL;
99 +}
100  
101  /* See build-id.h.  */
102  
103  const struct bfd_build_id *
104 -build_id_bfd_get (bfd *abfd)
105 +build_id_bfd_shdr_get (bfd *abfd)
106  {
107    if (!bfd_check_format (abfd, bfd_object)
108        && !bfd_check_format (abfd, bfd_core))
109 @@ -43,6 +101,348 @@ build_id_bfd_get (bfd *abfd)
110    return NULL;
111  }
112  
113 +/* Core files may have missing (corrupt) SHDR but PDHR is correct there.
114 +   bfd_elf_bfd_from_remote_memory () has too much overhead by
115 +   allocating/reading all the available ELF PT_LOADs.  */
116 +
117 +static struct bfd_build_id *
118 +build_id_phdr_get (bfd *templ, bfd_vma loadbase, unsigned e_phnum,
119 +                  Elf_Internal_Phdr *i_phdr)
120 +{
121 +  int i;
122 +  struct bfd_build_id *retval = NULL;
123 +
124 +  for (i = 0; i < e_phnum; i++)
125 +    if (i_phdr[i].p_type == PT_NOTE && i_phdr[i].p_filesz > 0)
126 +      {
127 +       Elf_Internal_Phdr *hdr = &i_phdr[i];
128 +       gdb_byte *buf;
129 +       int err;
130 +
131 +       buf = (gdb_byte *) xmalloc (hdr->p_filesz);
132 +       err = target_read_memory (loadbase + i_phdr[i].p_vaddr, buf,
133 +                                 hdr->p_filesz);
134 +       if (err == 0)
135 +         retval = build_id_buf_get (templ, buf, hdr->p_filesz);
136 +       else
137 +         retval = NULL;
138 +       xfree (buf);
139 +       if (retval != NULL)
140 +         break;
141 +      }
142 +  return retval;
143 +}
144 +
145 +/* First we validate the file by reading in the ELF header and checking
146 +   the magic number.  */
147 +
148 +static inline bfd_boolean
149 +elf_file_p (Elf64_External_Ehdr *x_ehdrp64)
150 +{
151 +  gdb_assert (sizeof (Elf64_External_Ehdr) >= sizeof (Elf32_External_Ehdr));
152 +  gdb_assert (offsetof (Elf64_External_Ehdr, e_ident)
153 +             == offsetof (Elf32_External_Ehdr, e_ident));
154 +  gdb_assert (sizeof (((Elf64_External_Ehdr *) 0)->e_ident)
155 +             == sizeof (((Elf32_External_Ehdr *) 0)->e_ident));
156 +
157 +  return ((x_ehdrp64->e_ident[EI_MAG0] == ELFMAG0)
158 +         && (x_ehdrp64->e_ident[EI_MAG1] == ELFMAG1)
159 +         && (x_ehdrp64->e_ident[EI_MAG2] == ELFMAG2)
160 +         && (x_ehdrp64->e_ident[EI_MAG3] == ELFMAG3));
161 +}
162 +
163 +/* Translate an ELF file header in external format into an ELF file header in
164 +   internal format.  */
165 +
166 +#define H_GET_WORD(bfd, ptr) (is64 ? H_GET_64 (bfd, (ptr))             \
167 +                                  : H_GET_32 (bfd, (ptr)))
168 +#define H_GET_SIGNED_WORD(bfd, ptr) (is64 ? H_GET_S64 (bfd, (ptr))     \
169 +                                         : H_GET_S32 (bfd, (ptr)))
170 +
171 +static void
172 +elf_swap_ehdr_in (bfd *abfd,
173 +                 const Elf64_External_Ehdr *src64,
174 +                 Elf_Internal_Ehdr *dst)
175 +{
176 +  int is64 = bfd_get_arch_size (abfd) == 64;
177 +#define SRC(field) (is64 ? src64->field \
178 +                        : ((const Elf32_External_Ehdr *) src64)->field)
179 +
180 +  int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma;
181 +  memcpy (dst->e_ident, SRC (e_ident), EI_NIDENT);
182 +  dst->e_type = H_GET_16 (abfd, SRC (e_type));
183 +  dst->e_machine = H_GET_16 (abfd, SRC (e_machine));
184 +  dst->e_version = H_GET_32 (abfd, SRC (e_version));
185 +  if (signed_vma)
186 +    dst->e_entry = H_GET_SIGNED_WORD (abfd, SRC (e_entry));
187 +  else
188 +    dst->e_entry = H_GET_WORD (abfd, SRC (e_entry));
189 +  dst->e_phoff = H_GET_WORD (abfd, SRC (e_phoff));
190 +  dst->e_shoff = H_GET_WORD (abfd, SRC (e_shoff));
191 +  dst->e_flags = H_GET_32 (abfd, SRC (e_flags));
192 +  dst->e_ehsize = H_GET_16 (abfd, SRC (e_ehsize));
193 +  dst->e_phentsize = H_GET_16 (abfd, SRC (e_phentsize));
194 +  dst->e_phnum = H_GET_16 (abfd, SRC (e_phnum));
195 +  dst->e_shentsize = H_GET_16 (abfd, SRC (e_shentsize));
196 +  dst->e_shnum = H_GET_16 (abfd, SRC (e_shnum));
197 +  dst->e_shstrndx = H_GET_16 (abfd, SRC (e_shstrndx));
198 +
199 +#undef SRC
200 +}
201 +
202 +/* Translate an ELF program header table entry in external format into an
203 +   ELF program header table entry in internal format.  */
204 +
205 +static void
206 +elf_swap_phdr_in (bfd *abfd,
207 +                 const Elf64_External_Phdr *src64,
208 +                 Elf_Internal_Phdr *dst)
209 +{
210 +  int is64 = bfd_get_arch_size (abfd) == 64;
211 +#define SRC(field) (is64 ? src64->field                                        \
212 +                        : ((const Elf32_External_Phdr *) src64)->field)
213 +
214 +  int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma;
215 +
216 +  dst->p_type = H_GET_32 (abfd, SRC (p_type));
217 +  dst->p_flags = H_GET_32 (abfd, SRC (p_flags));
218 +  dst->p_offset = H_GET_WORD (abfd, SRC (p_offset));
219 +  if (signed_vma)
220 +    {
221 +      dst->p_vaddr = H_GET_SIGNED_WORD (abfd, SRC (p_vaddr));
222 +      dst->p_paddr = H_GET_SIGNED_WORD (abfd, SRC (p_paddr));
223 +    }
224 +  else
225 +    {
226 +      dst->p_vaddr = H_GET_WORD (abfd, SRC (p_vaddr));
227 +      dst->p_paddr = H_GET_WORD (abfd, SRC (p_paddr));
228 +    }
229 +  dst->p_filesz = H_GET_WORD (abfd, SRC (p_filesz));
230 +  dst->p_memsz = H_GET_WORD (abfd, SRC (p_memsz));
231 +  dst->p_align = H_GET_WORD (abfd, SRC (p_align));
232 +
233 +#undef SRC
234 +}
235 +
236 +#undef H_GET_SIGNED_WORD
237 +#undef H_GET_WORD
238 +
239 +static Elf_Internal_Phdr *
240 +elf_get_phdr (bfd *templ, bfd_vma ehdr_vma, unsigned *e_phnum_pointer,
241 +              bfd_vma *loadbase_pointer)
242 +{
243 +  /* sizeof (Elf64_External_Ehdr) >= sizeof (Elf32_External_Ehdr)  */
244 +  Elf64_External_Ehdr x_ehdr64;        /* Elf file header, external form */
245 +  Elf_Internal_Ehdr i_ehdr;    /* Elf file header, internal form */
246 +  bfd_size_type x_phdrs_size;
247 +  gdb_byte *x_phdrs_ptr;
248 +  Elf_Internal_Phdr *i_phdrs;
249 +  int err;
250 +  unsigned int i;
251 +  bfd_vma loadbase;
252 +  int loadbase_set;
253 +
254 +  gdb_assert (templ != NULL);
255 +  gdb_assert (sizeof (Elf64_External_Ehdr) >= sizeof (Elf32_External_Ehdr));
256 +
257 +  /* Read in the ELF header in external format.  */
258 +  err = target_read_memory (ehdr_vma, (bfd_byte *) &x_ehdr64, sizeof x_ehdr64);
259 +  if (err)
260 +    {
261 +      if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE)
262 +        warning (_("build-id: Error reading ELF header at address 0x%lx"),
263 +                (unsigned long) ehdr_vma);
264 +      return NULL;
265 +    }
266 +
267 +  /* Now check to see if we have a valid ELF file, and one that BFD can
268 +     make use of.  The magic number must match, the address size ('class')
269 +     and byte-swapping must match our XVEC entry.  */
270 +
271 +  if (! elf_file_p (&x_ehdr64)
272 +      || x_ehdr64.e_ident[EI_VERSION] != EV_CURRENT
273 +      || !((bfd_get_arch_size (templ) == 64
274 +            && x_ehdr64.e_ident[EI_CLASS] == ELFCLASS64)
275 +           || (bfd_get_arch_size (templ) == 32
276 +              && x_ehdr64.e_ident[EI_CLASS] == ELFCLASS32)))
277 +    {
278 +      if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE)
279 +        warning (_("build-id: Unrecognized ELF header at address 0x%lx"),
280 +                (unsigned long) ehdr_vma);
281 +      return NULL;
282 +    }
283 +
284 +  /* Check that file's byte order matches xvec's */
285 +  switch (x_ehdr64.e_ident[EI_DATA])
286 +    {
287 +    case ELFDATA2MSB:          /* Big-endian */
288 +      if (! bfd_header_big_endian (templ))
289 +       {
290 +         if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE)
291 +           warning (_("build-id: Unrecognized "
292 +                      "big-endian ELF header at address 0x%lx"),
293 +                    (unsigned long) ehdr_vma);
294 +         return NULL;
295 +       }
296 +      break;
297 +    case ELFDATA2LSB:          /* Little-endian */
298 +      if (! bfd_header_little_endian (templ))
299 +       {
300 +         if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE)
301 +           warning (_("build-id: Unrecognized "
302 +                      "little-endian ELF header at address 0x%lx"),
303 +                    (unsigned long) ehdr_vma);
304 +         return NULL;
305 +       }
306 +      break;
307 +    case ELFDATANONE:          /* No data encoding specified */
308 +    default:                   /* Unknown data encoding specified */
309 +      if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE)
310 +       warning (_("build-id: Unrecognized "
311 +                  "ELF header endianity at address 0x%lx"),
312 +                (unsigned long) ehdr_vma);
313 +      return NULL;
314 +    }
315 +
316 +  elf_swap_ehdr_in (templ, &x_ehdr64, &i_ehdr);
317 +
318 +  /* The file header tells where to find the program headers.
319 +     These are what we use to actually choose what to read.  */
320 +
321 +  if (i_ehdr.e_phentsize != (bfd_get_arch_size (templ) == 64
322 +                             ? sizeof (Elf64_External_Phdr)
323 +                            : sizeof (Elf32_External_Phdr))
324 +      || i_ehdr.e_phnum == 0)
325 +    {
326 +      if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE)
327 +       warning (_("build-id: Invalid ELF program headers from the ELF header "
328 +                  "at address 0x%lx"), (unsigned long) ehdr_vma);
329 +      return NULL;
330 +    }
331 +
332 +  x_phdrs_size = (bfd_get_arch_size (templ) == 64 ? sizeof (Elf64_External_Phdr)
333 +                                               : sizeof (Elf32_External_Phdr));
334 +
335 +  i_phdrs = (Elf_Internal_Phdr *) xmalloc (i_ehdr.e_phnum * (sizeof *i_phdrs + x_phdrs_size));
336 +  x_phdrs_ptr = (gdb_byte *) &i_phdrs[i_ehdr.e_phnum];
337 +  err = target_read_memory (ehdr_vma + i_ehdr.e_phoff, (bfd_byte *) x_phdrs_ptr,
338 +                           i_ehdr.e_phnum * x_phdrs_size);
339 +  if (err)
340 +    {
341 +      free (i_phdrs);
342 +      if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE)
343 +        warning (_("build-id: Error reading "
344 +                  "ELF program headers at address 0x%lx"),
345 +                (unsigned long) (ehdr_vma + i_ehdr.e_phoff));
346 +      return NULL;
347 +    }
348 +
349 +  loadbase = ehdr_vma;
350 +  loadbase_set = 0;
351 +  for (i = 0; i < i_ehdr.e_phnum; ++i)
352 +    {
353 +      elf_swap_phdr_in (templ, (Elf64_External_Phdr *)
354 +                              (x_phdrs_ptr + i * x_phdrs_size), &i_phdrs[i]);
355 +      /* IA-64 vDSO may have two mappings for one segment, where one mapping
356 +        is executable only, and one is read only.  We must not use the
357 +        executable one (PF_R is the first one, PF_X the second one).  */
358 +      if (i_phdrs[i].p_type == PT_LOAD && (i_phdrs[i].p_flags & PF_R))
359 +       {
360 +         /* Only the first PT_LOAD segment indicates the file bias.
361 +            Next segments may have P_VADDR arbitrarily higher.
362 +            If the first segment has P_VADDR zero any next segment must not
363 +            confuse us, the first one sets LOADBASE certainly enough.  */
364 +         if (!loadbase_set && i_phdrs[i].p_offset == 0)
365 +           {
366 +             loadbase = ehdr_vma - i_phdrs[i].p_vaddr;
367 +             loadbase_set = 1;
368 +           }
369 +       }
370 +    }
371 +
372 +  if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE)
373 +    warning (_("build-id: Found ELF header at address 0x%lx, loadbase 0x%lx"),
374 +            (unsigned long) ehdr_vma, (unsigned long) loadbase);
375 +
376 +  *e_phnum_pointer = i_ehdr.e_phnum;
377 +  *loadbase_pointer = loadbase;
378 +  return i_phdrs;
379 +}
380 +
381 +/* BUILD_ID_ADDR_GET gets ADDR located somewhere in the object.
382 +   Find the first section before ADDR containing an ELF header.
383 +   We rely on the fact the sections from multiple files do not mix.
384 +   FIXME: We should check ADDR is contained _inside_ the section with possibly
385 +   missing content (P_FILESZ < P_MEMSZ).  These omitted sections are currently
386 +   hidden by _BFD_ELF_MAKE_SECTION_FROM_PHDR.  */
387 +
388 +static CORE_ADDR build_id_addr;
389 +struct build_id_addr_sect
390 +  {
391 +    struct build_id_addr_sect *next;
392 +    asection *sect;
393 +  };
394 +static struct build_id_addr_sect *build_id_addr_sect;
395 +
396 +static void build_id_addr_candidate (bfd *abfd, asection *sect, void *obj)
397 +{
398 +  if (build_id_addr >= bfd_section_vma (sect))
399 +    {
400 +      struct build_id_addr_sect *candidate;
401 +
402 +      candidate = (struct build_id_addr_sect *) xmalloc (sizeof *candidate);
403 +      candidate->next = build_id_addr_sect;
404 +      build_id_addr_sect = candidate;
405 +      candidate->sect = sect;
406 +    }
407 +}
408 +
409 +struct bfd_build_id *
410 +build_id_addr_get (CORE_ADDR addr)
411 +{
412 +  struct build_id_addr_sect *candidate;
413 +  struct bfd_build_id *retval = NULL;
414 +  Elf_Internal_Phdr *i_phdr = NULL;
415 +  bfd_vma loadbase = 0;
416 +  unsigned e_phnum = 0;
417 +
418 +  if (core_bfd == NULL)
419 +    return NULL;
420 +
421 +  build_id_addr = addr;
422 +  gdb_assert (build_id_addr_sect == NULL);
423 +  bfd_map_over_sections (core_bfd, build_id_addr_candidate, NULL);
424 +
425 +  /* Sections are sorted in the high-to-low VMAs order.
426 +     Stop the search on the first ELF header we find.
427 +     Do not continue the search even if it does not contain NT_GNU_BUILD_ID.  */
428 +
429 +  for (candidate = build_id_addr_sect; candidate != NULL;
430 +       candidate = candidate->next)
431 +    {
432 +      i_phdr = elf_get_phdr (core_bfd,
433 +                            bfd_section_vma (candidate->sect),
434 +                            &e_phnum, &loadbase);
435 +      if (i_phdr != NULL)
436 +       break;
437 +    }
438 +
439 +  if (i_phdr != NULL)
440 +    {
441 +      retval = build_id_phdr_get (core_bfd, loadbase, e_phnum, i_phdr);
442 +      xfree (i_phdr);
443 +    }
444 +
445 +  while (build_id_addr_sect != NULL)
446 +    {
447 +      candidate = build_id_addr_sect;
448 +      build_id_addr_sect = candidate->next;
449 +      xfree (candidate);
450 +    }
451 +
452 +  return retval;
453 +}
454 +
455  /* See build-id.h.  */
456  
457  int
458 @@ -51,7 +451,7 @@ build_id_verify (bfd *abfd, size_t check_len, const bfd_byte *check)
459    const struct bfd_build_id *found;
460    int retval = 0;
461  
462 -  found = build_id_bfd_get (abfd);
463 +  found = build_id_bfd_shdr_get (abfd);
464  
465    if (found == NULL)
466      warning (_("File \"%s\" has no build-id, file skipped"),
467 @@ -66,63 +466,166 @@ build_id_verify (bfd *abfd, size_t check_len, const bfd_byte *check)
468    return retval;
469  }
470  
471 +static char *
472 +link_resolve (const char *symlink, int level)
473 +{
474 +  char buf[PATH_MAX + 1], *retval;
475 +  gdb::unique_xmalloc_ptr<char> target;
476 +  ssize_t got;
477 +
478 +  if (level > 10)
479 +    return xstrdup (symlink);
480 +
481 +  got = readlink (symlink, buf, sizeof (buf));
482 +  if (got < 0 || got >= sizeof (buf))
483 +    return xstrdup (symlink);
484 +  buf[got] = '\0';
485 +
486 +  if (IS_ABSOLUTE_PATH (buf))
487 +    target = make_unique_xstrdup (buf);
488 +  else
489 +    {
490 +      const std::string dir (ldirname (symlink));
491 +
492 +      target = xstrprintf ("%s"
493 +#ifndef HAVE_DOS_BASED_FILE_SYSTEM
494 +                          "/"
495 +#else /* HAVE_DOS_BASED_FILE_SYSTEM */
496 +                          "\\"
497 +#endif /* HAVE_DOS_BASED_FILE_SYSTEM */
498 +                          "%s", dir.c_str(), buf);
499 +    }
500 +
501 +  retval = link_resolve (target.get (), level + 1);
502 +  return retval;
503 +}
504 +
505  /* Helper for build_id_to_debug_bfd.  LINK is a path to a potential
506     build-id-based separate debug file, potentially a symlink to the real file.
507     If the file exists and matches BUILD_ID, return a BFD reference to it.  */
508  
509  static gdb_bfd_ref_ptr
510 -build_id_to_debug_bfd_1 (const std::string &link, size_t build_id_len,
511 -                        const bfd_byte *build_id)
512 +build_id_to_debug_bfd_1 (const std::string &orig_link, size_t build_id_len,
513 +                        const bfd_byte *build_id, char **link_return)
514  {
515 +  gdb_bfd_ref_ptr ret_bfd = {};
516 +  std::string ret_link;
517 +
518    if (separate_debug_file_debug)
519      {
520 -      fprintf_unfiltered (gdb_stdlog, _("  Trying %s..."), link.c_str ());
521 -      gdb_flush (gdb_stdlog);
522 +      fprintf_unfiltered (gdb_stdlog, _("  Trying %s..."), orig_link.c_str ());
523 +      gdb_flush (gdb_stdout);
524      }
525  
526 -  /* lrealpath() is expensive even for the usually non-existent files.  */
527 -  gdb::unique_xmalloc_ptr<char> filename_holder;
528 -  const char *filename = nullptr;
529 -  if (startswith (link, TARGET_SYSROOT_PREFIX))
530 -    filename = link.c_str ();
531 -  else if (access (link.c_str (), F_OK) == 0)
532 +  for (unsigned seqno = 0;; seqno++)
533      {
534 -      filename_holder.reset (lrealpath (link.c_str ()));
535 -      filename = filename_holder.get ();
536 -    }
537 +      std::string link = orig_link;
538  
539 -  if (filename == NULL)
540 -    {
541 -      if (separate_debug_file_debug)
542 -       fprintf_unfiltered (gdb_stdlog,
543 -                           _(" no, unable to compute real path\n"));
544 +      if (seqno > 0)
545 +       {
546 +         /* There can be multiple build-id symlinks pointing to real files
547 +            with the same build-id (such as hard links).  Some of the real
548 +            files may not be installed.  */
549  
550 -      return {};
551 -    }
552 +         string_appendf (link, ".%u", seqno);
553 +       }
554  
555 -  /* We expect to be silent on the non-existing files.  */
556 -  gdb_bfd_ref_ptr debug_bfd = gdb_bfd_open (filename, gnutarget);
557 +      ret_link = link;
558  
559 -  if (debug_bfd == NULL)
560 -    {
561 -      if (separate_debug_file_debug)
562 -       fprintf_unfiltered (gdb_stdlog, _(" no, unable to open.\n"));
563 +      struct stat statbuf_trash;
564 +
565 +      /* `access' automatically dereferences LINK.  */
566 +      if (lstat (link.c_str (), &statbuf_trash) != 0)
567 +       {
568 +         /* Stop increasing SEQNO.  */
569 +         break;
570 +       }
571 +
572 +      /* lrealpath() is expensive even for the usually non-existent files.  */
573 +      gdb::unique_xmalloc_ptr<char> filename_holder;
574 +      const char *filename = nullptr;
575 +      if (startswith (link, TARGET_SYSROOT_PREFIX))
576 +       filename = link.c_str ();
577 +      else if (access (link.c_str (), F_OK) == 0)
578 +       {
579 +         filename_holder.reset (lrealpath (link.c_str ()));
580 +         filename = filename_holder.get ();
581 +       }
582 +
583 +      if (filename == NULL)
584 +       {
585 +         if (separate_debug_file_debug)
586 +           fprintf_unfiltered (gdb_stdlog,
587 +                              _(" no, unable to compute real path\n"));
588 +
589 +         continue;
590 +       }
591 +
592 +      /* We expect to be silent on the non-existing files.  */
593 +      gdb_bfd_ref_ptr debug_bfd = gdb_bfd_open (filename, gnutarget);
594 +
595 +      if (debug_bfd == NULL)
596 +       {
597 +         if (separate_debug_file_debug)
598 +           fprintf_unfiltered (gdb_stdlog, _(" no, unable to open.\n"));
599  
600 -      return {};
601 +         continue;
602 +       }
603 +
604 +      if (!build_id_verify (debug_bfd.get(), build_id_len, build_id))
605 +       {
606 +         if (separate_debug_file_debug)
607 +           fprintf_unfiltered (gdb_stdlog,
608 +                               _(" no, build-id does not match.\n"));
609 +
610 +         continue;
611 +       }
612 +
613 +      ret_bfd = debug_bfd;
614 +      break;
615      }
616  
617 -  if (!build_id_verify (debug_bfd.get(), build_id_len, build_id))
618 +  std::string link_all;
619 +
620 +  if (ret_bfd != NULL)
621      {
622        if (separate_debug_file_debug)
623 -       fprintf_unfiltered (gdb_stdlog, _(" no, build-id does not match.\n"));
624 +       fprintf_unfiltered (gdb_stdlog, _(" yes!\n"));
625 +    }
626 +  else
627 +    {
628 +      /* If none of the real files is found report as missing file
629 +        always the non-.%u-suffixed file.  */
630 +      std::string link0 = orig_link;
631  
632 -      return {};
633 +      /* If the symlink has target request to install the target.
634 +        BASE-debuginfo.rpm contains the symlink but BASE.rpm may be missing.
635 +        https://bugzilla.redhat.com/show_bug.cgi?id=981154  */
636 +      std::string link0_resolved (link_resolve (link0.c_str (), 0));
637 +
638 +      if (link_all.empty ())
639 +       link_all = link0_resolved;
640 +      else
641 +       {
642 +         /* Use whitespace instead of DIRNAME_SEPARATOR to be compatible with
643 +            its possible use as an argument for installation command.  */
644 +         link_all += " " + link0_resolved;
645 +       }
646      }
647  
648 -  if (separate_debug_file_debug)
649 -    fprintf_unfiltered (gdb_stdlog, _(" yes!\n"));
650 +  if (link_return != NULL)
651 +    {
652 +      if (ret_bfd != NULL)
653 +       {
654 +         *link_return = xstrdup (ret_link.c_str ());
655 +       }
656 +      else
657 +       {
658 +         *link_return = xstrdup (link_all.c_str ());
659 +       }
660 +    }
661  
662 -  return debug_bfd;
663 +  return ret_bfd;
664  }
665  
666  /* Common code for finding BFDs of a given build-id.  This function
667 @@ -131,7 +634,7 @@ build_id_to_debug_bfd_1 (const std::string &link, size_t build_id_len,
668  
669  static gdb_bfd_ref_ptr
670  build_id_to_bfd_suffix (size_t build_id_len, const bfd_byte *build_id,
671 -                       const char *suffix)
672 +                       const char *suffix, char **link_return)
673  {
674    /* Keep backward compatibility so that DEBUG_FILE_DIRECTORY being "" will
675       cause "/.build-id/..." lookups.  */
676 @@ -154,16 +657,17 @@ build_id_to_bfd_suffix (size_t build_id_len, const bfd_byte *build_id,
677        if (size > 0)
678         {
679           size--;
680 -         string_appendf (link, "%02x/", (unsigned) *data++);
681 +         string_appendf (link, "%02x", (unsigned) *data++);
682         }
683 -
684 +      if (size > 0)
685 +       link += "/";
686        while (size-- > 0)
687         string_appendf (link, "%02x", (unsigned) *data++);
688  
689        link += suffix;
690  
691        gdb_bfd_ref_ptr debug_bfd
692 -       = build_id_to_debug_bfd_1 (link, build_id_len, build_id);
693 +       = build_id_to_debug_bfd_1 (link, build_id_len, build_id, link_return);
694        if (debug_bfd != NULL)
695         return debug_bfd;
696  
697 @@ -174,7 +678,8 @@ build_id_to_bfd_suffix (size_t build_id_len, const bfd_byte *build_id,
698        if (!gdb_sysroot.empty ())
699         {
700           link = gdb_sysroot + link;
701 -         debug_bfd = build_id_to_debug_bfd_1 (link, build_id_len, build_id);
702 +         debug_bfd = build_id_to_debug_bfd_1 (link, build_id_len, build_id,
703 +                                              link_return);
704           if (debug_bfd != NULL)
705             return debug_bfd;
706         }
707 @@ -183,30 +688,649 @@ build_id_to_bfd_suffix (size_t build_id_len, const bfd_byte *build_id,
708    return {};
709  }
710  
711 +char *
712 +build_id_to_filename (const struct bfd_build_id *build_id, char **link_return)
713 +{
714 +  gdb_bfd_ref_ptr abfd;
715 +  char *result;
716 +
717 +  abfd = build_id_to_exec_bfd (build_id->size, build_id->data, link_return);
718 +  if (abfd == NULL)
719 +    return NULL;
720 +
721 +  result = xstrdup (bfd_get_filename (abfd.get ()));
722 +  return result;
723 +}
724 +
725 +#ifdef HAVE_LIBRPM
726 +
727 +#include <rpm/rpmlib.h>
728 +#include <rpm/rpmts.h>
729 +#include <rpm/rpmdb.h>
730 +#include <rpm/header.h>
731 +#ifdef DLOPEN_LIBRPM
732 +#include <dlfcn.h>
733 +#endif
734 +
735 +/* Workarodun https://bugzilla.redhat.com/show_bug.cgi?id=643031
736 +   librpm must not exit() an application on SIGINT
737 +
738 +   Enable or disable a signal handler.  SIGNUM: signal to enable (or disable
739 +   if negative).  HANDLER: sa_sigaction handler (or NULL to use
740 +   rpmsqHandler()).  Returns: no. of refs, -1 on error.  */
741 +extern int rpmsqEnable (int signum, /* rpmsqAction_t handler */ void *handler);
742 +int
743 +rpmsqEnable (int signum, /* rpmsqAction_t handler */ void *handler)
744 +{
745 +  return 0;
746 +}
747 +
748 +/* This MISSING_RPM_HASH tracker is used to collect all the missing rpm files
749 +   and avoid their duplicities during a single inferior run.  */
750 +
751 +static struct htab *missing_rpm_hash;
752 +
753 +/* This MISSING_RPM_LIST tracker is used to collect and print as a single line
754 +   all the rpms right before the nearest GDB prompt.  It gets cleared after
755 +   each such print (it is questionable if we should clear it after the print).
756 +   */
757 +
758 +struct missing_rpm
759 +  {
760 +    struct missing_rpm *next;
761 +    char rpm[1];
762 +  };
763 +static struct missing_rpm *missing_rpm_list;
764 +static int missing_rpm_list_entries;
765 +
766 +/* Returns the count of newly added rpms.  */
767 +
768 +static int
769 +#ifndef GDB_INDEX_VERIFY_VENDOR
770 +missing_rpm_enlist (const char *filename)
771 +#else
772 +missing_rpm_enlist_1 (const char *filename, int verify_vendor)
773 +#endif
774 +{
775 +  static int rpm_init_done = 0;
776 +  rpmts ts;
777 +  rpmdbMatchIterator mi;
778 +  int count = 0;
779 +
780 +#ifdef DLOPEN_LIBRPM
781 +  /* Duplicate here the declarations to verify they match.  The same sanity
782 +     check is present also in `configure.ac'.  */
783 +  extern char * headerFormat(Header h, const char * fmt, errmsg_t * errmsg);
784 +  static char *(*headerFormat_p) (Header h, const char * fmt, errmsg_t *errmsg);
785 +  extern int rpmReadConfigFiles(const char * file, const char * target);
786 +  static int (*rpmReadConfigFiles_p) (const char * file, const char * target);
787 +  extern rpmdbMatchIterator rpmdbFreeIterator(rpmdbMatchIterator mi);
788 +  static rpmdbMatchIterator (*rpmdbFreeIterator_p) (rpmdbMatchIterator mi);
789 +  extern Header rpmdbNextIterator(rpmdbMatchIterator mi);
790 +  static Header (*rpmdbNextIterator_p) (rpmdbMatchIterator mi);
791 +  extern rpmts rpmtsCreate(void);
792 +  static rpmts (*rpmtsCreate_p) (void);
793 +  extern rpmts rpmtsFree(rpmts ts);
794 +  static rpmts (*rpmtsFree_p) (rpmts ts);
795 +  extern rpmdbMatchIterator rpmtsInitIterator(const rpmts ts, rpmTag rpmtag,
796 +                                              const void * keyp, size_t keylen);
797 +  static rpmdbMatchIterator (*rpmtsInitIterator_p) (const rpmts ts,
798 +                                                   rpmTag rpmtag,
799 +                                                   const void *keyp,
800 +                                                   size_t keylen);
801 +#else  /* !DLOPEN_LIBRPM */
802 +# define headerFormat_p headerFormat
803 +# define rpmReadConfigFiles_p rpmReadConfigFiles
804 +# define rpmdbFreeIterator_p rpmdbFreeIterator
805 +# define rpmdbNextIterator_p rpmdbNextIterator
806 +# define rpmtsCreate_p rpmtsCreate
807 +# define rpmtsFree_p rpmtsFree
808 +# define rpmtsInitIterator_p rpmtsInitIterator
809 +#endif /* !DLOPEN_LIBRPM */
810 +
811 +  gdb_assert (filename != NULL);
812 +
813 +  if (strcmp (filename, BUILD_ID_MAIN_EXECUTABLE_FILENAME) == 0)
814 +    return 0;
815 +
816 +  if (is_target_filename (filename))
817 +    return 0;
818 +
819 +  if (filename[0] != '/')
820 +    {
821 +      warning (_("Ignoring non-absolute filename: <%s>"), filename);
822 +      return 0;
823 +    }
824 +
825 +  if (!rpm_init_done)
826 +    {
827 +      static int init_tried;
828 +
829 +      /* Already failed the initialization before?  */
830 +      if (init_tried)
831 +        return 0;
832 +      init_tried = 1;
833 +
834 +#ifdef DLOPEN_LIBRPM
835 +      {
836 +       void *h;
837 +
838 +       h = dlopen (DLOPEN_LIBRPM, RTLD_LAZY);
839 +       if (!h)
840 +         {
841 +           warning (_("Unable to open \"%s\" (%s), "
842 +                     "missing debuginfos notifications will not be displayed"),
843 +                    DLOPEN_LIBRPM, dlerror ());
844 +           return 0;
845 +         }
846 +
847 +       if (!((headerFormat_p = (char *(*) (Header h, const char * fmt, errmsg_t *errmsg)) dlsym (h, "headerFormat"))
848 +             && (rpmReadConfigFiles_p = (int (*) (const char * file, const char * target)) dlsym (h, "rpmReadConfigFiles"))
849 +             && (rpmdbFreeIterator_p = (rpmdbMatchIterator (*) (rpmdbMatchIterator mi)) dlsym (h, "rpmdbFreeIterator"))
850 +             && (rpmdbNextIterator_p = (Header (*) (rpmdbMatchIterator mi)) dlsym (h, "rpmdbNextIterator"))
851 +             && (rpmtsCreate_p = (rpmts (*) (void)) dlsym (h, "rpmtsCreate"))
852 +             && (rpmtsFree_p = (rpmts (*) (rpmts ts)) dlsym (h, "rpmtsFree"))
853 +             && (rpmtsInitIterator_p = (rpmdbMatchIterator (*) (const rpmts ts, rpmTag rpmtag, const void *keyp, size_t keylen)) dlsym (h, "rpmtsInitIterator"))))
854 +         {
855 +           warning (_("Opened library \"%s\" is incompatible (%s), "
856 +                     "missing debuginfos notifications will not be displayed"),
857 +                    DLOPEN_LIBRPM, dlerror ());
858 +           if (dlclose (h))
859 +             warning (_("Error closing library \"%s\": %s\n"), DLOPEN_LIBRPM,
860 +                      dlerror ());
861 +           return 0;
862 +         }
863 +      }
864 +#endif /* DLOPEN_LIBRPM */
865 +
866 +      if (rpmReadConfigFiles_p (NULL, NULL) != 0)
867 +       {
868 +         warning (_("Error reading the rpm configuration files"));
869 +         return 0;
870 +       }
871 +
872 +      rpm_init_done = 1;
873 +    }
874 +
875 +  ts = rpmtsCreate_p ();
876 +
877 +  mi = rpmtsInitIterator_p (ts, RPMTAG_BASENAMES, filename, 0);
878 +  if (mi != NULL)
879 +    {
880 +#ifndef GDB_INDEX_VERIFY_VENDOR
881 +      for (;;)
882 +#else
883 +      if (!verify_vendor) for (;;)
884 +#endif
885 +       {
886 +         Header h;
887 +         char *debuginfo, **slot, *s, *s2;
888 +         errmsg_t err;
889 +         size_t srcrpmlen = sizeof (".src.rpm") - 1;
890 +         size_t debuginfolen = sizeof ("-debuginfo") - 1;
891 +         rpmdbMatchIterator mi_debuginfo;
892 +
893 +         h = rpmdbNextIterator_p (mi);
894 +         if (h == NULL)
895 +           break;
896 +
897 +         /* Verify the debuginfo file is not already installed.  */
898 +
899 +         debuginfo = headerFormat_p (h, "%{sourcerpm}-debuginfo.%{arch}",
900 +                                     &err);
901 +         if (!debuginfo)
902 +           {
903 +             warning (_("Error querying the rpm file `%s': %s"), filename,
904 +                      err);
905 +             continue;
906 +           }
907 +         /* s = `.src.rpm-debuginfo.%{arch}' */
908 +         s = strrchr (debuginfo, '-') - srcrpmlen;
909 +         s2 = NULL;
910 +         if (s > debuginfo && memcmp (s, ".src.rpm", srcrpmlen) == 0)
911 +           {
912 +             /* s2 = `-%{release}.src.rpm-debuginfo.%{arch}' */
913 +             s2 = (char *) memrchr (debuginfo, '-', s - debuginfo);
914 +           }
915 +         if (s2)
916 +           {
917 +             /* s2 = `-%{version}-%{release}.src.rpm-debuginfo.%{arch}' */
918 +             s2 = (char *) memrchr (debuginfo, '-', s2 - debuginfo);
919 +           }
920 +         if (!s2)
921 +           {
922 +             warning (_("Error querying the rpm file `%s': %s"), filename,
923 +                      debuginfo);
924 +             xfree (debuginfo);
925 +             continue;
926 +           }
927 +         /* s = `.src.rpm-debuginfo.%{arch}' */
928 +         /* s2 = `-%{version}-%{release}.src.rpm-debuginfo.%{arch}' */
929 +         memmove (s2 + debuginfolen, s2, s - s2);
930 +         memcpy (s2, "-debuginfo", debuginfolen);
931 +         /* s = `XXXX.%{arch}' */
932 +         /* strlen ("XXXX") == srcrpmlen + debuginfolen */
933 +         /* s2 = `-debuginfo-%{version}-%{release}XX.%{arch}' */
934 +         /* strlen ("XX") == srcrpmlen */
935 +         memmove (s + debuginfolen, s + srcrpmlen + debuginfolen,
936 +                  strlen (s + srcrpmlen + debuginfolen) + 1);
937 +         /* s = `-debuginfo-%{version}-%{release}.%{arch}' */
938 +
939 +         /* RPMDBI_PACKAGES requires keylen == sizeof (int).  */
940 +         /* RPMDBI_LABEL is an interface for NVR-based dbiFindByLabel().  */
941 +         mi_debuginfo = rpmtsInitIterator_p (ts, (rpmTag) RPMDBI_LABEL, debuginfo, 0);
942 +         xfree (debuginfo);
943 +         if (mi_debuginfo)
944 +           {
945 +             rpmdbFreeIterator_p (mi_debuginfo);
946 +             count = 0;
947 +             break;
948 +           }
949 +
950 +         /* The allocated memory gets utilized below for MISSING_RPM_HASH.  */
951 +         debuginfo = headerFormat_p (h,
952 +                                     "%{name}-%{version}-%{release}.%{arch}",
953 +                                     &err);
954 +         if (!debuginfo)
955 +           {
956 +             warning (_("Error querying the rpm file `%s': %s"), filename,
957 +                      err);
958 +             continue;
959 +           }
960 +
961 +         /* Base package name for `debuginfo-install'.  We do not use the
962 +            `yum' command directly as the line
963 +                yum --enablerepo='*debug*' install NAME-debuginfo.ARCH
964 +            would be more complicated than just:
965 +                debuginfo-install NAME-VERSION-RELEASE.ARCH
966 +            Do not supply the rpm base name (derived from .src.rpm name) as
967 +            debuginfo-install is unable to install the debuginfo package if
968 +            the base name PKG binary rpm is not installed while for example
969 +            PKG-libs would be installed (RH Bug 467901).
970 +            FUTURE: After multiple debuginfo versions simultaneously installed
971 +            get supported the support for the VERSION-RELEASE tags handling
972 +            may need an update.  */
973 +
974 +         if (missing_rpm_hash == NULL)
975 +           {
976 +             /* DEL_F is passed NULL as MISSING_RPM_LIST's HTAB_DELETE
977 +                should not deallocate the entries.  */
978 +
979 +             missing_rpm_hash = htab_create_alloc (64, htab_hash_string,
980 +                              (int (*) (const void *, const void *)) streq,
981 +                                                   NULL, xcalloc, xfree);
982 +           }
983 +         slot = (char **) htab_find_slot (missing_rpm_hash, debuginfo, INSERT);
984 +         /* XCALLOC never returns NULL.  */
985 +         gdb_assert (slot != NULL);
986 +         if (*slot == NULL)
987 +           {
988 +             struct missing_rpm *missing_rpm;
989 +
990 +             *slot = debuginfo;
991 +
992 +             missing_rpm = (struct missing_rpm *) xmalloc (sizeof (*missing_rpm) + strlen (debuginfo));
993 +             strcpy (missing_rpm->rpm, debuginfo);
994 +             missing_rpm->next = missing_rpm_list;
995 +             missing_rpm_list = missing_rpm;
996 +             missing_rpm_list_entries++;
997 +           }
998 +         else
999 +           xfree (debuginfo);
1000 +         count++;
1001 +       }
1002 +#ifdef GDB_INDEX_VERIFY_VENDOR
1003 +      else /* verify_vendor */
1004 +       {
1005 +         int vendor_pass = 0, vendor_fail = 0;
1006 +
1007 +         for (;;)
1008 +           {
1009 +             Header h;
1010 +             errmsg_t err;
1011 +             char *vendor;
1012 +
1013 +             h = rpmdbNextIterator_p (mi);
1014 +             if (h == NULL)
1015 +               break;
1016 +
1017 +             vendor = headerFormat_p (h, "%{vendor}", &err);
1018 +             if (!vendor)
1019 +               {
1020 +                 warning (_("Error querying the rpm file `%s': %s"), filename,
1021 +                          err);
1022 +                 continue;
1023 +               }
1024 +             if (strcmp (vendor, "Red Hat, Inc.") == 0)
1025 +               vendor_pass = 1;
1026 +             else
1027 +               vendor_fail = 1;
1028 +             xfree (vendor);
1029 +           }
1030 +         count = vendor_pass != 0 && vendor_fail == 0;
1031 +       }
1032 +#endif
1033 +
1034 +      rpmdbFreeIterator_p (mi);
1035 +    }
1036 +
1037 +  rpmtsFree_p (ts);
1038 +
1039 +  return count;
1040 +}
1041 +
1042 +#ifdef GDB_INDEX_VERIFY_VENDOR
1043 +missing_rpm_enlist (const char *filename)
1044 +{
1045 +  return missing_rpm_enlist_1 (filename, 0);
1046 +}
1047 +
1048 +extern int rpm_verify_vendor (const char *filename);
1049 +int
1050 +rpm_verify_vendor (const char *filename)
1051 +{
1052 +  return missing_rpm_enlist_1 (filename, 1);
1053 +}
1054 +#endif
1055 +
1056 +static bool
1057 +missing_rpm_list_compar (const char *ap, const char *bp)
1058 +{
1059 +  return strcoll (ap, bp) < 0;
1060 +}
1061 +
1062 +/* It returns a NULL-terminated array of strings needing to be FREEd.  It may
1063 +   also return only NULL.  */
1064 +
1065 +static void
1066 +missing_rpm_list_print (void)
1067 +{
1068 +  struct missing_rpm *list_iter;
1069 +
1070 +  if (missing_rpm_list_entries == 0)
1071 +    return;
1072 +
1073 +  std::vector<const char *> array (missing_rpm_list_entries);
1074 +  size_t idx = 0;
1075 +
1076 +  for (list_iter = missing_rpm_list; list_iter != NULL;
1077 +       list_iter = list_iter->next)
1078 +    {
1079 +      array[idx++] = list_iter->rpm;
1080 +    }
1081 +  gdb_assert (idx == missing_rpm_list_entries);
1082 +
1083 +  std::sort (array.begin (), array.end (), missing_rpm_list_compar);
1084 +
1085 +  /* We zero out the number of missing RPMs here because of a nasty
1086 +     bug (see RHBZ 1801974).
1087 +
1088 +     When we call 'puts_unfiltered' below, if pagination is on and if
1089 +     the number of missing RPMs is big enough to trigger pagination,
1090 +     we will end up in an infinite recursion.  The call chain looks
1091 +     like this:
1092 +
1093 +     missing_rpm_list_print -> puts_unfiltered -> fputs_maybe_filtered
1094 +     -> prompt_for_continue -> display_gdb_prompt ->
1095 +     debug_flush_missing -> missing_rpm_list_print ...
1096 +
1097 +     For this reason, we make sure MISSING_RPM_LIST_ENTRIES is zero
1098 +     *before* calling any print function.  */
1099 +  missing_rpm_list_entries = 0;
1100 +
1101 +  printf_unfiltered (_("Missing separate debuginfos, use: %s"),
1102 +#ifdef DNF_DEBUGINFO_INSTALL
1103 +                    "dnf "
1104 +#endif
1105 +                    "debuginfo-install");
1106 +  for (const char *el : array)
1107 +    {
1108 +      puts_unfiltered (" ");
1109 +      puts_unfiltered (el);
1110 +    }
1111 +  puts_unfiltered ("\n");
1112 +
1113 +  while (missing_rpm_list != NULL)
1114 +    {
1115 +      list_iter = missing_rpm_list;
1116 +      missing_rpm_list = list_iter->next;
1117 +      xfree (list_iter);
1118 +    }
1119 +}
1120 +
1121 +static void
1122 +missing_rpm_change (void)
1123 +{
1124 +  debug_flush_missing ();
1125 +
1126 +  gdb_assert (missing_rpm_list == NULL);
1127 +  if (missing_rpm_hash != NULL)
1128 +    {
1129 +      htab_delete (missing_rpm_hash);
1130 +      missing_rpm_hash = NULL;
1131 +    }
1132 +}
1133 +
1134 +enum missing_exec
1135 +  {
1136 +    /* Init state.  EXEC_BFD also still could be NULL.  */
1137 +    MISSING_EXEC_NOT_TRIED,
1138 +    /* We saw a non-NULL EXEC_BFD but RPM has no info about it.  */
1139 +    MISSING_EXEC_NOT_FOUND,
1140 +    /* We found EXEC_BFD by RPM and we either have its symbols (either embedded
1141 +       or separate) or the main executable's RPM is now contained in
1142 +       MISSING_RPM_HASH.  */
1143 +    MISSING_EXEC_ENLISTED
1144 +  };
1145 +static enum missing_exec missing_exec = MISSING_EXEC_NOT_TRIED;
1146 +
1147 +#endif /* HAVE_LIBRPM */
1148 +
1149 +void
1150 +debug_flush_missing (void)
1151 +{
1152 +#ifdef HAVE_LIBRPM
1153 +  missing_rpm_list_print ();
1154 +#endif
1155 +}
1156 +
1157 +/* This MISSING_FILEPAIR_HASH tracker is used only for the duplicite messages
1158 +     yum --enablerepo='*debug*' install ...
1159 +   avoidance.  */
1160 +
1161 +struct missing_filepair
1162 +  {
1163 +    char *binary;
1164 +    char *debug;
1165 +    char data[1];
1166 +  };
1167 +
1168 +static struct htab *missing_filepair_hash;
1169 +static struct obstack missing_filepair_obstack;
1170 +
1171 +static void *
1172 +missing_filepair_xcalloc (size_t nmemb, size_t nmemb_size)
1173 +{
1174 +  void *retval;
1175 +  size_t size = nmemb * nmemb_size;
1176 +
1177 +  retval = obstack_alloc (&missing_filepair_obstack, size);
1178 +  memset (retval, 0, size);
1179 +  return retval;
1180 +}
1181 +
1182 +static hashval_t
1183 +missing_filepair_hash_func (const struct missing_filepair *elem)
1184 +{
1185 +  hashval_t retval = 0;
1186 +
1187 +  retval ^= htab_hash_string (elem->binary);
1188 +  if (elem->debug != NULL)
1189 +    retval ^= htab_hash_string (elem->debug);
1190 +
1191 +  return retval;
1192 +}
1193 +
1194 +static int
1195 +missing_filepair_eq (const struct missing_filepair *elem1,
1196 +                      const struct missing_filepair *elem2)
1197 +{
1198 +  return strcmp (elem1->binary, elem2->binary) == 0
1199 +         && ((elem1->debug == NULL) == (elem2->debug == NULL))
1200 +         && (elem1->debug == NULL || strcmp (elem1->debug, elem2->debug) == 0);
1201 +}
1202 +
1203 +static void
1204 +missing_filepair_change (void)
1205 +{
1206 +  if (missing_filepair_hash != NULL)
1207 +    {
1208 +      obstack_free (&missing_filepair_obstack, NULL);
1209 +      /* All their memory came just from missing_filepair_OBSTACK.  */
1210 +      missing_filepair_hash = NULL;
1211 +    }
1212 +#ifdef HAVE_LIBRPM
1213 +  missing_exec = MISSING_EXEC_NOT_TRIED;
1214 +#endif
1215 +}
1216 +
1217 +static void
1218 +debug_print_executable_changed (void)
1219 +{
1220 +#ifdef HAVE_LIBRPM
1221 +  missing_rpm_change ();
1222 +#endif
1223 +  missing_filepair_change ();
1224 +}
1225 +
1226 +/* Notify user the file BINARY with (possibly NULL) associated separate debug
1227 +   information file DEBUG is missing.  DEBUG may or may not be the build-id
1228 +   file such as would be:
1229 +     /usr/lib/debug/.build-id/dd/b1d2ce632721c47bb9e8679f369e2295ce71be.debug
1230 +   */
1231 +
1232 +void
1233 +debug_print_missing (const char *binary, const char *debug)
1234 +{
1235 +  size_t binary_len0 = strlen (binary) + 1;
1236 +  size_t debug_len0 = debug ? strlen (debug) + 1 : 0;
1237 +  struct missing_filepair missing_filepair_find;
1238 +  struct missing_filepair *missing_filepair;
1239 +  struct missing_filepair **slot;
1240 +
1241 +  if (build_id_verbose < BUILD_ID_VERBOSE_FILENAMES)
1242 +    return;
1243 +
1244 +  if (missing_filepair_hash == NULL)
1245 +    {
1246 +      obstack_init (&missing_filepair_obstack);
1247 +      missing_filepair_hash = htab_create_alloc (64,
1248 +       (hashval_t (*) (const void *)) missing_filepair_hash_func,
1249 +       (int (*) (const void *, const void *)) missing_filepair_eq, NULL,
1250 +       missing_filepair_xcalloc, NULL);
1251 +    }
1252 +
1253 +  /* Use MISSING_FILEPAIR_FIND first instead of calling obstack_alloc with
1254 +     obstack_free in the case of a (rare) match.  The problem is ALLOC_F for
1255 +     MISSING_FILEPAIR_HASH allocates from MISSING_FILEPAIR_OBSTACK maintenance
1256 +     structures for MISSING_FILEPAIR_HASH.  Calling obstack_free would possibly
1257 +     not to free only MISSING_FILEPAIR but also some such structures (allocated
1258 +     during the htab_find_slot call).  */
1259 +
1260 +  missing_filepair_find.binary = (char *) binary;
1261 +  missing_filepair_find.debug = (char *) debug;
1262 +  slot = (struct missing_filepair **) htab_find_slot (missing_filepair_hash,
1263 +                                                     &missing_filepair_find,
1264 +                                                     INSERT);
1265 +
1266 +  /* While it may be still printed duplicitely with the missing debuginfo file
1267 +   * it is due to once printing about the binary file build-id link and once
1268 +   * about the .debug file build-id link as both the build-id symlinks are
1269 +   * located in the debuginfo package.  */
1270 +
1271 +  if (*slot != NULL)
1272 +    return;
1273 +
1274 +  missing_filepair = (struct missing_filepair *) obstack_alloc (&missing_filepair_obstack,
1275 +                                                               sizeof (*missing_filepair) - 1
1276 +                                                               + binary_len0 + debug_len0);
1277 +  missing_filepair->binary = missing_filepair->data;
1278 +  memcpy (missing_filepair->binary, binary, binary_len0);
1279 +  if (debug != NULL)
1280 +    {
1281 +      missing_filepair->debug = missing_filepair->binary + binary_len0;
1282 +      memcpy (missing_filepair->debug, debug, debug_len0);
1283 +    }
1284 +  else
1285 +    missing_filepair->debug = NULL;
1286 +
1287 +  *slot = missing_filepair;
1288 +
1289 +#ifdef HAVE_LIBRPM
1290 +  if (missing_exec == MISSING_EXEC_NOT_TRIED)
1291 +    {
1292 +      const char *execfilename = get_exec_file (0);
1293 +
1294 +      if (execfilename != NULL)
1295 +       {
1296 +         if (missing_rpm_enlist (execfilename) == 0)
1297 +           missing_exec = MISSING_EXEC_NOT_FOUND;
1298 +         else
1299 +           missing_exec = MISSING_EXEC_ENLISTED;
1300 +       }
1301 +    }
1302 +  if (missing_exec != MISSING_EXEC_ENLISTED)
1303 +    if ((binary[0] == 0 || missing_rpm_enlist (binary) == 0)
1304 +       && (debug == NULL || missing_rpm_enlist (debug) == 0))
1305 +#endif /* HAVE_LIBRPM */
1306 +      {
1307 +       /* We do not collect and flush these messages as each such message
1308 +          already requires its own separate lines.  */
1309 +
1310 +       fprintf_unfiltered (gdb_stdlog,
1311 +                           _("Missing separate debuginfo for %s\n"), binary);
1312 +        if (debug != NULL)
1313 +         fprintf_unfiltered (gdb_stdlog, _("Try: %s %s\n"),
1314 +#ifdef DNF_DEBUGINFO_INSTALL
1315 +                             "dnf"
1316 +#else
1317 +                             "yum"
1318 +#endif
1319 +                             " --enablerepo='*debug*' install", debug);
1320 +      }
1321 +}
1322 +
1323  /* See build-id.h.  */
1324  
1325  gdb_bfd_ref_ptr
1326 -build_id_to_debug_bfd (size_t build_id_len, const bfd_byte *build_id)
1327 +build_id_to_debug_bfd (size_t build_id_len, const bfd_byte *build_id,
1328 +                      char **link_return)
1329  {
1330 -  return build_id_to_bfd_suffix (build_id_len, build_id, ".debug");
1331 +  return build_id_to_bfd_suffix (build_id_len, build_id, ".debug",
1332 +                                link_return);
1333  }
1334  
1335  /* See build-id.h.  */
1336  
1337  gdb_bfd_ref_ptr
1338 -build_id_to_exec_bfd (size_t build_id_len, const bfd_byte *build_id)
1339 +build_id_to_exec_bfd (size_t build_id_len, const bfd_byte *build_id,
1340 +                     char **link_return)
1341  {
1342 -  return build_id_to_bfd_suffix (build_id_len, build_id, "");
1343 +  return build_id_to_bfd_suffix (build_id_len, build_id, "", link_return);
1344  }
1345  
1346  /* See build-id.h.  */
1347  
1348  std::string
1349 -find_separate_debug_file_by_buildid (struct objfile *objfile)
1350 +find_separate_debug_file_by_buildid (struct objfile *objfile,
1351 +                       gdb::unique_xmalloc_ptr<char> *build_id_filename_return)
1352  {
1353    const struct bfd_build_id *build_id;
1354  
1355 -  build_id = build_id_bfd_get (objfile->obfd);
1356 +  if (build_id_filename_return)
1357 +    *build_id_filename_return = NULL;
1358 +
1359 +  build_id = build_id_bfd_shdr_get (objfile->obfd);
1360    if (build_id != NULL)
1361      {
1362        if (separate_debug_file_debug)
1363 @@ -214,8 +1338,21 @@ find_separate_debug_file_by_buildid (struct objfile *objfile)
1364                             _("\nLooking for separate debug info (build-id) for "
1365                               "%s\n"), objfile_name (objfile));
1366  
1367 +      char *build_id_filename_cstr = NULL;
1368        gdb_bfd_ref_ptr abfd (build_id_to_debug_bfd (build_id->size,
1369 -                                                  build_id->data));
1370 +                                                  build_id->data,
1371 +             (!build_id_filename_return ? NULL : &build_id_filename_cstr)));
1372 +      if (build_id_filename_return)
1373 +       {
1374 +         if (!build_id_filename_cstr)
1375 +           gdb_assert (!*build_id_filename_return);
1376 +         else
1377 +           {
1378 +             *build_id_filename_return = gdb::unique_xmalloc_ptr<char> (build_id_filename_cstr);
1379 +             build_id_filename_cstr = NULL;
1380 +           }
1381 +       }
1382 +
1383        /* Prevent looping on a stripped .debug file.  */
1384        if (abfd != NULL
1385           && filename_cmp (bfd_get_filename (abfd.get ()),
1386 @@ -228,3 +1365,22 @@ find_separate_debug_file_by_buildid (struct objfile *objfile)
1387  
1388    return std::string ();
1389  }
1390 +
1391 +void _initialize_build_id ();
1392 +
1393 +void
1394 +_initialize_build_id ()
1395 +{
1396 +  add_setshow_zinteger_cmd ("build-id-verbose", no_class, &build_id_verbose,
1397 +                           _("\
1398 +Set debugging level of the build-id locator."), _("\
1399 +Show debugging level of the build-id locator."), _("\
1400 +Level 1 (default) enables printing the missing debug filenames,\n\
1401 +level 2 also prints the parsing of binaries to find the identificators."),
1402 +                           NULL,
1403 +                           show_build_id_verbose,
1404 +                           &setlist, &showlist);
1405 +
1406 +  gdb::observers::executable_changed.attach (debug_print_executable_changed,
1407 +                                             "build-id");
1408 +}
1409 diff --git a/gdb/build-id.h b/gdb/build-id.h
1410 --- a/gdb/build-id.h
1411 +++ b/gdb/build-id.h
1412 @@ -23,9 +23,10 @@
1413  #include "gdb_bfd.h"
1414  #include "gdbsupport/rsp-low.h"
1415  
1416 -/* Locate NT_GNU_BUILD_ID from ABFD and return its content.  */
1417 +/* Separate debuginfo files have corrupted PHDR but SHDR is correct there.
1418 +   Locate NT_GNU_BUILD_ID from ABFD and return its content.  */
1419  
1420 -extern const struct bfd_build_id *build_id_bfd_get (bfd *abfd);
1421 +extern const struct bfd_build_id *build_id_bfd_shdr_get (bfd *abfd);
1422  
1423  /* Return true if ABFD has NT_GNU_BUILD_ID matching the CHECK value.
1424     Otherwise, issue a warning and return false.  */
1425 @@ -38,21 +39,26 @@ extern int build_id_verify (bfd *abfd,
1426     can be found, return NULL.  */
1427  
1428  extern gdb_bfd_ref_ptr build_id_to_debug_bfd (size_t build_id_len,
1429 -                                             const bfd_byte *build_id);
1430 +                                             const bfd_byte *build_id,
1431 +                                             char **link_return = NULL);
1432 +
1433 +extern char *build_id_to_filename (const struct bfd_build_id *build_id,
1434 +                                  char **link_return);
1435  
1436  /* Find and open a BFD for an executable file given a build-id.  If no BFD
1437     can be found, return NULL.  The returned reference to the BFD must be
1438     released by the caller.  */
1439  
1440  extern gdb_bfd_ref_ptr build_id_to_exec_bfd (size_t build_id_len,
1441 -                                            const bfd_byte *build_id);
1442 +                                            const bfd_byte *build_id,
1443 +                                            char **link_return);
1444  
1445  /* Find the separate debug file for OBJFILE, by using the build-id
1446     associated with OBJFILE's BFD.  If successful, returns the file name for the
1447     separate debug file, otherwise, return an empty string.  */
1448  
1449 -extern std::string find_separate_debug_file_by_buildid
1450 -  (struct objfile *objfile);
1451 +extern std::string find_separate_debug_file_by_buildid (struct objfile *objfile,
1452 +                      gdb::unique_xmalloc_ptr<char> *build_id_filename_return);
1453  
1454  /* Return an hex-string representation of BUILD_ID.  */
1455  
1456 diff --git a/gdb/coffread.c b/gdb/coffread.c
1457 --- a/gdb/coffread.c
1458 +++ b/gdb/coffread.c
1459 @@ -710,7 +710,8 @@ coff_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
1460    /* Try to add separate debug file if no symbols table found.   */
1461    if (!objfile->has_partial_symbols ())
1462      {
1463 -      std::string debugfile = find_separate_debug_file_by_buildid (objfile);
1464 +      std::string debugfile = find_separate_debug_file_by_buildid (objfile,
1465 +                                                                  NULL);
1466  
1467        if (debugfile.empty ())
1468         debugfile = find_separate_debug_file_by_debuglink (objfile);
1469 diff --git a/gdb/corelow.c b/gdb/corelow.c
1470 --- a/gdb/corelow.c
1471 +++ b/gdb/corelow.c
1472 @@ -22,6 +22,10 @@
1473  #include <signal.h>
1474  #include <fcntl.h>
1475  #include "frame.h"             /* required by inferior.h */
1476 +#include "auxv.h"
1477 +#include "build-id.h"
1478 +#include "elf/common.h"
1479 +#include "gdbcmd.h"
1480  #include "inferior.h"
1481  #include "infrun.h"
1482  #include "symtab.h"
1483 @@ -356,6 +360,8 @@ add_to_thread_list (asection *asect, asection *reg_sect)
1484      switch_to_thread (thr);                    /* Yes, make it current.  */
1485  }
1486  
1487 +static bool build_id_core_loads = true;
1488 +
1489  /* Issue a message saying we have no core to debug, if FROM_TTY.  */
1490  
1491  static void
1492 @@ -392,19 +398,26 @@ core_file_command (const char *filename, int from_tty)
1493  static void
1494  locate_exec_from_corefile_build_id (bfd *abfd, int from_tty)
1495  {
1496 -  const bfd_build_id *build_id = build_id_bfd_get (abfd);
1497 +  const bfd_build_id *build_id = build_id_bfd_shdr_get (abfd);
1498    if (build_id == nullptr)
1499      return;
1500  
1501 +  char *build_id_filename;
1502    gdb_bfd_ref_ptr execbfd
1503 -    = build_id_to_exec_bfd (build_id->size, build_id->data);
1504 +    = build_id_to_exec_bfd (build_id->size, build_id->data,
1505 +                           &build_id_filename);
1506  
1507    if (execbfd != nullptr)
1508      {
1509        exec_file_attach (bfd_get_filename (execbfd.get ()), from_tty);
1510        symbol_file_add_main (bfd_get_filename (execbfd.get ()),
1511                             symfile_add_flag (from_tty ? SYMFILE_VERBOSE : 0));
1512 +      if (current_program_space->symfile_object_file != NULL)
1513 +       current_program_space->symfile_object_file->flags |=
1514 +         OBJF_BUILD_ID_CORE_LOADED;
1515      }
1516 +  else
1517 +    debug_print_missing (BUILD_ID_MAIN_EXECUTABLE_FILENAME, build_id_filename);
1518  }
1519  
1520  /* See gdbcore.h.  */
1521 @@ -1209,4 +1222,11 @@ _initialize_corelow ()
1522            maintenance_print_core_file_backed_mappings,
1523            _("Print core file's file-backed mappings."),
1524            &maintenanceprintlist);
1525 +
1526 +  add_setshow_boolean_cmd ("build-id-core-loads", class_files,
1527 +                          &build_id_core_loads, _("\
1528 +Set whether CORE-FILE loads the build-id associated files automatically."), _("\
1529 +Show whether CORE-FILE loads the build-id associated files automatically."),
1530 +                          NULL, NULL, NULL,
1531 +                          &setlist, &showlist);
1532  }
1533 diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
1534 --- a/gdb/doc/gdb.texinfo
1535 +++ b/gdb/doc/gdb.texinfo
1536 @@ -21524,6 +21524,27 @@ information files.
1537  
1538  @end table
1539  
1540 +You can also adjust the current verbosity of the @dfn{build id} locating.
1541 +
1542 +@table @code
1543 +
1544 +@kindex set build-id-verbose
1545 +@item set build-id-verbose 0
1546 +No additional messages are printed.
1547 +
1548 +@item set build-id-verbose 1
1549 +Missing separate debug filenames are printed.
1550 +
1551 +@item set build-id-verbose 2
1552 +Missing separate debug filenames are printed and also all the parsing of the
1553 +binaries to find their @dfn{build id} content is printed.
1554 +
1555 +@kindex show build-id-verbose
1556 +@item show build-id-verbose
1557 +Show the current verbosity value for the @dfn{build id} content locating.
1558 +
1559 +@end table
1560 +
1561  @cindex @code{.gnu_debuglink} sections
1562  @cindex debug link sections
1563  A debug link is a special section of the executable file named
1564 diff --git a/gdb/dwarf2/index-cache.c b/gdb/dwarf2/index-cache.c
1565 --- a/gdb/dwarf2/index-cache.c
1566 +++ b/gdb/dwarf2/index-cache.c
1567 @@ -97,7 +97,7 @@ index_cache::store (dwarf2_per_objfile *per_objfile)
1568      return;
1569  
1570    /* Get build id of objfile.  */
1571 -  const bfd_build_id *build_id = build_id_bfd_get (obj->obfd);
1572 +  const bfd_build_id *build_id = build_id_bfd_shdr_get (obj->obfd);
1573    if (build_id == nullptr)
1574      {
1575        index_cache_debug ("objfile %s has no build id",
1576 @@ -114,7 +114,8 @@ index_cache::store (dwarf2_per_objfile *per_objfile)
1577  
1578    if (dwz != nullptr)
1579      {
1580 -      const bfd_build_id *dwz_build_id = build_id_bfd_get (dwz->dwz_bfd.get ());
1581 +      const bfd_build_id *dwz_build_id
1582 +       = build_id_bfd_shdr_get (dwz->dwz_bfd.get ());
1583  
1584        if (dwz_build_id == nullptr)
1585         {
1586 diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
1587 --- a/gdb/dwarf2/read.c
1588 +++ b/gdb/dwarf2/read.c
1589 @@ -5476,7 +5476,7 @@ get_gdb_index_contents_from_section (objfile *obj, T *section_owner)
1590  static gdb::array_view<const gdb_byte>
1591  get_gdb_index_contents_from_cache (objfile *obj, dwarf2_per_bfd *dwarf2_per_bfd)
1592  {
1593 -  const bfd_build_id *build_id = build_id_bfd_get (obj->obfd);
1594 +  const bfd_build_id *build_id = build_id_bfd_shdr_get (obj->obfd);
1595    if (build_id == nullptr)
1596      return {};
1597  
1598 @@ -5489,7 +5489,7 @@ get_gdb_index_contents_from_cache (objfile *obj, dwarf2_per_bfd *dwarf2_per_bfd)
1599  static gdb::array_view<const gdb_byte>
1600  get_gdb_index_contents_from_cache_dwz (objfile *obj, dwz_file *dwz)
1601  {
1602 -  const bfd_build_id *build_id = build_id_bfd_get (dwz->dwz_bfd.get ());
1603 +  const bfd_build_id *build_id = build_id_bfd_shdr_get (dwz->dwz_bfd.get ());
1604    if (build_id == nullptr)
1605      return {};
1606  
1607 diff --git a/gdb/elfread.c b/gdb/elfread.c
1608 --- a/gdb/elfread.c
1609 +++ b/gdb/elfread.c
1610 @@ -1270,7 +1270,9 @@ elf_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
1611            && objfile->separate_debug_objfile == NULL
1612            && objfile->separate_debug_objfile_backlink == NULL)
1613      {
1614 -      std::string debugfile = find_separate_debug_file_by_buildid (objfile);
1615 +      gdb::unique_xmalloc_ptr<char> build_id_filename;
1616 +      std::string debugfile
1617 +       = find_separate_debug_file_by_buildid (objfile, &build_id_filename);
1618  
1619        if (debugfile.empty ())
1620         debugfile = find_separate_debug_file_by_debuglink (objfile);
1621 @@ -1285,7 +1287,7 @@ elf_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
1622        else
1623         {
1624           has_dwarf2 = false;
1625 -         const struct bfd_build_id *build_id = build_id_bfd_get (objfile->obfd);
1626 +         const struct bfd_build_id *build_id = build_id_bfd_shdr_get (objfile->obfd);
1627  
1628           if (build_id != nullptr)
1629             {
1630 @@ -1310,6 +1312,10 @@ elf_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
1631                       has_dwarf2 = true;
1632                     }
1633                 }
1634 +               /* Check if any separate debug info has been extracted out.  */
1635 +               else if (bfd_get_section_by_name (objfile->obfd, ".gnu_debuglink")
1636 +                        != NULL)
1637 +                 debug_print_missing (objfile_name (objfile), build_id_filename.get ());
1638             }
1639         }
1640      }
1641 diff --git a/gdb/exec.c b/gdb/exec.c
1642 --- a/gdb/exec.c
1643 +++ b/gdb/exec.c
1644 @@ -238,7 +238,7 @@ validate_exec_file (int from_tty)
1645    current_exec_file = get_exec_file (0);
1646  
1647    const bfd_build_id *exec_file_build_id
1648 -    = build_id_bfd_get (current_program_space->exec_bfd ());
1649 +    = build_id_bfd_shdr_get (current_program_space->exec_bfd ());
1650    if (exec_file_build_id != nullptr)
1651      {
1652        /* Prepend the target prefix, to force gdb_bfd_open to open the
1653 @@ -251,7 +251,7 @@ validate_exec_file (int from_tty)
1654        if (abfd != nullptr)
1655         {
1656           const bfd_build_id *target_exec_file_build_id
1657 -           = build_id_bfd_get (abfd.get ());
1658 +           = build_id_bfd_shdr_get (abfd.get ());
1659  
1660           if (target_exec_file_build_id != nullptr)
1661             {
1662 diff --git a/gdb/objfiles.h b/gdb/objfiles.h
1663 --- a/gdb/objfiles.h
1664 +++ b/gdb/objfiles.h
1665 @@ -769,6 +769,10 @@ struct objfile
1666    bool skip_jit_symbol_lookup = false;
1667  };
1668  
1669 +/* This file was loaded according to the BUILD_ID_CORE_LOADS rules.  */
1670 +
1671 +#define OBJF_BUILD_ID_CORE_LOADED static_cast<enum objfile_flag>(1 << 12)
1672 +
1673  /* A deleter for objfile.  */
1674  
1675  struct objfile_deleter
1676 diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c
1677 --- a/gdb/python/py-objfile.c
1678 +++ b/gdb/python/py-objfile.c
1679 @@ -132,7 +132,7 @@ objfpy_get_build_id (PyObject *self, void *closure)
1680  
1681    try
1682      {
1683 -      build_id = build_id_bfd_get (objfile->obfd);
1684 +      build_id = build_id_bfd_shdr_get (objfile->obfd);
1685      }
1686    catch (const gdb_exception &except)
1687      {
1688 @@ -600,7 +600,7 @@ objfpy_lookup_objfile_by_build_id (const char *build_id)
1689        /* Don't return separate debug files.  */
1690        if (objfile->separate_debug_objfile_backlink != NULL)
1691         continue;
1692 -      obfd_build_id = build_id_bfd_get (objfile->obfd);
1693 +      obfd_build_id = build_id_bfd_shdr_get (objfile->obfd);
1694        if (obfd_build_id == NULL)
1695         continue;
1696        if (objfpy_build_id_matches (obfd_build_id, build_id))
1697 diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
1698 --- a/gdb/solib-svr4.c
1699 +++ b/gdb/solib-svr4.c
1700 @@ -45,6 +45,7 @@
1701  #include "auxv.h"
1702  #include "gdb_bfd.h"
1703  #include "probe.h"
1704 +#include "build-id.h"
1705  
1706  static struct link_map_offsets *svr4_fetch_link_map_offsets (void);
1707  static int svr4_have_link_map_offsets (void);
1708 @@ -1248,9 +1249,51 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
1709           continue;
1710         }
1711  
1712 -      strncpy (newobj->so_name, buffer.get (), SO_NAME_MAX_PATH_SIZE - 1);
1713 -      newobj->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
1714 -      strcpy (newobj->so_original_name, newobj->so_name);
1715 +      {
1716 +       struct bfd_build_id *build_id;
1717 +
1718 +       strncpy (newobj->so_original_name, buffer.get (), SO_NAME_MAX_PATH_SIZE - 1);
1719 +       newobj->so_original_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
1720 +       /* May get overwritten below.  */
1721 +       strcpy (newobj->so_name, newobj->so_original_name);
1722 +
1723 +       build_id = build_id_addr_get (((lm_info_svr4 *) newobj->lm_info)->l_ld);
1724 +       if (build_id != NULL)
1725 +         {
1726 +           char *name, *build_id_filename;
1727 +
1728 +           /* Missing the build-id matching separate debug info file
1729 +              would be handled while SO_NAME gets loaded.  */
1730 +           name = build_id_to_filename (build_id, &build_id_filename);
1731 +           if (name != NULL)
1732 +             {
1733 +               strncpy (newobj->so_name, name, SO_NAME_MAX_PATH_SIZE - 1);
1734 +               newobj->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
1735 +               xfree (name);
1736 +             }
1737 +           else
1738 +             {
1739 +               debug_print_missing (newobj->so_name, build_id_filename);
1740 +
1741 +               /* In the case the main executable was found according to
1742 +                  its build-id (from a core file) prevent loading
1743 +                  a different build of a library with accidentally the
1744 +                  same SO_NAME.
1745 +
1746 +                  It suppresses bogus backtraces (and prints "??" there
1747 +                  instead) if the on-disk files no longer match the
1748 +                  running program version.  */
1749 +
1750 +               if (current_program_space->symfile_object_file != NULL
1751 +                   && (current_program_space->symfile_object_file->flags
1752 +                       & OBJF_BUILD_ID_CORE_LOADED) != 0)
1753 +                 newobj->so_name[0] = 0;
1754 +             }
1755 +
1756 +           xfree (build_id_filename);
1757 +           xfree (build_id);
1758 +         }
1759 +      }
1760  
1761        /* If this entry has no name, or its name matches the name
1762          for the main executable, don't include it in the list.  */
1763 diff --git a/gdb/source.c b/gdb/source.c
1764 --- a/gdb/source.c
1765 +++ b/gdb/source.c
1766 @@ -1199,7 +1199,7 @@ open_source_file (struct symtab *s)
1767               srcpath += s->filename;
1768             }
1769  
1770 -         const struct bfd_build_id *build_id = build_id_bfd_get (ofp->obfd);
1771 +         const struct bfd_build_id *build_id = build_id_bfd_shdr_get (ofp->obfd);
1772  
1773           /* Query debuginfod for the source file.  */
1774           if (build_id != nullptr && !srcpath.empty ())
1775 diff --git a/gdb/symfile.h b/gdb/symfile.h
1776 --- a/gdb/symfile.h
1777 +++ b/gdb/symfile.h
1778 @@ -332,12 +332,18 @@ bool expand_symtabs_matching
1779  void map_symbol_filenames (gdb::function_view<symbol_filename_ftype> fun,
1780                            bool need_fullname);
1781  
1782 +
1783  /* Target-agnostic function to load the sections of an executable into memory.
1784  
1785     ARGS should be in the form "EXECUTABLE [OFFSET]", where OFFSET is an
1786     optional offset to apply to each section.  */
1787  extern void generic_load (const char *args, int from_tty);
1788  
1789 +/* build-id support.  */
1790 +extern struct bfd_build_id *build_id_addr_get (CORE_ADDR addr);
1791 +extern void debug_print_missing (const char *binary, const char *debug);
1792 +#define BUILD_ID_MAIN_EXECUTABLE_FILENAME _("the main executable file")
1793 +
1794  /* From minidebug.c.  */
1795  
1796  extern gdb_bfd_ref_ptr find_separate_debug_file_in_section (struct objfile *);
1797 diff --git a/gdb/testsuite/gdb.base/corefile.exp b/gdb/testsuite/gdb.base/corefile.exp
1798 --- a/gdb/testsuite/gdb.base/corefile.exp
1799 +++ b/gdb/testsuite/gdb.base/corefile.exp
1800 @@ -343,3 +343,33 @@ gdb_test_multiple "core-file $corefile" $test {
1801         pass $test
1802      }
1803  }
1804 +
1805 +
1806 +# Test auto-loading of binary files through build-id from the core file.
1807 +set buildid [build_id_debug_filename_get $binfile]
1808 +set wholetest "binfile found by build-id"
1809 +if {$buildid == ""} {
1810 +    untested "$wholetest (binary has no build-id)"
1811 +} else {
1812 +    gdb_exit
1813 +    gdb_start
1814 +
1815 +    regsub {\.debug$} $buildid {} buildid
1816 +    set debugdir [standard_output_file ${testfile}-debugdir]
1817 +    file delete -force -- $debugdir
1818 +    file mkdir $debugdir/[file dirname $buildid]
1819 +    file copy $binfile $debugdir/$buildid
1820 +
1821 +    set test "show debug-file-directory"
1822 +    gdb_test_multiple $test $test {
1823 +       -re "The directory where separate debug symbols are searched for is \"(.*)\"\\.\r\n$gdb_prompt $" {
1824 +           set debugdir_orig $expect_out(1,string)
1825 +           pass $test
1826 +       }
1827 +    }
1828 +    gdb_test_no_output "set debug-file-directory $debugdir:$debugdir_orig" "set debug-file-directory"
1829 +    gdb_test "show build-id-core-loads" {Whether CORE-FILE loads the build-id associated files automatically is on\.}
1830 +    gdb_test "core-file $corefile" "\r\nProgram terminated with .*" "core-file without executable"
1831 +    gdb_test "info files" "Local exec file:\r\n\[ \t\]*`[string_to_regexp $debugdir/$buildid]', file type .*"
1832 +    pass $wholetest
1833 +}
1834 diff --git a/gdb/testsuite/gdb.base/gdbinit-history.exp b/gdb/testsuite/gdb.base/gdbinit-history.exp
1835 --- a/gdb/testsuite/gdb.base/gdbinit-history.exp
1836 +++ b/gdb/testsuite/gdb.base/gdbinit-history.exp
1837 @@ -185,7 +185,8 @@ proc test_empty_history_filename { } {
1838      global env
1839      global gdb_prompt
1840  
1841 -    set common_history [list "set height 0" "set width 0"]
1842 +    set common_history [list "set height 0" "set width 0" \
1843 +                           "set build-id-verbose 0"]
1844  
1845      set test_dir [standard_output_file history_test]
1846      remote_exec host "mkdir -p $test_dir"
1847 diff --git a/gdb/testsuite/gdb.base/new-ui-pending-input.exp b/gdb/testsuite/gdb.base/new-ui-pending-input.exp
1848 --- a/gdb/testsuite/gdb.base/new-ui-pending-input.exp
1849 +++ b/gdb/testsuite/gdb.base/new-ui-pending-input.exp
1850 @@ -62,6 +62,7 @@ proc test_command_line_new_ui_pending_input {} {
1851      set options ""
1852      append options " -iex \"set height 0\""
1853      append options " -iex \"set width 0\""
1854 +    append options " -iex \"set build-id-verbose 0\""
1855      append options " -iex \"new-ui console $extra_tty_name\""
1856      append options " -ex \"b $bpline\""
1857      append options " -ex \"run\""
1858 diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
1859 --- a/gdb/testsuite/lib/gdb.exp
1860 +++ b/gdb/testsuite/lib/gdb.exp
1861 @@ -141,7 +141,8 @@ if ![info exists INTERNAL_GDBFLAGS] {
1862                    "-nx" \
1863                    "-data-directory $BUILD_DATA_DIRECTORY" \
1864                    {-iex "set height 0"} \
1865 -                  {-iex "set width 0"}]]
1866 +                  {-iex "set width 0"} \
1867 +                  {-iex "set build-id-verbose 0"}]]
1868  }
1869  
1870  # The variable gdb_prompt is a regexp which matches the gdb prompt.
1871 @@ -2200,6 +2201,17 @@ proc default_gdb_start { } {
1872         }
1873      }
1874  
1875 +    # Turn off the missing warnings as the testsuite does not expect it.
1876 +    send_gdb "set build-id-verbose 0\n"
1877 +    gdb_expect 10 {
1878 +       -re "$gdb_prompt $" {
1879 +           verbose "Disabled the missing debug infos warnings." 2
1880 +       }
1881 +       timeout {
1882 +           warning "Could not disable the missing debug infos warnings.."
1883 +       }
1884 +    }
1885 +
1886      gdb_debug_init
1887      return 0
1888  }
1889 diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp
1890 --- a/gdb/testsuite/lib/mi-support.exp
1891 +++ b/gdb/testsuite/lib/mi-support.exp
1892 @@ -322,6 +322,16 @@ proc default_mi_gdb_start { args } {
1893             warning "Couldn't set the width to 0."
1894         }
1895      }
1896 +    # Turn off the missing warnings as the testsuite does not expect it.
1897 +    send_gdb "190-gdb-set build-id-verbose 0\n"
1898 +    gdb_expect 10 {
1899 +       -re ".*190-gdb-set build-id-verbose 0\r\n190\\\^done\r\n$mi_gdb_prompt$" {
1900 +           verbose "Disabled the missing debug infos warnings." 2
1901 +       }
1902 +       timeout {
1903 +           warning "Could not disable the missing debug infos warnings.."
1904 +       }
1905 +    }
1906  
1907      if { $separate_inferior_pty } {
1908         mi_create_inferior_pty
This page took 0.344698 seconds and 3 git commands to generate.