一种二进制翻译中库函数调用的处理方法

文档序号:6626131阅读:162来源:国知局
专利名称:一种二进制翻译中库函数调用的处理方法
技术领域
本发明涉及计算机领域的二进制翻译技术,尤其涉及动静结合方式下二进制翻译中对库函数调用的处理方法。
背景技术
二进制翻译技术是目前解决软件移植问题的一个研究热点,能将现有的软件移植到新开发的处理器上执行,使新处理器摆脱向前兼容的约束,对促进处理器体系结构的发展和国产微处理器的推广具有重要意义。
在介绍本发明之前,首先简要讲解本发明所涉及的一些背景技术,主要包括动静结合二进制翻译系统的特点;被执行程序与系统之间的翻译界面定在系统调用一级的原因;过程链接表(Procedure Linkage Table以下简称PLT)和全局偏移表(Global Offset Table以下简称GOT)的工作原理;以及X86和MIPS在进行函数调用时参数和返回值的传递方法。
动静结合二进制翻译系统综合了动态和静态二进制翻译系统的优点。优化以静态为主,利用传统的静态编译优化方法对翻译出来的本地码进行深度优化,避免动态优化的时间消耗,我们称静态模块翻译出来的目标机本地代码为静态本地码。动态模块把静态本地码装入内存执行,并且翻译静态模块不能翻译的源二进制代码,把间接跳转和间接调用的目标传给静态模块帮助其进一步扩大翻译优化的范围。经过几遍动静结合的迭代翻译之后,能够得到质量较好的本地码。
被执行程序与系统之间的翻译界面定在系统调用一级而不是定在主文件和共享库之间的原因主要有两点(1)可能造成全局变量在不同的文件中有多个副本,不便于管理;(2)对于结构变量,由于源与目标机器对齐方式不同,占用空间可能不同,可能造成目标机本地的库函数对X86的结构变量的引用错误。
GOT(全局偏移表)与PLT(过程链接表)是ELF(可执行和可链接格式)文件提供的处理库函数动态链接的标准结构。GOT的作用是记录一个文件中调用的库函数的地址,这个地址在发生库函数调用时由动态链接器填写。PLT包括两部分,所有库函数公用的PLT表项(PLT0),以及每个库函数自己的PLT表项(PLTi,i=1,2,…)。调用库函数时,控制转入库函数对应的PLTi中,然后间接跳转到PLT0中,PLT0调用动态链接器的fixup函数,再由fixup执行要调用的库函数并且填写GOT。以后再调用这个库函数时,就依照GOT中的地址把控制转移到库函数。PLT的伪代码如图1所示。
X86/Linux系统的参数传递是采用堆栈形式进行的。主调函数(Caller)把参数存入堆栈中,被调函数(Callee)从堆栈中取出参数,参与相应的操作。返回值的传递方式分情况处理,对于单一数据,通过eax寄存器或者浮点寄存器ST(0)传递;若是结构类型,传参时将返回值地址作为参数压栈,Callee将返回值存入参数指定的地址完成传递工作。MIPS/Linux系统的传参和传返回值比较复杂,采用堆栈和寄存器结合的形式。传参方式对整数和浮点数区分处理,提供了4个整型寄存器($4-$7)和4个浮点寄存器($f12-$f15)用于传参,当寄存器不够用时借助堆栈。传递返回值的方式类似于传参方式,有专门的返回寄存器,当返回值超过返回寄存器的存储限制,则借助堆栈传送。
通过对背景知识的分析我们知道,由于翻译界面定在系统调用一级,源机器的库函数代码也是被翻译的对象。由于采用动静结合的二进制翻译方式,可以事先对源机器共享库的库函数代码进行静态翻译,把静态本地码存在磁盘上,动态模块把需要的共享库的本地码装入内存。
目前二进制翻译中对库函数调用的处理方法主要有两种一种方法是对本地库函数的简单包装,这种方法主要应用在翻译界面定在主文件和共享库之间的情况,具体就是在目标机上用内存模拟X86的堆栈及其参数压栈和取返回值的行为,通过包装的方法与本地的库函数之间传递参数和返回值,但是存在前面所述的多个副本以及对齐方式的问题;另一种方法是在目标机上模拟X86的动态链接机制以及参数和返回值传递约定,这种方法主要应用在翻译界面定在系统调用一级的情况。具体就是在目标机上用内存模拟X86的堆栈及其参数压栈和取返回值的行为,按照X86处理动态链接的执行流程,把PLT、fixup函数、库函数的源二进制代码都进行翻译执行。由于翻译会造成代码膨胀,因此会造成执行效率的下降。

发明内容
本发明的目的是针对现有技术存在的缺陷,消除由于全局变量多个副本以及结构变量对齐方式差异带来的问题,提高二进制翻译中对库函数调用处理的效率。
为了达到上述目的,本发明提供了一种二进制翻译中库函数调用的处理方法,包括以下步骤a.建立库函数分类查询表;b.利用动静结合二进制翻译系统中的静态模块对主文件和它涉及的共享库中的库函数进行翻译;c.在控制转移到动态翻译之前,把静态翻译好的本地码装入内存,这部分本地码包括被执行主文件和共享库中的库函数两部分;d.在目标机中用内存模拟X86的寄存器和堆栈;具体定义如图2所示;e.依次对X86二进制程序中的每个基本块进行处理,取X86二进制程序中的第一个基本块;f.判别基本块的结束指令的指令类型是否为CALL指令,如果是,则进行步骤g,如果否,则进行步骤h;g.调用CALL指令处理模块处理CALL指令;h.判断是否所有的基本块都处理了?如果是,则结束;如果否,则进行步骤i;i.取下一个基本块,然后进行步骤f。
在上述方案中,可包装库函数是一种库函数,没有全局变量多个副本和结构变量对齐方式差异,可以调用本地的库函数。
在上述方案中,PLT短路库函数是一种库函数,其本地码在静态模块已经翻译过,动态模块直接跳入静态本地码中,不需要翻译执行PLT和fixup函数。
在上述方案中,包含以下步骤f1)判断CALL的目标是否为库函数?,如果是,则进行步骤f2,如果否,则进行步骤f8;f2)查询库函数分类表;f3)判断是否是可包装库函数,如果是,进行步骤f4,如果否,进行步骤f5;f4)进行可包装库函数处理;f5)判断是否是PLT短路库函数?,如果是,进行步骤f6,如果否,进行步骤f7f6)进行PLT短路库函数处理;f7)在目标机上模拟X86的参数和返回值传递约定,按照X86处理动态链接的执行流程,把PLT、fixup函数、库函数的源二进制代码都进行翻译执行;f8)模拟X86传参和返回值约定的方法对这种主文件内部的普通函数调用进行处理。
在上述方案中,在步骤f4中,包含以下子步骤f41)根据相应库函数的行参说明,在本基本块内往前找压参数的语句;f42)判断是否查找成功?如果是,则进行步骤f43,如果否,则进行步骤f44;f43)删除本基本块内找到的那些压参数指令翻译后对应的本地码,并形成如下本地代码将这些参数按照目标机传参约定放入到相应的寄存器和堆栈中;X86模拟寄存器ESP=X86模拟寄存器ESP-所有参数总大小;调用本地库函数;按照目标机传返回值约定取出返回值,然后按照X86约定放入到X86模拟寄存器或内存中;f44)在目标机上模拟X86的参数和返回值传递约定,调用包装的本地库函数完成库函数调用的处理。
在上述方案中,在步骤f6中,包含以下子步骤f61)在静态部分提供的本地码和动态部分翻译的本地码中查找当前要处理的库函数的本地码;f62)判断是否查找成功?,如果是,进行步骤f63,如果否,进行步骤f64;f63)把调用库函数的CALL指令翻译成如下的本地代码跳转到库函数本地码在内存中存放的地址,并且把返回地址放入约定好的寄存器中;f64)生成跳转目标是空的转移指令,并做好标记,同时把返回地址放入约定好的寄存器中,当把库函数的本地码装入内存或者翻译之后,再把本地码的存放地址填入跳转指令中。
因此,本发明尽可能地对源X86二进制程序中的库函数调用进行识别和提升;对于可包装库函数,用目标机本地的约定进行传参和返回值处理,这样省去了对X86参数压栈和从堆栈中取返回值的模拟,避免了频繁的内存操作,使用本地的库函数,也不会因为翻译PLT、fixup函数、库函数的源二进制代码造成代码膨胀导致的性能损失,提高了程序执行的效率;对于PLT短路库函数,虽然继续维护X86模拟堆栈,但是控制流不进入PLT和动态链接器的fixup函数,即不翻译PLT和动态链接器的fixup函数的源二进制代码,避免了因为翻译PLT、fixup函数造成代码膨胀导致的性能损失,控制流直接进入库函数的本地码,也能够较好地提高程序执行的效率。
综上所述,本发明中对可包装库函数的处理带来的性能上的提高强于对PLT短路库函数的处理,但是对于库函数不具有普适性,不是所有的库函数都是可包装库函数;PLT短路库函数虽然不如可包装库函数对性能提高的贡献大,但是具有较强的普适性。但总的来说,两种情况的处理都具有较好的效率。


图1是现有技术中PLT的伪代码(摘自ELF手册)示意图;图2是现有技术中目标机中用内存模拟X86的寄存器和堆栈示意图;图3是本发明中一种二进制翻译中库函数调用的处理方法的流程图;图4是本发明中对CALL指令的处理方法流程图;图5是本发明中对可包装库函数的处理方法流程图;图6是本发明中对PLT短路库函数的处理方法流程图。
具体实施例方式
在本发明中,定义两个术语可包装库函数和PLT短路库函数。如果某个库函数没有全局变量多个副本和结构变量对齐方式差异这两种问题,那么可以调用本地的库函数,这样就不会因为翻译PLT、fixup函数、库函数的源二进制代码造成代码膨胀导致的性能损失,本发明中称这类库函数为可包装库函数;有些库函数的本地码在静态模块已经翻译过,动态模块可以直接跳入静态本地码中,不需要翻译执行PLT和fixup函数,相当于把动态链接在某种程度上还原回静态链接,也避免了因为翻译PLT、fixup函数造成的性能损失,本发明中称这类库函数为PLT短路库函数。
本发明提出了一种二进制翻译中库函数调用的处理方法,对于可包装库函数和PLT短路库函数分别处理,同时在处理之前建立库函数分类查询表来区分可包装库函数和PLT短路库函数,以便对每个库函数分类处理,若某个库函数不在分类查询表中,则采取在目标机上模拟X86的动态链接机制以及参数和返回值传递约定的方法处理。
本发明建立在如下三个基本的原则上一是尽可能地识别和提升原X86二进制程序的库函数调用;二是对可包装库函数尽可能地避免在处理库函数调用时模拟X86的堆栈,而是用目标机本地函数调用约定来处理库函数调用,从而提高翻译出来的本地码的执行效率;三是对于PLT短路库函数尽可能地利用已经翻译好的本地码,尤其是静态模块翻译的质量较高的本地码,尽可能地避免翻译PLT和动态链接器的X86代码,从而提高翻译出来的本地码的执行效率。
下面参照附图详细说明本发明的技术方案。
如图3所示,一种二进制翻译中库函数调用的处理方法包括以下步骤步骤1,首先,建立库函数分类查询表;动静结合二进制翻译系统中的静态模块和动态模块都要参照这个表;步骤2,利用动静结合二进制翻译系统中的静态模块对主文件和它涉及的共享库中的库函数进行翻译;步骤3,在控制转移到动态翻译之前,把静态翻译好的本地码装入内存,这部分本地码包括被执行主文件和共享库中的库函数两部分;步骤4,在目标机中用内存模拟X86的寄存器和堆栈;具体定义如图2所示;步骤5,依次对X86二进制程序中的每个基本块进行处理,取X86二进制程序中的第一个基本块;步骤6,判别基本块的结束指令的指令类型是否为CALL指令,如果是,则进行步骤7,如果否,则进行步骤8;步骤7,调用CALL指令处理模块处理CALL指令;
步骤8,判断是否所有的基本块都处理了?如果是,则结束;如果否,则进行步骤9;步骤9,取下一个基本块,然后进行步骤6。
如图4所示,在步骤6中,包含以下步骤步骤61,判断CALL的目标是否为库函数?,如果是,则进行步骤62,如果否,则进行步骤68;步骤62,查询库函数分类表;步骤63,判断是否是可包装库函数,如果是,进行步骤64,如果否,进行步骤65;步骤64,进行可包装库函数处理;步骤65,判断是否是PLT短路库函数?,如果是,进行步骤66,如果否,进行步骤67;步骤66,进行PLT短路库函数处理;步骤67,在目标机上模拟X86的参数和返回值传递约定,按照X86处理动态链接的执行流程,把PLT、fixup函数、库函数的源二进制代码都进行翻译执行;步骤68,模拟X86传参和返回值约定的方法对这种主文件内部的普通函数调用进行处理。
如图5所示,在步骤64中,包含以下子步骤步骤400,根据相应库函数的行参说明,在本基本块内往前找压参数的语句;步骤410,判断是否查找成功?如果是,则进行步骤420,如果否,则进行步骤430;步骤420,删除本基本块内找到的那些压参数指令翻译后对应的本地码,并形成如下本地代码将这些参数按照目标机传参约定放入到相应的寄存器和堆栈中;X86模拟寄存器ESP=X86模拟寄存器ESP-所有参数总大小;调用本地库函数;按照目标机传返回值约定取出返回值,然后按照X86约定放入到X86模拟寄存器或内存中。
步骤430,在目标机上模拟X86的参数和返回值传递约定,调用包装的本地库函数完成库函数调用的处理。
如图6所示,在步骤66中,包含以下子步骤步骤600,在静态部分提供的本地码和动态部分翻译的本地码中查找当前要处理的库函数的本地码;步骤610,判断是否查找成功?,如果是,进行步骤620,如果否,进行步骤630;步骤620,把调用库函数的CALL指令翻译成如下的本地代码跳转到库函数本地码在内存中存放的地址,并且把返回地址放入约定好的寄存器中。
步骤630,由于目标库函数的本地码可能没有被动态模块装入或者没有被翻译,因此采用回填的方法处理库函数的调用;具体就是生成跳转目标是空的转移指令,并做好标记,同时把返回地址放入约定好的寄存器中,当把库函数的本地码装入内存或者翻译之后,再把本地码的存放地址填入跳转指令中。
本发明所提供的动静结合二进制翻译中的库函数调用处理方法具有如下特点在翻译前对库函数进行分类,分为可包装库函数和PLT短路库函数;静态模块会对库函数进行一定程度的翻译并把翻译结果传给动态模块;对源X86二进制程序中的库函数调用进行识别和提升;对于可包装库函数,用目标机本地的约定进行传参和返回值处理,这样能省去将参数压入X86模拟堆栈,然后又从堆栈中取出放入到目标机传参寄存器或堆栈中过程中频繁对内存的操作,提高了程序执行的效率;对于PLT短路库函数,虽然继续维护X86模拟堆栈,但是控制流不进入PLT和动态链接器的fixup函数,即不翻译PLT和动态链接器的fixup函数的源二进制代码,直接进入库函数的本地码,也能够提高程序执行的效率。
最后应说明的是以上实施例仅用以说明而非限制本发明的技术方案,尽管参照上述实施例对本发明进行了详细说明,本领域的普通技术人员应当理解依然可以对本发明进行修改或者等同替换,而不脱离本发明的精神和范围的任何修改或局部替换,其均应涵盖在本发明的权利要求范围当中。
权利要求
1.一种二进制翻译中库函数调用的处理方法,包括以下步骤a.建立库函数分类查询表,在表中,对可包装库函数和PLT短路库函数做分类;b.利用动静结合二进制翻译系统中的静态模块对主文件和它涉及的共享库中的库函数进行翻译;c.在控制转移到动态翻译之前,把静态翻译好的本地码装入内存,这部分本地码包括被执行主文件和共享库中的库函数两部分;d.在目标机中用内存模拟X86的寄存器和堆栈;e.依次对X86二进制程序中的每个基本块进行处理,取X86二进制程序中的第一个基本块;f.判别基本块的结束指令的指令类型是否为CALL指令,如果是,则进行步骤g,如果否,则进行步骤h;g.调用CALL指令处理模块处理CALL指令;h.判断是否所有的基本块都处理了,如果是,则结束;如果否,则进行步骤i;i.取下一个基本块,然后进行步骤f。
2.如权利要求1所述的一种二进制翻译中库函数调用的处理方法,其特征在于,在步骤f中,包含以下步骤f1)判断CALL的目标是否为库函数,如果是,则进行步骤f2,如果否,则进行步骤f8;f2)查询库函数分类表;f3)判断是否是可包装库函数,如果是,进行步骤f4,如果否,进行步骤f5;f4)进行可包装库函数处理;f5)判断是否是PLT短路库函数,如果是,进行步骤f6,如果否,进行步骤f7;f6)进行PLT短路库函数处理;f7)在目标机上模拟X86的参数和返回值传递约定,按照X86处理动态链接的执行流程,把PLT、fixup函数、库函数的源二进制代码都进行翻译执行;执行流程,把PLT、fixup函数、库函数的源二进制代码都进行翻译执行;f8)模拟X86传参和返回值约定的方法对这种主文件内部的普通函数调用进行处理。
3.如权利要求2所述的一种二进制翻译中库函数调用的处理方法,其特征在于,在步骤f4中,包含以下子步骤f41)根据相应库函数的行参说明,在本基本块内往前找压参数的语句;f42)判断是否查找成功,如果是,则进行步骤f43,如果否,则进行步骤f44;f43)删除本基本块内找到的那些压参数指令翻译后对应的本地码,并形成如下本地代码将这些参数按照目标机传参约定放入到相应的寄存器和堆栈中;X86模拟寄存器ESP=X86模拟寄存器ESP-所有参数总大小;调用本地库函数;按照目标机传返回值约定取出返回值,然后按照X86约定放入到X86模拟寄存器或内存中;f44)在目标机上模拟X86的参数和返回值传递约定,调用包装的本地库函数完成库函数调用的处理。
4.如权利要求2所述的一种二进制翻译中库函数调用的处理方法,其特征在于,在步骤f6中,包含以下子步骤f61)在静态部分提供的本地码和动态部分翻译的本地码中查找当前要处理的库函数的本地码;f62)判断是否查找成功,如果是,进行步骤f63,如果否,进行步骤f64;f63)把调用库函数的CALL指令翻译成如下的本地代码跳转到库函数本地码在内存中存放的地址,并且把返回地址放入约定好的寄存器中;f64)生成跳转目标是空的转移指令,并做好标记,同时把返回地址放入约定好的寄存器中,当把库函数的本地码装入内存或者翻译之后,再把本地码的存放地址填入跳转指令中。
5.如权利要求1或2所述的一种二进制翻译中库函数调用的处理方法,其特征在于,所述的可包装库函数是一种库函数,没有全局变量多个副本和结构变量对齐方式差异,可以调用本地的库函数。
6.如权利要求1或2所述的一种二进制翻译中库函数调用的处理方法,其特征在于,所述的PLT短路库函数是一种库函数,其本地码在静态模块已经翻译过,动态模块直接跳入静态本地码中,不需要翻译执行PLT和fixup函数。
全文摘要
本发明公开了一种二进制翻译中库函数调用的处理方法,尽可能地对源X86二进制程序中的库函数调用进行识别和提升;对于可包装库函数,用目标机本地的约定进行传参和返回值处理,这样省去了对X86参数压栈和从堆栈中取返回值的模拟,避免了频繁的内存操作,使用本地的库函数,也不会因为翻译PLT、fixup函数、库函数的源二进制代码造成代码膨胀导致的性能损失,提高了程序执行的效率;对于PLT短路库函数,虽然继续维护X86模拟堆栈,但是控制流不进入PLT和动态链接器的fixup函数,即不翻译PLT和动态链接器的fixup函数的源二进制代码,避免了因为翻译PLT、fixup函数造成代码膨胀导致的性能损失,控制流直接进入库函数的本地码,也能够较好地提高程序执行的效率。
文档编号G06F9/45GK1892602SQ200510080339
公开日2007年1月10日 申请日期2005年7月1日 优先权日2005年7月1日
发明者杨浩, 唐锋, 谢海斌, 武成岗, 张兆庆, 冯晓兵, 崔慧敏, 陈龙 申请人:中国科学院计算技术研究所
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1