Bug 25618 - use of gcc lto breaks --exclude-libs
Summary: use of gcc lto breaks --exclude-libs
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: 2.34
: P2 normal
Target Milestone: 2.35
Assignee: Not yet assigned to anyone
URL: https://sourceware.org/ml/binutils/20...
Keywords:
Depends on:
Blocks:
 
Reported: 2020-03-01 16:54 UTC by Alexander Sergeyev
Modified: 2020-03-02 01:11 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed: 2020-03-01 00:00:00


Attachments
source files and shell validation script (727 bytes, application/x-tar)
2020-03-01 16:54 UTC, Alexander Sergeyev
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Alexander Sergeyev 2020-03-01 16:54:30 UTC
Created attachment 12329 [details]
source files and shell validation script

(Originally reported to GCC bug tracker: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93980)

The apparent issue is that with LTO disabled -Wl,--exclude-libs,ALL flag works as intended, but with -flto -- symbols from linked archives are not hidden anymore.

The issue is easily reproduced with about 10 lines of code with no std libs involved. The reproducer consists of a static library "foo" and a shared library "bar" that links with "foo" (and we would like to hide "foo" symbols in "bar").

foo.h:
#pragma once
__attribute__((visibility("default"))) int foo();

foo.cc:
#include "foo.h"
int foo() { return 100; }

bar.h:
#pragma once
__attribute__((visibility("default"))) int bar();

bar.cc:
#include "bar.h"
#include "foo.h"
int bar() { return foo(); }

Build commands:
g++ -fPIC -fvisibility=hidden -fvisibility-inlines-hidden -flto -c foo.cc -o .foo.o
ar qc .foo.a .foo.o
g++ -fPIC -fvisibility=hidden -fvisibility-inlines-hidden -flto -c bar.cc -o .bar.o
g++ -Wl,--exclude-libs,ALL -flto -shared -o libbar.so .bar.o .foo.a
readelf --dyn-syms --wide libbar.so | c++filt

The last command produces both bar() and foo() -- that is, foo() is not hidden. Replacing -flto with -fno-lto gives only bar(), which is the expected result. The issue is present when using both ld.bfd and ld.gold (ie -fuse-ld=gold).

--

$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-pc-linux-gnu/9.2.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /var/tmp/portage/sys-devel/gcc-9.2.0-r4/work/gcc-9.2.0/configure --host=x86_64-pc-linux-gnu --build=x86_64-pc-linux-gnu --prefix=/usr --bindir=/usr/x86_64-pc-linux-gnu/gcc-bin/9.2.0 --includedir=/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/include --datadir=/usr/share/gcc-data/x86_64-pc-linux-gnu/9.2.0 --mandir=/usr/share/gcc-data/x86_64-pc-linux-gnu/9.2.0/man --infodir=/usr/share/gcc-data/x86_64-pc-linux-gnu/9.2.0/info --with-gxx-include-dir=/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/include/g++-v9 --with-python-dir=/share/gcc-data/x86_64-pc-linux-gnu/9.2.0/python --enable-languages=c,c++,go,fortran --enable-obsolete --enable-secureplt --disable-werror --with-system-zlib --disable-nls --enable-checking=release --with-bugurl=https://bugs.gentoo.org/ --with-pkgversion='Gentoo 9.2.0-r4 p5' --disable-esp --enable-libstdcxx-time --with-build-config=bootstrap-lto --disable-libstdcxx-pch --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-clocale=gnu --disable-multilib --with-multilib-list=m64 --disable-altivec --disable-fixed-point --enable-targets=all --enable-libgomp --disable-libmudflap --disable-libssp --disable-systemtap --enable-vtable-verify --enable-lto --without-isl --enable-default-pie --enable-default-ssp
Thread model: posix
gcc version 9.2.0 (Gentoo 9.2.0-r4 p5)

$ ld -v
GNU ld (Gentoo 2.34 p1) 2.34.0
Comment 1 Alexander Sergeyev 2020-03-01 17:16:19 UTC
A patch for the issue is proposed by H.J. Lu (see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93980#c4). 

diff --git a/ld/plugin.c b/ld/plugin.c
index 47c053e5a0a..5960df65243 100644
--- a/ld/plugin.c
+++ b/ld/plugin.c
@@ -1242,6 +1242,8 @@ plugin_object_p (bfd *ibfd)
       ibfd->plugin_format = bfd_plugin_yes;
       ibfd->plugin_dummy_bfd = abfd;
       bfd_make_readable (abfd);
+      if (ibfd->my_archive != NULL)
+  abfd->no_export = ibfd->my_archive->no_export;
       return abfd->xvec;
     }
   else
Comment 2 H.J. Lu 2020-03-01 21:08:07 UTC
A patch is posted at

https://sourceware.org/ml/binutils/2020-03/msg00000.html
Comment 3 H.J. Lu 2020-03-02 01:10:09 UTC
Fixed for 2.35.
Comment 4 Sourceware Commits 2020-03-02 01:11:30 UTC
The master branch has been updated by H.J. Lu <hjl@sourceware.org>:

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

commit 2aa90762b71af7f04032d2bebed6470070d3d801
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Sun Mar 1 17:07:12 2020 -0800

    plugin: Copy the no_export field to the IR dummy object
    
    Copy the no_export field to the IR dummy object when claiming an IR
    object.
    
    	PR ld/25618
    	* plugin.c (plugin_object_p): Copy the no_export field to the IR
    	dummy object.
    	* testsuite/ld-plugin/lto.exp (lto_link_elf_tests): Add
    	PR ld/25618 tests.
    	* testsuite/ld-plugin/pr25618.d: New file.
    	* testsuite/ld-plugin/pr25618a.cc: Likewise.
    	* testsuite/ld-plugin/pr25618a.h: Likewise.
    	* testsuite/ld-plugin/pr25618b.cc: Likewise.
    	* testsuite/ld-plugin/pr25618b.h: Likewise.