bug-binutils
[Top][All Lists]
Advanced

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

[Bug ld/26314] New: Linking LTO objects with conflicting symbol definiti


From: nickc at redhat dot com
Subject: [Bug ld/26314] New: Linking LTO objects with conflicting symbol definitions from static and shared libraries fails
Date: Wed, 29 Jul 2020 12:53:57 +0000

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

            Bug ID: 26314
           Summary: Linking LTO objects with conflicting symbol
                    definitions from static and shared libraries fails
           Product: binutils
           Version: 2.35
            Status: NEW
          Severity: normal
          Priority: P2
         Component: ld
          Assignee: unassigned at sourceware dot org
          Reporter: nickc at redhat dot com
  Target Milestone: ---

In simplest terms, if we use LTO to build binutils the resultant binaries will
fault all over the place.  If you look at it in the debugger we'll have jumped
to 0x0 via an indirect jump out of the PLT.  The problem is the GOT entries are
zero'd out.

It looks like the preconditions are:

First, we need to have a DSO which provides a symbol definition (libbfd).

Second, we need to have an executable which links against that DSO (ar).  The
components of that executable are LTO objects and in one or more of those LTO'd
objects there must be another definition of the symbol in question (-liberty
and
libiberty.a referenced on the command line to link ar).

The when linking the executable the linker has to merge the two definitions. 
In
general we'll prefer the version from the executable over the version from the
DSO.

However, in the case of an LTO link, the symbol's input section is marked as
SEC_EXCLUDE for the main executable (that seems to be an artifact of LTO and
the
section flags it uses).  In that scenario the output section will be reset to
the ABS section.  The net result is we create a dynamic symbol with an absolute
type.

When the dynamic linker performs its symbol resolution that absolute dynamic
symbol will take precedence over the symbol in the DSO and the dynamic linker
will slam a new value into the GOT entry for the symbol.

This is fairly abstract, so here is a reproducer in the form of binutils
itself that you can examine in a debugger.  It uses the Fedora rawhide (f33) 
binutils sources:

  1. fedpkg clone binutils

  2. sed -i -e 's/%define _lto_cflags/#define _lto_cflags/' binutils.spec
  [This step disables a workaround currently in the binutils.spec.
  The  workaround disables building the binutils with LTO enabled].

  3. fedpkg srpm
  4. fedpkg mock-config > my.cfg
  5. mock -r my.cfg --without=testsuite *.src.rpm
  6. mock --uniqueext=xxx --dnf -r my.cfg shell
  7. nm --dynamic /builddir/build/BUILD/binutils-2.35/binutils/.libs/ar

  This will show lots of entries, including:

  0000000000000000 A lrealpath

  Attempts to run the ar binary will fail, as will all the other newly
  built binutils tools.

  [I am attempting to create a simpler, stand alone reproducer for this
  problem.  I will add an update to this PR when/if I find one].

  Jeff Law has come up with a hack which appears to fix the problem,
  but we are not sure if it is the correct solution:

diff --git a/bfd/elflink.c b/bfd/elflink.c
index 998b72f228..2f06e835c1 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -1633,7 +1633,8 @@ _bfd_elf_merge_symbol (bfd *abfd,
       && newdef
       && (olddef
          || (h->root.type == bfd_link_hash_common
-             && (newweak || newfunc))))
+             && (newweak || newfunc)))
+      && (oldsec->flags & SEC_EXCLUDE) == 0)
     {
       *override = TRUE;
       newdef = FALSE;

THe effect here is the symbol will be resolved via the libbfd.so DSO.  That
doesn't seem entirely correct since we have a definition of lrealpath in
libiberty, which is referenced twice on the link line.

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