aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Seitz <keiths@redhat.com>2021-03-25 10:31:48 -0700
committerKeith Seitz <keiths@redhat.com>2021-03-26 10:47:48 -0700
commitff5b3e1458875830595e8c1d1fab6624264b3935 (patch)
treee304ca791ac8d5e519f60d7b92eaa77384783c75
parentb1f3973b9c55a1406c13ade5cb14239d5b17a465 (diff)
downloadgdb-ff5b3e1458875830595e8c1d1fab6624264b3935.zip
gdb-ff5b3e1458875830595e8c1d1fab6624264b3935.tar.gz
gdb-ff5b3e1458875830595e8c1d1fab6624264b3935.tar.bz2
Save/restore file offset while reading notes in core file
A recent bug (RH BZ 1931344) has exposed a bug in the core file build-ID support that I introduced a while ago. It is pretty easy to demonstate the problem following a simplified procedure outlined in that bug: [shell1] shell1$ /usr/libexec/qemu-kvm [shell2] shell2$ pkill -SEGV -x qemu-kvm [shell1] Segmentation fault (core dumped) Load this core file into GDB without specifying an executable (an unfortunate Fedora/RHEL-ism), and GDB will inform the user to install debuginfo for the "missing" executable: $ gdb -nx -q core.12345 ... Missing separate debuginfo for the main executable file Try: dnf --enablerepo='*debug*' install /usr/lib/debug/.build-id/e2/e9c66d3117fb2bbb5b2be122f04f2664e5df54 Core was generated by `/usr/libexec/qemu-kvm'. Program terminated with signal SIGSEGV, Segmentation fault. ... The suggested build-ID is actaully for gmp not qemu-kvm. The problem lies in _bfd_elf_core_find_build_id, where we loop over program headers looking for note segments: /* Read in program headers and parse notes. */ for (i = 0; i < i_ehdr.e_phnum; ++i, ++i_phdr) { Elf_External_Phdr x_phdr; if (bfd_bread (&x_phdr, sizeof (x_phdr), abfd) != sizeof (x_phdr)) goto fail; elf_swap_phdr_in (abfd, &x_phdr, i_phdr); if (i_phdr->p_type == PT_NOTE && i_phdr->p_filesz > 0) { elf_read_notes (abfd, offset + i_phdr->p_offset, i_phdr->p_filesz, i_phdr->p_align); if (abfd->build_id != NULL) return TRUE; } elf_read_notes uses bfd_seek to forward the stream to the location of the note segment. When control returns to _bfd_elf_core_fild_build_id, the stream is no longer in the location looking at program headers, and all subsequent reads will read from the wrong file offset. To fix this, this patch marks the stream location and ensures that it is restored after elf_read_notes is called. bfd/ChangeLog 2021-03-26 Keith Seitz <keiths@redhat.com> * elfcore.h (_bfd_elf_core_find_build_id): Seek file offset of program headers after calling elf_read_notes.
-rw-r--r--bfd/ChangeLog5
-rw-r--r--bfd/elfcore.h7
2 files changed, 12 insertions, 0 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 3245f8c..6f3fccc 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,8 @@
+2021-03-26 Keith Seitz <keiths@redhat.com>
+
+ * elfcore.h (_bfd_elf_core_find_build_id): Seek file
+ offset of program headers after calling elf_read_notes.
+
2021-03-23 Jan Beulich <jbeulich@suse.com>
* dwarf2.c (read_indexed_string): Rename index to idx.
diff --git a/bfd/elfcore.h b/bfd/elfcore.h
index 3015e58..4e63834 100644
--- a/bfd/elfcore.h
+++ b/bfd/elfcore.h
@@ -410,6 +410,13 @@ NAME(_bfd_elf, core_find_build_id)
{
elf_read_notes (abfd, offset + i_phdr->p_offset,
i_phdr->p_filesz, i_phdr->p_align);
+
+ /* Make sure ABFD returns to processing the program headers. */
+ if (bfd_seek (abfd, (file_ptr) (offset + i_ehdr.e_phoff
+ + (i + 1) * sizeof (x_phdr)),
+ SEEK_SET) != 0)
+ goto fail;
+
if (abfd->build_id != NULL)
return TRUE;
}