免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1414 | 回复: 0
打印 上一主题 下一主题

有关于全局符号介入与多个动态库存在相同的符号相互覆盖的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2016-05-03 10:55 |只看该作者 |倒序浏览
小弟最近在看《程序员的自我修养》,书中提到了全局符号介入问题,根据书中的代码进行了实验,实验代码如下:
a1.c
  1. #include <stdio.h>
  2. void a()
  3. {
  4.         printf("a1.c\n");
  5. }
复制代码
a2.c
  1. #include <stdio.h>
  2. void a()
  3. {
  4.         printf("a2.c\n");
  5. }
复制代码
b1.c
  1. void a();

  2. void b1()
  3. {
  4.         a();
  5. }
复制代码
b2.c
  1. void a();

  2. void b2()
  3. {
  4.         a();
  5. }
复制代码
编译命令如下:
  1. gcc -fPIC -shared a1.c -o a1.so
  2. gcc -fPIC -shared a2.c -o a2.so
  3. gcc -fPIC -shared b1.c a1.so -o b1.so
  4. gcc -fPIC -shared b2.c a2.so -o b2.so
复制代码
最后是main.c
  1. #include <stdio.h>

  2. void b1();
  3. void b2();

  4. int main()
  5. {
  6.         b1();
  7.         b2();
  8.         return 0;
  9. }
复制代码
编译命令如下:
  1. gcc main.c b1.so b2.so -o main -Xlinker -rpath ./
复制代码
最后程序运行结果如下:
  1. ./main
  2. a1.c
  3. a1.c
复制代码
根据书中给出的解释是:当一个符号需要被加入全局符号表时,如果相同的符号名已经存在,则后加入的符号被忽略。到现在为止一切正常。
接下来问题就来了,偶然在网上看到了一段代码,并测试之。
foo.c
  1. #include <stdio.h>

  2. struct {
  3.     int a;
  4.     int b;
  5. } b = { 3, 3 };

  6. int main();

  7. void foo()
  8. {
  9.     b.a = 4;
  10.     b.b = 4;
  11.     printf("foo:\t(&b)=0x%08x\n\tsizeof(b)=%d\n\tb.a=%d\n\tb.b=%d\n\tmain:0x%08x\n",
  12.         &b, sizeof b, b.a, b.b, main);
  13. }
复制代码
t1.c
  1. #include <stdio.h>

  2. int b = 1;
  3. int c = 1;

  4. int main()
  5. {
  6.     int count = 5;
  7.     while (count-- > 0) {
  8.         t2();
  9.         foo();
  10.         printf("t1:\t(&b)=0x%08x\n\t(&c)=0x%08x\n\tsizeof(b)=%d\n\tb=%d\n\tc=%d\n",
  11.             &b, &c, sizeof b, b, c);
  12.         sleep(1);
  13.     }
  14.     return 0;
  15. }
复制代码
t2.c
  1. #include <stdio.h>

  2. int b;
  3. int c;

  4. int t2()
  5. {
  6.     printf("t2:\t(&b)=0x%08x\n\t(&c)=0x%08x\n\tsizeof(b)=%d\n\tb=%d\n\tc=%d\n",
  7.         &b, &c, sizeof b, b, c);
  8.     return 0;
  9. }
复制代码
makefile如下:
  1. export LD_LIBRARY_PATH:=.

  2. test: t1.o t2.o
  3.         gcc -shared -fPIC -o libfoo.so foo.c
  4.         gcc -o test t1.o t2.o -L. -lfoo

  5. t1.o: t1.c
  6. t2.o: t2.c

  7. .PHONY:clean
  8. clean:
  9.         rm -f *.o *.so test*
复制代码
首先只对程序源码静态分析就可以发现:强符号b被定义了两次,不过编译时并没有报重定义错误,这是我的第一个问题?接下来看运行。
  1. t2:        (&b)=0x00601050
  2.         (&c)=0x00601054
  3.         sizeof(b)=4
  4.         b=1
  5.         c=1
  6. foo:        (&b)=0x00601050
  7.         sizeof(b)=8
  8.         b.a=4
  9.         b.b=4
  10.         main:0x00400766
  11. t1:        (&b)=0x00601050
  12.         (&c)=0x00601054
  13.         sizeof(b)=4
  14.         b=4
  15.         c=4
  16. t2:        (&b)=0x00601050
  17.         (&c)=0x00601054
  18.         sizeof(b)=4
  19.         b=4
  20.         c=4
  21. foo:        (&b)=0x00601050
  22.         sizeof(b)=8
  23.         b.a=4
  24.         b.b=4
  25.         main:0x00400766
  26. t1:        (&b)=0x00601050
  27.         (&c)=0x00601054
  28.         sizeof(b)=4
  29.         b=4
  30.         c=4
  31. t2:        (&b)=0x00601050
  32.         (&c)=0x00601054
  33.         sizeof(b)=4
  34.         b=4
  35.         c=4
  36. foo:        (&b)=0x00601050
  37.         sizeof(b)=8
  38.         b.a=4
  39.         b.b=4
  40.         main:0x00400766
  41. t1:        (&b)=0x00601050
  42.         (&c)=0x00601054
  43.         sizeof(b)=4
  44.         b=4
  45.         c=4
  46. t2:        (&b)=0x00601050
  47.         (&c)=0x00601054
  48.         sizeof(b)=4
  49.         b=4
  50.         c=4
  51. foo:        (&b)=0x00601050
  52.         sizeof(b)=8
  53.         b.a=4
  54.         b.b=4
  55.         main:0x00400766
  56. t1:        (&b)=0x00601050
  57.         (&c)=0x00601054
  58.         sizeof(b)=4
  59.         b=4
  60.         c=4
  61. t2:        (&b)=0x00601050
  62.         (&c)=0x00601054
  63.         sizeof(b)=4
  64.         b=4
  65.         c=4
  66. foo:        (&b)=0x00601050
  67.         sizeof(b)=8
  68.         b.a=4
  69.         b.b=4
  70.         main:0x00400766
  71. t1:        (&b)=0x00601050
  72.         (&c)=0x00601054
  73.         sizeof(b)=4
  74.         b=4
  75.         c=4
复制代码
通过程序可以清晰的发现,一开始b、c的值都还是1,但调用动态链接库中的foo函数后,b、c的内存地址没有改变,但值却改变了。
通过readelf -r 命令可以发现,test中并不存在b、c符号,证明上述符号在形成可执行文件时已完成重定位,但通过赋值情况来看,好像是运行加入的libfoo.so中的b将t1.c中的b覆盖了。
说了这么多,可能大家都乱了,现在把我的问题给大家总结以下
在第一个例子中:后加入的全局符号被忽略。
在第二个例子中:后加入的全局符号又覆盖前面被加入符号。
这两个例子从我直观上看是前后矛盾的,所以哪位大神可以给我分析,小弟万分感谢。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP