]> git.pld-linux.org Git - packages/gdb.git/blob - gdb-6.6-buildid-locate.patch
- up to 8.3
[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/gdb/build-id.c b/gdb/build-id.c
10 --- a/gdb/build-id.c
11 +++ b/gdb/build-id.c
12 @@ -26,11 +26,67 @@
13  #include "objfiles.h"
14  #include "filenames.h"
15  #include "gdbcore.h"
16 +#include "libbfd.h"
17 +#include "gdbcore.h"
18 +#include "gdbcmd.h"
19 +#include "observable.h"
20 +#include "elf/external.h"
21 +#include "elf/internal.h"
22 +#include "elf/common.h"
23 +#include "elf-bfd.h"
24 +#include <sys/stat.h>
25 +
26 +#define BUILD_ID_VERBOSE_NONE 0
27 +#define BUILD_ID_VERBOSE_FILENAMES 1
28 +#define BUILD_ID_VERBOSE_BINARY_PARSE 2
29 +static int build_id_verbose = BUILD_ID_VERBOSE_FILENAMES;
30 +static void
31 +show_build_id_verbose (struct ui_file *file, int from_tty,
32 +                      struct cmd_list_element *c, const char *value)
33 +{
34 +  fprintf_filtered (file, _("Verbosity level of the build-id locator is %s.\n"),
35 +                   value);
36 +}
37 +/* Locate NT_GNU_BUILD_ID and return its matching debug filename.
38 +   FIXME: NOTE decoding should be unified with the BFD core notes decoding.  */
39 +
40 +static struct bfd_build_id *
41 +build_id_buf_get (bfd *templ, gdb_byte *buf, bfd_size_type size)
42 +{
43 +  bfd_byte *p;
44 +
45 +  p = buf;
46 +  while (p < buf + size)
47 +    {
48 +      /* FIXME: bad alignment assumption.  */
49 +      Elf_External_Note *xnp = (Elf_External_Note *) p;
50 +      size_t namesz = H_GET_32 (templ, xnp->namesz);
51 +      size_t descsz = H_GET_32 (templ, xnp->descsz);
52 +      bfd_byte *descdata = (gdb_byte *) xnp->name + BFD_ALIGN (namesz, 4);
53 +
54 +      if (H_GET_32 (templ, xnp->type) == NT_GNU_BUILD_ID
55 +         && namesz == sizeof "GNU"
56 +         && memcmp (xnp->name, "GNU", sizeof "GNU") == 0)
57 +       {
58 +         size_t sz = descsz;
59 +         gdb_byte *data = (gdb_byte *) descdata;
60 +         struct bfd_build_id *retval;
61 +
62 +         retval = (struct bfd_build_id *) xmalloc (sizeof *retval - 1 + sz);
63 +         retval->size = sz;
64 +         memcpy (retval->data, data, sz);
65 +
66 +         return retval;
67 +       }
68 +      p = descdata + BFD_ALIGN (descsz, 4);
69 +    }
70 +  return NULL;
71 +}
72  
73  /* See build-id.h.  */
74  
75  const struct bfd_build_id *
76 -build_id_bfd_get (bfd *abfd)
77 +build_id_bfd_shdr_get (bfd *abfd)
78  {
79    if (!bfd_check_format (abfd, bfd_object))
80      return NULL;
81 @@ -42,6 +98,348 @@ build_id_bfd_get (bfd *abfd)
82    return NULL;
83  }
84  
85 +/* Core files may have missing (corrupt) SHDR but PDHR is correct there.
86 +   bfd_elf_bfd_from_remote_memory () has too much overhead by
87 +   allocating/reading all the available ELF PT_LOADs.  */
88 +
89 +static struct bfd_build_id *
90 +build_id_phdr_get (bfd *templ, bfd_vma loadbase, unsigned e_phnum,
91 +                  Elf_Internal_Phdr *i_phdr)
92 +{
93 +  int i;
94 +  struct bfd_build_id *retval = NULL;
95 +
96 +  for (i = 0; i < e_phnum; i++)
97 +    if (i_phdr[i].p_type == PT_NOTE && i_phdr[i].p_filesz > 0)
98 +      {
99 +       Elf_Internal_Phdr *hdr = &i_phdr[i];
100 +       gdb_byte *buf;
101 +       int err;
102 +
103 +       buf = (gdb_byte *) xmalloc (hdr->p_filesz);
104 +       err = target_read_memory (loadbase + i_phdr[i].p_vaddr, buf,
105 +                                 hdr->p_filesz);
106 +       if (err == 0)
107 +         retval = build_id_buf_get (templ, buf, hdr->p_filesz);
108 +       else
109 +         retval = NULL;
110 +       xfree (buf);
111 +       if (retval != NULL)
112 +         break;
113 +      }
114 +  return retval;
115 +}
116 +
117 +/* First we validate the file by reading in the ELF header and checking
118 +   the magic number.  */
119 +
120 +static inline bfd_boolean
121 +elf_file_p (Elf64_External_Ehdr *x_ehdrp64)
122 +{
123 +  gdb_assert (sizeof (Elf64_External_Ehdr) >= sizeof (Elf32_External_Ehdr));
124 +  gdb_assert (offsetof (Elf64_External_Ehdr, e_ident)
125 +             == offsetof (Elf32_External_Ehdr, e_ident));
126 +  gdb_assert (sizeof (((Elf64_External_Ehdr *) 0)->e_ident)
127 +             == sizeof (((Elf32_External_Ehdr *) 0)->e_ident));
128 +
129 +  return ((x_ehdrp64->e_ident[EI_MAG0] == ELFMAG0)
130 +         && (x_ehdrp64->e_ident[EI_MAG1] == ELFMAG1)
131 +         && (x_ehdrp64->e_ident[EI_MAG2] == ELFMAG2)
132 +         && (x_ehdrp64->e_ident[EI_MAG3] == ELFMAG3));
133 +}
134 +
135 +/* Translate an ELF file header in external format into an ELF file header in
136 +   internal format.  */
137 +
138 +#define H_GET_WORD(bfd, ptr) (is64 ? H_GET_64 (bfd, (ptr))             \
139 +                                  : H_GET_32 (bfd, (ptr)))
140 +#define H_GET_SIGNED_WORD(bfd, ptr) (is64 ? H_GET_S64 (bfd, (ptr))     \
141 +                                         : H_GET_S32 (bfd, (ptr)))
142 +
143 +static void
144 +elf_swap_ehdr_in (bfd *abfd,
145 +                 const Elf64_External_Ehdr *src64,
146 +                 Elf_Internal_Ehdr *dst)
147 +{
148 +  int is64 = bfd_get_arch_size (abfd) == 64;
149 +#define SRC(field) (is64 ? src64->field \
150 +                        : ((const Elf32_External_Ehdr *) src64)->field)
151 +
152 +  int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma;
153 +  memcpy (dst->e_ident, SRC (e_ident), EI_NIDENT);
154 +  dst->e_type = H_GET_16 (abfd, SRC (e_type));
155 +  dst->e_machine = H_GET_16 (abfd, SRC (e_machine));
156 +  dst->e_version = H_GET_32 (abfd, SRC (e_version));
157 +  if (signed_vma)
158 +    dst->e_entry = H_GET_SIGNED_WORD (abfd, SRC (e_entry));
159 +  else
160 +    dst->e_entry = H_GET_WORD (abfd, SRC (e_entry));
161 +  dst->e_phoff = H_GET_WORD (abfd, SRC (e_phoff));
162 +  dst->e_shoff = H_GET_WORD (abfd, SRC (e_shoff));
163 +  dst->e_flags = H_GET_32 (abfd, SRC (e_flags));
164 +  dst->e_ehsize = H_GET_16 (abfd, SRC (e_ehsize));
165 +  dst->e_phentsize = H_GET_16 (abfd, SRC (e_phentsize));
166 +  dst->e_phnum = H_GET_16 (abfd, SRC (e_phnum));
167 +  dst->e_shentsize = H_GET_16 (abfd, SRC (e_shentsize));
168 +  dst->e_shnum = H_GET_16 (abfd, SRC (e_shnum));
169 +  dst->e_shstrndx = H_GET_16 (abfd, SRC (e_shstrndx));
170 +
171 +#undef SRC
172 +}
173 +
174 +/* Translate an ELF program header table entry in external format into an
175 +   ELF program header table entry in internal format.  */
176 +
177 +static void
178 +elf_swap_phdr_in (bfd *abfd,
179 +                 const Elf64_External_Phdr *src64,
180 +                 Elf_Internal_Phdr *dst)
181 +{
182 +  int is64 = bfd_get_arch_size (abfd) == 64;
183 +#define SRC(field) (is64 ? src64->field                                        \
184 +                        : ((const Elf32_External_Phdr *) src64)->field)
185 +
186 +  int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma;
187 +
188 +  dst->p_type = H_GET_32 (abfd, SRC (p_type));
189 +  dst->p_flags = H_GET_32 (abfd, SRC (p_flags));
190 +  dst->p_offset = H_GET_WORD (abfd, SRC (p_offset));
191 +  if (signed_vma)
192 +    {
193 +      dst->p_vaddr = H_GET_SIGNED_WORD (abfd, SRC (p_vaddr));
194 +      dst->p_paddr = H_GET_SIGNED_WORD (abfd, SRC (p_paddr));
195 +    }
196 +  else
197 +    {
198 +      dst->p_vaddr = H_GET_WORD (abfd, SRC (p_vaddr));
199 +      dst->p_paddr = H_GET_WORD (abfd, SRC (p_paddr));
200 +    }
201 +  dst->p_filesz = H_GET_WORD (abfd, SRC (p_filesz));
202 +  dst->p_memsz = H_GET_WORD (abfd, SRC (p_memsz));
203 +  dst->p_align = H_GET_WORD (abfd, SRC (p_align));
204 +
205 +#undef SRC
206 +}
207 +
208 +#undef H_GET_SIGNED_WORD
209 +#undef H_GET_WORD
210 +
211 +static Elf_Internal_Phdr *
212 +elf_get_phdr (bfd *templ, bfd_vma ehdr_vma, unsigned *e_phnum_pointer,
213 +              bfd_vma *loadbase_pointer)
214 +{
215 +  /* sizeof (Elf64_External_Ehdr) >= sizeof (Elf32_External_Ehdr)  */
216 +  Elf64_External_Ehdr x_ehdr64;        /* Elf file header, external form */
217 +  Elf_Internal_Ehdr i_ehdr;    /* Elf file header, internal form */
218 +  bfd_size_type x_phdrs_size;
219 +  gdb_byte *x_phdrs_ptr;
220 +  Elf_Internal_Phdr *i_phdrs;
221 +  int err;
222 +  unsigned int i;
223 +  bfd_vma loadbase;
224 +  int loadbase_set;
225 +
226 +  gdb_assert (templ != NULL);
227 +  gdb_assert (sizeof (Elf64_External_Ehdr) >= sizeof (Elf32_External_Ehdr));
228 +
229 +  /* Read in the ELF header in external format.  */
230 +  err = target_read_memory (ehdr_vma, (bfd_byte *) &x_ehdr64, sizeof x_ehdr64);
231 +  if (err)
232 +    {
233 +      if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE)
234 +        warning (_("build-id: Error reading ELF header at address 0x%lx"),
235 +                (unsigned long) ehdr_vma);
236 +      return NULL;
237 +    }
238 +
239 +  /* Now check to see if we have a valid ELF file, and one that BFD can
240 +     make use of.  The magic number must match, the address size ('class')
241 +     and byte-swapping must match our XVEC entry.  */
242 +
243 +  if (! elf_file_p (&x_ehdr64)
244 +      || x_ehdr64.e_ident[EI_VERSION] != EV_CURRENT
245 +      || !((bfd_get_arch_size (templ) == 64
246 +            && x_ehdr64.e_ident[EI_CLASS] == ELFCLASS64)
247 +           || (bfd_get_arch_size (templ) == 32
248 +              && x_ehdr64.e_ident[EI_CLASS] == ELFCLASS32)))
249 +    {
250 +      if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE)
251 +        warning (_("build-id: Unrecognized ELF header at address 0x%lx"),
252 +                (unsigned long) ehdr_vma);
253 +      return NULL;
254 +    }
255 +
256 +  /* Check that file's byte order matches xvec's */
257 +  switch (x_ehdr64.e_ident[EI_DATA])
258 +    {
259 +    case ELFDATA2MSB:          /* Big-endian */
260 +      if (! bfd_header_big_endian (templ))
261 +       {
262 +         if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE)
263 +           warning (_("build-id: Unrecognized "
264 +                      "big-endian ELF header at address 0x%lx"),
265 +                    (unsigned long) ehdr_vma);
266 +         return NULL;
267 +       }
268 +      break;
269 +    case ELFDATA2LSB:          /* Little-endian */
270 +      if (! bfd_header_little_endian (templ))
271 +       {
272 +         if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE)
273 +           warning (_("build-id: Unrecognized "
274 +                      "little-endian ELF header at address 0x%lx"),
275 +                    (unsigned long) ehdr_vma);
276 +         return NULL;
277 +       }
278 +      break;
279 +    case ELFDATANONE:          /* No data encoding specified */
280 +    default:                   /* Unknown data encoding specified */
281 +      if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE)
282 +       warning (_("build-id: Unrecognized "
283 +                  "ELF header endianity at address 0x%lx"),
284 +                (unsigned long) ehdr_vma);
285 +      return NULL;
286 +    }
287 +
288 +  elf_swap_ehdr_in (templ, &x_ehdr64, &i_ehdr);
289 +
290 +  /* The file header tells where to find the program headers.
291 +     These are what we use to actually choose what to read.  */
292 +
293 +  if (i_ehdr.e_phentsize != (bfd_get_arch_size (templ) == 64
294 +                             ? sizeof (Elf64_External_Phdr)
295 +                            : sizeof (Elf32_External_Phdr))
296 +      || i_ehdr.e_phnum == 0)
297 +    {
298 +      if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE)
299 +       warning (_("build-id: Invalid ELF program headers from the ELF header "
300 +                  "at address 0x%lx"), (unsigned long) ehdr_vma);
301 +      return NULL;
302 +    }
303 +
304 +  x_phdrs_size = (bfd_get_arch_size (templ) == 64 ? sizeof (Elf64_External_Phdr)
305 +                                               : sizeof (Elf32_External_Phdr));
306 +
307 +  i_phdrs = (Elf_Internal_Phdr *) xmalloc (i_ehdr.e_phnum * (sizeof *i_phdrs + x_phdrs_size));
308 +  x_phdrs_ptr = (gdb_byte *) &i_phdrs[i_ehdr.e_phnum];
309 +  err = target_read_memory (ehdr_vma + i_ehdr.e_phoff, (bfd_byte *) x_phdrs_ptr,
310 +                           i_ehdr.e_phnum * x_phdrs_size);
311 +  if (err)
312 +    {
313 +      free (i_phdrs);
314 +      if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE)
315 +        warning (_("build-id: Error reading "
316 +                  "ELF program headers at address 0x%lx"),
317 +                (unsigned long) (ehdr_vma + i_ehdr.e_phoff));
318 +      return NULL;
319 +    }
320 +
321 +  loadbase = ehdr_vma;
322 +  loadbase_set = 0;
323 +  for (i = 0; i < i_ehdr.e_phnum; ++i)
324 +    {
325 +      elf_swap_phdr_in (templ, (Elf64_External_Phdr *)
326 +                              (x_phdrs_ptr + i * x_phdrs_size), &i_phdrs[i]);
327 +      /* IA-64 vDSO may have two mappings for one segment, where one mapping
328 +        is executable only, and one is read only.  We must not use the
329 +        executable one (PF_R is the first one, PF_X the second one).  */
330 +      if (i_phdrs[i].p_type == PT_LOAD && (i_phdrs[i].p_flags & PF_R))
331 +       {
332 +         /* Only the first PT_LOAD segment indicates the file bias.
333 +            Next segments may have P_VADDR arbitrarily higher.
334 +            If the first segment has P_VADDR zero any next segment must not
335 +            confuse us, the first one sets LOADBASE certainly enough.  */
336 +         if (!loadbase_set && i_phdrs[i].p_offset == 0)
337 +           {
338 +             loadbase = ehdr_vma - i_phdrs[i].p_vaddr;
339 +             loadbase_set = 1;
340 +           }
341 +       }
342 +    }
343 +
344 +  if (build_id_verbose >= BUILD_ID_VERBOSE_BINARY_PARSE)
345 +    warning (_("build-id: Found ELF header at address 0x%lx, loadbase 0x%lx"),
346 +            (unsigned long) ehdr_vma, (unsigned long) loadbase);
347 +
348 +  *e_phnum_pointer = i_ehdr.e_phnum;
349 +  *loadbase_pointer = loadbase;
350 +  return i_phdrs;
351 +}
352 +
353 +/* BUILD_ID_ADDR_GET gets ADDR located somewhere in the object.
354 +   Find the first section before ADDR containing an ELF header.
355 +   We rely on the fact the sections from multiple files do not mix.
356 +   FIXME: We should check ADDR is contained _inside_ the section with possibly
357 +   missing content (P_FILESZ < P_MEMSZ).  These omitted sections are currently
358 +   hidden by _BFD_ELF_MAKE_SECTION_FROM_PHDR.  */
359 +
360 +static CORE_ADDR build_id_addr;
361 +struct build_id_addr_sect
362 +  {
363 +    struct build_id_addr_sect *next;
364 +    asection *sect;
365 +  };
366 +static struct build_id_addr_sect *build_id_addr_sect;
367 +
368 +static void build_id_addr_candidate (bfd *abfd, asection *sect, void *obj)
369 +{
370 +  if (build_id_addr >= bfd_section_vma (abfd, sect))
371 +    {
372 +      struct build_id_addr_sect *candidate;
373 +
374 +      candidate = (struct build_id_addr_sect *) xmalloc (sizeof *candidate);
375 +      candidate->next = build_id_addr_sect;
376 +      build_id_addr_sect = candidate;
377 +      candidate->sect = sect;
378 +    }
379 +}
380 +
381 +struct bfd_build_id *
382 +build_id_addr_get (CORE_ADDR addr)
383 +{
384 +  struct build_id_addr_sect *candidate;
385 +  struct bfd_build_id *retval = NULL;
386 +  Elf_Internal_Phdr *i_phdr = NULL;
387 +  bfd_vma loadbase = 0;
388 +  unsigned e_phnum = 0;
389 +
390 +  if (core_bfd == NULL)
391 +    return NULL;
392 +
393 +  build_id_addr = addr;
394 +  gdb_assert (build_id_addr_sect == NULL);
395 +  bfd_map_over_sections (core_bfd, build_id_addr_candidate, NULL);
396 +
397 +  /* Sections are sorted in the high-to-low VMAs order.
398 +     Stop the search on the first ELF header we find.
399 +     Do not continue the search even if it does not contain NT_GNU_BUILD_ID.  */
400 +
401 +  for (candidate = build_id_addr_sect; candidate != NULL;
402 +       candidate = candidate->next)
403 +    {
404 +      i_phdr = elf_get_phdr (core_bfd,
405 +                            bfd_section_vma (core_bfd, candidate->sect),
406 +                            &e_phnum, &loadbase);
407 +      if (i_phdr != NULL)
408 +       break;
409 +    }
410 +
411 +  if (i_phdr != NULL)
412 +    {
413 +      retval = build_id_phdr_get (core_bfd, loadbase, e_phnum, i_phdr);
414 +      xfree (i_phdr);
415 +    }
416 +
417 +  while (build_id_addr_sect != NULL)
418 +    {
419 +      candidate = build_id_addr_sect;
420 +      build_id_addr_sect = candidate->next;
421 +      xfree (candidate);
422 +    }
423 +
424 +  return retval;
425 +}
426 +
427  /* See build-id.h.  */
428  
429  int
430 @@ -50,7 +448,7 @@ build_id_verify (bfd *abfd, size_t check_len, const bfd_byte *check)
431    const struct bfd_build_id *found;
432    int retval = 0;
433  
434 -  found = build_id_bfd_get (abfd);
435 +  found = build_id_bfd_shdr_get (abfd);
436  
437    if (found == NULL)
438      warning (_("File \"%s\" has no build-id, file skipped"),
439 @@ -65,62 +463,173 @@ build_id_verify (bfd *abfd, size_t check_len, const bfd_byte *check)
440    return retval;
441  }
442  
443 +static char *
444 +link_resolve (const char *symlink, int level)
445 +{
446 +  char buf[PATH_MAX + 1], *target, *retval;
447 +  ssize_t got;
448 +
449 +  if (level > 10)
450 +    return xstrdup (symlink);
451 +
452 +  got = readlink (symlink, buf, sizeof (buf));
453 +  if (got < 0 || got >= sizeof (buf))
454 +    return xstrdup (symlink);
455 +  buf[got] = '\0';
456 +
457 +  if (IS_ABSOLUTE_PATH (buf))
458 +    target = xstrdup (buf);
459 +  else
460 +    {
461 +      const std::string dir (ldirname (symlink));
462 +
463 +      target = xstrprintf ("%s"
464 +#ifndef HAVE_DOS_BASED_FILE_SYSTEM
465 +                          "/"
466 +#else /* HAVE_DOS_BASED_FILE_SYSTEM */
467 +                          "\\"
468 +#endif /* HAVE_DOS_BASED_FILE_SYSTEM */
469 +                          "%s", dir.c_str(), buf);
470 +    }
471 +
472 +  retval = link_resolve (target, level + 1);
473 +  xfree (target);
474 +  return retval;
475 +}
476 +
477  /* Helper for build_id_to_debug_bfd.  LINK is a path to a potential
478     build-id-based separate debug file, potentially a symlink to the real file.
479     If the file exists and matches BUILD_ID, return a BFD reference to it.  */
480  
481  static gdb_bfd_ref_ptr
482 -build_id_to_debug_bfd_1 (const std::string &link, size_t build_id_len,
483 -                        const bfd_byte *build_id)
484 +build_id_to_debug_bfd_1 (const std::string &orig_link, size_t build_id_len,
485 +                        const bfd_byte *build_id, char **link_return,
486 +                        int add_debug_suffix)
487  {
488 +  gdb_bfd_ref_ptr ret_bfd = {};
489 +  std::string ret_link;
490 +
491    if (separate_debug_file_debug)
492      {
493 -      printf_unfiltered (_("  Trying %s..."), link.c_str ());
494 +      printf_unfiltered (_("  Trying %s..."), orig_link.c_str ());
495        gdb_flush (gdb_stdout);
496      }
497  
498 -  /* lrealpath() is expensive even for the usually non-existent files.  */
499 -  gdb::unique_xmalloc_ptr<char> filename;
500 -  if (access (link.c_str (), F_OK) == 0)
501 -    filename.reset (lrealpath (link.c_str ()));
502 -
503 -  if (filename == NULL)
504 +  for (unsigned seqno = 0;; seqno++)
505      {
506 -      if (separate_debug_file_debug)
507 -       printf_unfiltered (_(" no, unable to compute real path\n"));
508 +      std::string link = orig_link;
509  
510 -      return {};
511 -    }
512 +      if (seqno > 0)
513 +       {
514 +         /* There can be multiple build-id symlinks pointing to real files
515 +            with the same build-id (such as hard links).  Some of the real
516 +            files may not be installed.  */
517  
518 -  /* We expect to be silent on the non-existing files.  */
519 -  gdb_bfd_ref_ptr debug_bfd = gdb_bfd_open (filename.get (), gnutarget, -1);
520 +         string_appendf (link, ".%u", seqno);
521 +       }
522  
523 -  if (debug_bfd == NULL)
524 -    {
525 -      if (separate_debug_file_debug)
526 -       printf_unfiltered (_(" no, unable to open.\n"));
527 +      if (add_debug_suffix)
528 +       link += ".debug";
529 +
530 +      ret_link = link;
531 +
532 +      struct stat statbuf_trash;
533 +
534 +      /* `access' automatically dereferences LINK.  */
535 +      if (lstat (link.c_str (), &statbuf_trash) != 0)
536 +       {
537 +         /* Stop increasing SEQNO.  */
538 +         break;
539 +       }
540 +
541 +      /* lrealpath() is expensive even for the usually non-existent files.  */
542 +      gdb::unique_xmalloc_ptr<char> filename;
543 +
544 +      if (access (link.c_str (), F_OK) == 0)
545 +       filename.reset (lrealpath (link.c_str ()));
546 +
547 +      if (filename == NULL)
548 +       {
549 +         if (separate_debug_file_debug)
550 +           printf_unfiltered (_(" no, unable to compute real path\n"));
551 +
552 +         continue;
553 +       }
554 +
555 +      /* We expect to be silent on the non-existing files.  */
556 +      gdb_bfd_ref_ptr debug_bfd = gdb_bfd_open (filename.get (), gnutarget, -1);
557 +
558 +      if (debug_bfd == NULL)
559 +       {
560 +         if (separate_debug_file_debug)
561 +           printf_unfiltered (_(" no, unable to open.\n"));
562 +
563 +         continue;
564 +       }
565 +
566 +      if (!build_id_verify (debug_bfd.get(), build_id_len, build_id))
567 +       {
568 +         if (separate_debug_file_debug)
569 +           printf_unfiltered (_(" no, build-id does not match.\n"));
570 +
571 +         continue;
572 +       }
573  
574 -      return {};
575 +      ret_bfd = debug_bfd;
576 +      break;
577      }
578  
579 -  if (!build_id_verify (debug_bfd.get(), build_id_len, build_id))
580 +  std::string link_all;
581 +
582 +  if (ret_bfd != NULL)
583      {
584        if (separate_debug_file_debug)
585 -       printf_unfiltered (_(" no, build-id does not match.\n"));
586 +       printf_unfiltered (_(" yes!\n"));
587 +    }
588 +  else
589 +    {
590 +      /* If none of the real files is found report as missing file
591 +        always the non-.%u-suffixed file.  */
592 +      std::string link0 = orig_link;
593 +
594 +      if (add_debug_suffix)
595 +       link0 += ".debug";
596 +
597 +      /* If the symlink has target request to install the target.
598 +        BASE-debuginfo.rpm contains the symlink but BASE.rpm may be missing.
599 +        https://bugzilla.redhat.com/show_bug.cgi?id=981154  */
600 +      std::string link0_resolved (link_resolve (link0.c_str (), 0));
601  
602 -      return {};
603 +      if (link_all.empty ())
604 +       link_all = link0_resolved;
605 +      else
606 +       {
607 +         /* Use whitespace instead of DIRNAME_SEPARATOR to be compatible with
608 +            its possible use as an argument for installation command.  */
609 +         link_all += " " + link0_resolved;
610 +       }
611      }
612  
613 -  if (separate_debug_file_debug)
614 -    printf_unfiltered (_(" yes!\n"));
615 +  if (link_return != NULL)
616 +    {
617 +      if (ret_bfd != NULL)
618 +       {
619 +         *link_return = xstrdup (ret_link.c_str ());
620 +       }
621 +      else
622 +       {
623 +         *link_return = xstrdup (link_all.c_str ());
624 +       }
625 +    }
626  
627 -  return debug_bfd;
628 +  return ret_bfd;
629  }
630  
631  /* See build-id.h.  */
632  
633  gdb_bfd_ref_ptr
634 -build_id_to_debug_bfd (size_t build_id_len, const bfd_byte *build_id)
635 +build_id_to_debug_bfd (size_t build_id_len, const bfd_byte *build_id,
636 +                      char **link_return, int add_debug_suffix)
637  {
638    /* Keep backward compatibility so that DEBUG_FILE_DIRECTORY being "" will
639       cause "/.build-id/..." lookups.  */
640 @@ -143,16 +652,16 @@ build_id_to_debug_bfd (size_t build_id_len, const bfd_byte *build_id)
641        if (size > 0)
642         {
643           size--;
644 -         string_appendf (link, "%02x/", (unsigned) *data++);
645 +         string_appendf (link, "%02x", (unsigned) *data++);
646         }
647 -
648 +      if (size > 0)
649 +       link += "/";
650        while (size-- > 0)
651         string_appendf (link, "%02x", (unsigned) *data++);
652  
653 -      link += ".debug";
654 -
655        gdb_bfd_ref_ptr debug_bfd
656 -       = build_id_to_debug_bfd_1 (link, build_id_len, build_id);
657 +       = build_id_to_debug_bfd_1 (link, build_id_len, build_id,
658 +                                  link_return, add_debug_suffix);
659        if (debug_bfd != NULL)
660         return debug_bfd;
661  
662 @@ -166,7 +675,8 @@ build_id_to_debug_bfd (size_t build_id_len, const bfd_byte *build_id)
663        if (strcmp (gdb_sysroot, TARGET_SYSROOT_PREFIX) != 0)
664         {
665           link = gdb_sysroot + link;
666 -         debug_bfd = build_id_to_debug_bfd_1 (link, build_id_len, build_id);
667 +         debug_bfd = build_id_to_debug_bfd_1 (link, build_id_len, build_id,
668 +                                              link_return, add_debug_suffix);
669           if (debug_bfd != NULL)
670             return debug_bfd;
671         }
672 @@ -175,22 +685,190 @@ build_id_to_debug_bfd (size_t build_id_len, const bfd_byte *build_id)
673    return {};
674  }
675  
676 +char *
677 +build_id_to_filename (const struct bfd_build_id *build_id, char **link_return)
678 +{
679 +  gdb_bfd_ref_ptr abfd;
680 +  char *result;
681 +  
682 +  abfd = build_id_to_debug_bfd (build_id->size, build_id->data, link_return, 0);
683 +  if (abfd == NULL)
684 +    return NULL;
685 +
686 +  result = xstrdup (bfd_get_filename (abfd));
687 +  abfd.release ();
688 +  return result;
689 +}
690 +
691 +/* This MISSING_FILEPAIR_HASH tracker is used only for the duplicite messages
692 +     Try to install the hash file ...
693 +   avoidance.  */
694 +
695 +struct missing_filepair
696 +  {
697 +    char *binary;
698 +    char *debug;
699 +    char data[1];
700 +  };
701 +
702 +static struct htab *missing_filepair_hash;
703 +static struct obstack missing_filepair_obstack;
704 +
705 +static void *
706 +missing_filepair_xcalloc (size_t nmemb, size_t nmemb_size)
707 +{
708 +  void *retval;
709 +  size_t size = nmemb * nmemb_size;
710 +
711 +  retval = obstack_alloc (&missing_filepair_obstack, size);
712 +  memset (retval, 0, size);
713 +  return retval;
714 +}
715 +
716 +static hashval_t
717 +missing_filepair_hash_func (const struct missing_filepair *elem)
718 +{
719 +  hashval_t retval = 0;
720 +
721 +  retval ^= htab_hash_string (elem->binary);
722 +  if (elem->debug != NULL)
723 +    retval ^= htab_hash_string (elem->debug);
724 +
725 +  return retval;
726 +}
727 +
728 +static int
729 +missing_filepair_eq (const struct missing_filepair *elem1,
730 +                      const struct missing_filepair *elem2)
731 +{
732 +  return strcmp (elem1->binary, elem2->binary) == 0
733 +         && ((elem1->debug == NULL) == (elem2->debug == NULL))
734 +         && (elem1->debug == NULL || strcmp (elem1->debug, elem2->debug) == 0);
735 +}
736 +
737 +static void
738 +missing_filepair_change (void)
739 +{
740 +  if (missing_filepair_hash != NULL)
741 +    {
742 +      obstack_free (&missing_filepair_obstack, NULL);
743 +      /* All their memory came just from missing_filepair_OBSTACK.  */
744 +      missing_filepair_hash = NULL;
745 +    }
746 +}
747 +
748 +static void
749 +debug_print_executable_changed (void)
750 +{
751 +  missing_filepair_change ();
752 +}
753 +
754 +/* Notify user the file BINARY with (possibly NULL) associated separate debug
755 +   information file DEBUG is missing.  DEBUG may or may not be the build-id
756 +   file such as would be:
757 +     /usr/lib/debug/.build-id/dd/b1d2ce632721c47bb9e8679f369e2295ce71be.debug
758 +   */
759 +
760 +void
761 +debug_print_missing (const char *binary, const char *debug)
762 +{
763 +  size_t binary_len0 = strlen (binary) + 1;
764 +  size_t debug_len0 = debug ? strlen (debug) + 1 : 0;
765 +  struct missing_filepair missing_filepair_find;
766 +  struct missing_filepair *missing_filepair;
767 +  struct missing_filepair **slot;
768 +
769 +  if (build_id_verbose < BUILD_ID_VERBOSE_FILENAMES)
770 +    return;
771 +
772 +  if (missing_filepair_hash == NULL)
773 +    {
774 +      obstack_init (&missing_filepair_obstack);
775 +      missing_filepair_hash = htab_create_alloc (64,
776 +       (hashval_t (*) (const void *)) missing_filepair_hash_func,
777 +       (int (*) (const void *, const void *)) missing_filepair_eq, NULL,
778 +       missing_filepair_xcalloc, NULL);
779 +    }
780 +
781 +  /* Use MISSING_FILEPAIR_FIND first instead of calling obstack_alloc with
782 +     obstack_free in the case of a (rare) match.  The problem is ALLOC_F for
783 +     MISSING_FILEPAIR_HASH allocates from MISSING_FILEPAIR_OBSTACK maintenance
784 +     structures for MISSING_FILEPAIR_HASH.  Calling obstack_free would possibly
785 +     not to free only MISSING_FILEPAIR but also some such structures (allocated
786 +     during the htab_find_slot call).  */
787 +
788 +  missing_filepair_find.binary = (char *) binary;
789 +  missing_filepair_find.debug = (char *) debug;
790 +  slot = (struct missing_filepair **) htab_find_slot (missing_filepair_hash,
791 +                                                     &missing_filepair_find,
792 +                                                     INSERT);
793 +
794 +  /* While it may be still printed duplicitely with the missing debuginfo file
795 +   * it is due to once printing about the binary file build-id link and once
796 +   * about the .debug file build-id link as both the build-id symlinks are
797 +   * located in the debuginfo package.  */
798 +
799 +  if (*slot != NULL)
800 +    return;
801 +
802 +  missing_filepair = (struct missing_filepair *) obstack_alloc (&missing_filepair_obstack,
803 +                                                               sizeof (*missing_filepair) - 1
804 +                                                               + binary_len0 + debug_len0);
805 +  missing_filepair->binary = missing_filepair->data;
806 +  memcpy (missing_filepair->binary, binary, binary_len0);
807 +  if (debug != NULL)
808 +    {
809 +      missing_filepair->debug = missing_filepair->binary + binary_len0;
810 +      memcpy (missing_filepair->debug, debug, debug_len0);
811 +    }
812 +  else
813 +    missing_filepair->debug = NULL;
814 +
815 +  *slot = missing_filepair;
816 +
817 +  /* We do not collect and flush these messages as each such message
818 +     already requires its own separate lines.  */
819 +
820 +  fprintf_unfiltered (gdb_stdlog,
821 +                     _("Missing separate debuginfo for %s\n"), binary);
822 +  if (debug != NULL)
823 +    fprintf_unfiltered (gdb_stdlog, _("Try to install the hash file %s\n"),
824 +                       debug);
825 +}
826 +
827  /* See build-id.h.  */
828  
829  std::string
830 -find_separate_debug_file_by_buildid (struct objfile *objfile)
831 +find_separate_debug_file_by_buildid (struct objfile *objfile,
832 +                       gdb::unique_xmalloc_ptr<char> *build_id_filename_return)
833  {
834    const struct bfd_build_id *build_id;
835  
836 -  build_id = build_id_bfd_get (objfile->obfd);
837 +  if (build_id_filename_return)
838 +    *build_id_filename_return = NULL;
839 +
840 +  build_id = build_id_bfd_shdr_get (objfile->obfd);
841    if (build_id != NULL)
842      {
843        if (separate_debug_file_debug)
844         printf_unfiltered (_("\nLooking for separate debug info (build-id) for "
845                              "%s\n"), objfile_name (objfile));
846  
847 +      char *build_id_filename_cstr = NULL;
848        gdb_bfd_ref_ptr abfd (build_id_to_debug_bfd (build_id->size,
849 -                                                  build_id->data));
850 +                                                   build_id->data,
851 +             (!build_id_filename_return ? NULL : &build_id_filename_cstr), 1));
852 +      if (build_id_filename_return)
853 +       {
854 +         if (!build_id_filename_cstr)
855 +           gdb_assert (!*build_id_filename_return);
856 +         else
857 +           {
858 +             *build_id_filename_return = gdb::unique_xmalloc_ptr<char> (build_id_filename_cstr);
859 +             build_id_filename_cstr = NULL;
860 +           }
861 +       }
862 +
863        /* Prevent looping on a stripped .debug file.  */
864        if (abfd != NULL
865           && filename_cmp (bfd_get_filename (abfd.get ()),
866 @@ -203,3 +881,21 @@ find_separate_debug_file_by_buildid (struct objfile *objfile)
867  
868    return std::string ();
869  }
870 +
871 +extern void _initialize_build_id (void);
872 +
873 +void
874 +_initialize_build_id (void)
875 +{
876 +  add_setshow_zinteger_cmd ("build-id-verbose", no_class, &build_id_verbose,
877 +                           _("\
878 +Set debugging level of the build-id locator."), _("\
879 +Show debugging level of the build-id locator."), _("\
880 +Level 1 (default) enables printing the missing debug filenames,\n\
881 +level 2 also prints the parsing of binaries to find the identificators."),
882 +                           NULL,
883 +                           show_build_id_verbose,
884 +                           &setlist, &showlist);
885 +
886 +  gdb::observers::executable_changed.attach (debug_print_executable_changed);
887 +}
888 diff --git a/gdb/build-id.h b/gdb/build-id.h
889 --- a/gdb/build-id.h
890 +++ b/gdb/build-id.h
891 @@ -23,9 +23,10 @@
892  #include "gdb_bfd.h"
893  #include "common/rsp-low.h"
894  
895 -/* Locate NT_GNU_BUILD_ID from ABFD and return its content.  */
896 +/* Separate debuginfo files have corrupted PHDR but SHDR is correct there.
897 +   Locate NT_GNU_BUILD_ID from ABFD and return its content.  */
898  
899 -extern const struct bfd_build_id *build_id_bfd_get (bfd *abfd);
900 +extern const struct bfd_build_id *build_id_bfd_shdr_get (bfd *abfd);
901  
902  /* Return true if ABFD has NT_GNU_BUILD_ID matching the CHECK value.
903     Otherwise, issue a warning and return false.  */
904 @@ -39,14 +40,19 @@ extern int build_id_verify (bfd *abfd,
905     the caller.  */
906  
907  extern gdb_bfd_ref_ptr build_id_to_debug_bfd (size_t build_id_len,
908 -                                             const bfd_byte *build_id);
909 +                                             const bfd_byte *build_id,
910 +                                             char **link_return,
911 +                                             int add_debug_suffix);
912 +
913 +extern char *build_id_to_filename (const struct bfd_build_id *build_id,
914 +                                  char **link_return);
915  
916  /* Find the separate debug file for OBJFILE, by using the build-id
917     associated with OBJFILE's BFD.  If successful, returns the file name for the
918     separate debug file, otherwise, return an empty string.  */
919  
920 -extern std::string find_separate_debug_file_by_buildid
921 -  (struct objfile *objfile);
922 +extern std::string find_separate_debug_file_by_buildid (struct objfile *objfile,
923 +                      gdb::unique_xmalloc_ptr<char> *build_id_filename_return);
924  
925  /* Return an hex-string representation of BUILD_ID.  */
926  
927 diff --git a/gdb/coffread.c b/gdb/coffread.c
928 --- a/gdb/coffread.c
929 +++ b/gdb/coffread.c
930 @@ -729,7 +729,8 @@ coff_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
931    /* Try to add separate debug file if no symbols table found.   */
932    if (!objfile_has_partial_symbols (objfile))
933      {
934 -      std::string debugfile = find_separate_debug_file_by_buildid (objfile);
935 +      std::string debugfile = find_separate_debug_file_by_buildid (objfile,
936 +                                                                  NULL);
937  
938        if (debugfile.empty ())
939         debugfile = find_separate_debug_file_by_debuglink (objfile);
940 diff --git a/gdb/corelow.c b/gdb/corelow.c
941 --- a/gdb/corelow.c
942 +++ b/gdb/corelow.c
943 @@ -43,6 +43,10 @@
944  #include "gdb_bfd.h"
945  #include "completer.h"
946  #include "common/filestuff.h"
947 +#include "auxv.h"
948 +#include "elf/common.h"
949 +#include "gdbcmd.h"
950 +#include "build-id.h"
951  
952  #ifndef O_LARGEFILE
953  #define O_LARGEFILE 0
954 @@ -320,6 +324,54 @@ add_to_thread_list (bfd *abfd, asection *asect, void *reg_sect_arg)
955      inferior_ptid = ptid;                      /* Yes, make it current.  */
956  }
957  
958 +static int build_id_core_loads = 1;
959 +
960 +static void
961 +build_id_locate_exec (int from_tty)
962 +{
963 +  CORE_ADDR at_entry;
964 +  struct bfd_build_id *build_id;
965 +  char *execfilename;
966 +  char *build_id_filename;
967 +  struct cleanup *back_to;
968 +
969 +  if (exec_bfd != NULL || symfile_objfile != NULL)
970 +    return;
971 +
972 +  if (target_auxv_search (current_top_target (), AT_ENTRY, &at_entry) <= 0)
973 +    return;
974 +
975 +  build_id = build_id_addr_get (at_entry);
976 +  if (build_id == NULL)
977 +    return;
978 +  back_to = make_cleanup (xfree, build_id);
979 +
980 +  /* SYMFILE_OBJFILE should refer to the main executable (not only to its
981 +     separate debug info file).  gcc44+ keeps .eh_frame only in the main
982 +     executable without its duplicate .debug_frame in the separate debug info
983 +     file - such .eh_frame would not be found if SYMFILE_OBJFILE would refer
984 +     directly to the separate debug info file.  */
985 +
986 +  execfilename = build_id_to_filename (build_id, &build_id_filename);
987 +  make_cleanup (xfree, build_id_filename);
988 +
989 +  if (execfilename != NULL)
990 +    {
991 +      make_cleanup (xfree, execfilename);
992 +      exec_file_attach (execfilename, from_tty);
993 +      symbol_file_add_main (execfilename,
994 +                           symfile_add_flag (!from_tty ? 0 : SYMFILE_VERBOSE));
995 +      if (symfile_objfile != NULL)
996 +        symfile_objfile->flags |= OBJF_BUILD_ID_CORE_LOADED;
997 +    }
998 +  else
999 +    debug_print_missing (_("the main executable file"), build_id_filename);
1000 +
1001 +  do_cleanups (back_to);
1002 +
1003 +  /* No automatic SOLIB_ADD as the libraries would get read twice.  */
1004 +}
1005 +
1006  /* Issue a message saying we have no core to debug, if FROM_TTY.  */
1007  
1008  static void
1009 @@ -455,6 +507,14 @@ core_target_open (const char *arg, int from_tty)
1010         switch_to_thread (thread);
1011      }
1012  
1013 +  /* Find the build_id identifiers.  If it gets executed after
1014 +     POST_CREATE_INFERIOR we would clash with asking to discard the already
1015 +     loaded VDSO symbols.  If it gets executed before bfd_map_over_sections
1016 +     INFERIOR_PTID is still not set and libthread_db initialization crashes on
1017 +     PID == 0 in ps_pglobal_lookup.  */
1018 +  if (build_id_core_loads != 0)
1019 +    build_id_locate_exec (from_tty);
1020 +
1021    post_create_inferior (target, from_tty);
1022  
1023    /* Now go through the target stack looking for threads since there
1024 @@ -1063,4 +1123,11 @@ void
1025  _initialize_corelow (void)
1026  {
1027    add_target (core_target_info, core_target_open, filename_completer);
1028 +
1029 +  add_setshow_boolean_cmd ("build-id-core-loads", class_files,
1030 +                          &build_id_core_loads, _("\
1031 +Set whether CORE-FILE loads the build-id associated files automatically."), _("\
1032 +Show whether CORE-FILE loads the build-id associated files automatically."),
1033 +                          NULL, NULL, NULL,
1034 +                          &setlist, &showlist);
1035  }
1036 diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
1037 --- a/gdb/doc/gdb.texinfo
1038 +++ b/gdb/doc/gdb.texinfo
1039 @@ -19945,6 +19945,27 @@ information files.
1040  
1041  @end table
1042  
1043 +You can also adjust the current verbosity of the @dfn{build id} locating.
1044 +
1045 +@table @code
1046 +
1047 +@kindex set build-id-verbose
1048 +@item set build-id-verbose 0
1049 +No additional messages are printed.
1050 +
1051 +@item set build-id-verbose 1
1052 +Missing separate debug filenames are printed.
1053 +
1054 +@item set build-id-verbose 2
1055 +Missing separate debug filenames are printed and also all the parsing of the
1056 +binaries to find their @dfn{build id} content is printed.
1057 +
1058 +@kindex show build-id-verbose
1059 +@item show build-id-verbose
1060 +Show the current verbosity value for the @dfn{build id} content locating.
1061 +
1062 +@end table
1063 +
1064  @cindex @code{.gnu_debuglink} sections
1065  @cindex debug link sections
1066  A debug link is a special section of the executable file named
1067 diff --git a/gdb/dwarf-index-cache.c b/gdb/dwarf-index-cache.c
1068 --- a/gdb/dwarf-index-cache.c
1069 +++ b/gdb/dwarf-index-cache.c
1070 @@ -93,7 +93,7 @@ index_cache::store (struct dwarf2_per_objfile *dwarf2_per_objfile)
1071    if (!enabled ())
1072      return;
1073  
1074 -  const bfd_build_id *build_id = build_id_bfd_get (obj->obfd);
1075 +  const bfd_build_id *build_id = build_id_bfd_shdr_get (obj->obfd);
1076    if (build_id == nullptr)
1077      {
1078        if (debug_index_cache)
1079 diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
1080 --- a/gdb/dwarf2read.c
1081 +++ b/gdb/dwarf2read.c
1082 @@ -2727,7 +2727,7 @@ dwarf2_get_dwz_file (struct dwarf2_per_objfile *dwarf2_per_objfile)
1083      }
1084  
1085    if (dwz_bfd == NULL)
1086 -    dwz_bfd = build_id_to_debug_bfd (buildid_len, buildid);
1087 +    dwz_bfd = build_id_to_debug_bfd (buildid_len, buildid, NULL, 1);
1088  
1089    if (dwz_bfd == NULL)
1090      error (_("could not find '.gnu_debugaltlink' file for %s"),
1091 @@ -6237,7 +6237,7 @@ get_gdb_index_contents_from_section (objfile *obj, T *section_owner)
1092  static gdb::array_view<const gdb_byte>
1093  get_gdb_index_contents_from_cache (objfile *obj, dwarf2_per_objfile *dwarf2_obj)
1094  {
1095 -  const bfd_build_id *build_id = build_id_bfd_get (obj->obfd);
1096 +  const bfd_build_id *build_id = build_id_bfd_shdr_get (obj->obfd);
1097    if (build_id == nullptr)
1098      return {};
1099  
1100 @@ -6250,7 +6250,7 @@ get_gdb_index_contents_from_cache (objfile *obj, dwarf2_per_objfile *dwarf2_obj)
1101  static gdb::array_view<const gdb_byte>
1102  get_gdb_index_contents_from_cache_dwz (objfile *obj, dwz_file *dwz)
1103  {
1104 -  const bfd_build_id *build_id = build_id_bfd_get (dwz->dwz_bfd.get ());
1105 +  const bfd_build_id *build_id = build_id_bfd_shdr_get (dwz->dwz_bfd.get ());
1106    if (build_id == nullptr)
1107      return {};
1108  
1109 diff --git a/gdb/elfread.c b/gdb/elfread.c
1110 --- a/gdb/elfread.c
1111 +++ b/gdb/elfread.c
1112 @@ -1287,7 +1287,9 @@ elf_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
1113            && objfile->separate_debug_objfile == NULL
1114            && objfile->separate_debug_objfile_backlink == NULL)
1115      {
1116 -      std::string debugfile = find_separate_debug_file_by_buildid (objfile);
1117 +      gdb::unique_xmalloc_ptr<char> build_id_filename;
1118 +      std::string debugfile
1119 +       = find_separate_debug_file_by_buildid (objfile, &build_id_filename);
1120  
1121        if (debugfile.empty ())
1122         debugfile = find_separate_debug_file_by_debuglink (objfile);
1123 @@ -1299,6 +1301,10 @@ elf_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
1124           symbol_file_add_separate (debug_bfd.get (), debugfile.c_str (),
1125                                     symfile_flags, objfile);
1126         }
1127 +      /* Check if any separate debug info has been extracted out.  */
1128 +      else if (bfd_get_section_by_name (objfile->obfd, ".gnu_debuglink")
1129 +              != NULL)
1130 +       debug_print_missing (objfile_name (objfile), build_id_filename.get ());
1131      }
1132  }
1133  
1134 diff --git a/gdb/objfiles.h b/gdb/objfiles.h
1135 --- a/gdb/objfiles.h
1136 +++ b/gdb/objfiles.h
1137 @@ -554,6 +554,10 @@ struct objfile
1138    htab_t static_links {};
1139  };
1140  
1141 +/* This file was loaded according to the BUILD_ID_CORE_LOADS rules.  */
1142 +
1143 +#define OBJF_BUILD_ID_CORE_LOADED static_cast<enum objfile_flag>(1 << 12)
1144 +
1145  /* Declarations for functions defined in objfiles.c */
1146  
1147  extern struct gdbarch *get_objfile_arch (const struct objfile *);
1148 diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c
1149 --- a/gdb/python/py-objfile.c
1150 +++ b/gdb/python/py-objfile.c
1151 @@ -132,7 +132,7 @@ objfpy_get_build_id (PyObject *self, void *closure)
1152  
1153    TRY
1154      {
1155 -      build_id = build_id_bfd_get (objfile->obfd);
1156 +      build_id = build_id_bfd_shdr_get (objfile->obfd);
1157      }
1158    CATCH (except, RETURN_MASK_ALL)
1159      {
1160 @@ -535,7 +535,7 @@ objfpy_lookup_objfile_by_build_id (const char *build_id)
1161        /* Don't return separate debug files.  */
1162        if (objfile->separate_debug_objfile_backlink != NULL)
1163         continue;
1164 -      obfd_build_id = build_id_bfd_get (objfile->obfd);
1165 +      obfd_build_id = build_id_bfd_shdr_get (objfile->obfd);
1166        if (obfd_build_id == NULL)
1167         continue;
1168        if (objfpy_build_id_matches (obfd_build_id, build_id))
1169 diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
1170 --- a/gdb/solib-svr4.c
1171 +++ b/gdb/solib-svr4.c
1172 @@ -45,6 +45,7 @@
1173  #include "auxv.h"
1174  #include "gdb_bfd.h"
1175  #include "probe.h"
1176 +#include "build-id.h"
1177  
1178  static struct link_map_offsets *svr4_fetch_link_map_offsets (void);
1179  static int svr4_have_link_map_offsets (void);
1180 @@ -1345,9 +1346,51 @@ svr4_read_so_list (CORE_ADDR lm, CORE_ADDR prev_lm,
1181           continue;
1182         }
1183  
1184 -      strncpy (newobj->so_name, buffer.get (), SO_NAME_MAX_PATH_SIZE - 1);
1185 -      newobj->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
1186 -      strcpy (newobj->so_original_name, newobj->so_name);
1187 +      {
1188 +       struct bfd_build_id *build_id;
1189 +
1190 +       strncpy (newobj->so_original_name, buffer.get (), SO_NAME_MAX_PATH_SIZE - 1);
1191 +       newobj->so_original_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
1192 +       /* May get overwritten below.  */
1193 +       strcpy (newobj->so_name, newobj->so_original_name);
1194 +
1195 +       build_id = build_id_addr_get (((lm_info_svr4 *) newobj->lm_info)->l_ld);
1196 +       if (build_id != NULL)
1197 +         {
1198 +           char *name, *build_id_filename;
1199 +
1200 +           /* Missing the build-id matching separate debug info file
1201 +              would be handled while SO_NAME gets loaded.  */
1202 +           name = build_id_to_filename (build_id, &build_id_filename);
1203 +           if (name != NULL)
1204 +             {
1205 +               strncpy (newobj->so_name, name, SO_NAME_MAX_PATH_SIZE - 1);
1206 +               newobj->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
1207 +               xfree (name);
1208 +             }
1209 +           else
1210 +             {
1211 +               debug_print_missing (newobj->so_name, build_id_filename);
1212 +
1213 +               /* In the case the main executable was found according to
1214 +                  its build-id (from a core file) prevent loading
1215 +                  a different build of a library with accidentally the
1216 +                  same SO_NAME.
1217 +
1218 +                  It suppresses bogus backtraces (and prints "??" there
1219 +                  instead) if the on-disk files no longer match the
1220 +                  running program version.  */
1221 +
1222 +               if (symfile_objfile != NULL
1223 +                   && (symfile_objfile->flags
1224 +                       & OBJF_BUILD_ID_CORE_LOADED) != 0)
1225 +                 newobj->so_name[0] = 0;
1226 +             }
1227 +
1228 +           xfree (build_id_filename);
1229 +           xfree (build_id);
1230 +         }
1231 +      }
1232  
1233        /* If this entry has no name, or its name matches the name
1234          for the main executable, don't include it in the list.  */
1235 diff --git a/gdb/symfile.h b/gdb/symfile.h
1236 --- a/gdb/symfile.h
1237 +++ b/gdb/symfile.h
1238 @@ -531,6 +531,10 @@ void expand_symtabs_matching
1239  void map_symbol_filenames (symbol_filename_ftype *fun, void *data,
1240                            int need_fullname);
1241  
1242 +/* build-id support.  */
1243 +extern struct bfd_build_id *build_id_addr_get (CORE_ADDR addr);
1244 +extern void debug_print_missing (const char *binary, const char *debug);
1245 +
1246  /* From dwarf2read.c */
1247  
1248  /* Names for a dwarf2 debugging section.  The field NORMAL is the normal
1249 diff --git a/gdb/testsuite/gdb.base/corefile.exp b/gdb/testsuite/gdb.base/corefile.exp
1250 --- a/gdb/testsuite/gdb.base/corefile.exp
1251 +++ b/gdb/testsuite/gdb.base/corefile.exp
1252 @@ -311,3 +311,33 @@ gdb_test_multiple "core-file $corefile" $test {
1253         pass $test
1254      }
1255  }
1256 +
1257 +
1258 +# Test auto-loading of binary files through build-id from the core file.
1259 +set buildid [build_id_debug_filename_get $binfile]
1260 +set wholetest "binfile found by build-id"
1261 +if {$buildid == ""} {
1262 +    untested "$wholetest (binary has no build-id)"
1263 +} else {
1264 +    gdb_exit
1265 +    gdb_start
1266 +
1267 +    regsub {\.debug$} $buildid {} buildid
1268 +    set debugdir [standard_output_file ${testfile}-debugdir]
1269 +    file delete -force -- $debugdir
1270 +    file mkdir $debugdir/[file dirname $buildid]
1271 +    file copy $binfile $debugdir/$buildid
1272 +
1273 +    set test "show debug-file-directory"
1274 +    gdb_test_multiple $test $test {
1275 +       -re "The directory where separate debug symbols are searched for is \"(.*)\"\\.\r\n$gdb_prompt $" {
1276 +           set debugdir_orig $expect_out(1,string)
1277 +           pass $test
1278 +       }
1279 +    }
1280 +    gdb_test_no_output "set debug-file-directory $debugdir:$debugdir_orig" "set debug-file-directory"
1281 +    gdb_test "show build-id-core-loads" {Whether CORE-FILE loads the build-id associated files automatically is on\.}
1282 +    gdb_test "core-file $corefile" "\r\nProgram terminated with .*" "core-file without executable"
1283 +    gdb_test "info files" "Local exec file:\r\n\[ \t\]*`[string_to_regexp $debugdir/$buildid]', file type .*"
1284 +    pass $wholetest
1285 +}
1286 diff --git a/gdb/testsuite/gdb.base/new-ui-pending-input.exp b/gdb/testsuite/gdb.base/new-ui-pending-input.exp
1287 --- a/gdb/testsuite/gdb.base/new-ui-pending-input.exp
1288 +++ b/gdb/testsuite/gdb.base/new-ui-pending-input.exp
1289 @@ -62,6 +62,7 @@ proc test_command_line_new_ui_pending_input {} {
1290      set options ""
1291      append options " -iex \"set height 0\""
1292      append options " -iex \"set width 0\""
1293 +    append options " -iex \"set build-id-verbose 0\""
1294      append options " -iex \"new-ui console $extra_tty_name\""
1295      append options " -ex \"b $bpline\""
1296      append options " -ex \"run\""
1297 diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
1298 --- a/gdb/testsuite/lib/gdb.exp
1299 +++ b/gdb/testsuite/lib/gdb.exp
1300 @@ -1697,6 +1697,16 @@ proc default_gdb_start { } {
1301             warning "Couldn't set the width to 0."
1302         }
1303      }
1304 +    # Turn off the missing warnings as the testsuite does not expect it.
1305 +    send_gdb "set build-id-verbose 0\n"
1306 +    gdb_expect 10 {
1307 +       -re "$gdb_prompt $" {
1308 +           verbose "Disabled the missing debug infos warnings." 2
1309 +       }
1310 +       timeout {
1311 +           warning "Could not disable the missing debug infos warnings.."
1312 +       }
1313 +    }
1314      return 0
1315  }
1316  
1317 diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp
1318 --- a/gdb/testsuite/lib/mi-support.exp
1319 +++ b/gdb/testsuite/lib/mi-support.exp
1320 @@ -309,6 +309,16 @@ proc default_mi_gdb_start { args } {
1321             warning "Couldn't set the width to 0."
1322         }
1323      }
1324 +    # Turn off the missing warnings as the testsuite does not expect it.
1325 +    send_gdb "190-gdb-set build-id-verbose 0\n"
1326 +    gdb_expect 10 {
1327 +       -re ".*190-gdb-set build-id-verbose 0\r\n190\\\^done\r\n$mi_gdb_prompt$" {
1328 +           verbose "Disabled the missing debug infos warnings." 2
1329 +       }
1330 +       timeout {
1331 +           warning "Could not disable the missing debug infos warnings.."
1332 +       }
1333 +    }
1334  
1335      if { $separate_inferior_pty } {
1336         mi_create_inferior_pty
This page took 0.253266 seconds and 3 git commands to generate.