bug-binutils
[Top][All Lists]
Advanced

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

[Bug gold/16900] New: [PATCH] when linked with gold, NetBSD ld.elf_so cr


From: ben at minix3 dot org
Subject: [Bug gold/16900] New: [PATCH] when linked with gold, NetBSD ld.elf_so crashes due to missing .plt.got entry
Date: Sun, 04 May 2014 01:59:06 +0000

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

            Bug ID: 16900
           Summary: [PATCH] when linked with gold, NetBSD ld.elf_so
                    crashes due to missing .plt.got entry
           Product: binutils
           Version: 2.25 (HEAD)
            Status: NEW
          Severity: normal
          Priority: P2
         Component: gold
          Assignee: ian at airs dot com
          Reporter: ben at minix3 dot org
                CC: ccoutant at google dot com

Created attachment 7585
  --> https://sourceware.org/bugzilla/attachment.cgi?id=7585&action=edit
.tar file with script to reproduce the problem; .o files (as the script
generates on my end); executables (as the script generates on my end); patch
file with suggested solution.

Hi, I'm Ben, from the Minix project (www.minix3.org). Pleased to meet you.

We're using Gold to link (while crossbuilding), among other things, some NetBSD
code as part of the Minix build.

This bug is about a problem I can reproduce on unmodified binutils HEAD,
19a170752b with a small test case.

Observations:
  - NetBSD ld.elf_so linked using gold crashes.
  - it turns out ld.elf_so mis-computes the relocbase at startup time.
  - it turns out due to _DYNAMIC ptr not being stored correctly in the GOT.
  - when linking a shared object (the ld.so executable in my case), the first
    entry of .plt.got was 0, where ld.so expects the _DYNAMIC pointer
  - all static executables linked with gold are OK
  - the exact same ld invocation and inputs with bfd-ld results in an OK binary

How to reproduce:
  - see compile.sh script in the attached tar; it is a self-contained, fairly
minimal test case to reproduce the problem on my end (native gcc & gold on
ubuntu).

 I did the minimum amount of digging to solve the problem for us. Therefore the
analysis and patch may be crude. Nevertheless, here they are:

 Analysis:
  - it seems .plt.got is only initialized in gold if there are unresolved
external
    references; with -Bsymbolic, which ld.so is linked with, these can all
vanish
    and so .plt.got is left uninitialized.

Suggested solution:
  - in patch: as long as there is a global_offset_table_, make sure there is
    a .plt.got initialized to contain it in do_finalize_sections().

The current result of readelf -x .got.plt:
   0x0000128c 00000000 00000000 00000000          ............

with the patch:
   0x000012c4 54120000 00000000 00000000          T...........

With matching nm output for _DYNAMIC:
   00001254 d _DYNAMIC

Attached: .tar file with
  - script to reproduce the problem by compiling and linking 2 C files, with
patch and info in comments
  - the generated object files on my side to eliminate compiling dependencies
  - the 2 resulting ('wrong' and 'right') binaries after linking on my side
  - 0001-gold-i386-fix-missing-_DYNAMIC-ptr-in-.plt.got.patch: patchfile
containing suggested fix. looks like this:

commit e940b61beb39318c0c457ce85dff19a40a3e3e2f
Author: Ben Gras <address@hidden>
Date:   Sat May 3 19:40:19 2014 +0200

    gold i386: fix missing _DYNAMIC ptr in .plt.got

    In some circumstances (e.g. -Bsymbolic and no external references)
    make_plt_section() isn't triggered leaving it empty, while sometimes
    still needed for shared objects.

        gold/
            * i386.cc (Target_i386::do_finalize_sections): add call to
make_plt_section()
              if there is no plt_ but there is a GOT, so that the first entry
is always
              initialized.

diff --git a/gold/i386.cc b/gold/i386.cc
index a2f7522..f06d60d 100644
--- a/gold/i386.cc
+++ b/gold/i386.cc
@@ -2543,6 +2543,10 @@ Target_i386::do_finalize_sections(
   Symbol* sym = this->global_offset_table_;
   if (sym != NULL)
     {
+      // create a plt
+      if (this->plt_ == NULL)
+        this->make_plt_section(symtab, layout);
+
       uint32_t data_size = this->got_plt_->current_data_size();
       symtab->get_sized_symbol<32>(sym)->set_symsize(data_size);
     }



Again, the patch and/or the description in the commit may be too crude, it's
just as far as I've gotten understanding gold (and ELF for that matter).

-- 
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]