版权所有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/)
BuyVM在昨天宣布上线了第四个数据中心产品:迈阿密,基于KVM架构的VPS主机,采用AMD Ryzen 3900X CPU,DDR4内存,NVMe硬盘,1Gbps带宽,不限制流量方式,最低$2/月起,支持Linux或者Windows操作系统。这是一家成立于2010年的国外主机商,提供基于KVM架构的VPS产品,数据中心除了新上的迈阿密外还包括美国拉斯维加斯、新泽西和卢森堡等,主机均为1Gbps带...
tmthosting怎么样?tmthosting家本站也分享过多次,之前也是不温不火的商家,加上商家的价格略贵,之到斯巴达商家出现,这个商家才被中国用户熟知,原因就是斯巴达家的机器是三网回程AS4837线路,而且也没有多余的加价,斯巴达家断货后,有朋友发现TMTHosting竟然也在同一机房,所以大家就都入手了TMTHosting家的机器。目前,TMTHosting商家放出了夏季优惠,针对VPS推...
Hostiger商家我们可能以前也是有见过的,以前他们的域名是Hostigger,后来进行微调后包装成现在的。而且推出Columbus Day哥伦布日优惠活动,提供全场的VPS主机首月7折月付2.79美元起的优惠。这里我们普及一下基础知识,Columbus Day ,即为每年10月12日,是一些美洲国家的节日,纪念克里斯托弗·哥伦布在北美登陆,为美国的联邦假日。Hostiger 商家是一个成立于2...
64位和32位的区别为你推荐
18comic.fun黑色禁药http://www.lovecomic.cn/attachment/Fid_18/18_4_00d3b0cb502ea74.jpg这幅画名字叫什么?刘祚天DJ是什么职业?同ip域名不同的几个ip怎样和同一个域名对应上m.2828dy.com电影虫www.dyctv.com这个电影站能下载电影吗?5xoy.com求个如月群真汉化版下载地址www.bbb551.com广州欢乐在线551要收费吗?lcoc.topeagle solder stop mask top是什么层www.ijinshan.com好电脑要用什么样的软件ww.66bobo.comfq55点com是什么网站ww.66bobo.com这个www.中国应急救援网.com查询证件是真是假?
美国和欧洲vps 花生壳免费域名 外贸主机 天猫双十一抢红包 申请个人网页 京东商城双十一活动 台湾谷歌地址 gspeed 699美元 免费吧 空间合租 个人免费主页 php服务器 畅行云 测速电信 稳定空间 广东主机托管 后门 重庆联通服务器托管 美国主机侦探 更多