Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ubuntu bionic x86_64: static libc++.a version 9 cannot be used in shared libraries since build without -fPIC #42949

Closed
llvmbot opened this issue Oct 8, 2019 · 20 comments
Assignees
Labels
bugzilla Issues migrated from bugzilla packaging

Comments

@llvmbot
Copy link
Collaborator

llvmbot commented Oct 8, 2019

Bugzilla Link 43604
Resolution FIXED
Resolved on Jul 27, 2021 11:24
Version unspecified
OS Linux
Blocks #48661
Reporter LLVM Bugzilla Contributor
CC @chandlerc,@MaskRay,@ldionne,@sylvestre,@tstellar
Fixed by commit(s) 21c24ae

Extended Description

/usr/bin/ld: /usr/lib/llvm-9/lib/libc++.a(algorithm.cpp.o): relocation R_X86_64_32S against .rodata._ZNSt3__16__sortIRNS_6__lessIccEEPcEEvT0_S5_T_' can not be used when making a shared object; recompile with -fPIC /usr/bin/ld: /usr/lib/llvm-9/lib/libc++.a(chrono.cpp.o): relocation R_X86_64_32 against .rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: /usr/lib/llvm-9/lib/libc++.a(condition_variable.cpp.o): relocation R_X86_64_32 against .rodata.str1.1' can not be used when making a shared object; recompile with -fPIC /usr/bin/ld: /usr/lib/llvm-9/lib/libc++.a(exception.cpp.o): relocation R_X86_64_32S against symbol _ZTVSt16nested_exception' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: /usr/lib/llvm-9/lib/libc++.a(future.cpp.o): relocation R_X86_64_32 against .rodata.str1.1' can not be used when making a shared object; recompile with -fPIC /usr/bin/ld: /usr/lib/llvm-9/lib/libc++.a(hash.cpp.o): relocation R_X86_64_32 against .rodata' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: /usr/lib/llvm-9/lib/libc++.a(ios.cpp.o): relocation R_X86_64_32S against symbol _ZTVNSt3__18ios_baseE' can not be used when making a shared object; recompile with -fPIC /usr/bin/ld: /usr/lib/llvm-9/lib/libc++.a(iostream.cpp.o): relocation R_X86_64_32 against .bss' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: /usr/lib/llvm-9/lib/libc++.a(locale.cpp.o): relocation R_X86_64_32 against .bss' can not be used when making a shared object; recompile with -fPIC /usr/bin/ld: /usr/lib/llvm-9/lib/libc++.a(memory.cpp.o): relocation R_X86_64_32 against .rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: /usr/lib/llvm-9/lib/libc++.a(mutex.cpp.o): relocation R_X86_64_32 against .rodata.str1.1' can not be used when making a shared object; recompile with -fPIC /usr/bin/ld: /usr/lib/llvm-9/lib/libc++.a(new.cpp.o): relocation R_X86_64_32 against symbol _ZTISt9bad_alloc' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: /usr/lib/llvm-9/lib/libc++.a(regex.cpp.o): relocation R_X86_64_32 against symbol __gxx_personality_v0' can not be used when making a shared object; recompile with -fPIC /usr/bin/ld: /usr/lib/llvm-9/lib/libc++.a(stdexcept.cpp.o): relocation R_X86_64_32S against symbol _ZTVSt11logic_error' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: /usr/lib/llvm-9/lib/libc++.a(string.cpp.o): relocation R_X86_64_32 against .rodata.str1.1' can not be used when making a shared object; recompile with -fPIC /usr/bin/ld: /usr/lib/llvm-9/lib/libc++.a(system_error.cpp.o): relocation R_X86_64_32S against symbol _ZTVNSt3__114error_categoryE' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: /usr/lib/llvm-9/lib/libc++.a(thread.cpp.o): relocation R_X86_64_32 against .rodata.str1.1' can not be used when making a shared object; recompile with -fPIC /usr/bin/ld: /usr/lib/llvm-9/lib/libc++.a(vector.cpp.o): relocation R_X86_64_32 against .rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: /usr/lib/llvm-9/lib/libc++.a(charconv.cpp.o): relocation R_X86_64_32S against `.rodata' can not be used when making a shared object; recompile with -fPIC

@llvmbot
Copy link
Collaborator Author

llvmbot commented Oct 8, 2019

assigned to @ldionne

@llvmbot
Copy link
Collaborator Author

llvmbot commented Oct 8, 2019

libc++ from llvm-8 have no such problem

@chandlerc
Copy link
Member

Unsure who all to CC here, but this issue makes the apt.llvm.org Debian packages really broken. The issue persists to this day with LLVM 12.

Basic example of how this works well with libstdc++ but not with libc++:

$ cat plugin_test.cpp
#include <iostream>
__attribute__((visibility("default")))
extern "C" void plugin() {
        std::cout << "Hello World from a plugin!" << std::endl;
}
$ clang++-12 -shared -o plugin.so -fvisibility=hidden plugin_test.cpp -static-libstdc++
$ ldd plugin.so
        linux-vdso.so.1 (0x00007ffcb707c000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f993b614000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f993b5f9000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f993b407000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f993b8c2000)
$ clang++-12 -shared -o plugin.so -fvisibility=hidden plugin_test.cpp -stdlib=libc++ -static-libstdc++
/usr/bin/ld: /tmp/plugin_test-e54e21.o: relocation R_X86_64_32 against undefined symbol `__gxx_personality_v0' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc++.a(string.cpp.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc++.a(ios.cpp.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc++.a(ios.instantiations.cpp.o): relocation R_X86_64_32S against symbol `_ZTVNSt3__115basic_streambufIcNS_11char_traitsIcEEEE' can not be used when making a 
shared object; recompile with -fPIC
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc++.a(iostream.cpp.o): relocation R_X86_64_32 against `.bss' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc++.a(locale.cpp.o): relocation R_X86_64_32 against `.bss' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc++.a(charconv.cpp.o): relocation R_X86_64_32S against `.rodata' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc++.a(exception.cpp.o): relocation R_X86_64_32S against symbol `_ZTVSt16nested_exception' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc++.a(memory.cpp.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc++.a(mutex.cpp.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc++.a(new.cpp.o): relocation R_X86_64_32 against undefined symbol `_ZTISt9bad_alloc' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc++.a(stdexcept.cpp.o): relocation R_X86_64_32S against undefined symbol `_ZTVSt11logic_error' can not be used when making a shared object; recompile with -f
PIC
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc++.a(system_error.cpp.o): relocation R_X86_64_32S against symbol `_ZTVNSt3__114error_categoryE' can not be used when making a shared object; recompile with 
-fPIC
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc++.a(vector.cpp.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc++.a(condition_variable.cpp.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc++.a(thread.cpp.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc++.a(future.cpp.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Note that libstdc++ isn't one of the DSOs in the first ldd printout. This shows that we are successfully statically linking the archives despite building a shared library.

I've verified that this happens at least with 10, 11, and 12.

Any chance we could fix this? I'm pretty sure this just a CMake setting getting flipped, and so it'd be particularly nice to actually push fresh debian archives with this fix as w/o it the debian packages are completely broken for this use case.

@chandlerc
Copy link
Member

I forgot to add that this mostly breaks use of a statically linked libc++ with PIE executables:

$ cat test.cpp
#include <iostream>
int main () {
        std::cout << "Hello World!" << std::endl;
}
$ clang++-12 -o test test.cpp -pie -static-libstdc++
$ ./test
Hello World!
$ ldd test
        linux-vdso.so.1 (0x00007ffe539ec000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f9c05271000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f9c05256000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f9c05064000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f9c054bb000)
$ clang++-12 -o test test.cpp -pie -stdlib=libc++ -static-libstdc++
/usr/bin/ld: /tmp/test-6352e1.o: relocation R_X86_64_32 against undefined symbol `__gxx_personality_v0' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc++.a(string.cpp.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc++.a(ios.cpp.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc++.a(ios.instantiations.cpp.o): relocation R_X86_64_32S against symbol `_ZTVNSt3__115basic_streambufIcNS_11char_traitsIcEEEE' can not be used when making a 
PIE object; recompile with -fPIE
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc++.a(iostream.cpp.o): relocation R_X86_64_32 against `.bss' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc++.a(locale.cpp.o): relocation R_X86_64_32 against `.bss' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc++.a(charconv.cpp.o): relocation R_X86_64_32S against `.rodata' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc++.a(exception.cpp.o): relocation R_X86_64_32S against symbol `_ZTVSt16nested_exception' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc++.a(memory.cpp.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc++.a(mutex.cpp.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc++.a(new.cpp.o): relocation R_X86_64_32 against undefined symbol `_ZTISt9bad_alloc' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc++.a(stdexcept.cpp.o): relocation R_X86_64_32S against undefined symbol `_ZTVSt11logic_error' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc++.a(system_error.cpp.o): relocation R_X86_64_32S against symbol `_ZTVNSt3__114error_categoryE' can not be used when making a PIE object; recompile with -fP
IE
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc++.a(vector.cpp.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc++.a(condition_variable.cpp.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc++.a(thread.cpp.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc++.a(future.cpp.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a PIE object; recompile with -fPIE
clang: error: linker command failed with exit code 1 (use -v to see invocation)

All of this testing is done on a vanilla Ubuntu 20.04 (LTS) install with the https://apt.llvm.org/llvm.sh script used to install the relevant packages.

@ldionne
Copy link
Member

ldionne commented Jun 1, 2021

I'm digging through this issue now. I believe the following commit is relevant for context:

commit 30f305efe27928b15d24c7670cce54d26dd2e348
Author: Louis Dionne <ldionne@apple.com>
Date:   Thu Mar 14 14:38:38 2019 +0000

    [libc++] Do not force building with -fPIC (re-applying)

    Summary:
    In r355746, we stopped forcing to build with -fPIC because that should
    be specified by the CMAKE_POSITION_INDEPENDENT_CODE option at CMake
    configure time (and by default -fPIC is used for shared libraries anyways).

    However, r355746 had to be reverted in r355756 because we were not
    actually building the shared library with -fPIC. The reason is that
    we were sharing an object library between the static and the shared
    library, which caused flags for static libraries to be used when
    building object files that were going to be used for a shared library.

    Since this was resolved by r356150, we can stop forcing -fPIC again.

    Differential Revision: https://reviews.llvm.org/D59250

    llvm-svn: 356153

Basically, I removed -fPIC from both the static and the shared libc++ builds so that the CMake default would be used. The CMake defaults are -fPIC for shared libraries, and nothing for static libraries. Hence, that commit changed the static library from being built with -fPIC to not being built with -fPIC (but there was no change for the shared library).

At the time, it seemed excessive to force whoever's building libc++ (e.g. vendors) to use -fPIC if they don't want to. The idea was to use -DCMAKE_POSITION_INDEPENDENT_CODE=ON if one wanted to build with PIC enabled, as intended by CMake. I'm still thinking this is probably the right thing to do, since not everyone wants to build with -fPIC (for example, Apple does not, even for the shared library).

So, I acknowledge 100% that the problem you're seeing exists and needs to be fixed. I'm just not certain whether:

(1) we should start enforcing -fPIC unconditionnally in libc++ again, or
(2) modify the build scripts such that we set -DCMAKE_POSITION_INDEPENDENT_CODE=ON when we build for the LLVM release

I'd be leaning towards (2) since that would bring back the ability to use libc++.a as released by LLVM in shared libraries and PIE executables without forcing all vendors to go down the same route.

On the other hand, I'm not super well versed in the whole PIE/PIC story, so I read this to try and get a better idea of the tradeoffs: https://lists.debian.org/debian-devel/2016/05/msg00309.html.

This seems to suggest that nowadays, avoiding -fPIC might just not be worth it, and so perhaps it would be reasonable to simply force -fPIC down everybody's throat for the sake of consistency. I'm certainly open to that option if someone knowledgeable can argue for it. Do we lose anything at all besides by enabling -fPIC?

@chandlerc
Copy link
Member

I'm digging through this issue now. I believe the following commit is
relevant for context:

commit 30f305efe27928b15d24c7670cce54d26dd2e348
Author: Louis Dionne <ldionne@apple.com>
Date:   Thu Mar 14 14:38:38 2019 +0000

    [libc++] Do not force building with -fPIC (re-applying)

    Summary:
    In r355746, we stopped forcing to build with -fPIC because that

should
be specified by the CMAKE_POSITION_INDEPENDENT_CODE option at CMake
configure time (and by default -fPIC is used for shared libraries
anyways).

    However, r355746 had to be reverted in r355756 because we were not
    actually building the shared library with -fPIC. The reason is that
    we were sharing an object library between the static and the shared
    library, which caused flags for static libraries to be used when
    building object files that were going to be used for a shared

library.

    Since this was resolved by r356150, we can stop forcing -fPIC again.

    Differential Revision: https://reviews.llvm.org/D59250

    llvm-svn: 356153

Basically, I removed -fPIC from both the static and the shared libc++
builds so that the CMake default would be used. The CMake defaults are
-fPIC for shared libraries, and nothing for static libraries. Hence, that
commit changed the static library from being built with -fPIC to not being
built with -fPIC (but there was no change for the shared library).

At the time, it seemed excessive to force whoever's building libc++ (e.g.
vendors) to use -fPIC if they don't want to. The idea was to use
-DCMAKE_POSITION_INDEPENDENT_CODE=ON if one wanted to build with PIC
enabled, as intended by CMake. I'm still thinking this is probably the right
thing to do, since not everyone wants to build with -fPIC (for example,
Apple does not, even for the shared library).

So, I acknowledge 100% that the problem you're seeing exists and needs to be
fixed. I'm just not certain whether:

(1) we should start enforcing -fPIC unconditionnally in libc++ again, or
(2) modify the build scripts such that we set
-DCMAKE_POSITION_INDEPENDENT_CODE=ON when we build for the LLVM release

I'd be leaning towards (2) since that would bring back the ability to use
libc++.a as released by LLVM in shared libraries and PIE executables without
forcing all vendors to go down the same route.

I might go with (2) if possible for patching the LLVM-12 release, and I would really love to see a patch release with this fixed. It seems a strict improvement at low cost (only the .a files change).

On the other hand, I'm not super well versed in the whole PIE/PIC story, so
I read this to try and get a better idea of the tradeoffs:
https://lists.debian.org/debian-devel/2016/05/msg00309.html.

This seems to suggest that nowadays, avoiding -fPIC might just not be
worth it, and so perhaps it would be reasonable to simply force -fPIC down
everybody's throat for the sake of consistency. I'm certainly open to that
option if someone knowledgeable can argue for it. Do we lose anything at all
besides by enabling -fPIC?

I largely agree with this assessment. I think that building .o files and .a files with PIC always (on Linux ABIs at least) and then letting the linker do its thing for .so and executables is the best choice.

At the least, it'd be nice of users that build their own libc++ got the right defaults out of the box here, and the right default seems almost certainly for PIC .a files -- otherwise PIE isn't ever really an option.

@MaskRay
Copy link
Member

MaskRay commented Jun 4, 2021

The -fPIE/-fPIC distinction is ELF specific. The only differences are:

  • -fPIE can use more optimized thread-local storage models. (Windows/Darwin only support one model and have no such complexity.)
  • An external linkage function/variable with STB_GLOBAL binding and STV_DEFAULT visibility is interposable by default.
    (Very unfortunate traditional interpretation) GCC suppresses interprocedural optimizations (including inlining) for non-vague-linkage functions for -fPIC.
    Interprocedural optimizations are enabled for GCC -fPIE.

The main CMake file uses -fno-semantic-interposition by default now (https://reviews.llvm.org/D102453) so the second benefit is moot.
The first actually matters a bit for certain applications but probably small for libc++.

I know very little about CMake and just learned CMAKE_POSITION_INDEPENDENT_CODE.
Since there is a standard CMake variable, perhaps we should move our LLVM_ENABLE_PIC logic to CMAKE_POSITION_INDEPENDENT_CODE instead...
There is a difference about different defaults:
LLVM_ENABLE_PIC is on by default (the default libLLVM*.a/libclang*.a get -fPIC instead of -fPIE) while (I guess) CMAKE_POSITION_INDEPENDENT_CODE is off for certain build configurations?

llvm/CMakeLists.txt
410:option(LLVM_ENABLE_PIC "Build Position-Independent Code" ON)

I think defaulting CMAKE_POSITION_INDEPENDENT_CODE to on makes a lot of sense...

@sylvestre
Copy link
Collaborator

Try to rebuild -12 packages (apt.llvm.org) with
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
(stage 2)

but I am getting the same issue:

echo '#include
int main () {
std::cout << "Hello World!" << std::endl;
}'>test.cpp

clang++-12 -o test test.cpp -pie -stdlib=libc++ -static-libstdc++

/usr/bin/ld: /tmp/test-75d1cf.o: relocation R_X86_64_32 against undefined symbol __gxx_personality_v0' can not be used when making a PIE object; recompile with -fPIE /usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/libc++.a(string.cpp.o): relocation R_X86_64_32 against .rodata.str1.1' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/libc++.a(ios.cpp.o): relocation R_X86_64_32 against .rodata.str1.1' can not be used when making a PIE object; recompile with -fPIE /usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/libc++.a(ios.instantiations.cpp.o): relocation R_X86_64_32S against symbol _ZTVNSt3__115basic_streambufIcNS_11char_traitsIcEEEE' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/libc++.a(iostream.cpp.o): relocation R_X86_64_32 against .bss' can not be used when making a PIE object; recompile with -fPIE /usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/libc++.a(locale.cpp.o): relocation R_X86_64_32 against .bss' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/libc++.a(charconv.cpp.o): relocation R_X86_64_32S against .rodata' can not be used when making a PIE object; recompile with -fPIE /usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/libc++.a(exception.cpp.o): relocation R_X86_64_32S against symbol _ZTVSt16nested_exception' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/libc++.a(memory.cpp.o): relocation R_X86_64_32 against .rodata.str1.1' can not be used when making a PIE object; recompile with -fPIE /usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/libc++.a(mutex.cpp.o): relocation R_X86_64_32 against .rodata.str1.1' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/libc++.a(new.cpp.o): relocation R_X86_64_32 against undefined symbol _ZTISt9bad_alloc' can not be used when making a PIE object; recompile with -fPIE /usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/libc++.a(stdexcept.cpp.o): relocation R_X86_64_32S against undefined symbol _ZTVSt11logic_error' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/libc++.a(system_error.cpp.o): relocation R_X86_64_32S against symbol _ZTVNSt3__114error_categoryE' can not be used when making a PIE object; recompile with -fPIE /usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/libc++.a(vector.cpp.o): relocation R_X86_64_32 against .rodata.str1.1' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/libc++.a(condition_variable.cpp.o): relocation R_X86_64_32 against .rodata.str1.1' can not be used when making a PIE object; recompile with -fPIE /usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/libc++.a(thread.cpp.o): relocation R_X86_64_32 against .rodata.str1.1' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/libc++.a(future.cpp.o): relocation R_X86_64_32 against .rodata.str1.1' can not be used when making a PIE object; recompile with -fPIE /usr/bin/ld: /tmp/test-75d1cf.o: warning: relocation in read-only section .text'
clang: error: linker command failed with exit code 1 (use -v to see invocation)

@chandlerc
Copy link
Member

Some of those errors are from your test, try:

clang++-12 -o test -fPIC test.cpp -pie -stdlib=libc++ -static-libstdc++

The -fPIC (or -fPIE, not a big diff here) impacts test.cpp` and will fix some of the errors.

The others do look like the same bug here. But the path to libc++.a looks like the system libc++.a... is this after installing the new package?

Is the stage2 build where you're adding the CMake flag the one that is building the runtimes, or just the stage2 compiler? Maybe need to pass the CMake flags specifically to the runtimes part of the build (which can happen even in stage1)

@tstellar
Copy link
Collaborator

tstellar commented Jun 4, 2021

Can this be fixed by just setting the necessary CMake variable when building the debian packages?

@chandlerc
Copy link
Member

Can this be fixed by just setting the necessary CMake variable when building
the debian packages?

Somewhere, yes. Not sure where the CMake variables are set when building the debian packages. If you point me at the script I can try to suggest how to fix things.

@sylvestre
Copy link
Collaborator

Here is the patch that I applied:

diff --git a/debian/rules b/debian/rules
index a5d9445..ad76399 100755
--- a/debian/rules
+++ b/debian/rules
@@ -395,6 +395,7 @@ override_dh_auto_configure: preconfigure
-DCMAKE_VERBOSE_MAKEFILE=ON
-DCMAKE_BUILD_TYPE=RelWithDebInfo
-DCMAKE_CXX_FLAGS_RELWITHDEBINFO="$(opt_flags)" \

  •   -DCMAKE_POSITION_INDEPENDENT_CODE=ON \
      -DLLVM_LINK_LLVM_DYLIB=ON \
      -DLLVM_INSTALL_UTILS=ON \
      -DLLVM_VERSION_SUFFIX= \
    

sources are:
https://salsa.debian.org/pkg-llvm-team/llvm-toolchain/-/tree/12/debian

you can find the tarballs:
https://apt.llvm.org/unstable/pool/main/l/llvm-toolchain-12/

for example:
dget -x https://apt.llvm.org/unstable/pool/main/l/llvm-toolchain-12/llvm-toolchain-12_12.0.1~%2b%2b20210604062548%2bf2ce10d14b7c-1~exp1~20210604043255.98.dsc
cd llvm-toolchain-12*

dpkg-buildpackage -nc -b

(takes a while)

@chandlerc
Copy link
Member

Here is the patch that I applied:

diff --git a/debian/rules b/debian/rules
index a5d9445..ad76399 100755
--- a/debian/rules
+++ b/debian/rules
@@ -395,6 +395,7 @@ override_dh_auto_configure: preconfigure
-DCMAKE_VERBOSE_MAKEFILE=ON
-DCMAKE_BUILD_TYPE=RelWithDebInfo
-DCMAKE_CXX_FLAGS_RELWITHDEBINFO="$(opt_flags)" \

  •   -DCMAKE_POSITION_INDEPENDENT_CODE=ON \
      -DLLVM_LINK_LLVM_DYLIB=ON \
      -DLLVM_INSTALL_UTILS=ON \
      -DLLVM_VERSION_SUFFIX= \
    

You'll also want to add it to the bootstrap passthrough flag list I would guess?

I would love to send you patches to this file, but there is no license and so I'm unsure how to do so... While patching this, maybe add the fix suggested here so that the resulting archive also works out of the box? llvm/llvm-bugzilla-archive#46321 #c5

@sylvestre
Copy link
Collaborator

You'll also want to add it to the bootstrap passthrough flag list I would
guess?
Arf, yeah, you are probably correct. This is biting me one more time :(

I just started a new build to see if it fixes the issue.

I would love to send you patches to this file, but there is no license and
so I'm unsure how to do so...
The license is the same as llvm
https://salsa.debian.org/pkg-llvm-team/llvm-toolchain/-/blob/12/debian/copyright#L27
(to simplify applying patches upstream)

While patching this, maybe add the fix
suggested here so that the resulting archive also works out of the box?
llvm/llvm-bugzilla-archive#46321 #c5

Sure, I will have a look.

@sylvestre
Copy link
Collaborator

Chandler, failed again -even with CLANG_BOOTSTRAP_PASSTHROUGH

diff --git a/debian/rules b/debian/rules
index a5d9445..a1201cb 100755
--- a/debian/rules
+++ b/debian/rules
@@ -395,6 +395,7 @@ override_dh_auto_configure: preconfigure
-DCMAKE_VERBOSE_MAKEFILE=ON
-DCMAKE_BUILD_TYPE=RelWithDebInfo
-DCMAKE_CXX_FLAGS_RELWITHDEBINFO="$(opt_flags)" \

  •   -DCMAKE_POSITION_INDEPENDENT_CODE=ON \
      -DLLVM_LINK_LLVM_DYLIB=ON \
      -DLLVM_INSTALL_UTILS=ON \
      -DLLVM_VERSION_SUFFIX= \
    

@@ -417,7 +418,7 @@ override_dh_auto_configure: preconfigure
-DLLVM_POLLY_LINK_INTO_TOOLS=ON
-DBOOTSTRAP_CMAKE_CXX_FLAGS='$(BOOTSTRAP_CXXFLAGS_EXTRA)'
-DBOOTSTRAP_CMAKE_C_FLAGS='$(BOOTSTRAP_CFLAGS_EXTRA)' \

  •   -DCLANG_BOOTSTRAP_PASSTHROUGH="CMAKE_INSTALL_PREFIX;CMAKE_VERBOSE_MAKEFILE;CMAKE_BUILD_TYPE;CMAKE_CXX_FLAGS_RELWITHDEBINFO;LLVM_LINK_LLVM_DYLIB;LLVM_INSTALL_UTILS;LLVM_VERSION_SUFFIX;LLVM_ENABLE_SPHINX;SPHINX_WARNINGS_AS_ERRORS;LLVM_BUILD_LLVM_DYLIB;LLVM_ENABLE_RTTI;LLVM_ENABLE_FFI;LIBCLANG_LIBRARY_VERSION;ENABLE_LINKER_BUILD_ID;POLLY_BUNDLED_JSONCPP;LLVM_EXPERIMENTAL_TARGETS_TO_BUILD;LLVM_USE_PERF;LLVM_ENABLE_ASSERTIONS;LLVM_BINUTILS_INCDIR;LLVM_HOST_TRIPLE;LLVM_COMPILER_CHECKED;COMPILER_RT_BUILD_BUILTINS;LIBOMP_LIBFLAGS;CMAKE_SHARED_LINKER_FLAGS;PYTHON_EXECUTABLE;LLVM_ENABLE_Z3_SOLVER;LLVM_POLLY_LINK_INTO_TOOLS;CLANG_VENDOR"
    
  •   -DCLANG_BOOTSTRAP_PASSTHROUGH="CMAKE_INSTALL_PREFIX;CMAKE_VERBOSE_MAKEFILE;CMAKE_BUILD_TYPE;CMAKE_CXX_FLAGS_RELWITHDEBINFO;LLVM_LINK_LLVM_DYLIB;LLVM_INSTALL_UTILS;LLVM_VERSION_SUFFIX;LLVM_ENABLE_SPHINX;SPHINX_WARNINGS_AS_ERRORS;LLVM_BUILD_LLVM_DYLIB;LLVM_ENABLE_RTTI;LLVM_ENABLE_FFI;LIBCLANG_LIBRARY_VERSION;ENABLE_LINKER_BUILD_ID;POLLY_BUNDLED_JSONCPP;LLVM_EXPERIMENTAL_TARGETS_TO_BUILD;LLVM_USE_PERF;LLVM_ENABLE_ASSERTIONS;LLVM_BINUTILS_INCDIR;LLVM_HOST_TRIPLE;LLVM_COMPILER_CHECKED;COMPILER_RT_BUILD_BUILTINS;LIBOMP_LIBFLAGS;CMAKE_SHARED_LINKER_FLAGS;PYTHON_EXECUTABLE;LLVM_ENABLE_Z3_SOLVER;LLVM_POLLY_LINK_INTO_TOOLS;CLANG_VENDOR;CMAKE_POSITION_INDEPENDENT_CODE"
      FOUND_VERSION=`grep LLVM_VERSION_STRING build-llvm/include/llvm/Config/llvm-config.h|cut -d\" -f2`; \
      if ! echo "$(LLVM_VERSION_FULL)"|grep "$$FOUND_VERSION"; then \
              echo "mistmatch of version. Found: $$FOUND_VERSION / Expected: $(LLVM_VERSION_FULL)"; \
    

$ clang++-12 -o test -fPIC test.cpp -pie -stdlib=libc++ -static-libstdc++
/usr/bin/ld: /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/libc++.a(string.cpp.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a PIE object; recompile with -fPIE

@ldionne
Copy link
Member

ldionne commented Jun 15, 2021

Okay, so I created two patches to try and solve this problem, which embody the two ways I see of fixing this:

  1. https://reviews.llvm.org/D104327: This patch changes test-release.sh so that the LLVM releases we build are built with CMAKE_POSITION_INDEPENDENT_CODE=ON. I believe that is the correct layer at which to apply the fix. Whether it should be done in a CMake cache or some other way is up for debate, but the layer at which the fix resides is the "distribution" or "packaging" layer.

  2. https://reviews.llvm.org/D104328: This patch changes the libc++ and libc++abi CMake files to always use POSITION_INDEPENDENT_CODE=ON. It should achieve the same thing, however the fix lives at a lower layer, i.e. in the build system itself. In my opinion, this is the wrong layer for this fix to live in, since someone could arguably come and ask to build libc++/libc++abi without fPIC. However, since fPIC is apparently a no-brainer in practice, I don't have an objection with always building with fPIC enabled, and my objection is mostly on conceptual grounds.

Once we've settled on the approach, I'll merge this to main, and then create another review to cherry-pick to release/12.x.

@chandlerc
Copy link
Member

I don't feel particularly strongly about this, but figured I'd share my perspective...

Okay, so I created two patches to try and solve this problem, which embody
the two ways I see of fixing this:

  1. https://reviews.llvm.org/D104327: This patch changes test-release.sh so
    that the LLVM releases we build are built with
    CMAKE_POSITION_INDEPENDENT_CODE=ON. I believe that is the correct layer at
    which to apply the fix. Whether it should be done in a CMake cache or some
    other way is up for debate, but the layer at which the fix resides is the
    "distribution" or "packaging" layer.

  2. https://reviews.llvm.org/D104328: This patch changes the libc++ and
    libc++abi CMake files to always use POSITION_INDEPENDENT_CODE=ON. It should
    achieve the same thing, however the fix lives at a lower layer, i.e. in the
    build system itself. In my opinion, this is the wrong layer for this fix to
    live in, since someone could arguably come and ask to build libc++/libc++abi
    without fPIC. However, since fPIC is apparently a no-brainer in practice, I
    don't have an objection with always building with fPIC enabled, and my
    objection is mostly on conceptual grounds.

IMO, there is a relevant layering distinction here, but I'd put it in a slightly different place.

The difference I would draw is between the build of libraries directly part of LLVM and Clang, and the runtime libraries that are used automatically by clang invocations of various forms.

For runtime libraries, I think always using PIC is reasonable. But for non-runtime LLVM and Clang libraries, I don't think it's nearly as reasonable.

Unfortunately, neither patch is exactly this runtimes vs. non-runtimes split...
#​1 - covers all the runtimes but also non-runtimes...
#​2 - doesn't impose on non-runtimes, but misses compiler-rt and libunwind.

So to an extent, I prefer #​1 because it at least covers all the runtimes... But if folks want, I think there is a viable separation here if anyone really wants to pursue it.

Once we've settled on the approach, I'll merge this to main, and then
create another review to cherry-pick to release/12.x.

@tstellar
Copy link
Collaborator

We need some consensus on how to fix this soon (1 or 2 days) or this fix won't make the release. We can work-around this problem by passing -DMAKE_POSITION_INDEPENDENT_CODE=ON to the release script when building LLVM, so another option would be to ask the release testers to use this option when building the packages.

@ldionne
Copy link
Member

ldionne commented Jul 27, 2021

This should be fixed by:

commit 21c24ae9029a1fcd1c76b61b1c48b81b5c66c606
Author: Louis Dionne <ldionne.2@gmail.com>
Date:   Tue Jun 15 18:47:38 2021 -0400

    [runtimes] Always build libc++, libc++abi and libunwind with -fPIC

    Building the libraries with -fPIC ensures that we can link an executable
    against the static libraries with -fPIE. Furthermore, there is apparently
    basically no downside to building the libraries with position independent
    code, since modern toolchains are sufficiently clever.

    This commit enforces that we always build the runtime libraries with -fPIC.
    This is another take on D104327, which instead makes the decision of whether
    to build with -fPIC or not to the build script that drives the runtimes'
    build.

    Fixes llvm/llvm-project#42949 .

    Differential Revision: https://reviews.llvm.org/D104328

That should have been committed in time for the LLVM 13 release. I had no strong preference between the two approaches I proposed above, but I ended up going with D104328 because I am more familiar with the runtimes' build scripts than the release scripts.

If this patch causes an issue for someone, please contact me and we'll figure something out.

Sylvestre (or someone else), can you please confirm whether you're still seeing the issue after 21c24ae?

@tstellar
Copy link
Collaborator

mentioned in issue #48661

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 10, 2021
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla packaging
Projects
None yet
Development

No branches or pull requests

6 participants