llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
29.13k stars 12.01k forks source link

relocation `R_X86_64_PC32` against undefined hidden symbol error when building a C++ shared library that links against static boost libraries #39830

Closed llvmbot closed 1 month ago

llvmbot commented 5 years ago
Bugzilla Link 40484
Version 7.0
OS Linux
Reporter LLVM Bugzilla Contributor
CC @DougGregor,@thehcma,@kevinlrak,@zygoloid,@riyazvp

Extended Description

We are getting a 'relocation R_X86_64_PC32 against undefined hidden symbol error' when building a C++ shared library that links against static boost libraries (built with -fPIC). I have a reproduction below. There a few details that may help:

Here is a reproduction:

I have a very simple test.cpp file:

#include <boost/regex.hpp>

int test()
{
    boost::regex const regex("a");
    return 0;
}
clang++-7 -fPIC -I $BOOST_PATH/include -c test.cpp

clang++-7 -fPIC -shared -o libtest.so test.o $BOOST_PATH//lib/libboost_regex.a

/usr/bin/ld: /opt/boost-1.69.0/lib/libboost_regex.a(regex.o): relocation R_X86_64_PC32 against undefined hidden symbol `_ZTCN5boost10wrapexceptISt13runtime_errorEE0_NS_16exception_detail10clone_implINS3_19error_info_injectorIS1_EEEE' can not be used when making a shared object
/usr/bin/ld: final link failed: Bad value

c++filt _ZTCN5boost10wrapexceptISt13runtime_errorEE0_NS_16exception_detail10clone_implINS3_19error_info_injectorIS1_EEEE gives:

construction vtable for boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<std::runtime_error> >-in-boost::wrapexcept<std::runtime_error>

We are using Boost 1.69 with only static libaries. Here is how we built it:

./bootstrap.sh
./b2 -d+2 -a install -j 16 -prefix=$BOOST_PATH link=static cxxflags="-fPIC" variant=release
f3f93b06-43ec-4608-9f19-a7b417a1a81b commented 4 years ago

We have also run into the same with boost 1.72.0 built with gcc 7.3.0 and then the test case compiled with either clang 7.1.0 and clang 10.0.0.

cassie-nahar commented 4 years ago

We are also experiencing this with Boost 1.70 tested on both clang 6.0.0-1ubuntu2 and clang 10.0.0 from github master. Our Boost was compiled with gcc 7.4.0

llvmbot commented 5 years ago

It also reproduces with the clang-10 master as of today.

86916a59-c16d-4adf-b4aa-7128af079255 commented 5 years ago

We can also repro this bug with boost-1.71.0 as well.

gigcastro commented 1 year ago

I encounter the same issue while compiling a shared library project with Clang 10.0.0-4ubuntu1 on Ubuntu 20 with boost 1.71 installed from apt and building with CMake.

Linker complained on a compilation unit that was only including boost/uuid/uuid.hpp and boost/uuid/uuid_io.hpp: relocation R_X86_64_PC32 against undefined hidden symbol _ZTCN5boost10wrapexceptISt13runtime_errorEE0_NS_16exception_detail10clone_implINS3_19error_info_injectorIS1_EEEE can not be used when making a shared object /usr/bin/ld: final link failed: bad value

C++filt returns: construction vtable for boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<std::runtime_error> >-in-boost::wrapexcept<std::runtime_error>

eraser00 commented 2 months ago

It looks like an ABI compat problem with gcc and clang since clang-6.X and gcc-6.x

Here is a short code snippet to reproduce the difference in short:

the godbolt link

#include <stdexcept>

namespace A {
namespace B {

class VirtualBase {
 public:
  virtual void rethrow() const = 0;
};

template <typename T>
struct BWrap {
  int b{0};
};

template <typename T>
class BImpl : public BWrap<T>, virtual VirtualBase {
 public:
  void rethrow() const override { throw *this; }
  int a{1};
};

}  // namespace B

template <typename T>
struct AWrap : public B::BImpl<B::BWrap<T>> {
  int c{0};
};

}  // namespace A

int Test() {
  A::AWrap<std::runtime_error> a;
  return 0;
}

the vtable of A::AWrap clang produce a name: A::B::BImpl<A::AWrap<std::runtime_error>::BWrap<std::runtime_error>>-in-A::AWrap<std::runtime_error>

but gcc produce: A::B::BImpl<A::B::BWrap<std::runtime_error> >-in-A::AWrap<std::runtime_error>

The boost::exception has a similar but more complex std::runtime_error wrapper, which is the trigger of the linking error mentioned above.

We test this src file with all the available x86_64 clang and GCC, and keep reproducing this difference in multiple -fclang-abi-compat versions.

We have no idea about the cause of this difference.

PS. Re-compile your static boost library with clang can fix the linking error mentioned above. Just a work around suggestion~

eraser00 commented 1 month ago

We notice that in https://github.com/llvm/llvm-project/pull/109970 @tcwzxx finally fix this problem.

tcwzxx commented 1 month ago

Resolved in #109970

llvmbot commented 1 month ago

@llvm/issue-subscribers-clang-frontend

Author: None (llvmbot)

| | | | --- | --- | | Bugzilla Link | [40484](https://llvm.org/bz40484) | | Version | 7.0 | | OS | Linux | | Reporter | LLVM Bugzilla Contributor | | CC | @DougGregor,@thehcma,@kevinlrak,@zygoloid,@riyazvp | ## Extended Description We are getting a 'relocation `R_X86_64_PC32` against undefined hidden symbol error' when building a C++ shared library that links against static boost libraries (built with `-fPIC`). I have a reproduction below. There a few details that may help: - The error only happens with clang (I tried 6 and 7) but not with gcc - It does not matter whether boost is built with clang or gcc, so I believe the problem is related to the compilation of the object file that is being made into a shared library - The problem is somewhat related to a class called 'wrapexcept' in boost, as it is always a symbol related to this class that is causing a problem. The symbol is a 'construction vtable', so there is multi-inheritance and templates involved and certainly this is related to the fact that boost is built with `-fvisibility=hidden -fvisibility-inlines-hidden`. - A potentially related earlier bug is: llvm/llvm-project#9085 Here is a reproduction: I have a very simple `test.cpp` file: ```cpp #include <boost/regex.hpp> int test() { boost::regex const regex("a"); return 0; } ``` ``` clang++-7 -fPIC -I $BOOST_PATH/include -c test.cpp clang++-7 -fPIC -shared -o libtest.so test.o $BOOST_PATH//lib/libboost_regex.a /usr/bin/ld: /opt/boost-1.69.0/lib/libboost_regex.a(regex.o): relocation R_X86_64_PC32 against undefined hidden symbol `_ZTCN5boost10wrapexceptISt13runtime_errorEE0_NS_16exception_detail10clone_implINS3_19error_info_injectorIS1_EEEE' can not be used when making a shared object /usr/bin/ld: final link failed: Bad value c++filt _ZTCN5boost10wrapexceptISt13runtime_errorEE0_NS_16exception_detail10clone_implINS3_19error_info_injectorIS1_EEEE gives: construction vtable for boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<std::runtime_error> >-in-boost::wrapexcept<std::runtime_error> ``` We are using Boost 1.69 with only static libaries. Here is how we built it: ``` ./bootstrap.sh ./b2 -d+2 -a install -j 16 -prefix=$BOOST_PATH link=static cxxflags="-fPIC" variant=release ```