Bug 24456

Summary: bfd elf.c assertion for multiple relocations to same section
Product: binutils Reporter: Joe Lawrence <joe.lawrence>
Component: binutilsAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: normal CC: mbenes, nickc
Priority: P2    
Version: 2.23   
Target Milestone: ---   
Host: Target:
Build: Last reconfirmed:
Attachments: Test binary

Description Joe Lawrence 2019-04-15 21:40:06 UTC
We're working on an upstream kernel feature [1] which adds a new
relocation section to kernel modules and when loading the .ko's symbol
information into crash utility (which includes gdb, which includes bfd)
it's hitting an assertion in elf.c that isn't giving much information to
debug.

Here is the assertion when running crash (with a bit of extra
debugging):

  % insmod /lib/modules/5.1.0-rc4+/kernel/samples/livepatch/livepatch-annotated-sample.ko
  % crash
  ...
  crash> mod -s livepatch_annotated_sample /lib/modules/5.1.0-rc4+/kernel/samples/livepatch/livepatch-annotated-sample.ko
  shindex=34, name=.klp.rela.vmlinux..text
  *p_hdr(0x57f6150) == NULL = 0, this_idx=3
  BFD: BFD (GNU Binutils) 2.23.52.20130312 assertion fail elf.c:1881
       MODULE       NAME                           SIZE  OBJECT FILE
  ffffffffc05cb380  livepatch_annotated_sample    16384  /lib/modules/5.1.0-rc4+/kernel/samples/livepatch/livepatch-annotated-sample.ko


and the corresponding assertion, with extra debugging, in elf.c:

 1545 bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
 ....
 1563   switch (hdr->sh_type)
 1564     {
 ....
 1784     case SHT_REL:
 1785     case SHT_RELA:
 ....
 1871         esdt = elf_section_data (target_sect);
 1872         if (hdr->sh_type == SHT_RELA)
 1873           p_hdr = &esdt->rela.hdr;
 1874         else
 1875           p_hdr = &esdt->rel.hdr;
 1876
 1877 if (*p_hdr != NULL) {
 1878         printf("shindex=%d\nname=%s\n", shindex, name);
 1879         printf("*p_hdr(%p) == NULL = %d, this_idx=%d\n", *p_hdr, (*p_hdr == NULL), esdt->this_idx);
 1880 }
 1881         BFD_ASSERT (*p_hdr == NULL);


I noticed that it is processing our new section, index 34,
.klp.rela.vmlinux..text and finds an existing p_hdr to section
index 3, .text:

  % eu-readelf --relocs /lib/modules/5.1.0-rc4+/kernel/samples/livepatch/livepatch-annotated-sample.ko

  Relocation section [ 4] '.rela.text' for section [ 3] '.text' at offset 0xc8 contains 7 entries:
    Offset              Type            Value               Addend Name
    0x0000000000000001  X86_64_PC32     000000000000000000      -4 __fentry__
    0x000000000000000f  X86_64_32S      000000000000000000      +0 .rodata.str1.1
    0x0000000000000014  X86_64_PC32     000000000000000000      -4 seq_printf
    0x0000000000000021  X86_64_PC32     000000000000000000      -4 __fentry__
    0x0000000000000028  X86_64_32S      000000000000000000      +0 .data
    0x000000000000002d  X86_64_PC32     000000000000000000      -4 klp_enable_patch
    0x0000000000000041  X86_64_PC32     000000000000000000      -4 __fentry__

  Relocation section [34] '.klp.rela.vmlinux..text' for section [ 3] '.text' at offset 0x4a080 contains 1 entry:
    Offset              Type            Value               Addend Name
    0x0000000000000008  X86_64_PC32     000000000000000000      -4 .klp.sym.vmlinux.saved_command_line,0


Unfortunately it is less than trivial to move crash utility's version of
gdb / binutils forward, so I couldn't directly test with a newer version
of binutils.  However, elf.c :: bfd_section_from_shdr() still seems to
contain this assertion, though in a slightly more direct format:

        /* PR 17512: file: 0b4f81b7.  */
        if (*p_hdr != NULL)
          goto fail;


There other binutils utilities that are also reporting problems, but
with an error message too vague to determine why they are failing.  They
are perhaps related, and possibly easier to debug/verify for our
purposes here.

Here's what a fresh clone + build of binutils-gdb tree versions of
objdump and gdb think of our new object file [2]:

  % git describe HEAD
  users/ARM/embedded-gdb-master-2018q4-978-g48574d91bf12

  % ./binutils/objdump -D /tmp/bug/livepatch-annotated-sample.ko
  ./binutils/objdump: /tmp/bug/livepatch-annotated-sample.ko: bad value

  % ./gdb/gdb -q /tmp/bug/livepatch-annotated-sample.ko
  "/tmp/bug/livepatch-annotated-sample.ko": not in executable format: bad value

Both of those tools work as expected with an ordinary kernel module [3]
(ie, one with any extra relocation sections to '.text').

[1] https://lore.kernel.org/lkml/20190410155058.9437-1-joe.lawrence@redhat.com/
[2] http://people.redhat.com/~jolawren/bug/livepatch-annotated-sample.ko
[3] http://people.redhat.com/~jolawren/bug/livepatch-sample.ko
Comment 1 Sourceware Commits 2019-08-23 12:23:23 UTC
The master branch has been updated by Nick Clifton <nickc@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=a7ba389645d178c43100ec47e513389ae8bf8f93

commit a7ba389645d178c43100ec47e513389ae8bf8f93
Author: Nick Clifton <nickc@redhat.com>
Date:   Fri Aug 23 13:22:02 2019 +0100

    Stop the BFD library from failing when encountering a second set of relocs for the same section.
    
    	PR 24456
    	* elf.c (bfd_section_from_shdr): Issue an informative warning
    	message and continue processing other sections after encountering
    	a reloc section for a section which already has other relocs
    	associated with it.
Comment 2 Nick Clifton 2019-08-23 12:28:50 UTC
Hi Joe,

  Sorry for dropping this PR.

  I have now checked in a patch which makes the BFD library generate a
  more helpful warning message, and then continue processing the rest
  of the input file.  The downside though, is that this patch does not
  enable processing of the extra reloc section - it is just ignored -
  but I feel that that is better than just failing outright.

    % objdump -D livepatch-annotated-sample.ko > /dev/null
    objdump: livepatch-annotated-sample.ko: warning: multiple relocation sections for section .text found - ignoring all but the first

    % echo $?
    0

  I hope that this will suffice for your purposes.

Cheers
  Nick
Comment 3 Joe Lawrence 2019-08-23 15:05:52 UTC
Hi Nick,

Thanks for revisiting this one!  I can confirm that with the latest master branch, objdump can now process the .ko's that we've generated with multiple section relocations.  Even if those follow-up relocations aren't processed, it is very helpful to at least dump assembly, sections, etc. when debugging.

Thanks,

-- Joe
Comment 4 Nick Clifton 2019-08-27 10:32:58 UTC
OK, I am going to close this PR.  If it turns out that there is a need to process the other reloc sections then this PR can be reopened, or a new one filed.  I suspect however that enabling support for them will be difficult, as it is likely to invole a lot of rewriting of the internals of the BFD library.
Comment 5 Nick Clifton 2019-09-11 08:59:39 UTC
Created attachment 11987 [details]
Test binary