Bug 15758 - Gold segfault when using -q option
Summary: Gold segfault when using -q option
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: gold (show other bugs)
Version: unspecified
: P2 normal
Target Milestone: ---
Assignee: Cary Coutant
URL:
Keywords:
: 15769 (view as bug list)
Depends on:
Blocks:
 
Reported: 2013-07-19 17:39 UTC by law
Modified: 2013-11-11 02:00 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description law 2013-07-19 17:39:53 UTC
gold is segfaulting when linking the following testcode.

t.c (compile with -fPIC):

__thread int a;

void _start(void) {
    a = 2;
}



Starting program: /tmp/binutils/gold/ld-new t.o -q

Breakpoint 3, gold::Sized_relobj_file<64, false>::emit_relocs_scan (this=0xa644f0, symtab=0x7fffffff7980, layout=0x7fffffff7be0,
    plocal_syms=0x7ffff7ffb468 "", p=...) at /home/law/UPSTREAM/binutils/gold/reloc.cc:550
550       gold_assert(rr != NULL);
(gdb) c
Continuing.

Breakpoint 3, gold::Sized_relobj_file<64, false>::emit_relocs_scan (this=0xa644f0, symtab=0x7fffffff7980, layout=0x7fffffff7be0,
    plocal_syms=0x7ffff7ffb468 "", p=...) at /home/law/UPSTREAM/binutils/gold/reloc.cc:550
550       gold_assert(rr != NULL);
(gdb) bt
#0  gold::Sized_relobj_file<64, false>::emit_relocs_scan (this=0xa644f0, symtab=0x7fffffff7980, layout=0x7fffffff7be0, plocal_syms=0x7ffff7ffb468 "",
    p=...) at /home/law/UPSTREAM/binutils/gold/reloc.cc:550
#1  0x00000000006c5d68 in gold::Sized_relobj_file<64, false>::do_scan_relocs (this=0xa644f0, symtab=0x7fffffff7980, layout=0x7fffffff7be0, rd=0xa4a770)
    at /home/law/UPSTREAM/binutils/gold/reloc.cc:469
#2  0x00000000006c2c7a in gold::Relobj::scan_relocs (this=0xa644f0, symtab=0x7fffffff7980, layout=0x7fffffff7be0, rd=0xa4a770)
    at /home/law/UPSTREAM/binutils/gold/object.h:1057
#3  0x00000000006c27c1 in gold::Scan_relocs::run (this=0xa69020) at /home/law/UPSTREAM/binutils/gold/reloc.cc:188
#4  0x000000000073e38b in gold::Workqueue::find_and_run_task (this=0x7fffffff7630, thread_number=0) at /home/law/UPSTREAM/binutils/gold/workqueue.cc:319
#5  0x000000000073e9b4 in gold::Workqueue::process (this=0x7fffffff7630, thread_number=0) at /home/law/UPSTREAM/binutils/gold/workqueue.cc:495
#6  0x0000000000404016 in main (argc=3, argv=0x7fffffffdb68) at /home/law/UPSTREAM/binutils/gold/main.cc:252
(gdb) p rr
$5 = (gold::Relocatable_relocs *) 0x0


It appears the relocatable_relocs are set up in:

gold::Sized_relobj_file

  for (std::vector<unsigned int>::const_iterator p = reloc_sections.begin();
       p != reloc_sections.end();
       ++p)
[ ... ]
     Output_section* data_section = out_sections[data_shndx];
      if (data_section == reinterpret_cast<Output_section*>(2))
        {
          // The layout for the data section was deferred, so we need
          // to defer the relocation section, too.
          const char* name = pnames + shdr.get_sh_name();
          this->deferred_layout_relocs_.push_back(
              Deferred_layout(i, name, pshdr, 0, elfcpp::SHT_NULL));
          out_sections[i] = reinterpret_cast<Output_section*>(2);
          out_section_offsets[i] = invalid_address;
          continue;
        }
      if (data_section == NULL)
        {
          out_sections[i] = NULL;
          out_section_offsets[i] = invalid_address;
          continue;
        }

      Relocatable_relocs* rr = new Relocatable_relocs();
      this->set_relocatable_relocs(i, rr);

We have no appropriate out_section for the section reloc section.  Thus data_section is NULL and we call this->set_relocatable_relocs, ultimately leading to the assertion failure.

I'm not at all familiar with the gold code, so I'm not sure how to proceed at the moment.  Your thoughts would be appreciated.
Comment 1 Cary Coutant 2013-07-19 17:45:18 UTC
I'll take a look.
Comment 2 Cary Coutant 2013-07-22 16:40:10 UTC
*** Bug 15769 has been marked as a duplicate of this bug. ***
Comment 3 dwk 2013-11-06 02:28:58 UTC
I am encountering a very similar bug when trying to compile Firefox (latest source tree, Aurora 27+) with --emit-relocs. An in-source-tree autoconf test case called llvm-pr8927.m4, which is designed to catch LLVM's pr8927 bug (http://llvm.org/pr8927), is failing because of gold. Here is the test case:

$ cat test.c
struct foobar {
  int x;
};
static const struct foobar* foo() {
  static const struct foobar d = { 0 };
  return &d;
}
static const struct foobar* bar() {
  static const struct foobar d = { 0 };
  return &d;
}
__attribute__((noinline)) int zed(const struct foobar *a,
                                  const struct foobar *b) {
  return a == b;
}
int main() {
  return zed(foo(), bar());
}
$ gcc test.c -c
$ /tmp/binutils/gold/ld-new test.o -q
/tmp/binutils/gold/ld-new: internal error in emit_relocs_scan, at reloc.cc:550
$

I built gold from source (git commit dd0845d, version reports as "GNU gold (GNU Binutils 2.24.51.20131031) 1.11") to get a stacktrace from the latest version.

$ gdb -q --args /tmp/binutils/gold/ld-new test.o -q
Reading symbols from /tmp/binutils/gold/ld-new...done.
(gdb) b reloc.cc:550
Breakpoint 1 at 0x5d78c3: reloc.cc:550. (4 locations)
(gdb) r
Starting program: /tmp/binutils/gold/ld-new test.o -q

Breakpoint 1, gold::Sized_relobj_file<64, false>::emit_relocs_scan (
    this=this@entry=0x9799c0, symtab=symtab@entry=0x7fffffff8180, 
    layout=layout@entry=0x7fffffff83e0, 
    plocal_syms=plocal_syms@entry=0x7ffff7ff7508 "", p=...) at reloc.cc:550
550   gold_assert(rr != NULL);
(gdb) bt
#0  gold::Sized_relobj_file<64, false>::emit_relocs_scan (
    this=this@entry=0x9799c0, symtab=symtab@entry=0x7fffffff8180, 
    layout=layout@entry=0x7fffffff83e0, 
    plocal_syms=plocal_syms@entry=0x7ffff7ff7508 "", p=...) at reloc.cc:550
#1  0x00000000005d91fc in gold::Sized_relobj_file<64, false>::do_scan_relocs (
    this=0x9799c0, symtab=0x7fffffff8180, layout=0x7fffffff83e0, rd=0x9706f0)
    at reloc.cc:469
#2  0x00000000005d22e4 in scan_relocs (rd=<optimized out>, 
    layout=<optimized out>, symtab=<optimized out>, this=<optimized out>)
    at object.h:1069
#3  gold::Scan_relocs::run (this=0x97e250) at reloc.cc:188
#4  0x0000000000617aa5 in gold::Workqueue::find_and_run_task (
    this=this@entry=0x7fffffff7e30, thread_number=thread_number@entry=0)
    at workqueue.cc:319
#5  0x0000000000617dca in gold::Workqueue::process (
    this=this@entry=0x7fffffff7e30, thread_number=thread_number@entry=0)
    at workqueue.cc:495
#6  0x0000000000406674 in main (argc=3, argv=0x7fffffffe388) at main.cc:252
(gdb) p rr
$1 = (gold::Relocatable_relocs *) 0x97bff0
(gdb) c
Continuing.

Breakpoint 1, gold::Sized_relobj_file<64, false>::emit_relocs_scan (
    this=this@entry=0x9799c0, symtab=symtab@entry=0x7fffffff8180, 
    layout=layout@entry=0x7fffffff83e0, 
    plocal_syms=plocal_syms@entry=0x7ffff7ff7508 "", p=...) at reloc.cc:550
550   gold_assert(rr != NULL);
(gdb) bt
#0  gold::Sized_relobj_file<64, false>::emit_relocs_scan (
    this=this@entry=0x9799c0, symtab=symtab@entry=0x7fffffff8180, 
    layout=layout@entry=0x7fffffff83e0, 
    plocal_syms=plocal_syms@entry=0x7ffff7ff7508 "", p=...) at reloc.cc:550
#1  0x00000000005d91fc in gold::Sized_relobj_file<64, false>::do_scan_relocs (
    this=0x9799c0, symtab=0x7fffffff8180, layout=0x7fffffff83e0, rd=0x9706f0)
    at reloc.cc:469
#2  0x00000000005d22e4 in scan_relocs (rd=<optimized out>, 
    layout=<optimized out>, symtab=<optimized out>, this=<optimized out>)
    at object.h:1069
#3  gold::Scan_relocs::run (this=0x97e250) at reloc.cc:188
#4  0x0000000000617aa5 in gold::Workqueue::find_and_run_task (
    this=this@entry=0x7fffffff7e30, thread_number=thread_number@entry=0)
    at workqueue.cc:319
#5  0x0000000000617dca in gold::Workqueue::process (
    this=this@entry=0x7fffffff7e30, thread_number=thread_number@entry=0)
    at workqueue.cc:495
#6  0x0000000000406674 in main (argc=3, argv=0x7fffffffe388) at main.cc:252
(gdb) p rr
$2 = (gold::Relocatable_relocs *) 0x0
(gdb) q

The interesting part is that it reaches line 550 of reloc.cc twice, and the first time it succeeds. Maybe this will help provide context for why the second time fails (triggering the assert). Note that this is just a simple test case, but if I disable the test case then the final linking of some component of Firefox fails at the end as well.

I hope this additional test case helps in debugging this bug in gold. I am also unfamiliar with gold's codebase and don't really know how to investigate this issue. For now, I can use ld (Firefox provides ./configure --disable-gold), but I would be willing to assist with debugging this further if necessary.
Comment 4 Sourceware Commits 2013-11-06 18:38:14 UTC
       via  1d946cb356d22867128b40b9560857f930b2b0b0 (commit)
      from  b9502d3fd7848cd4d843be8bdc28633a3d24438d (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

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

commit 1d946cb356d22867128b40b9560857f930b2b0b0
Author: Cary Coutant <ccoutant@google.com>
Date:   Wed Nov 6 10:34:26 2013 -0800

    Fix assert failure with --emit-relocs and .eh_frame sections.
    
    gold/
    	PR gold/15758
    	* object.cc (Sized_relobj_file::do_layout): Handle .eh_frame sections
    	before reloc sections.

-----------------------------------------------------------------------

Summary of changes:
 gold/ChangeLog |    6 ++++++
 gold/object.cc |   44 ++++++++++++++++++++++----------------------
 2 files changed, 28 insertions(+), 22 deletions(-)
Comment 5 Cary Coutant 2013-11-06 18:42:58 UTC
Fixed on trunk.
Comment 6 law 2013-11-07 16:41:33 UTC
Cary -- thanks.  Your patch resolves things on my end.

Thanks again,
jeff
Comment 7 dwk 2013-11-11 02:00:43 UTC
The fix works for me too, thanks Cary!