动态链接中数据的重定向例子

程序的大致框架:
主程序:

#include <stdio.h>
extern void hello(void);
extern int a;
int main(void)
{
    printf("in main.c a=%d\n", a);
    printf("in main.c &a=%p\n", &a);
    hello();
    return 0;
}

共享对象:

#include <stdio.h>
int a = 1;
void hello(void)
{
    printf("lib.c a=%d\n", a);
    printf("lib.c &a=%p\n", &a);
    return;
}

考虑这么几种情况
(1)共享对象定义了静态变量a=1,主程序定义了全局变量a并且没有初始化,分别在共享对象和主程序里面打印a的值
结果:共享对象中a=1,主程序a=0.
分析:因为共享对象中使用了静态变量,属于模块内部的数据引用,使用了位置无关代码,并且a不需要重定向,因此a=1,主程序中由于a没有定义,被分配到了.bss段,当加载程序时初始化为0.
(2)共享对象定义了全局变量a=1,主程序定义了全局变量a并且没有初始化,分别在共享对象和主程序里面打印a的值
结果:共享对象中a=1,主程序a=1.
分析:因为共享对象中使用了全局变量,属于模块之间的数据引用,此时a被放在了.got段,需要重定向,主程序中由于a定义了,被分配到了.bss段,当加载程序时,由于主程序中a没有初始化,在动态链接时,会把共享对象中a的值拷贝到主程序中a的地址,于是a=1,因此无论是在主程序还是在共享对象中,两者打印的都是主程序中a的值。通过打印a的地址也可以知道,打印的是同一个地址的值。
这时我们查看一下a在两个模块中动态链接的信息:
主程序动态链接信息:

Relocation section '.rela.dyn' at offset 0x4d8 contains 2 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000600a60  000700000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0
000000600ab0  000900000005 R_X86_64_COPY     0000000000600ab0 a + 0

共享对象动态链接信息:

Relocation section '.rela.dyn' at offset 0x400 contains 9 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000200758  000000000008 R_X86_64_RELATIVE                    0000000000000640
000000200760  000000000008 R_X86_64_RELATIVE                    0000000000000600
000000200988  000000000008 R_X86_64_RELATIVE                    0000000000200988
000000200930  000200000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_deregisterTMClone + 0
000000200938  000700000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0
000000200940  000900000006 R_X86_64_GLOB_DAT 0000000000200990 a + 0
000000200948  000b00000006 R_X86_64_GLOB_DAT 0000000000000000 _Jv_RegisterClasses + 0

很明显在主程序中,从Type属性看,a其实是一个copy,复制了共享对象中的a的值。而共享对象,a的值是一个需要重定向的数据,存放在.got.
(3)共享对象定义了全局变量a=1,主程序定义了全局变量a=2,分别在共享对象和主程序里面打印a的值
结果:共享对象中a=2,主程序a=2.
分析:这个和情况2有点类似,只是主程序中a已经有值了,动态链接时,不会把共享对象中a的值复制到主程序中,剩下的重定向一样。

这个例子很好的说明了共享对象和主程序中数据的重定向,当然这个例子也可以延伸为函数的调用,不过基本思想大致一样。

猜你喜欢

转载自blog.csdn.net/whoami_I/article/details/82684319