glibc库的版本兼容问题

问题背景:

本地编译的动态共享库(.so)在另外一台服务器上编译链接报错

报错信息如下:

/lib64/libc.so.6: version 'GLIBC_2.14' not found(require ./libsmscrypt.so) 
symbol memcpy, version GLIBC_2.14 not defined in file libc.so.6 with link time reference

原因分析:

根据报错信息可以看出so库中memcpy函数使用了高版本的实现,而运行机器上的glibc库中没有相应版本实现,因此需要提供链接低版本glibc库的so库。

分析及解决:

从报错信息可以看出找不到GLIBC_2.14版本的memcpy函数

1、查看libsmscrypt.so中memcpy用的是哪个版本实现
$ objdump -T libsmscrypt.so | grep memcpy

qq 20171025130125

可以看出libsmscrypt.so中调用了GLIBC_2.14中的memcpy实现

2、查看系统glibc支持的版本
$ strings libc.so.6 | grep GLIBC

0df26615-8ca4-4437-9fde-c1c63a9b8040

3、查看glibc库包含了memcpy的哪些版本

$ objdump -T libc.so.6 | grep memcpy

a9d9579c-4e6a-4683-8308-550c6da7bcd2

可以看到本机glibc库提供了2.2.5和2.14版本的memcpy

4、指定libsmscrypt.so中memcpy函数使用2.2.5版本实现

在使用了memcpy的源文件中添加

__asm__(".symver memcpy, memcpy@GLIBC_2.2.5");

5、重新编译生成libsmscrypt.so,查看memcpy使用的版本是否改变

$ objdump -T libsmscrypt.so | grep memcpy

qq 20171025130908

可以看到,memcpy函数使用了2.2.5版本的实现。

完成。

局限性

__asm__(".symver memcpy, memcpy@GLIBC_2.2.5");只对一个源文件有效,当多个源文件使用了memcpy,需要在每个文件添加。

示例代码:

//test.c
#include "test1.h"
#include "test2.h"

int main()
{
    foo1();
    foo2();
    return 0;
}

//test1.c
#include "stdlib.h"
#include "string.h"

__asm__(".symver memcpy, memcpy@GLIBC_2.2.5");
void foo1()
{
    char *str = "hello world!";
    char *t = (char *)malloc(5);
    memcpy(t, str, 5);
    free(t);
}


//test2.c
#include "stdlib.h"
#include "string.h"
void foo2()
{
    char *str = "hello world!";
    char *t = (char *)malloc(5);
    memcpy(t, str, 5);
    free(t);
}

编译:$ gcc test.c test1.c test2.c -o test
查看memcpy依赖的版本:$ objdump -T test

97738a68-cfe1-467a-967f-eb434f4ab2b6

从截图可以看到同时用到了2.2.5和2.14版本的memcpy,说明确实只对一个文件起效。

更通用的实现:

编写一个单独的memcpy.c文件:

#include <string.h>

void *__memcpy_old(void *, const void *, size_t);

asm(".symver __memcpy_old, memcpy@GLIBC_2.2.5");
void *__wrap_memcpy(void *dest, const void *src, size_t n)
{
    return __memcpy_old(dest, src, n); 
}

将test1.c中的__asm__(".symver memcpy, memcpy@GLIBC_2.2.5");去掉

编译:$ gcc test.c test1.c test2.c memcpy.c -Wl,--wrap=memcpy -o test

gcc编译时使用 -Wl,--wrap=memcpy选项,使得链接器将memcpy解析为__wrap_memcpy。

查看:$ objdump -T test

b0e78d2e-a539-4645-add0-54e1b4e03369

可以看到memcpy现在只依赖2.2.5版本的实现

参考:
http://b.liuctic.com/2013/11/glibc_2-14-%E5%85%BC%E5%AE%B9%E9%97%AE%E9%A2%98-lib64libc-so-6-version-glibc_2-14-not-found/
glibc和Symbol Versioning和如何链接出低版本glibc可运行的程序 · BlahGeek's Blog
version `GLIBC_2.14' not found 解决方法._功名半纸的博客-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值