I am trying to build an executable on Linux that meets the following criteria:
My current dev environment is gcc4.8.5, glibc 2.17 on CentOS 7. The binary built does not work on systems with glibc < 2.14 due to a dependency on memcpy.
objdump -T main | fgrep GLIBC_2.14
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.14 memcpy
There was a breaking change to memcpy introduced in glibc 2.14 so I want to force the use of an older version. I came across this stackoverflow post Linking against older symbol version in a .so file but it did not work for me due to linker issues related to libstdc++. Here's my attempt at a solution below.
main.cpp
#include <iostream>
#include <string.h>
int main(int argc, char** argv)
{
char source[] = "once upon a midnight dreary...", dest[4];
memcpy(dest, source, sizeof dest);
std::cout << dest << std::endl;
}
wrap_memcpy.cpp
#include <string.h>
__asm__(".symver memcpy, memcpy@GLIBC_2.2.5");
void *__wrap_memcpy(void *dest, const void *src, size_t n)
{
return memcpy(dest, src, n);
}
compiler options and errors:
g++ -static-libgcc -static-libstdc++ wrap_memcpy.cpp main.cpp -o main -Wl,--wrap=memcpy
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/libstdc++.a(locale-inst.o): In function `std::ctype<char>::widen(char const*, char const*, char*) const':
(.text._ZNKSt5ctypeIcE5widenEPKcS2_Pc[_ZNKSt5ctypeIcE5widenEPKcS2_Pc]+0x5f): undefined reference to `__wrap_memcpy'
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/libstdc++.a(locale-inst.o): In function `std::__timepunct<char>::__timepunct(__locale_struct*, char const*, unsigned long)':
(.text._ZNSt11__timepunctIcEC2EP15__locale_structPKcm[_ZNSt11__timepunctIcEC5EP15__locale_structPKcm]+0x96): undefined reference to `__wrap_memcpy'
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/libstdc++.a(locale-inst.o): In function `std::messages<char>::messages(__locale_struct*, char const*, unsigned long)':
(.text._ZNSt8messagesIcEC2EP15__locale_structPKcm[_ZNSt8messagesIcEC5EP15__locale_structPKcm]+0x8e): undefined reference to `__wrap_memcpy'
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/libstdc++.a(locale-inst.o): In function `std::messages_byname<char>::messages_byname(char const*, unsigned long)':
(.text._ZNSt15messages_bynameIcEC2EPKcm[_ZNSt15messages_bynameIcEC5EPKcm]+0xd6): undefined reference to `__wrap_memcpy'
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/libstdc++.a(locale-inst.o): In function `std::__numpunct_cache<char>::_M_cache(std::locale const&)':
(.text._ZNSt16__numpunct_cacheIcE8_M_cacheERKSt6locale[_ZNSt16__numpunct_cacheIcE8_M_cacheERKSt6locale]+0x2ad): undefined reference to `__wrap_memcpy'
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/libstdc++.a(locale-inst.o):(.text._ZNSt16__numpunct_cacheIcE8_M_cacheERKSt6locale[_ZNSt16__numpunct_cacheIcE8_M_cacheERKSt6locale]+0x2cd): more undefined references to `__wrap_memcpy' follow
collect2: error: ld returned 1 exit status
What am I doing wrong here? I've also attempted other solutions in the stack overflow post and I get the same error. I've also tried building this on glibc 5.2.1 on Ubuntu 15.0.4 and got the same result. Note that statically linking memcpy (which is under the GPL license) into the binary is not an option because of licensing issues.
You need to wrap __wrap_memcpy in extern "C" {}, so that this function is is exported as a C function; otherwise its name will be decorated as a C++ function. In addition I strongly suggest some additional #ifdef, because this problem only occurs with later compiler versions and only for x64 (the conditions are not totally perfect, so may need to adjust them):
#if defined( __GNUC__ ) && defined( __LP64__ ) && __LP64__ >= 1 && \
(_GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) && \
(defined( __x86_64__ ) || defined( __i386__ ) ||\
defined( __i486__ ) || defined( __i586__ ) || defined( __i686__ ))
#include <string.h>
__asm__(".symver memcpy, memcpy@GLIBC_2.2.5");
extern "C"
{
void *__wrap_memcpy(void *dest, const void *src, size_t n)
{
return memcpy(dest, src, n);
}
}
#endif
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With