简体   繁体   中英

GCC ARM Cross-Compiling, what do errors like undefined reference to `__cxa_end_catch@CXXABI_1.3' indicate?

I successfully built a test application for an Intel Cyclone V SoC with the Intel Embedded Development Suite for FPGA SoCs. This application links against some target system specific libraries.

As the GCC shipped with the EDS is quite outdated and I need newer C++ features, I wanted to compile the whole thing with a current version of arm-linux-gnueabihf-g++ which I downloaded here from the ARM website.

Compiling the same project that builds fine with the original toolchain with the recent GCC leads to lots of errors like this:

pathToNewGcc-ARM/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/ld: intelFPGARootDir/18.1/hld/host/arm32/lib/libalteracl.so: undefined reference to `__cxa_end_catch@CXXABI_1.3'
pathToNewGcc-ARM/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/ld: intelFPGARootDir/18.1/hld/host/arm32/lib/libalteracl.so: undefined reference to `std::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::basic_stringstream(std::string const&, std::_Ios_Openmode)@GLIBCXX_3.4'
pathToNewGcc-ARM/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/ld: intelFPGARootDir/18.1/hld/host/arm32/lib/libalteracl.so: undefined reference to `std::cerr@GLIBCXX_3.4'
pathToNewGcc-ARM/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/ld: intelFPGARootDir/18.1/hld/host/arm32/lib/libalteracl.so: undefined reference to `operator delete(void*)@GLIBCXX_3.4'

libalteracl.so is one of the target system specific libraries distributed by Intel. Obviously something doesn't match here, however I'm not sure what's the exact problem. So, I need some explanation of how to interpret this errors and what could be done to fix them.

As some questions arose from the comments, here are some additional information

Target Architecture is a Dual-Core ARM Cortex A9. I loaded the ARM listed under AArch32 target with hard float (arm-linux-gnueabihf) on the ARM website linked above.

The build is done by CMake / CLion. The extracted generated Compiler/Linker calls are as follows:

Compiling:

pathToNewGcc-ARM/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-g++  -DCL_HPP_MINIMUM_OPENCL_VERSION=110 -DCL_HPP_TARGET_OPENCL_VERSION=200 -DJUCE_APP_CONFIG_HEADER=\"myProjectDir/JuceLibraryCode/AppConfig.h\" -DOPEN_CL_INTEL_FPGA -D_DEBUG=1 -IsomeFrameworkDir/JUCE/modules -IintelFPGARootDir/18.1/hld/host/include20  -g   -std=gnu++11 -o CMakeFiles/HostApplication.dir/Source/Main.cpp.o -c myProjectDir/Source/Main.cpp

Linking:

pathToNewGcc-ARM/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-g++  -g   -LintelFPGARootDir/18.1/hld/board/de10_standard/arm32/lib -LintelFPGARootDir/18.1/hld/host/arm32/lib -LintelFPGARootDir/18.1/hld/host/arm32/lib -Wl,--no-as-needed -lalteracl -lintel_soc32_mmd -lstdc++ -lelf CMakeFiles/HostApplication.dir/Source/Main.cpp.o CMakeFiles/HostApplication.dir/JuceLibraryCode/include_juce_core.cpp.o  -o HostApplication -lrt -ldl -lpthread

libalteracl.so should be a 32 Bit library as the whole target Architecture is 32 Bit

It seems, the reason for this is that libstdc++ in your toolchain does not provide versioned symbols...

On my host machine, I get

$ readelf -sW /usr/lib64/libstdc++.so.6 | c++filt | grep std::cerr | grep @
3091: 000000000018d340   272 OBJECT  GLOBAL DEFAULT   25 std::cerr@@GLIBCXX_3.4
$ readelf -sW /usr/lib64/libstdc++.so.6 | grep __cxa_end_catch | grep @
1997: 000000000008fe60   131 FUNC    GLOBAL DEFAULT   11 __cxa_end_catch@@CXXABI_1.3

But I don't see the versioned symbols for the toolchain you provided a link to:

$ readelf -sW ./arm-linux-gnueabihf/libc/usr/lib/libstdc++.so.6.0.25 | c++filt | grep std::cerr | grep @
(nothing)

So I think libalteracl.so has been linked against libstdc++ that provided versioned versions of the symbols. Maybe you'll have more luck with earlier toolchains from the same vendor.


From the manual :

Prerequisites

Minimum environment that supports a versioned ABI: A supported dynamic linker, a GNU linker of sufficient vintage to understand demangled C++ name globbing (ld) or the Sun linker, a shared executable compiled with g++, and shared libraries (libgcc_s, libstdc++) compiled by a compiler (g++) with a compatible ABI. Phew.

On top of all that, an additional constraint: libstdc++ did not attempt to version symbols (or age gracefully, really) until version 3.1.0.

Most modern GNU/Linux and BSD versions, particularly ones using GCC 3.1 and later, will meet the requirements above, as does Solaris 2.5 and up.

Configuring

It turns out that most of the configure options that change default behavior will impact the mangled names of exported symbols, and thus impact versioning and compatibility.

For more information on configure options, including ABI impacts, see: here

There is one flag that explicitly deals with symbol versioning: --enable-symvers .

In the end I successfully got it working with the arm-linux-gnueabihf-g++ supplied by the apt package manager, which is a bit older but supports all features I need and seems to have symbol naming as expected by the library and therefore succeeds to link.

This now introduces other errors on the target system, as the runtinme libraries present in this minimal Linux which is pre-built by the FPGA board manufacturer do not contain all needed features, so I'll have to update the system manually, but I might open another question regarding that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM