bug-binutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Bug gold/23016] New: assert in output.h on mix of .eh_frame types for x


From: thanm at google dot com
Subject: [Bug gold/23016] New: assert in output.h on mix of .eh_frame types for x86_64
Date: Thu, 29 Mar 2018 13:47:30 +0000

https://sourceware.org/bugzilla/show_bug.cgi?id=23016

            Bug ID: 23016
           Summary: assert in output.h on mix of .eh_frame types for
                    x86_64
           Product: binutils
           Version: unspecified
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: gold
          Assignee: ccoutant at gmail dot com
          Reporter: thanm at google dot com
                CC: ian at airs dot com
  Target Milestone: ---

Created attachment 10924
  --> https://sourceware.org/bugzilla/attachment.cgi?id=10924&action=edit
tar file containing C sources, makefile

The code in the gold linker that handles relocatable links seems to be having
problems when there are a mix of input object files from GCC and Clang
(x86_64), in some cases triggering an assert.

Given two C source files (contents unimportant, but each should have at least
one function), bug can be triggered by running the following commands:

  gcc -fPIC -g -O2 -c this.c
  clang -fPIC -g -O2 -c other.c
  gcc -fuse-ld=gold  -fPIC -g -O2  -Wl,-r -nostdlib -no-pie this.o other.o -o
rel.o

resulting in this assert:

  ld.gold: internal error in set_info_section, at
../../binutils/gold/output.h:3386

I've reproduced this on linux x86_64 with several versions of clang, gcc, and
ld.gold (including top of trunk for each). GCC 7 + clang 3.9 + gold 1.15 is one
starting point.

Stack trace for the assert looks like:

#0  gold::Output_section::set_info_section (this=0x<...> os=0x<...> at
../../binutils/gold/output.h:3382
#1  0x<...> in gold::Layout::layout_reloc<64, false> (this=0x<...>
object=0x<...> shdr=..., data_section=0x<...> rr=0x<...> at
../../binutils/gold/layout.cc:1354
#2  0x<...> in gold::Sized_relobj_file<64, false>::do_layout (this=0x<...>
symtab=0x<...> layout=0x<...> sd=0x<...> at ../../binutils/gold/object.cc:1856
#3  0x<...> in gold::Object::layout (this=0x<...> symtab=0x<...> layout=0x<...>
sd=0x<...> at ../../binutils/gold/object.h:651
#4  0x<...> in gold::Add_symbols::run (this=0x<...> at
../../binutils/gold/readsyms.cc:634
#5  0x<...> in gold::Workqueue::find_and_run_task (this=0x<...>
thread_number=0) at ../../binutils/gold/workqueue.cc:319
#6  0x<...> in gold::Workqueue::process (this=0x<...> thread_number=0) at
../../binutils/gold/workqueue.cc:495
#7  0x<...> in main (argc=6, argv=0x<...> at ../../binutils/gold/main.cc:252

The relocation section being laid out at the point of the assert is one of the
.rela.eh_frame sections. 

When I look at the gcc-compiled objects feeding into the link, I see .eh_frame
sections that look like:

  [ 7] .eh_frame
       PROGBITS        0000000000000000 000088 000038 00   0   0  8
       [0000000000000002]: ALLOC
  [ 8] .rela.eh_frame
       RELA            0000000000000000 0001e0 000018 18   9   7  8
       [0000000000000040]: INFO LINK

The corresponding sections from LLVM-backend compiled objects look like

  [16] .eh_frame
       X86_64_UNWIND   0000000000000000 0001e8 000030 00   0   0  8
       [0000000000000002]: ALLOC
  [17] .rela.eh_frame
       RELA            0000000000000000 000470 000018 18  20  16  8
       [0000000000000000]:

Note the section types -- this seems to be the crux of the problem. LLVM (as of
2013 or so) sets the section type to X86_64_UNWIND, not PROGBITS. The X86_64
ps-ABI recommends using this section type, but not all producers do (gcc does
not).

Googling assert in question turns up a few other instances, including:

 
https://stackoverflow.com/questions/47797817/ld-gold-internal-error-in-set-info-section-at-output-h3209
  https://sourceware.org/bugzilla/show_bug.cgi?id=15861

however it's not clear whether this is the same bug (some of the instances out
in the wild seem to involve the use of a linker script).

I spent a while in the debugger looking at what is happening. When gold
processes the two different .eh_frame sections, it effectively treats them as
distinct sections in the output file (since output section lookup is based on
name, type, and flags). In the case of the .rela.eh_frame sections, however, we
get only a single output section (since both input ".rela.eh_frame" sections
have the same name/type/flags). The assert is happening when
Layout::layout_reloc is called on the second relocation section. The code looks
like:

    gold_assert((this->info_section_ == NULL
                 || (this->info_section_ == os
                     && this->info_uses_section_index_))
                && this->info_symndx_ == NULL
                && this->info_ == 0);

Here "info_section_" is already pointing to the first output section for
.eh_frame, however we're trying to set it to the second output section.

I have been experimenting with fixes.  I note that for non-relocatable links,
gold is already effectively merging PROGBITS + X86_64_UNWIND .eh_frame sections
into a single merged PROGBITS section (see the "FIXME" comment in
Layout::make_eh_frame_section).  With this in mind, a similar way to solve the
problem would be to do the same merging for relocatable links. 

A patch to do this appears below; this fixes the assert.

A second possibility would be to change things so that the two separate
"flavors" of .eh_frame section are preserved in the output object for
relocatable links, meaning that there would have to be two separate relocation
sections as well. This would mean special handling of some sort when creating
output sections for .rela.eh_frame sections (e.g. not just calling
Layout::choose_output_section).

I am attaching a reproducer; unpack the tar file and run "make" (may need to
edit the makefile so that correct gcc and clang paths are picked up). Ex:

$ make THISCC=gcc-7 OTHERCC=clang-3.9 all
gcc-7 -fPIC -g -O2 -c this.c
clang-3.9 -fPIC -g -O2 -c other.c
gcc-7 -fuse-ld=gold  -fPIC -g -O2 -Wl,-r -nostdlib -no-pie this.o other.o -o
rel.o 
/usr/bin/ld.gold: internal error in set_info_section, at
../../gold/output.h:3386
collect2: error: ld returned 1 exit status
makefile:19: recipe for target 'rel.o' failed
make: *** [rel.o] Error 1
$

-----

Tentative patch:

diff --git a/gold/layout.cc b/gold/layout.cc
index f5fe805ea..987e12092 100644
--- a/gold/layout.cc
+++ b/gold/layout.cc
@@ -829,6 +829,13 @@ Layout::get_output_section(const char* name,
Stringpool::Key name_key,
       || lookup_type == elfcpp::SHT_PREINIT_ARRAY)
     lookup_type = elfcpp::SHT_PROGBITS;

+  // Some compilers assign a type of SHT_PROGBITS to the .eh_frame
+  // section, while others use the psABI-recommended SHT_X86_64_UNWIND.
+  // Insure that we combine the two in the resulting output file (mainly
+  // an issue for relocatable links).
+  if (lookup_type == elfcpp::SHT_X86_64_UNWIND)
+    lookup_type = elfcpp::SHT_PROGBITS;
+
   elfcpp::Elf_Xword lookup_flags = flags;

   // Ignoring SHF_WRITE and SHF_EXECINSTR here means that we combine

-- 
You are receiving this mail because:
You are on the CC list for the bug.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]