我正在尝试在满足以下条件的Linux上构建可执行文件:
我当前的开发环境是CentOS 7上的gcc4.8.5,glibc 2.17,由于对memcpy的依赖,内置的二进制文件在glibc <2.14的系统上不起作用。
objdump -T main | fgrep GLIBC_2.14
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.14 memcpy
glibc 2.14中对memcpy进行了重大更改,因此我想强制使用旧版本。我遇到了这个stackoverflow帖子,在.so文件中链接到较旧的符号版本,但是由于与libstdc ++相关的链接器问题,它对我不起作用。这是我在下面的解决方案中的尝试。
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);
}
编译器选项和错误:
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
我在这里做错了什么?我还在堆栈溢出后尝试了其他解决方案,但遇到了同样的错误。我还尝试在Ubuntu 15.0.4的glibc 5.2.1上构建此文件,并得到了相同的结果。请注意,由于许可问题,不能将memcpy(在GPL许可下)静态链接到二进制文件中。
您需要将__wrap_memcpy包装在extern“ C” {}中,以便将此函数导出为C函数。否则,其名称将被修饰为C ++函数。此外,我强烈建议使用其他#ifdef,因为此问题仅在更高版本的编译器版本中且仅针对x64出现(条件并非完全完美,因此可能需要对其进行调整):
#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
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句