我可以修改共享库文件以使我的可执行文件正常工作

时间:2014-04-24 05:11:41

标签: c shared-libraries

我使用say(abc.soa.cb.c)文件共享库文件c.c。 现在我通过可执行文件说target.out

我怀疑是......我可以删除abc.so并再次从(abc.soa.cb.c再次构建c.c并将其粘贴到任何地方我以前的abc.so出席了。 但是我的target.out是较旧的。

现在,如果我运行target.out,它将适用于新的abc.so ??

1 个答案:

答案 0 :(得分:0)

是的,它会起作用,但你必须小心。

我们以libtest.c为例:

int my_global_var = 42;

int sum(int a, int b)
{
    return a + b;
}

它可以用:

构建
gcc -fPIC -shared -o libtest.so libtest.c

使用readelf -s libtest.so,我们可以看到函数和全局变量作为公共符号公开:

$ readelf -s libtest.so
42: 0000000000200950     4 OBJECT  GLOBAL DEFAULT   21 my_global_var
...
47: 0000000000000665    42 FUNC    GLOBAL DEFAULT   11 sum
...

重要的是要注意.so文件没有指定这些符号的类型或原型。

现在让我们编写一个使用lib的程序:

#include <stdio.h>

/* provided by libtest */
int sum(int, int);
extern int my_global_var;

int main()
{
    printf("5 + 2 = %d and my_global_var = %d\n", sum(5, 2), my_global_var);

    return 0;
}

建立它:

gcc -L. -ltest -o program program.c

有效:

$ ./program 
5 + 2 = 7 and my_global_var = 42

我们可以看到program动态链接到libtest.so

$ ldd program
...
libtest.so (0x00007f1138c70000)
...

在没有类型或原型的程序头中再次引用符号summy_global_var

$ objdump --dynamic-reloc program 
DYNAMIC RELOCATION RECORDS
OFFSET           TYPE              VALUE 
0000000000600b00 R_X86_64_GLOB_DAT  __gmon_start__
0000000000600b50 R_X86_64_COPY     my_global_var
0000000000600b20 R_X86_64_JUMP_SLOT  printf
0000000000600b28 R_X86_64_JUMP_SLOT  __libc_start_main
0000000000600b30 R_X86_64_JUMP_SLOT  __gmon_start__
0000000000600b38 R_X86_64_JUMP_SLOT  sum

这就是它的工作原理,只要库文件存在并且它包含程序引用的符号,动态链接器就会很高兴并将这些符号的地址写入程序内存中的特殊间接表。

如果我们将my_global_var更改为43,请重建lib,然后运行该程序而不重建它:

$ ./program 
5 + 2 = 7 and my_global_var = 43

如果我们从lib中删除my_global_var,符号就会消失,程序无法启动,因为动态链接器不满意:

$ ./program 
./program: symbol lookup error: ./program: undefined symbol: my_global_var

现在是棘手的部分,让我们尝试更改sum的原型:

int my_global_var = 43;

float sum(float a, float b)
{
    return a + b;
}

我们重建了库,并运行程序:

$ ./program 
5 + 2 = 791621423 and my_global_var = 43

动态链接器不会抱怨,但是当程序将int传递给期望float s的函数时,结果就是垃圾。

总结一下:只要类型和原型保持绝对不变,它就会起作用。如果它们发生变化,链接器就不会抱怨并且会发生奇怪的事情。

要解决最后一个问题,大型库使用符号版本控制。这是一个非常复杂的主题,这里有一篇关于它的详细文章:http://www.trevorpounds.com/blog/?p=33