Search code examples
gcclinkerlibstdc++weak-linking

Strange linking behaviour with weak symbols (ARM-EABI unwinding routines __cxa_begin_cleanup)


I've got a problem with our ARM-EABI toolchain and/or libstdc++.

When I compile and link a simple C++ library consisting of the files test.cpp, TestClass.cpp, TestClass.h some unwinding support routines like __cxa_begin_cleanup are weak-referenced from the library, objdump -T showing them as

00000000  w   D  *UND*  00000000 __cxa_begin_cleanup
00000000  w   D  *UND*  00000000 __cxa_call_unexpected

__cxa_begin_cleanup is implemented in libsupc++, which our library is linked with, but the function is not linked into the library. Why?

If the code from the library is changed and a std::string is used (prepared in comments in test.cpp), the function __cxa_begin_cleanup will be linked to the resulting binary and objdump -T won't show them anymore.

There is a similar issue here, but the mentioned linker options --start-group and --end-group didn't help.

Can anyone help?

The ARM-EABI toolchain consists of: GCC 6.3.0 Binutils 2.27 Newlib 2.4.0

Commandline:

arm-eabi-gcc.exe test.cpp TestClass.cpp -fPIC -O0 -lstdc++ -lsupc++ -o a.out

Source:

test.cpp

#include <string>
#include "testclass.h"

int bur_heap_size = 0;

//std::string str1;

int fun ()
{
   TestClass obj1;
//   str1 = "blabla";
   return 0;
}

TestClass.cpp

#include "testclass.h"

TestClass::TestClass(){    public_member = 1;}
TestClass::~TestClass(){}
int TestClass::PublicMethodGetPublicMember(){    return public_member;}

TestClass.h

#ifndef TESTCLASS_H_
#define TESTCLASS_H_

class TestClass
{
    public:
    TestClass();
    ~TestClass();
    int PublicMethodGetPublicMember();
    public:
    int public_member;
};

#endif

Solution

  • See ELF Standard p. 1-18:

    When the link editor searches archive libraries, it extracts archive members that contain definitions of undefined global symbols. The member’s definition may be either a global or a weak symbol. The link editor does not extract archive members to resolve undefined weak symbols. Unresolved weak symbols have a zero value.

    This means for the example above, no object will be extracted from the library, because of the weak-declaration. But the usage of std::string leads to the extraction of the object, which also satisfies the used weak-Symbols.

    To "solve" this, it is possible to use the linker option -u symbol:

    Force symbol to be entered in the output file as an undefined symbol. Doing this may, for example, trigger linking of additional modules from standard libraries.