免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: detian
打印 上一主题 下一主题

关于“linux共享库内部plt调用”澄清几个问题,继续讨论 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-01-04 10:43 |显示全部楼层 |倒序浏览
澄清1:linux 2.6.23,intel x86 32位平台,程序和共享库都是elf格式。
澄清2:我是想弄清楚共享库自己内部的plt调用问题,因为共享库内部的函数可以互相调用,他们的调用也是通过共享库的plt实现。不是想讨论应用程序的plt调用。我给出的程序段是个共享库,sum()和_sum()都是共享库里的函数,plt是共享库自己的plt,不是应用程序的plt,sum()调用_sum()。

关于cjaizss,mik和system888net的回复,继续提问。

1、cjaizss: 代码被编译为PIC的,但PIC和这个call的地址是什么没有必然直接关系。这个叫符号重定位(relocation)。man elf

我的问题是,这个plt表和sum()函数中代码的都是共享库自己的,尤其是sum()中调用_sum()的call指令,是在各应用程序中共享的。“call + 操作数”,这是一条指令,就好像“mov a, 1”一样,这条指令连同操作数是被编译成一个机器代码放在代码段。共享库装载的时候,loader会对符号进行重定位,也就是说,“loader会修改这条机器代码”(因为,原来是在call 378,现在映射到两个不同的程序中后要分别修改成call 0x00111378和call 0x00122378,对吗?),使call到正确的地址。那么,这条被修改的机器代码是在共享库的代码段,如果对不同的程序有不同的修改,这条指令还能共享吗?如果不能共享,那共享库所谓的共享代码还有意义吗?

我就是想知道,共享库的代码是被各程序共享的,可是像这种需要重定位符号的代码怎么实现共享的呢?重定位之后,call的操作数不同了,“call+操作数”这条指令翻译后的机器指令也不同了,怎么能共享呢?这可能是我对“什么是PIC代码”不太了解。能推荐点儿资料吗?

2、system888net: 对于有虚拟内存管理的linux系统来讲:这是正常的.每个进程都拥有自己的程序地址空间,可以是不同的.

对应用程序来讲,你说的没有问题,应用程序调用共享库的过程,使用的是应用程序的plt,这个没错。共享库内部的函数互相调用,使用的是共享库自己的plt,不是应用程序的plt。共享库的代码被各程序共享,但是对于共享库符号重定位后,有些指令需要修改,这些修改后的指令在各程序中各不相同,因为他们的操作数(符号地址)不同了,但是这些被修改后的指令还能共享吗?

3、mik班主给出了应用程序调用共享库的got、plt使用过程,非常清楚。共享库内部的函数互相调用,共享库被映射到各进程后,代码部分一些指令要进行符号重定位,重定位后,受影响的机器代码(例如 call + 操作数)应该各不相同了,他们还在被共享吗?如果不再共享,也就是说,共享库里的代码映射到各进程后,进行符号重定位,因为要修改机器代码,那么各程序都要分配物理页保存修改的代码,那么这么一来共享库的代码就不再是“共享”的了。斑竹对这个有研究吗,或者推荐一些资料?

多谢各位,继续讨论。

[ 本帖最后由 detian 于 2009-1-4 11:00 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2009-01-04 15:24 |显示全部楼层

回复 #2 mik 的帖子

接着斑竹的看。
如果把斑竹的main改成我的sum(),偏移18处的call不变,然后把t.c编程一个so库libt.so。请问,libt.so被映射到两个不同的进程中后(并且,映射的起始地址不同),每个进程都要对t.o进行重定位,那么,重定位后偏移18处的call指令变成什么样的了?

理论上讲,这个call指令是共享库的代码,应该被各进程共享,比如说,要么是call 0x00111018,要么是call 0x00122018,因为是共享的嘛,该指令只可能一是个呀。

但是,奇怪的是,我在调试的时候,返回编出来偏移18处的代码在各进程中竟然是不同的,也就是说,在进程1中是call 0x00111018,进程2中是call 0x00122018,如何解释?

论坛徽章:
0
3 [报告]
发表于 2009-01-04 15:30 |显示全部楼层
原帖由 ice-pl 于 2009-1-4 15:11 发表
mik地解释已经非常清楚了,推荐lz先看看linker and loader 对连接器和加载器有个初步的认识.
对于obj 中
e8 fc ff ff ff  , fffffffc 是-4 为了连接器计算的时候更方便 这是汇编器把这里放这个数的原因之一.对 ...



我的问题是,如果这条指令是共享库中的代码,它被映射到各进程后,这条指令在各进程中是相同的,还是不同的?

如果相同,那call的目的地址在各进程中不一定相同,则该call指令一定会出错;
如果不同,那共享库的代码就不是在各进程中共享了。我就关心这个“共享库中的call”(不是应用程序中的call),重定位以后成什么样了。

多谢回复,请继续。

论坛徽章:
0
4 [报告]
发表于 2009-01-04 15:41 |显示全部楼层
原帖由 system888net 于 2009-1-4 12:56 发表




lz是关心在同一个动态库中两个函数之间调用的时候plt修改是否会共享吗? 因为没见到你的代码,所以只能这么理解了,若理解有误请LZ更正.

对于sum call _sum,虽然两个函数都在动态库中,但运行时都是从属 ...


对,我关心的就是同一个共享库中的两个函数之间的调用问题。
看我的代码。

mylib.c

#include <stdio.h>
int a,aa;
int sum(int,int);
int _sum(int,int);

int sum(int x, int y)
{
  a = 1;
  aa =2 ;
  a = _sum(x,y);
  printf("in sum, a =%d\n",a);
  return a;
}
int _sum(int x, int y)
{
  return x + y;
}

注意:
1、mylib.c生成libmylib.so
2、注意语句“a=_sum(x,y);”,返回编后是“4af:   e8 c4 fe ff ff          call   378 <_sum@plt>”。请注意,这个“call 378”在被映射到不同的进程后应该是call不同的地址,因为共享库自己的plt表项_sum@plt的地址在各进程中是不同的(因为共享库被映射的起始地址不同)。那么,如果这一句call在各进程中是不同的,那岂不是共享库的代码并没有被各进程共享?

论坛徽章:
0
5 [报告]
发表于 2009-01-06 11:15 |显示全部楼层

回复 #14 system888net 的帖子

我加了-fPIC,生成的就是位置无关的代码,也就是说,里面的代码地址都是相对于加载地址(设为0,文件起始)的偏移,也就是说call 378 <_sum@plt>,这里的378就是相对于加载地址的偏移。那么,现这个库被两个进程分别加载到了0x00111000和0x00122000,那么,loader要不要对这个call重定位?如果要,则在进程1中就是call 0x00111378,在进程2中就是call 0x00122378。这么一来,这个call就是每进程一份,而不是共享的了。也就是说,所谓的共享库,在这里是不能共享的了。

如果我的看法是对的,那么凡是共享库中一个函数call另一个函数的地方,几乎都不能在内存中共享,而如果不共享,COW是以页为单位,通常的机器一页4K,这就是说,凡是有call的地方,它所在的页必须copy出来,因为每个进程都需要重定位。试想一下,4k能包含多么多的代码,而不掉用其他函数的函数又会有几个,这么说来,所谓的共享库,在内存中的代码,几乎是完全不能共享的。

不知道我的理解对不?

论坛徽章:
0
6 [报告]
发表于 2009-01-06 14:04 |显示全部楼层

回复 #16 detian 的帖子

我的理解好像不对,call 378 <_sum@plt>这条指令好像不需要重定位,好像说什么call指令的编码方式保存的是“目的地址相对于当前指令地址的偏移”,这个没明白,忘了原来书上怎么说得了,再看看教材。

论坛徽章:
0
7 [报告]
发表于 2009-01-07 14:06 |显示全部楼层

回复 #18 system888net 的帖子

非常感谢。我原来的困惑就是这个call到底会不会被改。现在看来是不会改的。
既然不改,又怎么做到在不同的进程里call到不同的地址呢?
这个好像就是call/jump这种相对跳转指令的编码问题,说“编到call指令里面的数字,是目的地址相对于当前指令地址的偏移”,因此,在执行call指令时,实际要call过去的地址是:当前指令地址 + 保存在call指令中的偏移。
只要这个偏移固定,映射到哪个地址都无所谓。这就是call为什么能做到位置无关。
这一点我还在找教材看看。

多谢多谢。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP