版权所有IBM公司2004商标PowerPC上ELF可执行文件的符号解析(二)第1页,共7PowerPC上ELF可执行文件的符号解析(二)陈剑(chenjian@cn.
ibm.
com)软件工程师EMC金戈高级软件工程师EMC2004年2月01日作者首先介绍了在64位环境下PowerPC区别于32位的两个概念,接着讲述了在64位环境下PowerPCLinux是如何作变量符号动态解析,然后重点讲解函数符号动态符号解析,并辅以实例详细说明,最后总结了32位和64位实现函数符号动态解析的异同之处.
一.
概念在上一篇文章中介绍了符号解析的基本概念,象PLT表、Symbol表、Relocation表等,这些概念在64位环境仍然存在,但PLT表的意义在64位环境下发生了变化.
在讲解64位环境下PowerPC符号解析的过程之前,先说64位和32位环境在汇编语言这个层次上的两个不同之处.
1.
TOC(TableofContents)我们知道在32位环境下GOT表的地址是必须在汇编程序中计算出来的,具体的计算方法读者有兴趣可以自己写一个简单的程序,然后用gcc-fPIC-S来编译后察看汇编代码即可.
64位环境下PowerPC引入了一个新的概念:TOC.
它是可执行文件和共享库的一段数据,包括.
got、.
toc和smalldataarea(用来存放local的小于指定大小的数据),最大可以有64K字节.
PowerPC64ABI规定了寄存器r2专门用来存放TOC基址,通常是(TOC的起始地址+0x8000).
一般而言,TOC中各个section的顺序是.
gotàtocàsmalldataarea,所以TOC的起始地址就等于.
got的地址.
2.
函数描述符(FunctionDescriptor)64位和32位一个很大的不同点就是函数描述符的引入.
一个函数描述符是三个双字组成的结构:第一个双字是该函数的真正入口点第二个双字是该函数的TOC基址第三个双字是为其他语言,比如Pascal和PL/1准备的环境指针在64位环境下,和函数名相同的symbol名是函数描述符的地址,函数入口点symbol名是函数名前面加个点.
比如我们定义了一个函数voidFunc(),那么用汇编表示,Func是它的函数描述符,.
Func是它的函数入口点.
developerWorksibm.
com/developerWorks/cn/PowerPC上ELF可执行文件的符号解析(二)第2页,共7二.
变量符号动态解析过程变量符号的动态解析过程和32位的情况相比没有太多的变化,系统在载入程序过程中将变量symbol地址存入到TOC中,当需要引用变量symbol时就赋该变量所属的TOC基址到r2中,以r2作为基址加上(变量symbol在TOC中的偏移量)就可以从TOC中取得该symbol的实际地址.
所以仅仅是以r2替代GOT地址,相当于是换了个基址表示.
三.
函数符号动态解析过程当调用函数和被调用函数的TOC不同时,就会发生动态解析.
ld在生成可执行文件时会发现这点,就会为他们生成一段代码,由它来负责完成函数符号动态解析过程.
在32位情况下,这段代码放在PLT表中,通常是以下形式:.
PLTi:addir11,r0,4*(i-1)b.
PLTresolve在64位情况下,这段代码通常是以下形式::ldr12,func@got@plt(r2)/*func@got@plt(r2)表表func表.
PLT表表表表表表表func表表表表表表*/stdr2,40(r1)ldr0,0(r12)//r0表func表表表表表表表表表表表func表.
GLINKi表表ldr2,8(r12)//r2表func表TOC表表表表表表表表0mtctrr0bctr当第一次调用func函数时,它传输控制到中,会从func的.
PLT入口处取得func的入口地址(该值在载入程序时由dynamiclinker初始化为func的.
GLINKi入口),所以接着控制就会转到.
GLINKi.
下面的代码显示了dynamiclinker是如何初始化GLINK表和PLT表的:.
GLINK:.
GLINK0:ldr2,40(r1)addisr12,r2,.
PLT0@toc@haaddir12,r12,.
PLT0@toc@lldr11,0(r12)ldr2,8(r12)mtctrr11ldr11,16(r12)bctr.
GLINK1:lir0,0b.
GLINK0.
GLINKi://i32768lisr0,(N-1)>>16orir0,r0,(N-1)&0xffffb.
GLINK0.
.
.
.
PLT:.
PLT0:.
quadld_so_fixup_func.
quadld_so_toc.
quadld_so_identibm.
com/developerWorks/cn/developerWorksPowerPC上ELF可执行文件的符号解析(二)第3页,共7.
PLT1:.
quad.
GLINK1.
quad0.
quad0.
.
.
.
PLTi:.
quad.
GLINKi.
quad0.
quad0.
.
.
.
PLTN:.
quad.
GLINKN.
quad0.
quad0.
GLINKi入口将偏移量(就是Relocation表的index)置入r0,转入到.
GLINK0处执行;.
GLINK0取得dynamiclinker的函数描述符地址,并赋dynamiclinker的入口地址到寄存器ctr,赋dyanmiclinker的TOC地址到r2,赋第三项ld_so_ident(是一个唯一识别调用函数的信息,由dynamiclinker初始化)到r11,然后调用dynamiclinker的解析函数_dl_runtime_resolve;_dl_runtime_resolve会根据r0取得和该PLTentry对应的Relocationentry,得到symbolindex后就可以找到该函数符号的函数描述符,并从Relocationentry中得到.
PLTi的地址,将.
PLTi处的函数描述符修改为找到的函数描述符(也就是将找到的函数描述符拷贝到.
PLTi处),完成该次符号解析.
以后在该文件中若还有调用该函数的语句,就会在中载入真正的TOC和真正的入口地址,正确执行该函数.
下面将以程序为例,演示SUSESLES8.
1forIBMpSeries是如何动态解析函数符号printf的.
表表表表Sample.
c1表include23intmain(intargc,char*argv[])4{5printf("Hello,world!
\n");6printf("AnotherHello,world!
\n");7return0;8}四.
过程演示下面以SUSELinuxEnterpriseServer8.
1forIBMpSeries为例,演示64位PowerPCLinux下函数符号的动态解析过程.
在PowerPC上调试64位程序,我们必须安装cross-ppc64-gdb包.
1.
Rungdb:/opt/cross/bin/powerpc64-linux-gdbsample2.
反汇编main函数developerWorksibm.
com/developerWorks/cn/PowerPC上ELF可执行文件的符号解析(二)第4页,共7(gdb)disassemblemainDumpofassemblercodeforfunctionmain:……………………0x10000668:bl0x10000460//printf表表表linkage表表表0x1000066c:ldr2,40(r1)//表表main表表表TOC表表……………………(gdb)disassemble0x100004600x10000460:addisr12,r2,00x10000464:stdr2,40(r1)//表表main表表表TOC表表表表表0x10000468:ldr11,-32648(r12)/*表表printf表.
PLT表表表表表表表r11表表表表printf表.
GLINKi表表*/0x1000046c:ldr2,-32640(r12)//表表表表表00x10000470:mtctrr110x10000474:ldr11,-32632(r12)0x10000478:bctr//表表printf表.
GLINKi表表……………………(gdb)b*0x10000478Breakpoint1at0x100004783.
在sample的linkage函数中设置断点并运行sample(gdb)rStartingprogram:/home/essl/program/GOT/sampleBreakpoint1,0x0000000010000478in_init()(gdb)irctrr2//表表printf表.
GLINKi表表表表表ctr0x10000778268437368//0x10000778表表printf表.
GLINKi表表表表r20x004.
反汇编printf的.
GLINKi入口(gdb)disassemble0x100007780x10000778:lir0,1//表relocation表表表表表r00x1000077c:b0x10000750//表表.
GLINK0/*0x10000750表表GLINK0表表表表表*/……………………5.
反汇编.
GLINK0(gdb)disassemble0x100007500x10000750:ldr2,40(r1)/*表表main表表表TOC表表表表表r2*/0x10000754:addisr12,r2,00x10000758:ldr11,-32696(r12)/*表表_dl_runtime_resolve表表表表表表表表r11*/0x1000075c:ldr2,-32688(r12)/*表表_dl_runtime_resolve表TOC表表表表表r2*/0x10000760:mtctrr11/*ctr表表表表_dl_runtime_resolve表表表表表*/0x10000764:ldr11,-32680(r12)0x10000768:bctr//表表_dl_runtime_resolve表表(gdb)b*0x10000768Breakpoint2at0x10000768(gdb)cContinuing.
Breakpoint2,0x0000000010000768incall___do_global_ctors_aux()(gdb)irctr//表表_dl_runtime_resolve表表表表表ctr0x7fe001051c5492190098206.
反汇编_dl_runtime_resolveibm.
com/developerWorks/cn/developerWorksPowerPC上ELF可执行文件的符号解析(二)第5页,共7(gdb)disassemble0x7fe001051cDumpofassemblercodeforfunction_dl_runtime_resolve:0x7fe001051c:stdur1,-128(r1)……………………(gdb)c//_dl_runtime_resolve表表表表表表表表表表表表表printf表"Hello,World!
\n"表Continuing.
Hello,world!
Breakpoint1,0x0000000010000478in_init()/*程序打印完Hello,World!
后会接着调用printf("AnotherHello,World!
\n"),然后在我们设的第一个断点停住,让我们用irctrr2察看printf的linkagefunction所取得的printf的入口地址和printf的TOC指针*/(gdb)irctrr2ctr0x7fe0210738549221107512r20x7fe033a998549222328728/*我们发现printf的linkage函数取出来的printf的函数入口点和TOC指针值较第一次运行已经改变,只是由于printf所属的共享库此时已经被载入到内存中了,所以printf函数入口点的地址和它的TOC指针值已经确定下来了,所以可以说明printf的.
PLT入口的函数描述符在_dl_runtime_resolve做解析完后就被修正为真正的printf的函数描述符了*/五.
总结从以上的分析和演示过程中我们可以看到64位PowerPC的函数符号动态解析和32位的函数符号动态解析过程有下列几点不一样:1)64位有函数描述符的概念;32位没有;2)64位每个需要重定位的函数有自己的代码,这段代码调用.
GLINKi入口,接着是.
GLINK0入口,再调用_dl_runtime_resolve函数;而32位则是先调用.
PLTi入口,接着是.
PLTresolve,再调用_dl_runtime_resolve函数;3)64位的.
PLTi是函数描述符存放的地方;32位的.
PLTi是一段汇编代码,它在功能上相当于64位的.
GLINKi;4)64位的.
GLINK0功能上相当于32位的.
PLTresolve和.
PLTcalll,并且解析到符号值后不再需要像32位那样修改.
PLTi处的代码来完成跳转,而是通过修改.
PLTi处的函数描述符的函数入口部分,然后再取出值来完成跳转,这一点倒是和i386的做法有点类似,只不过i386是将解析到的符号值放在变量GOT[x+n]中.
developerWorksibm.
com/developerWorks/cn/PowerPC上ELF可执行文件的符号解析(二)第6页,共7参考资料1.
ELF1.
1规范中文版http://elfhack.
whitecell.
org/mydocs/ELF_chinese.
txt2.
ELF1.
2规范英文版ToolInterfaceStandard(TIS)ExecutableandLinkingFormatSpecificationhttp://x86.
ddj.
com/ftp/manuals/tools/elf.
pdf3.
SYSTEMVAPPLICATIONBINARYINTERFACEPowerPCProcessorSupplementhttp://www.
cloudcaptech.
com/MPC555%20Resources/Programming%20Environment/SVR4abippc.
pdf4.
64-bitPowerPCELFABISupplementftp://ftp.
penguinppc64.
org/pub/people/amodra/PPC-elf64abi.
txt.
gz5.
POWERPC汇编参考手册HTML文件:http://publib16.
boulder.
ibm.
com/pseries/en_US/aixassem/alangref/alangreftfrm.
htmPDF文件:http://publib16.
boulder.
ibm.
com/doc_link/en_US/a_doc_lib/aixassem/alangref/alangref.
pdfibm.
com/developerWorks/cn/developerWorksPowerPC上ELF可执行文件的符号解析(二)第7页,共7作者简介陈剑陈剑,IBM软件工程师,在IBM中国软件开发中心从事Linux相关软件的测试和开发工作.
你可以通过chenjian@cn.
ibm.
com和他联系.
金戈金戈,IBM高级软件工程师,在IBM中国软件开发中心主持Linux集群系统开发工作.
你可以通过jinge@cn.
ibm.
com和他联系.
版权所有IBM公司2004(www.
ibm.
com/legal/copytrade.
shtml)商标(www.
ibm.
com/developerworks/cn/ibm/trademarks/)
上次部落分享过VirMach提供的End of Life Plans系列的VPS主机,最近他们又发布了DEDICATED MIGRATION SPECIALS产品,并提供6.5-7.5折优惠码,优惠后最低每月27.3美元起。同样的这些机器现在订购,将在2021年9月30日至2022年4月30日之间迁移,目前这些等待迁移机器可以在洛杉矶、达拉斯、亚特兰大、纽约、芝加哥等5个地区机房开设,未来迁移的时...
提速啦(www.tisula.com)是赣州王成璟网络科技有限公司旗下云服务器品牌,目前拥有在籍员工40人左右,社保在籍员工30人+,是正规的国内拥有IDC ICP ISP CDN 云牌照资质商家,2018-2021年连续4年获得CTG机房顶级金牌代理商荣誉 2021年赣州市于都县创业大赛三等奖,2020年于都电子商务示范企业,2021年于都县电子商务融合推广大使。资源优势介绍:Ceranetwo...
今天看到一个网友从原来虚拟主机准备转移至服务器管理自己的业务。这里问到虚拟主机和服务器到底有什么不同,需要用到哪些工具软件。那准备在下班之间稍微摸鱼一下整理我们服务器安装环境和运维管理中常见需要用到的软件工具推荐。第一、系统镜像软件一般来说,我们云服务器或者独立服务器都是有自带镜像的。我们只需要选择镜像安装就可以,比如有 Windows和Linux。但是有些时候我们可能需要自定义镜像的高级玩法,这...
64位和32位的区别为你推荐
摩拜超15分钟加钱首次 微信扫 摩拜单车 需要 付压金吗特朗普取消访问丹麦特朗普访华后还会去那里?留学生认证留学生服务中心认证内容和范围?留学生认证国外留学生毕业证怎么进行认证呢?冯媛甑尸城女主角叫什么名字百度关键词分析百度竞价关键词分析需要从哪些数据入手?抓站工具抓鸡要什么工具?www.hyyan.com请问我是HY了吗?在线等www.ijinshan.com驱动人生是电脑自带的还是要安装啊!?在哪里呢?没有找到yinrentangzimotang氨基酸洗发水的功效咋样?
apache虚拟主机 河北服务器租用 注册cn域名 openv ion 中国特价网 云鼎网络 有益网络 linux空间 cn3 免费phpmysql空间 支持外链的相册 优酷黄金会员账号共享 河南移动梦网 中国联通宽带测试 云服务是什么意思 服务器是什么意思 服务器是什么 中国域名根服务器 主机系统 更多