CN108027748B - 指令集模拟器及其模拟器生成方法 - Google Patents
指令集模拟器及其模拟器生成方法 Download PDFInfo
- Publication number
- CN108027748B CN108027748B CN201680055109.2A CN201680055109A CN108027748B CN 108027748 B CN108027748 B CN 108027748B CN 201680055109 A CN201680055109 A CN 201680055109A CN 108027748 B CN108027748 B CN 108027748B
- Authority
- CN
- China
- Prior art keywords
- instruction
- subroutine
- program
- address
- machine language
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Active
Links
Classifications
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F8/00—Arrangements for software engineering
- G06F8/40—Transformation of program code
- G06F8/53—Decompilation; Disassembly
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F8/00—Arrangements for software engineering
- G06F8/30—Creation or generation of source code
- G06F8/31—Programming languages or programming paradigms
Landscapes
- Engineering & Computer Science (AREA)
- General Engineering & Computer Science (AREA)
- Theoretical Computer Science (AREA)
- Software Systems (AREA)
- Physics & Mathematics (AREA)
- General Physics & Mathematics (AREA)
- Computing Systems (AREA)
- Debugging And Monitoring (AREA)
Abstract
本发明的指令集模拟器(S)包括:子例程检测部件(1d、1e、1f、2);分支指令检测部件(1d、2);子例程调用指令检测部件(1c、1d);子例程源代码输出部件(3a、3e);识别符附加部件(3a4);无条件分支指令输出部件(3a5、3a6、3a8);以及子例程调用指令输出部件(3a8、3a9)。
Description
技术领域
本发明涉及通过从机器语言转换为程序源代码、或从程序源代码转换为机器语言而生成的指令集模拟器及其模拟器生成方法。
背景技术
以往,作为与本发明的技术关联的现有技术,有反编译器和指令集模拟器。
反编译器是从计算机直接执行的执行二进制(机器语言)转换为创建程序等的程序源代码的技术。即,反编译器进行从程序源代码转换为执行二进制的编译器的反转换。
反编译器技术的开发,始于1960年,最初用作协助将某个平台用的程序移植到另一平台的作业。之后,反编译器技术被应用于错误丢失的源代码的复原协助、程序的调试、病毒程序的发现和分析、程序内容的分析和理解、程序整体的高位处理结构的提取等。
另一方面,指令集模拟器是模拟处理器的动作并将执行二进制执行的工具,具有与反编译器技术作为目的的“复原可读性高的源程序”不同的目的。在指令集模拟器中,有下述翻译方式、静态编译方式、动态编译方式的3种类方式。
以下,说明3种类的指令集模拟器方式。再者,在以下“主机CPU”是指执行指令集模拟器的CPU。
翻译(Interpreter)方式(非专利文献3):从执行二进制逐一解码(解释)机器语言指令,同时模拟CPU动作。解码处理成为开销,模拟速度较慢。
静态编译(静态编译)方式(非专利文献4、5、8、9、10):集中解码所有执行二进制,在转换为主机CPU的机器语言指令后执行。此外,在转换为主机CPU的机器语言指令的过程中,还有转换为C语言等的源代码的情况。
动态编译(Dynamic compile)方式(非专利文献6、7):作为翻译方式的改进,通过将一次解码的主机CPU的机器语言指令序列保存在存储器中并执行它,减轻每次执行相同指令时每次解码的开销。由于进行从目标CPU指令集向主机CPU指令集的转换的二进制转换(Binary translation),所以这种方式需要全部安装指令集转换机构,所以工具安装非常复杂。
现有技术文献
非专利文献
非专利文献1:Michael Van Emmerik,″Static Single Assignment forDecompilation″,PhD Thesis,The University of Queensland,(2007http://www.backerstreet.com/decompiler/vanEmmerik_ssa.pdf)
非专利文献2:http://www.program-transformation.org/Transform/DeCompilation
非专利文献3:D.Burger,T.M.Austin,″The simplescalar tool set,version2.0″,Computer Architecture News,pp.13-25,1997
非专利文献4:C.Mills,S.Ahalt,J.Fowler,″Compiled instruction setsimulation″,Software-Practice and Exprerience,21(8),pp.877-889,1991
非专利文献5:Jianwen Zhu,and Daniel D.Gajski,″An Ultra-FastInstructionSet Simulator″,IEEE Trans.VLSI Systems,Vol.10,No.3,pp.363-373,2002
非专利文献6:A.Nohl,G.Braun,O/Schliebusch,R.Leupers,H.Meyr,A.Hoffmann,″A universal technique for fast and flexible instruction-setarchitecture simulation″,Proceedings of DATE 2002
非专利文献7:M.Reshadi,P.Mishra,N.Dutt,″Instruction Set CompiledSimulation:A Technique for Fast and Flexible Instruction Set Simulation″,Proceeding of DAC 2003,pp.758763,2003
非专利文献8:M.Bartholomeu,R.Azevedo,S.Rigo,G.Araujo,″Optimizationsfor compiled simulation using instruction type information″,Proceedings ofthe 16th Symposium on Computer Architecture and High Performance Computing(SBAC-PAD′04),pp.7481,2004
非专利文献9:Joseph D′Errico,Wei Qin,″Constrncting Portable CompiledInstruction-set Simulators An ADL-driven Approach″,Proceeding of DATE 2006,pp.112117,2006
非专利文献10:S.Bansal,A,Aiken,″Binary translation using peepholesuperoptimizers″,Proceedings of OSDI′08,PP.177-192,2008
非专利文献11:Wikipedia:Instruction Set Simulator http://ja.wikipedia.org/wiki/命令セットシミュレ一タhttp://en.wikipedia.org/wiki/Instruction_set_simulator
非专利文献12:Wikipedia:Binary Translation http://en.wikipedia.org/wiki/Binary_translation
发明内容
发明要解决的问题
然而,作为上述现有的反编译器的课题,有以下的技术课题(参照非专利文献1的P15~P28)。
第1,数据类型的复原困难。即,技术上非常难以从执行二进制估计原始的源代码的数据类型。
第2,“间接分支”的程序控制流程的分析困难。具体而言,将寄存器值代入PC(程序计数器)的指令,除了在C语言中的switch语句(分支指令)、case语句的代码安装中看到之外,即使在使用了函数指针的函数调用中也可将寄存器值代入PC。这样在数据依赖(程序执行转移因寄存器的值而改变)的情况下分析程序控制流程非常困难。
第3,函数自变量和返回值的复原困难。即,函数的自变量形式和返回值形式,不仅依存于目标处理器的指令集,还依存于调用约定(Calling Convention)(函数调用中的自变量形式和返回值形式的商定)。因此,没有这样的预备信息,就难以复原函数的自变量和返回值。
第4,在所谓完全性方面,由反编译器输出的源代码有以下2个课题。再者,在非专利文献1的P26~P27中,据说在2002年时列举的几个成果仅是dcc反编译器和REC(ReverseEngineering;逆向工程)这两个编译器。
作为第一课题,有人工编辑的必要性(REC)。许多现有的反编译器无人工编辑就不能成为可编译形式。具体而言,由于重视输出源代码的可读性,所以保证可编译形式的反编译器非常少。
作为第二课题,有程序复杂性的限度(dcc)。具体而言,即使在保证生成源代码的可编译形式的情况下,可处理的程序因程序复杂性的限制而被限定。
作为非专利文献1的方法和解决的课题,在反编译器的中间语言中采用SSA(static single assignment;静态单赋值)形式,通过进行高度的数据依赖性分析,进行可读性高的源输出。另外,可以将连接了多个单独的机器语言指令的“式”(expression)以可读性高的标记形式输出到源代码中,列举了函数自变量和返回值的正确提取、变量和函数自变量及返回值的数据类型的高精度推测、间接分支的程序控制流程的正确分析。
但是,没有特别提及排除或削减“人工编辑的必要性”的效果,而认为有关反编译器的完全性的效果是有限的。
因此,期望用于提高反编译器的完成度的技术构筑。为了克服所述的技术课题(一部分通过非专利文献1解决),需要与编译器环境相同程度的技术构筑,需要大量非常复杂的处理步骤。另一方面,编译器相比反编译器压倒性地大量需要,其开发资源(从事编译器开发的研究人员、技术人员、技术论坛等)也压倒性地庞大。因此,反编译器的技术成熟度远劣于编译器技术是极大的课题。
另一方面,所述的指令集模拟器可以满足作为反编译器技术课题即“完全性”(可以用任何程序可靠地模拟)。
通常,静态编译方式将所有执行二进制集中解码,所以可最快的模拟。可是,在将机器语言指令的解码结果转换为C源代码的方式的情况下(非专利文献4、8、9),相比直接由主机CPU执行(本地执行)原始的程序,非专利文献8中报告了需要14倍~54倍的模拟时间。
相对于此,在非专利文献5、10中,通过将转换结果直接作为主机CPU的机器语言指令输出,可进行各种各样的代码优化,可以实现与本机执行时间大致相当的模拟时间。另一方面,可以进行与执行二进制等效动作的源程序的生成的方式,即使在静态编译方式中,也只是在转换为主机CPU的机器语言指令之前输出源程序的方式(非专利文献4、8、9)。
再者,在非专利文献5、10中,将转换结果直接作为主机CPU的机器语言指令输出的方式,有无法将一个平台移植到另一平台、无法进行转换对象的程序的分析、无法进行病毒的发现、译码、分析等难点。
因此,供实际使用的方式,只有将机器语言指令的解码结果转换为C源代码的方式(非专利文献4、8、9)。
可是,如所述,将机器语言指令的解码结果转换为C源代码的方式(非专利文献4、8、9),模拟时间相比本地执行需要14倍~54倍的时间,有模拟时间长的问题。
此外,如后述,非专利文献4、8、9的方式有转换的C源代码的分析困难的问题。因此,病毒的发现、译码、分析困难。
这里,为了阐明本发明的结构,对与本发明途径(approach)最类似的非专利文献4、8、9具有的课题(本发明要解决的课题),表示C代码输出形式并具体地说明。
非专利文献4、8、9是,在所述静态编译方式指令集模拟器之中,将执行二进制的转换结果以C语言等的高级编程语言描述并输出的技术。这些C代码输出的方法,在随后的非专利文献8、9中也采用在最初的非专利文献4中提出的方式。
图53、图54中,表示在非专利文献4中说明的C代码输出形式。图53是非专利文献4的机器语言指令用C宏定义,图54是非专利文献4的与执行二进制进行等效动作的C代码输出。
图54的第4行的“register UL*S=M,*F=H,A=0,P=START;”意味着以下内容。
S是堆栈指针,F是帧指针,A是累加器,P是与PC(程序计数器)分别对应的函数内部的局部变量,是仅具有4个寄存器的极其简单的CPU模型。在从execute函数返回(图54的从下部起第3行)时,通过SAVESTATE宏(从图54的下部起第4行),将这些CPU寄存器值保存在全局变量中。
图54的第6行以后的“for(;;)switch(P)[…]”意味着以下。
是指令集模拟的主循环,反复执行,直至达到HALT指令(cpu停止指令)或default标签(分支到未定义指令地址、错误处理)为止。
switch(P)具有分支到与机器语言指令地址对应的各case语句(埋入在C宏内部)中的结构。
各机器语言指令用C宏将地址值作为case标签持有,包含该地址的机器语言指令动作的C描述。
在分支指令(CBLS:条件分支,JSR:子例程调用,UNLK:返回)的C宏中,是包含程序计数器的更新处理和break语句,在该机器语言指令处理之后,控制返回到switch语句,分支到下一指令地址的结构。
在一个switch语句中包含的case语句的数上有上限,所以为了应对较大的程序,需要将程序分割而使用多个switch语句来实现。(在后述的非专利文献8中也进行程序分割)
图55A、图55B中,表示引用了非专利文献4的方法的非专利文献8中的C代码结构。
图55A的第1行的“Region3()”是指定地址范围的机器语言指令的执行动作的描述。以下,说明各指令。
图55A的第3行的“switch语句”根据PC(程序计数器:图中ac_pc)的值,分支到相应的指令地址的case语句中。
图55A的第5、11行的“case语句”,情况的标签值对应于指令地址,该地址的指令的动作以C代码描述。也进行向下一指令的程序控制(PC的更新),通过末尾的各break语句返回到switch语句。
图55A的第18行的“default语句”,在Region3()的范围外的指令地址的情况下结束函数。
图55B的第1行的“Execute()”是模拟器的main函数,根据程序计数器的高位比特,称为与相应的程序区域对应的RegionXX()函数。
非专利文献8的C代码的优化方法(参照非专利文献8的5.优化技术(OptimizationTechniques))适用以下2个优化方法而被反映到C代码描述中。再者,这些优化方法在非专利文献4中所示的C代码中已经实现。
优化1(优化1):在PC不进行不连续的变化(分支,调用等)的通常的指令中,由于下一指令为紧随其后的case语句,所以删除无用的break语句。
优化2(优化2):仅在PC进行不连续的变化(分支,调用等)时,进行PC的更新。
上述非专利文献8的指令集模拟器,报告说相比当时的现有技术是最快的,但即便如此,相比本地执行,要花费14倍~54倍的模拟执行时间。
以下,说明有关由上述非专利文献4、8、9的方法得到的指令集模拟器的C代码(以后称为“指令集模拟器源代码”)的课题。
作为第1课题,作为需要与各指令地址对应的case语句的理由(非专利文献7:第3页、右栏第1段:Each instruction of the decoded application corresponds torespective behavior function call in the generated simulator.These functionsmust be accessed randomly,as all of them can be a potential target of a jumpinstruction....The switch is based on the Program Counter.),执行二进制与汇编程序不同,缺少分支目的地指令标签的信息。因此,没有判断哪个指令可作为分支目的地地址的信息。因此,基于“所有的”指令可作为分支目的地地址这样的前提,需要从switch语句可以转移到直接执行各case语句的指令动作代码的结构。
作为第2课题,由于模拟执行时间相比本地执行需要14倍~54倍的时间,所以以向另一CPU移植的目的来使用指令集模拟器源代码,因伴随很大的开销而是不实用的。模拟执行时间增大的要因来自与PC有关的switch语句和与各机器语言指令的地址对应的case语句的结构。
作为第3课题,是优化的问题。
在从switch语句向任意的case语句分支的代码结构中,由于缺少分支目的地信息,所以编译器中的代码优化非常困难。特别地,这里作为重要的代码优化,是除去在后面不使用的指令的“死代码除去”(dead code elimination),对模拟执行时间产生很大影响。在指令集模拟器的动作描述中,PC和状态标志(零标志,符号标志,溢出标志)被最频繁地更新,这些更新处理的描述占据全体的动作描述的大部分,由于它们不被优化,所以相比本地执行成为较大的处理开销的原因。
作为第4课题,有缺少分层结构的问题。
在分支指令中,PC更新处理之后,程序控制因break语句返回到switch语句后分支到case语句的一系列的处理也发生对转移表(存储器)的访问,所以这部分也成为处理开销的原因。即,由于执行二进制的函数分层结构没有被反映到输出C源代码中,所以成为处理花费长时间的原因。
作为第5课题,有可读性低这样的问题。
此外,从switch语句中包含的case语句的数的上限机械地分割了程序的C代码结构,作为源程序,可读性显著降低。因此,修正程序的程序错误的调试作业、程序的功能扩展等的代码改变作业等变得极其困难。
作为第6课题,有缺少程序控制流程分析的问题。
指令集模拟技术,聚焦在安装处理器的模拟功能的部分,有仍未取得与编译器和反编译器技术充分协同来发展的经历。因此,不存在取入了编译器技术的程序控制流程分析的机制的指令集模拟器。
图56、图57中,表示以往的嵌入式系统用软件开发环境的程序,说明各情况的优点、缺点。
图56中,表示没有使用以往的指令集模拟器的嵌入式系统用软件开发环境。
以往,不使用指令集模拟器的嵌入式系统用软件开发环境,有装载嵌入目标CPU的系统产品(真机)的情况;装载主机CPU的计算机的情况。
在软件开发环境为装载目标CPU的嵌入系统产品(真机)的情况下,目标CPU用的程序源代码或汇编代码由目标CPU用编译器转换为机器语言的执行二进制文件。执行二进制文件存储在装载嵌入目标CPU的系统产品的存储器中。
在这种情况中,开发的程序源代码或汇编代码装入最终产品的装载嵌入目标CPU的系统产品(真机)中,所以可进行详细的动作。可是,由于是真机,所以难以设定各种条件的测试情况,用于错误修正的调试作业困难。
另一方面,在软件开发环境为装载主机CPU的计算机的情况下,目标CPU用的程序源代码或汇编代码由主机CPU用编译器转换为机器语言的执行二进制文件。执行二进制文件存储在装载主机CPU的计算机中。
在这种情况中,开发的程序源代码或汇编代码装入装载主机CPU的计算机不是真机,所以详细的动作的再现无法实现。可是,由于是装载主机CPU的计算机,所以可设定各种条件的测试情况,用于错误修正的调试作业容易。
图57中,表示使用了以往的指令集模拟器的嵌入式系统用软件开发环境。
目标CPU用的程序源代码或汇编代码由目标CPU用编译器转换为机器语言的执行二进制文件。执行二进制文件由指令集模拟器转换为主机CPU用的执行二进制文件。主机CPU用的执行二进制文件由装载主机CPU的计算机执行。由指令集模拟器从目标CPU用的执行二进制文件转换为主机CPU用的执行二进制文件,所以在装载主机CPU的计算机中可进行详细动作的再现。
目标CPU用的执行二进制文件被转换为主机CPU用的执行二进制文件,所以机器语言的语法不同,模拟时间长。
从以上来看,若汇总现有技术要解决的课题时,作为现有技术,有将程序源代码转换为机器语言的反编译器技术;以及模拟处理器的动作而将执行二进制执行的指令集模拟器。
反编译器技术有以下课题。
第1,数据类型的复原困难。
第2,“间接分支”的程序控制流程的分析困难。
第3,函数自变量和返回值的复原困难。
第4,在所谓完全性方面由反编译器输出的源代码有以下2个课题。作为第一个课题,很多现有的反编译器不进行人工编辑就无法成为可编译形式。作为第二个课题,处理的程序因程序复杂性的限制而受到限定。
非专利文献1以可读性高的源输出解决上述第1数据类型的复原困难的问题,解决第2“间接分支”的程序控制流程的分析困难、第3函数自变量和返回值的复原困难等的问题。可是,未解决第4完全性的问题。
另一方面,在指令集模拟器中,可以满足对于以反编译器技术未解决的第4完全性。可是,相比直接由主机CPU执行(本地执行)原始的程序,指令集模拟器有花费14倍~54倍的模拟时间的问题。
在将目标CPU的机器语言指令直接作为主机CPU的机器语言指令输出的非专利文献5、10中,可以实现与本机执行时间大致相当的模拟时间。可是,在将机器语言指令作为另一机器语言指令输出的非专利文献5、10中,无法将一个平台移植到另一个平台,无法进行转换对象的程序的分析,有无法进行病毒的发现、译码、分析等问题。
因此,其结果,供实际使用的,仅是可以消除非专利文献5、10的问题即将一个平台无法移植到另一个平台、无法进行转换对象的程序的分析、无法进行病毒的发现、译码、分析等的、将机器语言指令的解码结果转换为C源代码的方式(非专利文献4、8、9)。
可是,如前述,在非专利文献4、8、9的指令集模拟器中,有下面要解决的课题。
作为第1课题,没有判断哪个指令可成为称为分支目的地地址的信息。
作为第2课题,模拟执行时间相比本地执行花费14倍~54倍的时间。
作为第3课题,编译器中的代码优化非常难以参与。
作为第4课题,缺少分层结构。
作为第5课题,复原的源程序甚至没有实现子例程的结构,所以作为源程序,可读性明显较低。
作为第6课题,缺少程序控制流程分析的机制。
因此,本申请是解决供实际使用的非专利文献4、8、9的上述的第1~第6课题的申请。
本发明鉴于上述实际状况完成的发明,目的在于提供从执行二进制可靠地进行源程序描述文件(指令集模拟器源代码:C语言描述)的复原,可以输出分析容易的源程序描述文件,可以构筑高速的指令集模拟环境的指令集模拟器及其模拟器生成方法。
解决问题的方案
为了解决所述课题,导入了以往从未考虑的以下详述的新的8个处理技术。
第1本发明的指令集模拟器,是将机器语言程序转换为程序源代码而生成的指令集模拟器,包括:子例程检测部件,检测所述机器语言程序中包含的子例程;分支指令检测部件,检测所述机器语言程序中包含的指令字之中具有分支目的地地址的分支指令;子例程调用指令检测部件,检测所述机器语言程序中包含的指令字之中具有子例程调用目的地地址的子例程调用指令;子例程源代码输出部件,输出由所述子例程检测部件检测所述机器语言程序所得的各子例程单位的程序源代码;识别符附加部件,在所述程序源代码的分支目的地的指令中附加表示所述分支目的地地址的识别符;无条件分支指令输出部件,将所述机器语言程序的所述分支指令作为对具有所述程序源代码的所述识别符的指令的无条件分支指令输出;以及子例程调用指令输出部件,将所述机器语言程序的子例程调用指令作为所述程序源代码的子例程调用指令输出。
第9本发明的指令集模拟器的模拟器生成方法是实现第1本发明的指令集模拟器的方法。
根据第1本发明或第9本发明,具有子例程检测部件、分支指令检测部件、子例程调用指令检测部件和识别符附加部件,所以具有判断哪个指令可成为分支目的地地址的信息(解决所述第1课题)。
机器语言程序的分支指令以程序源代码设为无条件分支指令而输出,并且机器语言程序中包含的子例程作为程序源代码的子例程而生成。可以复原机器语言程序的分层结构(解决所述第4课题)。
因此,有效地进行编译器的优化(解决所述第3课题),处理速度快(解决所述第2课题)。此外,可以实现指令集模拟器的完全性。
第2本发明的指令集模拟器,在第1本发明中,所述分支指令检测部件具有:简单分支指令检测部件,检测所述机器语言程序中包含的指令字之中可以指定分支目的地地址的简单分支指令;以及数据依赖分支指令检测部件,检测以寄存器值或存储器值确定所述机器语言程序中包含的分支目的地地址的数据依赖分支指令。
根据第2本发明,可以由简单分支指令检测部件检测简单分支指令,由数据依赖分支指令检测部件检测数据依赖分支指令,可顺利并且容易地进行程序源代码中的无条件分支指令化(解决所述第1课题、所述第6课题)。
第3本发明的指令集模拟器,在第2本发明中,包括:转移表记录部件,将所述机器语言程序的所述数据依赖分支指令的分支目的地地址记录在转移表信息存储单元中;以及数据依赖分支指令生成部件,基于所述数据依赖分支指令的所述分支目的地地址,从所述转移表信息存储单元检索相应的转移表信息,使用检索出的转移表信息,生成所述程序源代码的所述无条件分支指令。
第10本发明的指令集模拟器的模拟器生成方法,是实现第3本发明的指令集模拟器的方法。
根据第3本发明或第10本发明,从机器语言程序的分支指令,使用转移表信息,可以顺利并且容易地生成程序源代码的无条件分支指令(解决所述第1课题、所述第6课题)。
第4本发明的指令集模拟器,在第1本发明中,所述子例程调用指令检测部件具有:简单子例程调用指令检测部件,检测所述机器语言程序中包含的指令字之中可以指定调用目的地地址的简单子例程调用指令;以及数据依赖子例程调用指令检测部件,检测由寄存器值或存储器值确定所述机器语言程序中包含的调用目的地地址的数据依赖子例程调用指令。
根据第4本发明,可以由简单子例程调用指令检测部件检测简单子例程调用指令,由数据依赖子例程调用指令检测部件检测数据依赖子例程调用指令,可以顺利并且容易地生成程序源代码中的子例程调用指令(解决所述第1课题、所述第6课题)。
第5本发明的指令集模拟器,在第4本发明中,所述子例程调用指令输出部件包括:子例程机器语言地址表生成部件,生成将与子例程名和子例程机器语言地址形成对的信息有关的子例程机器语言地址表;子例程地址检索处理指令生成部件,从子例程机器语言地址检索所述程序源代码上的子例程,生成获取所述程序源代码上的子例程地址的子例程地址检索处理的程序;以及数据依赖子例程调用指令生成部件,根据所述子例程地址检索处理的指令,指定所述程序源代码的数据依赖子例程调用指令的调用目的地子例程,对该子例程进行调用处理。
第11本发明的指令集模拟器的模拟器生成方法,是实现第5本发明的指令集模拟器的方法。
根据第5本发明或第11本发明,在程序源代码上指定数据依赖子例程调用目的地的子例程,可以描述对其调用(解决所述第4课题)。
第6本发明的指令集模拟器,在第1本发明至第5发明的任何一个的本发明中,包括:寄存器变量展开部件,将所述机器语言程序的寄存器值作为所述程序源代码上的子例程自变量或局部变量来描述。
第12本发明的指令集模拟器的模拟器生成方法,是实现第6本发明的指令集模拟器的方法。
根据第6本发明或第12本发明,通过寄存器变量展开部件将机器语言程序的寄存器值作为所述程序源代码上的子例程自变量或局部变量来描述(解决所述第3课题、第4课题),所以可以加快指令集模拟器的处理速度(解决所述第2课题)。
第7本发明的指令集模拟器,在第1本发明至第5本发明的任何一个的本发明中,所述程序源代码是C语言的程序,不使用有关程序计数器的switch语句和有关各指令地址的case语句的代码结构,而使用对具有程序源代码上的识别符的指令的无条件分支指令和子例程调用指令,所述机器语言程序的子例程和所述程序源代码的子例程对应,所述机器语言程序中的子例程的分层被复原为所述程序源代码中的子例程的分层。
根据第7本发明的指令集模拟器,程序源代码是C语言的程序,不使用有关程序计数器的switch语句和有关各指令地址的case语句的代码结构,而使用对具有程序源代码上的识别符的指令的无条件分支指令和子例程调用指令,所以可以高效地进行优化。此外,机器语言程序的子例程和程序源代码的子例程对应,机器语言程序中的子例程的分层被复原为程序源代码中的子例程的分层(解决所述第4课题),所以优化能够高效地进行(解决所述第6课题),指令集模拟器的处理速度快(解决所述第2课题)。此外,程序源代码的可读性高,分析容易。因此,可以容易地进行恶意软件、病毒等的分析(解决所述第5课题)。
第8本发明的指令集模拟器,在第1本发明至第5本发明的任何一个的本发明中,由于机器语言程序中缺少码元信息,所以作为在所述子例程检测部件中无法检测所有的子例程的情况下相应处理的部件,包括:未注册机器语言地址检测部件,在未注册到所述子例程机器语言地址表中的机器语言地址通过数据依赖子例程指令被调用的情况下,在记录了该未注册机器语言地址后,强制结束指令集模拟器;以及未注册子例程程序源代码生成部件,对于未注册机器语言地址的子例程,由所述部件追加生成程序源代码。
第13本发明的指令集模拟器的模拟器生成方法,是实现第8本发明的指令集模拟器的方法。
根据第8本发明或第13本发明,由于机器语言程序中缺少码元信息,所以可以应对在子例程检测部件中无法检测所有的子例程的情况(解决所述第6课题)。
发明的效果
根据本发明,能够提供从执行二进制可以可靠地进行源程序描述文件的复原,可以输出分析容易的源程序描述文件,可以构筑高速的指令集模拟环境的指令集模拟器及其模拟器生成方法。
附图说明
图1表示C源代码的样本的图。
图2表示各机器语言指令的地址和32比特机器语言指令的16进制显示和反汇编的汇编指令的图。
图3表示通过本实施方式输出的C源描述的图。
图4A表示本发明的执行二进制的C描述输出的图。
图4B表示将本发明的执行二进制的C描述的再编译后的主机PC(X86指令集)的机器语言指令重合显示的图。
图5表示使用了第1实施方式的指令集模拟器的嵌入式系统用软件开发环境的图。
图6表示ELF文件的全体结构的概要的图。
图7表示第1实施方式的机器语言指令分析单元的功能框图。
图8表示包含了switch语句的函数jump_test的样本C程序的图。
图9表示数据依赖分支信息提取单元的功能框图。
图10表示图8的jump_test函数的ARMv5指令集的机器语言指令和汇编指令的图。
图11表示图8的jump_test函数的x86(64-bit)指令集的机器语言指令和汇编指令的图。
图12表示指令集模拟器的结构与分析对象的执行二进制文件5、指令集模拟器输出的指令集模拟器程序源代码的图。
图13表示ARMv5用指令集模拟器程序中的CPU资源的数据结构描述的一例子的图。
图14表示CPU资源参照用宏定义和指令执行条件判定用宏定义的图。
图15表示图10的″jump_test″函数的ARMv5指令集机器语言和汇编描述的4指令的图。
图16表示对图15的4个ARMv5指令集机器语言指令的宏调用描述的图。
图17表示SUB宏定义和CMP宏定义的图。
图18表示_SUB_宏定义(被SUB宏和CMP宏调用)的图。
图19表示在_SUB_宏内部称为的其他的宏的图。
图20表示图16中称为的STR宏定义的图。
图21表示_ADDR_,_m8_,_m16_,_m32_,D_CACHE_SIM各宏定义的图。
图22表示LDR宏定义的图。
图23表示由图16的4个机器语言指令程序生成宏调用生成的程序描述的图。
图24是子例程程序源生成单元的功能框图。
图25表示″jump_test″函数的子例程定义描述输出的图。
图26表示无条件分支指令的图。
图27表示无条件分支指令的程序描述的图。
图28表示子例程调用指令的图。
图29表示子例程调用指令的程序描述的图。
图30表示带条件的数据依赖分支指令和紧随其后的无条件分支指令的图。
图31表示带条件的数据依赖分支指令和紧随其后的无条件分支指令的程序描述的图。
图32表示实现数据依赖子例程调用的2个机器语言指令的图。
图33表示数据依赖子例程调用指令的程序描述的图。
图34表示与图10的″jump_test″函数的机器语言指令描述对应的程序描述的输出的图。
图35表示存储码元地址信息的_FP_INFO_结构体的图。
图36表示_FP_INFO_结构体的初始值设定用程序描述的图。
图37表示返回_FP_INFO_结构体的指针的_GET_FPI_函数的定义的图。
图38表示存储器初始化程序描述的例的图。
图39表示指令集模拟器的最高位函数的程序描述例1的图。
图40表示指令集模拟器的最高位函数的程序描述例2的图。
图41表示将main函数的自变量信息写入CPU存储器的程序描述的图。
图42表示第2实施方式的机器语言指令分析单元的功能框图的图。
图43表示第2实施方式的指令集模拟器的结构的图。
图44表示图10的″jump_test″函数的ARMv5机器语言指令的输入输出寄存器的图。
图45是子例程自变量提取单元的功能框图。
图46表示CPU资源参照用宏定义和指令执行条件判定用宏定义的图。
图47表示″jump_test″函数的子例程定义描述输出的图。
图48表示子例程调用指令的程序描述的图。
图49表示函数指针数据类型的定义的图。
图50表示数据依赖子例程调用指令的程序描述的图。
图51表示使用了第3实施方式的指令集模拟器的嵌入式系统用软件开发环境的图。
图52表示返回_FP_INFO_结构体的指针的_GET_FPI_函数的定义的图。
图53表示以往的非专利文献4的机器语言指令用C宏定义的图。
图54表示与以往的非专利文献4的执行二进制等效动作的C代码输出的图。
图55A表示引用了非专利文献4的方法的非专利文献8中的C代码结构的图。
图55B表示引用了非专利文献4的方法的非专利文献8中的C代码结构的图。
图56表示没有使用以往的指令集模拟器的嵌入式系统用软件开发环境的图。
图57表示使用了以往的指令集模拟器的嵌入式系统用软件开发环境的图。
具体实施方式
以下,一边参照相应的附图一边详细地说明本发明的实施方式。
<本发明的概要>
本发明的指令集模拟器,可以将由反编译技术可以构筑的程序流程控制分析功能和数据依赖性分析功能适用于静态编译(静态编译)方式。由此,确保指令集模拟器技术具有的“完全性”,使模拟速度提高至与本地执行同等。此外,确保复原源代码的一定的可读性。
再者,“完全性”是,无论什么样的程序,都能够“可靠”地执行能可靠地模拟等的执行二进制。
<<第1实施方式>>
为了阐明本发明的具体的内容,说明第1实施方式的指令集模拟器的C源代码输出。
<本发明的与执行二进制等效动作的C源代码输出>
图1中,表示C源代码的样本。
图2中表示将图1所示的C源代码样本转换为C编译器(gcc:GNU编译器Collection)中嵌入的处理器的ARMv5指令集的机器语言指令。在图2中,表示各机器语言指令的地址、32比特机器语言指令的16进制显示和反汇编的汇编指令。在图2中,左侧4位的字母数字是指令地址,中央8位的字母数字是16进制显示机器语言指令,右侧是汇编指令。
以下表示图2所示的ARMv5指令集的特征。
·16个寄存器(r0,...,r9,sl,fp,ip,sp,lr,pc):程序计数器(pc)也可以通过通常的指令改写。此外,通过更新pc的各种指令,可以实现各种各样的程序控制。
·执行条件:所有的指令包含5比特的执行条件标志,在执行条件不成立的情况下跳过执行。在图2中,popgt、beq、ble指令的后缀(gt,eq,le)是执行条件(greater than,equal,less orequal),没有执行条件后缀的指令被始终执行(al:always)。
·常量池:作为将32比特立即值(常量)加载到寄存器中的机制,采用在程序区域中嵌入的“常量池”。0x8234,0x8238,0x8428的各地址的数据(0x1b308,0x1b404,0x1b308)对应常量池。在加载这些常量时,用以pc为基址的加载指令(0x8218,0x8220,0x83c4)来实现。
图3中,表示通过本实施方式输出的C源描述。
以下说明通过本实施方式的指令集模拟器输出的C源描述的特征。
作为第一特征,一个机器语言指令与一个C宏调用指令(LDR,ADD,CMP等)一对一地对应。即,基本上具有执行以机器语言的源代码的描述的顺序处理的逐次处理的特征。实际的指令动作在各C宏描述的内部被定义。(非专利文献4也利用同样的C宏描述:参照图53、图54)
第二特征是,原始的C源代码(图1)的函数和从执行二进制由本实施方式的指令集模拟器生成的C描述的函数一对一地对应。即,原始的C源代码的函数分层被原样复原为由本实施方式的指令集模拟器S输出的C源描述。
C描述的函数调用结构的特征如下那样。
第1,函数的自变量(例如r0)以与CPU寄存器对应的参数名移交。函数自变量中未出现的其他的CPU寄存器被声明作为函数的局部变量。在图3中,至r0,r1,...,r9,s1,fp,...,pc为止是CPU通用寄存器变量(局部变量),cv,cc,...,cle是CPU状态寄存器变量(下述)。
第2,由于使用C描述的函数调用机构,所以作为CPU动作不需要在函数调用时需要的PC(程序计数器)和链路寄存器(lr:存储返回地址的寄存器)的更新处理。因此,可以抑制到与本地执行相同程度的函数调用的处理开销。
第3,在调用函数侧需要确保堆栈帧的情况下,将堆栈指针(sp)作为函数自变量移交。
第4,函数返回值通过以函数调用规则(依存编译器)规定的寄存器(上述例子中为r0)移交(图3的第12行)。即使原始的C函数为void型(没有返回值的函数),也输出将r0移交的描述,但不发生程序动作上的麻烦。因为编译器以r0在函数调用的前后被改写值作为前提,即使对r0代入“空”(值不定)的返回值,也不会被参照,所以没有问题。
第三特征是,在分支目的地指令之前配置C标签(L_083f0,L_083fc,L08400等)(识别符),分支指令以无条件分支指令的goto语句描述。
由此,不必使用以往的静态编译方式指令集模拟器(非专利文献4、8、9)生成的有关PC(程序计数器)的switch语句和有关各指令地址的case语句的代码结构。而且,可以将执行二进制的程序控制流程仍然以C语言的描述来表现。
通过将这样的与本来的程序控制流程同等的结构以C语言的描述来表现,可以最大限度地发挥编译器的优化处理的效果。因此,可以大幅度地缩短模拟执行时间。
<本实施方式的指令集模拟器执行时间>
本实施方式(本发明)的C源代码结构的特殊性质,实际上可以通过编译并执行本实施方式的指令集模拟器的C源代码来确认。图3的C源代码中出现的C宏的内部结构,为了将复杂的CPU动作忠实地以C语言的描述来表现而以相当复杂的代码构成。这里,说明尽管是复杂的CPU动作的C描述,但本指令集模拟器输出的C源代码如何生成高效的执行代码(主机CPU的执行二进制)。主机CPU是指执行指令集模拟器等的软件工具的处理器(台式和笔记本PC中装载的处理器等)。
在图4A、图4B中,表示将本发明的执行二进制的C描述输出和它的再编译后的主机PC(X86指令集)的机器语言指令重合显示。图4A、图4B中的以划线包围的部分是再编译后的主机PC(X86指令集)的机器语言指令。
·_my_put_prime_的函数调用(2处)被在线展开.
·ARMv5代码大小:26+7*2=40指令
get_primes函数:26指令
put_prime函数:7指令(在线展开2处)
·X86代码大小:42指令
尽管无法直接比较图2的ARMv5和图4A、图4B的X86的不同指令集,而至少以图4A、图4B所示的复杂的C宏构成,一个ARMv5指令和一个X86指令在数量上大致对应。其结果,可知本指令集模拟器的C源代码的编译器优化最大限度地有效。由于主机PC(X86指令集)的机器语言指令越少,执行时间越短,模拟时间越短,所以可知使用了本实施方式的指令集模拟器的情况下的模拟时间可以缩短。
此外,若实际地比较本机执行时间(直接编译和执行原始的C源代码)和本指令集模拟器S的模拟执行时间(从执行二进制,由指令集模拟器S输出C源代码,由主机CPU编译并执行该C源代码),则可成为以下结果。
若将测试程序的包含图2的代码的质数计算程序
由主机CPU:Intel Xeon 3.4GHz(Quad core),3.25GB memory
执行,则本机执行时间:0.7580秒。
相对于此,本实施方式(本发明)的指令集模拟器S的测试程序的包含图2的代码的质数计算程序的模拟执行时间为0.7699秒,本机执行时间:0.7580秒之比为1.016倍。
由此,以往的模拟执行时间相比本地执行为14倍~54倍,而根据本实施方式的指令集模拟器S,显然可以大幅度地缩短为1.016倍。
<使用了指令集模拟器的嵌入式系统用软件开发环境>
接着,说明使用了指令集模拟器S的嵌入式系统用软件开发环境。
图5中,表示使用了第1实施方式的指令集模拟器的嵌入式系统用软件开发环境。
目标CPU指将执行二进制的机器语言指令执行的处理器(嵌入式系统中装载的处理器等)。
主机CPU指执行指令集模拟器等的软件工具的处理器。例如,指台式和笔记本PC中装载的处理器等。
目标CPU用的程序源代码或汇编代码,由目标CPU用编译器转换为目标CPU用的执行二进制文件。执行二进制文件存储在装载目标CPU的嵌入系统产品的存储器中并执行。
在指令集模拟器S中的模拟时,指令集模拟器S的机器语言指令分析单元1读入目标CPU用的执行二进制文件,执行机器语言指令分析处理,输出码元信息列表r1、分支目的地地址列表r2、转移表信息列表r3。
指令集模拟器S的程序源代码输出单元2读入目标CPU用的执行二进制文件、码元信息列表r1、分支目的地地址列表r2、和转移表信息列表r3。然后,程序源代码输出单元2将指令集模拟器程序源代码(指令集模拟器S的程序源代码)输出。再者,在本实施方式中,指令集模拟器程序源代码相当于所述的C语言源代码。
指令集模拟器程序源代码通过主机CPU用编译器,被转换为主机CPU用的执行二进制文件。主机CPU用的执行二进制文件被加载到装载主机CPU的计算机的存储器中,并被执行。
指令集模拟器S使用软件实现。再者,也可以用硬件构成指令集模拟器S之中的至少一部分。
接着,详细地说明第1实施方式的指令集模拟器S的结构。
<执行二进制数据结构>
首先,说明执行二进制(机器语言)的数据结构。
图6中,表示ELF文件的全体结构的概要。
程序的执行二进制数据(机器语言数据)的格式,因编译器和OS而存在多种类型,但这里以ELF(Executable and Linkable Format;可执行和可链接格式)文件为例子,说明其内部结构。再者,下述中“存储位置”是指从ELF文件的开头起的偏移值,以字节数指定在ELF文件中存储的位置。
(1)ELF报头:位于ELF文件的开头,包含所有为了获取在ELF内部保存的各种数据而必需的信息。主要的项目如下。
文件种类是可执行文件、可链接文件、共享库等。
有CPU机种和版本、入口点(程序执行时的最初的地址)、程序报头表的存储位置、节报头表的存储位置的ELF报头的大小、程序报头表的1个入口的大小和入口数、节报头的1个入口的大小和入口数、存储了节名字符串表的节报头表索引等。
(2)程序报头表包含在由CPU执行ELF文件时,OS等为了确保存储器区域和准备存储器初始化等而必需的信息。1个入口包含与1个段(1个以上的部分构成)有关的以下的信息作为主要项目。
作为段型有可读入段、动态的链接段等。另外,有段的存储位置、段被配置在存储器上的虚拟地址和物理地址、段的文件大小和存储器大小、段的访问权(可执行、可读出、可写入的组合)等。
(3)二进制数据部分,存储机器语言指令数据(程序存储器数据)和数据存储器的初始值数据。
(4)节报头表
节(section)作为存储器区域(程序存储器和数据存储器)的结构单位,此外作为补充信息的存储单位存在。节报头表的1个入口包含有关1个节的以下的信息作为主要项目。
作为节名字符串信息有对节报头内的节名字符串表节的索引。
作为节类型有程序定义信息(存储器区域的结构单位、调试信息等)、码元表(程序地址信息、变量地址信息)、字符串表、再配置信息、动态链接信息等。
作为节属性有存储器区域占有(可读出)、可写入、可执行等。
另外,有节的存储器地址、节的存储位置、节的大小。
(5)码元表
码元主要包含存储器中存储的程序地址信息和变量信息,属于其中一个节。
码元表作为节报头表的1个入口来存储。码元包含以下的信息作为主要项目。
作为码元名字符串信息,有对节报头内的“码元名字符串表”的索引。
有码元的存储器地址、码元的大小。
作为码元属性,有绑定属性、类型属性、可视性属性。特别地,在类型属性中,将函数和其他可执行指令相关联的码元的属性称为“FUNC型”。
作为节索引,有码元所属的节的索引。
(6)特殊的码元:在由“码元表”定义的码元之中,在后述的“机器语言指令分析处理”中,包含需要特别的处理的码元。
“入口码元”:指将由ELF报头定义的“入口点”(程序执行时的最初的地址)作为“码元存储器地址”持有的“码元”。通过结束该“入口码元”的执行,程序执行结束,但作为通常的结束部件,执行停止CPU动作的“停止指令”或对下一个“程序结束处理码元”的子例程调用指令。
“程序结束处理码元”:指进行将程序执行结束的处理的码元。例如,在C语言中exit()函数是“程序结束处理码元”。
<执行程序的存储器区域的信息>
在所述ELF结构中,与存储了执行程序的存储器区域有关的信息,在几个分层中被定义。
·入口点(ELF报头项目):存储了在程序起动后最初执行的指令的地址
·具有“可执行”访问权的段(segment)的地址区域在程序报头表中被定义。
·具有“可执行”属性的节的地址区域在节报头表中被定义。
·具有“可执行”属性的节的地址区域中包含的码元的存储器地址在节报头表内定义的码元表中被定义。
这里,保证在执行文件中定义的信息是入口点和可执行段的地址区域,由于节报头表可省略,所以也可能有缺少节信息和码元信息的情况。
<用于机器语言指令分析处理的数据结构>
首先,说明成为在机器语言指令分析处理中需要的数据结构。
(1)“码元地址临时列表”:具有可执行属性,具有与函数等相关联的可执行码元的地址的列表结构。随着机器语言指令解释处理的进行而更新。
(2)“码元信息列表”:具有“码元信息”的列表结构。
“码元信息”存储与可执行码元有关的码元地址和指令地址列表的信息项目。
(A)码元地址
(B)指令地址列表:具有从码元地址可到达的全部指令的地址的列表结构。
(C)码元名字符串:从“码元表”中包含的“码元名字符串信息”生成。在“码元表”中不存在的码元和“码元表”本身不存在的情况下,根据生成不重复的字符串的任意的命名规则,生成“码元名字符串”。
(D)“数据依赖子例程指令标志”:表示在从码元地址可到达的全部指令的内部包含“数据依赖子例程指令”(1)不是不包含(0)的标志。
(3)“指令地址临时列表”:存储处理对象的机器语言指令,具有随着机器语言指令分析单元1的处理的进行而被更新(处理对象的指令地址被读入、删除)的指令地址的列表结构。
(4)“分支目的地地址列表”:具有带条件的分支指令和无条件分支指令的分支目的地地址的列表结构。
(5)“下一指令信息临时列表”:具有“下一指令信息”的列表结构。
“下一指令信息”是某个指令执行后与下一个可执行的指令(以后称为“下一指令”)有关的信息,由以下的数据项目构成。
A)下一指令地址
B)下一指令类型是以下3类型的其中之一。
1)“紧随其后”型:将存储了该指令字的存储器上的紧随其后的地址中存储的指令称为“紧随其后指令”。对PC(程序计数器)不作用的运算指令(ADD、SUB等)、加载指令(LDR)、存储指令(STR)等成为“紧随其后指令”的下一指令。
2)“分支”型:分支指令中的分支目的地地址
3)“调用”型:子例程调用指令中的调用目的地地址
此外,对应于上述3个“下一指令类型”,分别称为“紧随其后型下一指令”、“分支型下一指令”、“调用型下一指令”。
(6)“转移表信息列表r3”:“转移表信息”的列表结构。
“转移表信息”是通过后述的“数据依赖分支信息提取单元2的处理”而生成的信息,由以下的数据项目构成。
A)数据依赖分支指令地址
B)转移表大小(在数据依赖分支信息提取单元2的处理不成功的情况下,转移表大小为“0”)意味着在转移表信息列表中没有信息。
C)分支目的地地址表(1个入口存储分支目的地地址。“入口数”=“转移表大小”。)
<对列表结构的操作术语说明>
(1)对列表的“(非重复)追加”:指仅在列表中不存在与追加的数据相同的数据时,在列表的末尾追加数据。以后,基本上所有的列表保持的数据都是“非重复的”,所谓对列表的“追加”的表现,只要没有另有说明,就意味着“非重复的追加”。
(2)来自列表的“取出”:指取出列表的末尾的数据,删除该末尾数据。
<<第1实施方式>>
接着,说明第1实施方式的指令集模拟器S的机器语言指令分析单元1。
图7中,表示第1实施方式的机器语言指令分析单元的功能框图。
第1实施方式的机器语言指令分析单元1具有分析机器语言的作用,以便将在对象CPU中执行的分析对象的机器语言转换为C代码。
机器语言指令分析单元1具有码元地址预处理单元1a、码元地址获取单元1b、指令地址获取单元1c、下一指令信息提取单元1d、地址列表更新单元1e、以及数据依赖分支提取单元2。
机器语言指令分析单元1输出码元信息列表r1、分支目的地地址列表r2和转移表信息列表r3,以便从分析对象的机器语言创建C代码。
这里,作为实施方式1的机器语言指令分析单元1的处理,说明存在节报头表,而且在该表中码元表也被定义的前提成立情况下的处理流程。
<码元地址预处理单元1a>
码元地址预处理单元1a创建“码元地址临时列表”。
码元地址预处理单元1a将在节报头表内定义的码元表中,具有可执行属性的节的地址区域中包含的码元、即具有函数和其他可执行指令相关联的类型属性的码元(参照所述“FUNC型码元类型属性”)看作“可执行码元”。码元地址预处理单元1a通过将“可执行码元”的地址全部“追加”到“码元地址临时列表”中,创建“码元地址临时列表”。
之后,进至码元地址获取单元1b。
<码元地址获取单元1b>
(1)“码元地址临时列表”不是空的情况
A)码元地址获取单元1b从“码元地址临时列表”中“取出”一个码元地址(以后,将该码元称为“当前码元”)。
B)在“码元信息列表”中已经存在有关当前码元的“码元信息”的情况下(当前码元处理完毕),跳过所有后续的处理,立即返回到码元地址获取单元1b的处理的开始。
C)在“码元信息列表”中不存在有关当前码元的“码元信息”的情况下,将取出的当前码元的“码元信息”如下那样生成。再者,以后将该码元信息称为“当前码元信息”。
1)在“码元信息”的“码元地址”中设定“当前码元”地址。
2)生成“码元名字符串”。在码元被注册在“码元表”中的情况下,获取并生成“码元表”内的“码元名字符串信息”。另一方面,在码元未被注册在“码元表”中的情况下,根据任意的命名规则生成不重复字符串作为码元名(作为一例子,基于“码元地址”生成码元名:在码元地址为0x1234的情况中,设为“func_1234”等)。
3)将“数据依赖子例程指令标志”设定为“0”。
D)将当前码元的地址“追加”在“指令地址临时列表”中。然后,进至下述指令地址获取单元1c。
(2)另一方面,在“码元地址临时列表”为空的情况下,码元地址获取单元1b结束“机器语言指令分析单元1的处理”。
<指令地址获取单元1c>
(1)在“指令地址临时列表”不是“空”的情况下,指令地址获取单元1c从“指令地址临时列表”中“取出”一个指令地址。以后,将该地址称为“当前指令地址”。
在“当前指令地址”已经存在于“当前码元信息”的“指令地址列表”中的情况下(当前指令地址处理完毕),跳过后续的所有处理,立即返回到指令地址获取单元1c的处理的开始。
另一方面,在“当前指令地址”不存在于“当前码元信息”的“指令地址列表”中的情况下,将向“当前码元信息”的“指令地址列表”“追加”“当前指令地址”,进至下述下一指令信息提取单元1d的处理。
(2)另一方面,在“指令地址临时列表”为空的情况下,将“当前码元信息”的“指令地址列表”升序地排序。将“当前码元信息”“追加”在“码元信息列表r1”中。
然后,返回到码元地址获取单元1b的处理。
<下一指令信息提取单元1d>
下一指令信息提取单元1d基于“当前指令地址”,读出在“执行二进制文件”的“二进制数据部分”中存储的二进制数据,将该二进制数据看作机器语言指令。然后,下一指令信息提取单元1d将该机器语言指令解码(解释),执行与指令类别对应的以下(1)~(4)的处理,并生成“下一指令信息”,“追加”到“下一指令信息临时列表”中。
(1)在“简单分支指令”(仅用指令字可以指定分支目的地地址的分支指令)的情况下,下一指令信息提取单元1d从分支目的地地址生成“分支型”下一指令信息。
(2)在“数据依赖分支指令”(分支目的地地址是由寄存器值和存储器值确定的分支指令)的情况下,由于仅用指令字无法直接指定分支目的地,所以执行以下的处理。
首先,执行后述的“数据依赖分支信息提取单元2”,提取转移表信息列表r3的“转移表信息”。然后,下一指令信息提取单元1d对于提取出的“转移表信息”的“分支目的地地址列表r2”中存储的所有的分支目的地地址,生成“分支型”下一指令信息。
(3)在“简单子例程调用指令”(仅用指令字可以指定调用目的地地址的子例程调用指令)的情况下,下一指令信息提取单元1d从调用目的地地址生成“调用型”下一指令信息。
(4)在“数据依赖子例程调用指令”(调用目的地地址是由寄存器值和存储器值确定的子例程调用指令)的情况下,下一指令信息提取单元1d将“当前码元信息”的“数据依赖子例程指令标志”设定为“1”。再者,“数据依赖子例程调用指令”的调用目的地地址的解决,由后述的其他部件进行。
(5)对于有执行“紧随其后指令”的可能性的所有的指令:有执行“紧随其后指令”的可能性的指令是除了以下情况以外的所有指令。
A)无条件地执行的“简单分支指令”或“数据依赖分支指令”:因为任何一个分支目的地地址都为下一指令地址。
B)返回指令:因为从子例程复位时的“返回指令”无法唯一地确定复位目的地地址。
C)CPU停止指令:停止CPU的执行动作的指令。
D)“当前码元”为“入口码元”,向“程序结束处理码元”(进行结束所述程序执行的处理的码元)“子例程调用指令”的情况:因为在从“入口码元”调用了“程序结束处理码元”的情况下,该“子例程调用指令”为“入口码元”的最后的指令。
E)非机器语言指令:不适于以指令集规定的任何一个指令的情况。
上述以外的所有的指令(应注意的是,包含带条件的分支指令、带条件的数据依赖分支指令、子例程调用指令)全部有执行“紧随其后指令”的可能性,所以从“紧随其后指令地址”生成“紧随其后型”下一指令信息。
之后,进至地址列表更新单元1e。
<地址列表更新单元1e>
从由下一指令信息提取单元1d生成的“下一指令信息临时列表”,如下那样进行各种地址列表的更新处理。
(1)“紧随其后型”下一指令信息的更新,从“下一指令信息临时列表”中将“紧随其后型”下一指令信息全部“取出”,将它们追加到指令地址临时列表中。
(2)“分支型”下一指令信息的更新,从“下一指令信息临时列表”中“取出”全部“分支型”下一指令信息,将它们“追加”到分支目的地地址列表r2和指令地址临时列表中。
(3)“调用型”下一指令信息的更新,从“下一指令信息临时列表”中将“调用型”下一指令信息全部“取出”,将它们追加到码元地址临时列表中。有时很少存在以码元地址预处理单元1a中说明的方法提取的“可执行码元”以外的地址作为子例程调用目的地地址的子例程调用指令,是用于应对该情况的处理。目的在于不遗漏地分析调用的所有的子例程。
之后,返回指令地址获取单元1c。
<数据依赖分支信息提取单元2的处理的原理>
说明用于生成数据依赖分支信息的数据依赖分支信息提取单元2的处理原理。
图8中,表示包含了switch语句的函数jump_test的样本C程序。
在图8的样本C程序中,安装jump_test函数内的switch语句(switch(n)[case3:...case 8:...default:...])作为与变量n的值有关的数据依赖分支指令。
<数据依赖分支指令的动作原理>
数据依赖分支指令预先准备以下的指令要素和数据要素而动作。
(1)case语句的整数常量的最小值和最大值:图8的情况下,最小值为3,最大值为8。以后,标记为min_case_value=3,max_case_value=8。
(2)转移表:是存储了与switch语句内的各case语句对应的开头指令地址的地址表。转移表的大小,通常以max_case_value-min_case_value+1(图8的情况为8-3+1=6)提供。在转移表的最初的入口,存储与case min_case_value:对应的开头指令地址。在最后的入口,存储与case max_case_value:对应的开头指令地址。
此外,对于min_case_value<=idx<=max_case_value的范围的常量idx中case语句中不出现的值,在存在default语句的情况下存储与default语句对应的开头指令地址,在不存在default语句的情况下存储与紧随switch语句后的开头指令地址。
(3)转移表偏移值:通常,在switch(n)的处理中,jt_offset=n-min_case_value作为转移表偏移值计算。
(4)转移表偏移值的范围判定指令:对于所述转移表偏移值jt_offset,进行jt_offset>=0并且是否为jt_offset<=max_jt_index=max_case_value-min_case_value的范围判定。如果所述范围判定为“真”的情况,则在转移表内存在数据依赖分支目的地地址,在范围判定为“假”的情况下,在转移表内不存在数据依赖分支目的地地址。
(5)基于转移表偏移值的范围判定的带条件的分支指令:是在所述范围判定结果为“假”时分支的带条件的分支指令。此时的分支目的地地址,在存在default语句的情况下是与default语句对应的开头指令地址,在不存在default语句的情况下为紧随switch语句后的开头指令地址。
(6)转移表容纳存储器读出指令和数据依赖分支指令:在转移表偏移值的范围判定结果为“真”的情况下,对于存储了转移表的存储器地址jt_addr,读出按(jt_addr+jt_offset*a_size)计算的存储器的地址中存储的数据依赖分支目的地地址。这里,a_size是地址值的字长(字大小的字节长度),如果是32-bit指令集则为4(字节),如果是64-bit指令集则为8(字节)。通过将这样获取的分支目的地地址值代入PC(程序计数器),实现数据依赖分支。根据指令集,也有转移表容纳存储器读出指令和数据依赖分支指令以一个机器语言指令安装的情况(ARMv5指令集、x86指令集等)。
<数据依赖分支指令中的关联指令的配置>
(1)转移表偏移值的范围判定指令
(2)基于转移表偏移值的范围判定的带条件的分支指令
(3)存储转移表存储器读出指令
(4)数据依赖分支指令
再者,也有(3)、(4)为一个机器语言指令的情况(所述)。(2)也有在(4)之后立即到来的情况。
<数据依赖分支信息提取单元2>
在图9中,表示数据依赖分支信息提取单元的功能框图。
数据依赖分支信息提取单元2进行以下一系列的处理。假设数据依赖分支指令的地址已经由所述下一指令信息提取单元1d(图7)提供。
(1)“转移表容纳存储器读出指令”提取单元2a
数据依赖分支指令本身进行存储器读出的情况下,该指令是“转移表容纳存储器读出指令”。此外,在将寄存器值代入PC的数据依赖分支指令的情况下,对该数据依赖分支指令被执行前的寄存器进行存储器加载的指令为“转移表容纳存储器读出指令”。
(2)转移表容纳存储器地址分析部2b和转移表偏移寄存器提取单元2c
在转移表容纳存储器读出指令中,在存储器地址以“基址值(固定地址)+偏移值”的形式计算的情况下,将“基址值”指定为“转移表容纳存储器地址值”,将存储偏移值的寄存器指定为“转移表偏移寄存器”。
再者,“基址值”有作为“绝对地址”(机器语言指令指定地址值本身的信息)给予的情况,以及作为“PC相对地址”(机器语言指令指定在当前指令地址中相加的偏移值)计算的情况。
再者,在无法进行“转移表容纳存储器地址值”和“转移表偏移寄存器”的任何一个的指定的情况下,判断为不可能进行数据依赖分支信息提取,结束“数据依赖分支信息提取单元2的处理”。
(3)转移表偏移量范围判定指令提取单元2d和转移表大小提取单元2e
指定位于“转移表容纳存储器读出指令”被执行前的“相对转移表偏移寄存器的范围判定指令”。该范围判定指令的比较对象常量值是前述的max_jt_index,可以指定max_jt_index+1=max_case_value-min_case_value+1为转移表大小。在无法指定“相对转移表偏移寄存器的范围判定指令”的情况下和范围判定指令的比较对象不是常量值的情况下,判断为不可能进行数据依赖分支信息提取单元2的处理,结束“数据依赖分支信息提取单元2的处理”。
(4)分支目的地地址信息读出单元2f
从以所述指定的“转移表容纳存储器地址值”和“转移表大小”的信息,将在转移表中存储的分支目的地地址全部读出,存储在分支目的地地址表(机器语言地址表)中。
(5)转移表信息生成单元2g
生成由预先提供的“数据依赖分支指令”、上述(1)~(4)的工序中得到的“转移表大小”和“分支目的地地址表”构成的“数据依赖分支转移表信息”,“追加”到“数据依赖分支信息列表”中。生成的数据依赖分支转移表的信息,由所述下一指令信息提取单元1d使用。
<<机器语言指令分析处理的实施例1(ARMv5指令集的情况)>>
图10中,表示图8的jump_test函数的ARMv5指令集的机器语言指令和汇编指令。以“指令地址”(16进制标记)、“机器语言指令数据”(16进制标记)、“汇编指令描述”的顺序标记各行,对于对PC(程序计数器)作用的指令,还标记了该指令类别。
在以下的说明中,以在从“码元地址临时列表”获取了“jump_test”的地址0x8340为前提,说明之后的机器语言指令分析处理。
在表1中,表示至0x8340~0x834c为止的机器语言指令分析处理。
[表1]
A)在最初的部分的机器语言指令分析处理中,基于码元地址0x8340的指令,顺序地进行下一指令信息提取。由于0x8340,0x8344,0x8348的各指令是对PC没有作用的“通常指令”,所以只有“紧随其后指令”为下一指令。这些下一指令地址由地址列表更新单元1e“追加”在“指令地址临时列表”中后,被指令地址获取单元1c立即取出。
B)由于0x834c的指令为“数据依赖分支指令”,所以由数据依赖分支信息提取单元2进行该部分的下一指令信息提取处理。
在表2中,表示0x834c中的数据依赖分支信息提取单元2的处理。
[表2]
数据依赖分支信息提取单元2首先指定0x834c中的“转移表容纳存储器读出指令”与数据依赖分支指令相同,随后指定转移表容纳存储器地址为0x8354,转移表大小为6。最终,从地址0x8354读出6个分支目的地地址[0x8384,0x839c,0x836c,0x83a4,0x836c,0x8384],生成“转移表信息”。
在表3中,表示0x834c的下一指令信息提取单元1d的处理和0x8350的机器语言指令分析单元1的处理。
[表3]
A)对于0x834c的指令,从由数据依赖分支信息提取单元2生成的转移表信息获取6个分支目的地地址,而且由于0x834c的数据依赖分支指令是带条件的执行指令(ldrls),所以紧随其后指令(0x8350)也作为下一指令而生成下一指令信息临时列表。这里,6个分支目的地地址中也包含重复的地址,但应注意的是,在下一指令信息临时列表中,不追加重复的下一指令信息。在地址列表更新单元1e中,在“分支目的地地址列表”中“追加”4个(不重复)分支目的地地址,在“指令地址临时列表”中“追加”5个下一指令地址(分支型和紧随其后型)。
B)接着,指令地址获取单元1c将指令地址临时列表的末尾地址0x8350“取出”。由于该指令是“无条件分支指令”,所以下一指令信息提取单元1d将分支目的地地址0x839c提取作为下一指令地址。然后,地址列表更新单元1e将分支目的地地址0x839c追加到“分支目的地地址列表”和“指令地址临时列表”中。这里,由于在任何一个的列表中都存在0x839c,所以这些列表没有被更新。
在表4中,表示至0x83a4~0x83b4为止的机器语言指令分析处理。
[表4]
这些地址的指令接续仅将“紧随其后指令”作为下一指令的“通常指令”。最后的地址0x83b4是返回指令,由于不存在下一指令,所以指令地址临时列表没有被更新。再者,在中途的地址0x83a8,0x83ac中出现以下2个指令。
在表5中,表示0x83ac、0x83a8的机器语言指令和C语言指令。
[表5]
这里,0x83ac是转移到寄存器r3的值的“数据依赖分支指令”,在紧接其前的0x83a8中,由于有将pc(实际的值为当前指令地址0x83a8+8)代入链路寄存器lr的指令,所以可以判别0x83ac的指令实际上是“数据依赖子例程调用指令”。
在图8的样本C程序中,与func_pointer f;...f(n)的部分对应,变量f是函数指针(变量),f(n)是通过函数指针的子例程调用。所以相比“数据依赖分支指令”中的“转移表信息”是存储器上固化的数据,而可提取,也有在程序执行中设定“数据依赖子例程调用指令”中的“调用目的地地址”的情况,一般难以进行调用目的地地址的提取。
因此,这里,数据依赖子例程调用指令的下一指令信息只有“紧随其后指令”,数据依赖子例程调用目的地地址的解决,由后述的其他部件应对。即,“数据依赖子例程调用指令”的下一指令信息提取处理与“通常指令”为相同的处理。
在表6中,表示其他部分的机器语言指令分析处理。
[表6]
在分析对象指令地址0x836以后的机器语言指令分析处理中,继续进行与表4同样的对指令序列(多个“通常指令”和“返回指令”)的指令分析处理。
紧接分析对象指令地址0x836之前的指令地址列表和指令地址临时列表,如表6的上栏所示。
在表6的A栏的分析对象指令地址(0x836c-0x8380)中,取出指令地址临时列表的结束地址0x836c,从地址0x836c的指令起,连续地分析下一指令(紧随其后指令)地址,到达0x8380的返回指令(无下一指令)。
在表6的B栏的分析对象指令地址(0x839c-0x83a0)中,取出指令地址临时列表的结束地址0x839c,从地址0x839c的指令起,分析下一指令(紧随其后指令)地址,到达0x83a0的返回指令(无下一指令)。
在表6的C栏的分析对象指令地址(0x8384-0x8398)中,取出指令地址临时列表的结束地址0x8384,从地址0x8384的指令起,连续地分析下一指令(紧随其后指令)地址,到达0x8398的返回指令(无下一指令)。
在表6的C栏的最后,在指令地址获取单元1c中探测“指令地址临时列表”为“空”的状态(码元内全部指令分析结束),将“当前码元信息”的“指令地址列表”升序地排序。
<<机器语言指令分析处理的实施例2(x86(64-bit)指令集的情况)>>
在图11中,表示jump_test函数的x86(64-bit)指令集的机器语言指令和汇编指令。从左起,以“指令地址”(6位的16进制标记)、“机器语言指令数据”(以从左向右的顺序16进制数每2位地被划分)、“汇编指令描述”的顺序,标记各行。再者,对作用于PC(程序计数器)的指令,还标记该指令类别。
在以下的说明中,以码元地址获取单元1b从“码元地址临时列表”获取了jump_test的地址0x400560为前提,说明之后的机器语言指令分析处理。
在表7中,表示至图11的jump_test函数的0x400560-0x40056e为止的机器语言指令分析处理单元1的处理。
[表7]
A)最初,基于码元地址0x400560的指令,顺序地进行下一指令信息提取,由于0x400560,0x400563,0x400567的各指令是对PC不作用的“通常指令”,所以“紧随其后指令”为下一指令。
B)由于0x40056a的指令是“带条件的分支指令”,所以分支目的地地址0x400575和紧随其后指令地址0x40056c为下一指令地址。
C)由于0x40056e的指令是“数据依赖分支指令”,所以由数据依赖分支信息提取单元2进行该部分的下一指令信息提取单元1d的处理。
在表8中,表示图11的0x40056e中的数据依赖分支信息提取处理。
[表8]
这里,首先指定“转移表容纳存储器读出指令”与数据依赖分支指令相同,随后指定转移表容纳存储器地址为0x400738,转移表大小为6。最终,从地址0x400738读出6个分支目的地地址[0x400591,0x400575,0x400580,0x40059a,0x400580,0x400591],生成“转移表信息”。
在表9中,表示0x40056e的下一指令信息提取处理。
[表9]
对于0x40056e的指令,从由数据依赖分支信息提取单元2生成的转移表信息中获取6个分支目的地地址,生成下一指令信息临时列表。这里,在6个分支目的地地址中也包含重复的地址,但要注意的是,在下一指令信息临时列表中,不追加重复的下一指令信息。在地址更新单元中,在“分支目的地地址列表r2”和“指令地址临时列表”中“追加”4个(不重复)分支目的地地址,但由于在两列表中存在下一指令地址0x400575,所以实际上追加3个地址。
在表10中,表示其他部分的机器语言指令分析单元1的处理。
[表10]
紧接0x40059a之前,指令地址列表、指令地址临时列表如表10的上栏所示。
在0x40059a的以后的机器语言指令分析处理中,在接续了伴随一个下一指令的“通常指令”、“无条件分支指令”、“数据依赖子例程调用指令”的任何一个后,对到达“返回指令”或“处理完毕指令”的指令序列的指令分析处理继续进行。再者,对于解决“数据依赖子例程调用指令”的调用目的地地址,由其他部件进行。
在表10的A栏的分析对象指令地址(0x40059a,0x40059f,0x400587,0x400589,0x40058d,0x400590)中,在取出指令地址临时列表的结束地址0x40059a,连续地分析下一指令地址(紧随其后型、分支型)时,到达0x400590的返回指令(无下一指令)。
在表10的B栏的分析对象指令地址(0x400580,0x400587)中,取出指令地址临时列表的结束地址0x400580,分析下一指令地址,判定为紧随其后的0x400587为“处理完毕”(存在于当前码元的指令地址列表中)。
表10的C栏的分析对象指令地址(0x400591,0x400598,0x400587):取出指令地址临时列表的结束地址0x400591,在连续地分析下一指令地址(紧随其后型、分支型)时,判定为0x400587为“处理完毕”(存在于当前码元的指令地址列表中)。
表10的D栏的分析对象指令地址(0x400575,0x400577,0x40057b):取出指令地址临时列表的结束地址0x400575,连续地分析下一指令地址(紧随其后型),到达0x40057b的返回指令(无下一指令)。
在表10的D栏的最后,在“指令地址获取单元1c”探测“指令地址临时列表”为“空”的状态(码元内全部指令分析结束),将“当前码元信息”的“指令地址列表”升序地排序。
<指令集模拟器程序源代码输出单元3>
图12中,将指令集模拟器的结构与分析对象的执行二进制文件、指令集模拟器输出的指令集模拟器程序源代码一起表示。
指令集模拟器S包括机器语言指令分析单元1和指令集模拟器程序源代码输出单元3。
指令集模拟器程序源代码输出单元3从具有由机器语言指令分析单元2提取的信息的码元信息列表r1、分支目的地地址列表r2、转移表信息列表r3输出并生成指令集模拟器程序源代码。
指令集模拟器程序源代码输出单元3具有:子例程程序源生成单元3a、码元地址信息表源生成单元3b、存储器初始化程序描述生成单元3c、以及main函数程序描述生成单元3d。
指令集模拟器程序源代码4具有:子例程程序源4a、码元地址信息表源4b、main函数源4c、存储器初始化处理源4d、以及预先准备的机器语言指令程序生成宏定义源4e。
<指令集模拟器程序中的CPU资源的数据结构描述>
这里,说明作为用于生成“指令集模拟器程序源代码4”的准备而需要的CPU资源的数据结构描述。
这里,“CPU资源”指存储器和CPU寄存器(通用寄存器、内部状态寄存器等),这些“CPU资源”的状态在指令集模拟器程序上,需要将CPU动作作为实际的硬件在模拟器程序上忠实地再现。在图13中,表示ARMv5用指令集模拟器程序中的CPU资源的数据结构描述的一例子,在图14中,表示CPU资源参照用宏定义和指令执行条件判定用宏定义。
(1)存储器:声明作为char型(8比特)的数组。MEM_SIZE(存储器大小)从执行二进制文件中包含的“程序报头表”等中得到的信息指定需要的存储器大小(也确保需要的堆栈区域)。
(2)通用寄存器:声明作为16个32比特数组(无符号)。其中,r[13]用作堆栈指针(sp),r[14]用作链路寄存器(lr:存储子例程的复位地址),r[15]用作程序计数器(pc)。
(3)状态寄存器:声明作为cr,cc,cv,cls,cge,cle构成的6个32比特变量(无符号)。在表示用于判定ARMv5指令中的“指令执行条件”的CPU的状态的信息中使用它们。在执行实际的ARMv5指令集的CPU中,通常安装通过4个内部寄存器比特(Z:零,N:负,V:溢出,C:进位(位上升))的组合,判断14种类的执行条件的机构。作为资源描述,还可实现同样的4比特的状态寄存器,但在这里,通过声明作为6个32比特变量,意图在于削减用于“指令执行条件”的判定的软件上的运算量(后述)。
(4)CPU资源参照用宏定义:
A)_r_(n):用于参照第n通用寄存器的宏
B)_R_,_C_,_V_,_LS_,_LE_,_GE_:用于参照6个状态寄存器变量(cr,cc,cv,cls,cge,cle)的宏
C)_m8_,_m16_,_m32_:用于从存储器分别“读出”和“写入”8比特数据、16比特数据、32比特数据的宏
(5)指令执行条件判定用宏定义:在程序描述上进行基于所述6个状态寄存器变量参照宏的指令执行条件判定。指令执行条件为以下15种类。(下述中,将通常的Z/N/V/C的4比特的状态寄存器的条件判定式和图14的基于6个状态寄存器变量参照宏的条件判定式进行比较记载。)
A)AL(无条件):始终执行指令。
B)EQ(相等的条件)、NE(不相等的条件)
1)Z/N/V/C判定式:EQ(Z==1),NE(Z==0)
2)6状态变量判定式:EQ(_R_==0),NE(_R_!=0)
C)CS(进位的条件)、CC(进位清除的条件)
1)Z/N/V/C判定式:CS(C==1),CC(C==0)
2)6状态变量判定式:CS(_C_!=0),CC(_C_==0)
D)MI(相减的条件)、PL(相加的条件)
1)Z/N/V/C判定式:MI(N==1),PL(N==0)
2)6状态变量判定式:MI(((S32)_R_)<0),PL(((S32)_R_)>=0)
E)VS(溢出的条件)、VC(不溢出的条件)
1)Z/N/V/C判定式:VS(V==1),VC(V==0)
2)6状态变量判定式:VS(((S32)_V_)<0),VC(((S32)_V_)>=0)
F)HI(高于的条件)、LS(低于或相同的条件):无符号
1)Z/N/V/C判定式:HI(C==1&&Z==0),LS(C==0||Z==1)
2)6状态变量判定式:HI(_LS_==0),LS(_LS_!=0)
G)GE(大于或等于的条件)、LT(小于的条件):带符号
1)Z/N/V/C判定式:GE(N==V),LT(N!=V)
2)6状态变量判定式:GE(_GE_!=0),LT(_GE_==0)
H)GT(大于的条件)、LE(小于或等于的条件):带符号
1)Z/N/V/C判定式:GT(Z==0&&N==V),LE(Z==1&&N!=V)
2)6状态变量判定式:GT(_LE_==0),LE(_LE_!=0)
在通常的Z/N/V/C的4比特的状态寄存器的情况下,在除了AL的14种类的指令执行条件判定中,相对由1~3比特构成的判定式,在6状态变量判定式中,各自是基于1个状态变量的判定式,有在程序执行时以更少的运算数来判定的优点。
<机器语言指令程序生成宏定义源4e>
“机器语言指令程序生成宏”是,基于几个自变量(变量、常量、字符串),具有部分生成执行程序描述的功能的编程描述方法。
该“机器语言指令程序宏”定义被使用的所有的机器语言指令类别的各个类别(该宏定义理所当然为专用于目标CPU的指令集的描述)。再者,机器语言指令程序生成宏定义源4e是不依存分析对象的“执行二进制文件”的信息,所以事前准备。
图16中表示与图15中表示的4个机器语言指令对应的“机器语言指令程序宏”调用描述。以后,说明各机器语言指令程序宏。
<SUB宏描述(sub指令)和CMP宏描述(cmp指令)>
图17中,表示SUB宏定义和CMP宏定义。
对应sub指令而调用SUB宏,对应cmp指令而调用CMP宏。
(1)SUB宏和CMP宏中使用的自变量:
·c(表示执行条件的字符串):Z/N/V/C的4比特的状态寄存器
·v(指令比特字段):主要表示内部寄存器的更新条件的指令属性
·rd(输出寄存器ID):存储计算结果的寄存器号
·rn(第1操作数寄存器ID):存储第1操作数的寄存器号
·sh(移位属性):对第2操作数的移位处理属性
·rm(第2操作数寄存器ID):存储第2操作数的寄存器号
·val(立即值数据):第2操作数为立即值(常量)的情况的立即值数据
·pc(指令地址):这里与指令动作程序没有关系
(2)图18所示的_SUB_宏:是SUB宏和CMP宏进一步调用的内部宏。
这里,SUB宏和CMP宏中使用的自变量的意义如下。
·w_rd(输出属性):1的情况下存储在输出寄存器中,0的情况下不存储。
·cin(进位输入):减法的进位输入
·swap_op(操作数调换属性):1的情况下将第1操作数和第2操作数调换,0的情况下保持原样。
·c,v,rd,m,sh,rm,val:与SUB/CMP宏自变量相同意义
(3)_COND_宏:是_SUB_宏进一步调用的内部宏,在图14中被定义。“_COND_(c)”被定义为“if_COND_##c##_”的宏。“##”是“字符串连结预处理器”,所以例如_COND_(AL)被转换为“if_COND_AL_”,进而“_COND_AL_”根据该宏定义而被转换为“(1)”。
(4)状态寄存器变量更新描述:_fS_(v)为1的情况下,6个状态寄存器变量被更新。
(5)图19中表示在_SUB_宏内部调用的其他宏。
·IMM(rm,val):在图16的SUB宏调用和CMP宏调用中,作为这些宏自变量sh被提供“IMM”。图18中的“sh(rm,val)”的描述被转换为“IMM(rm,val)”,在该IMM宏定义中,最终被转换为“(val)”。
·_fS_(v):转换为((v>>2)&1)。这里,与取出v的低位第2比特(从第0比特起计数)的运算等价。
·与_fB_(v),_fH_(v),_fP_(v),_fU_(v),_fW_(v):_fS_(v)同样,定义取出v的指定比特的运算。在后述的STR宏中调用。
<STR宏描述(push指令)>
图20中表示在图16中调用的STR宏定义,图21中表示在该宏内部调用的_ADDR_,_D_CACHE_SIM宏定义。(补充:在原始的机器语言的汇编指令描述中为“push[lr]”(参照图15),但这是进行将堆栈指针sp(arm.r[13])“递减”(减去相当1数据字的地址)的值作为存储器地址,将链路寄存器lr(arm.r[14])写入存储器的动作,作为ARMv5中的str指令来安装。)
(1)STR宏中使用的自变量:
·c(表示执行条件的字符串):与SUB宏和CMP宏同样
·v(指令比特字段):地址偏移量计算方法、有无地址寄存器的更新、数据类型信息等的指令属性
·rd(写入数据寄存器ID):存储写入数据的寄存器号
·rn(基址寄存器ID):存储基址的寄存器号
·sh(移位属性):对偏移量操作数的移位处理属性
·rm(偏移寄存器ID):存储偏移值的寄存器号
·val(立即值数据):偏移值为立即值(常量)的情况的立即值数据
·pc(指令地址):当前指令地址(基址寄存器为PC(程序计数器)的情况下,当前指令地址在地址计算中使用)
(2)_ADDR_宏:生成在STR宏内部调用、进行写入存储器地址的计算的以下程序。从_ADDR_调用的宏_fU_(v),_fP_(v),_fW_(v),是指定地址的偏移量计算方法和有无基址寄存器_r_(rn)的更新等的指令属性。
(3)程序计数器的作用:从ARMv5指令集规范,在程序计数器(pc)用作基址时,“当前指令地址+8”成为基址(由_ADDR_宏定义)。此外,在用作写入数据寄存器时,“当前指令地址+12”成为写入数据(由对STR宏的变量d的代入语句定义)。
(4)写入数据类型:根据由_fB_(v),_fH_(v)(参照图20)给予的指令属性比特,描述8比特整数型(U8)、16比特整数型(U16)、32比特整数型(U32)各自的写入存储器动作(由图14的_m8_,_m16_,_m32_的各宏定义)。
(5)高速缓存模型:在高速缓存模拟为有效时(ENABLE_CACHE_MODEL被另外定义的情况),D_CACHE_SIM宏提供调用数据高速缓存模拟函数D_Cache_Sim(被另外定义)(参照图21)的机制。再者,在高速缓存模拟不有效的情况下,D_CACHE_SIM(addr,isRead)的描述(图21参照)被转换为“空字符串”。
<LDR宏描述(pop指令)>
图22中表示在图16称为的LDR宏定义。(补充:在原始的机器语言的汇编指令描述中为“pop[pc]”,这是将堆栈指针sp(arm.r[13])作为存储器地址,从存储器读出以所述push[lr]记录的“返回指令地址值”,进行使堆栈指针“递增”(相加相当1数据字的地址)的动作,作为ARMv5中的ldr指令来安装。)
这里,LDR宏(读入存储器)的自变量、在内部调用的宏与STR宏(写入存储器)大致共用。另一方面,存储器读出固有的动作如以下那样。
(1)读出数据的高位比特扩展:_fS_(v)==1的情况表示“带符号”数据,_fS(v)==0的情况表示“无符号”数据。在8比特型数据和16比特型数据中,“带符号”数据将高位比特进行“符号扩展”(用符号比特埋入),“无符号”数据将高位比特进行“插入0”。
(2)对程序计数器(pc)的加载动作:在LDR宏中,对程序计数器的加载指令看作为“返回指令”,生成执行“返回(return)语句”的程序描述。所述的“数据依赖分支指令”也执行ldr指令的对pc的加载,而通过后述的“数据依赖分支指令程序描述生成单元3a8”,以不适用LDR宏的程序描述来安装“数据依赖分支指令”。
<宏调用描述的宏展开后的程序描述>
前述的4个指令程序生成宏(SUB,STR,CMP,LDR)的调用,最终生成图23所示的程序描述。
<程序描述上的子例程命名规则>
说明图12所示的子例程程序源4a的程序描述上的“子例程命名规则”。
子例程命名规则中应注意的点是,例如,在C语言中,如main函数和exit函数那样,预约具有特别意义的子例程名,所以需要与预约子例程名不重复。
因此,将预先确定的“前缀字符串”(例如″_my_″等)连接到“码元信息”中包含的“码元名字符串”的开头,作为“子例程名字符串”。例如,与码元名″jump_test″对应的“子例程名字符串”,在“前缀字符串”设为″_my_″的情况下,为″_my_jump_test″。
此外,在不存在没有注册在执行二进制文件中的“码元表”中的码元和“码元表”本身的情况下,以所述的码元名生成规则生成。该情况下为相同的“前缀字符串”也没有关系。例如,在码元地址为0x1234的“未注册码元”名被生成为func_1234的情况下,也可以将该子例程名字符串设为″_my_func_1234″。
<子例程程序源生成单元3a>
这里,说明包含图16所示的机器语言指令程序生成宏调用描述,生成子例程程序源的“子例程程序源生成单元3a”(图24)。
<子例程信息获取单元3a1>
从由所述机器语言指令分析单元1生成的码元信息列表r1中取出一个码元信息。以后,将在这里取出的码元信息称为“当前码元信息”。
<子例程定义描述生成单元3a2>
基于“当前码元信息”中包含的“子例程名字符串”,生成图25所示的“子例程定义描述”。在“第1实施方式”中,没有返回值(void型),生成不取自变量的子例程的定义的描述。
<指令地址获取单元3a3>
指令地址获取单元3a3从“当前码元信息”的“指令地址列表”的开头顺序读出“指令地址”。以后将读出的“指令地址”称为“当前指令地址”。
<程序标签描述生成单元3a4>
在分支目的地地址列表r2(由机器语言指令分析单元1生成)中存在“当前指令地址”的情况下,为了可进行程序分支描述(goto语句等),生成用于识别指令(command)的“程序标签描述”。在所述ARMv5指令集的jump_test函数的机器语言指令分析处理中得到的“分支目的地地址列表”是[0x8384,0x839c,0x836c,0x83a4](参照表3)。与这些分支目的地地址对应的C语言的标签描述,例如,生成为″L_08384:″,″L_0839c:″,″L_0836c:″,″L_083a4:″即可。
<机器语言指令类别判定单元3a5>
在机器语言指令类别判定单元3a5中,基于“当前指令地址”,读出在“执行二进制文件”的“二进制数据部分”中存储的二进制数据。将该二进制数据看作机器语言指令,将该机器语言指令解码(解释)(与所述下一指令信息提取单元1d的机器语言指令解码处理相同的过程),判定以下的指令类别。
·“简单分支指令”(仅用指令字可以指定分支目的地地址的分支指令)的情况:进至简单分支指令程序描述生成单元3a6。
·“简单子例程调用指令”(仅用指令字可以指定调用目的地地址的子例程调用指令)的情况:进至简单子例程调用指令程序描述生成单元3a7。
·“数据依赖分支指令”(分支目的地地址为由寄存器值确定和由存储器值确定的分支指令)的情况:进至数据依赖分支指令程序描述生成单元3a8。
·“数据依赖子例程调用指令”(调用目的地地址为寄存器值和由存储器值确定的子例程调用指令)的情况:进至数据依赖子例程调用指令程序描述生成单元3a9。
·上述以外的情况:进至机器语言指令程序生成宏调用描述生成单元3a10。
<机器语言指令程序生成宏调用描述生成单元3a10>
这里,获取有关机器语言指令的动作的以下详细信息。
·指令类别:指定机器语言指令程序生成宏名。成为用于生成图16中的SUB,STR,CMP,LDR等的宏名的信息。
·作用寄存器号:指定操作数寄存器号和运算结果存储寄存器号。在图16的例子中,以下对应于作用寄存器号
SUB(AL,0x020,3,0,IMM,-1,...)(作用寄存器号:3,0
STR(AL,0x009,14,13,IMM,-1,...)(作用寄存器号:14,13
CMP(AL,0x024,0,3,IMM,-1,...)(作用寄存器号:0,3
LDR(AL,0x012,15,13,IMM,-1,...)(作用寄存器号:15,13
再者,上述中“-1”的自变量也与各宏的“rm”(第2操作数寄存器ID:存储第2操作数的寄存器号)自变量对应(SUB/CMP:第2操作数寄存器ID、STR/LDR:偏移寄存器ID),但由于第2操作数或偏移量操作数为常量,所以对应于无对应的寄存器。
·再者,上述中“-1”的指令属性信息:提取规定指令动作的细节的各种各样的属性信息。在图16的例子中,以下的数据对应它们的指令属性信息。
SUB(AL,0x020,3,0,IMM,-1,0x00000003,0x08340)
AL:执行条件(always:以无条件执行)
0x020:与指令比特字段自变量v对应(没有内部寄存器更新)
IMM:与移位属性自变量sh对应(第2操作数为立即值)
0x00000003:立即值数据
STR(AL,0x009,14,13,IMM,-1,0x00000004,0x08344)
AL:执行条件(always:以无条件执行)
0x009:与指令比特字段自变量v对应(包含地址偏移量计算方法、有无地址寄存器更新、数据宽度信息等)
IMM:与移位属性自变量sh对应(地址偏移量为立即值)
0x00000004:立即值数据
CMP(AL,0x024,0,3,IMM,-1,0x00000005,0x08348)
AL:执行条件(always:以无条件执行)
0x024:与指令比特字段自变量v(图17)对应
IMM:与移位属性自变量sh对应(第2操作数为立即值)
0x00000005:立即值数据
LDR(AL,0x012,15,13,IMM,-1,0x00000004,0x08380)
AL:执行条件(always:以无条件执行)
0x012:与指令比特字段自变量v对应
IMM:与移位属性自变量sh对应(地址偏移量为立即值)
0x00000004:立即值数据
基于有关这些机器语言指令的详细信息,生成“机器语言指令程序生成宏调用描述”。
<简单分支指令程序描述生成单元3a6>
对于仅用指令字可以指定分支目的地地址那样的“简单分支指令”,生成使用了goto语句(无条件分支指令)等的程序分支的描述。
以下,说明图10的机器语言指令描述中的图26的无条件分支指令(图10的第6行)。
这里,分支目的地地址是0x839c,通过所述程序标签描述生成单元3a4,标签语句L_0839c:被插入在0x839c的指令程序描述(图10的第25行)之前,所以生成分支到该标签的图27的程序描述。
此外,即使是带条件的分支的情况,在AL(always:以无条件执行)的取代中,可以仅插入对应的执行条件的字符串(EQ,NE等)来实现。
<简单子例程调用指令程序描述生成单元3a7>
对于仅用指令字可以指定调用目的地地址那样的“简单子例程调用指令”,生成进行图28所示的子例程调用的程序描述。
以下,说明调用jump_test函数的图29的机器语言指令描述。
这里,对于调用目的地的“子例程名字符串”,基于调用目的地地址,从“码元信息列表”中检索相应的码元信息,从该码元信息中包含的“码元名字符串”适用所述的“子例程命名规则”生成了“子例程名字符串”后,生成调用它的图29的程序描述。
此外,即使在带条件执行的子例程调用指令的情况下,在AL(always:以无条件执行)的取代中,仅插入对应的执行条件的字符串(EQ,NE等)就能够实现。
<数据依赖分支指令程序描述生成单元3a8>
对于分支目的地地址以寄存器值确定和以存储器值确定那样的“数据依赖分支指令”,从机器语言指令分析单元1生成的“转移表信息列表”,基于“数据依赖分支指令”的地址,检索相应的“转移表信息”,使用在该表中存储的“分支目的地地址表”,生成“数据依赖分支指令程序描述”。
以下,说明图10的机器语言指令描述中的图30的数据依赖分支指令(图10的第5、6行)。
这里,与“数据依赖分支指令”的地址0x834c对应的“转移表信息”如下。
.转移表大小:6
.分支目的地地址表:[0x8384,0x839c,0x836c,0x83a4,0x836c,0x8384]
使用该转移表信息和该“数据依赖分支指令”的执行条件(ls:less or same条件),生成图31那样的程序描述。
这里,在各case语句后出现的goto语句的标签,与“转移表信息”的“分支目的地地址表”的各分支目的地地址的标签对应。再者,与case0:和case5:对应的条件分支,对应于default标签。
<数据依赖子例程调用指令程序描述生成单元3a9>
对于调用目的地地址以寄存器值确定和以存储器值确定那样的“数据依赖子例程调用指令”,使用由后述的码元地址信息表源生成单元3b生成的“码元地址信息”,在程序描述上实现数据依赖子例程调用。
以下,说明图10的机器语言指令描述中的图32的数据依赖子例程调用指令。
这里,如所述,0x83ac是转移到寄存器r3的值的“数据依赖分支指令”,但在跟前的0x83a8中,由于有将pc(实际的值为当前指令地址0x83a8+8)代入链路寄存器lr的指令,所以可以判别0x83ac的指令实际为“数据依赖子例程调用指令”。与0x83a8和0x83ac的2指令对应的程序描述如图33那样。
此外,即使在带条件执行的数据依赖子例程调用指令的情况下,在AL(always:以无条件执行)的取代中,仅插入对应的执行条件的字符串(EQ,NE等)就能够实现。
再者,对于这里生成的图33的程序描述的内容,在后述的码元地址信息表源生成单元3b中说明。
<子例程程序源输出例>
图34中表示与图10的″jump_test″函数的ARMv5指令集的机器语言指令描述对应的子例程程序描述的输出例子。
<码元地址信息表源生成单元3b>
这里,说明用于执行由所述的数据依赖子例程调用指令程序描述生成单元3a9生成的程序描述的信息,并输出到程序源的处理。仅在“码元信息列表”中包含“码元信息”的“数据依赖子例程调用指令标志”为“1”的情况下,该处理是必要的。
首先,如图35所示,图33中某个_FP_INFO_是存储预先定义的码元地址信息的数据结构体。
此外,图33中某个_GET_FPI_(_r_(3))是,基于_r_(3)的值表示的“码元地址”,从后述的“码元地址信息表”返回对相应的“码元地址信息”的数据结构体的指针的函数的调用(后述)。即,通过使用fpi指示的对“码元地址信息”的数据结构体的指针,使用该数据结构体中存储的子例程的地址(func),在程序上实现所谓fpi->func()的数据依赖子例程调用。
接着,说明将“码元地址信息”以表形式存储的“码元地址信息表”的程序源输出方法。例如,假设生成表11那样的“码元信息列表”(省略“指令地址列表”)。
[表11]
码元地址 | 码元名 |
0x8218 | ″f0″ |
0x8220 | ″f1″ |
0x8238 | ″ff1″ |
0x8338 | ″ff2″ |
0x8340 | ″jump_test″ |
0x8448 | ″main″ |
图36中表示将该“码元信息列表”的信息设定作为前述的_FP_INFO_结构体的数组变量的初始值,用于在程序上可参照的程序描述。
在图36中,例如在[0x8218,my_f0]的描述中,0x8218是图35所示的_FP_INFO_结构体的成员变量addr的初始值,_my_f0是成员变量func的初始值。_my_f0是在码元名″f0″中具有“前缀字符串”″_my_″的子例程名字符串,实际是指对象子例程的地址值。这样一来,可以设定用于将执行二进制文件中的“码元地址”和程序描述上的“子例程地址”关联的数据结构体的初始值。
接着,基于图33中某个_GET_FPI_函数(基于“码元地址”,搜索与其相应的_FP_INFO_结构体并返回该指针的函数),可以用图37所示的简单的程序来实现。
此外,码元地址信息表中包含的码元数非常多;有_GET_FPI_函数的处理时间变长的顾虑,但在该情况下,使用“2分叉搜索法”或“散列搜索法”等,适用以码元地址为基础的搜索处理的高速化方法即可。
<存储器初始化程序描述生成单元3c>
在存储器初始化程序描述生成单元3c(指令集模拟器程序源代码输出单元3)中,生成用于指令集模拟器S的程序描述中的CPU的存储器区域的初始化的程序描述。
除了初始值被定义的数据区域之外,存储器区域的初始化的对象还有在程序区域中也包含初始值数据的情况。因此,程序区域也成为初始化的对象。
在执行二进制文件5的所述二进制数据部分存在存储器初始化数据,各存储器区域和“二进制数据部分”的位置关系的信息,以“程序报头表”中包含的所述“段”为单位,或以所述“节报头表”中包含的“节”为单位,被分别定义。
存储器初始化程序描述生成单元3b的存储器初始化处理的程序描述,定义它们中的其中一个单位中的处理。图38中表示“存储器初始化程序描述”的一例子。这里,描述“节(section)单位”的存储器初始化处理。
具有初始化数据的“.rodata”节在0x1260c-0x127e7的地址区域中被定义,该具体的初始化数据被定义作为unsigned char data[476]的初始化数据。成为将该数组数据通过memcpy函数复制到&arm._mem[0x1260c]的地址中的程序描述。
<main函数程序描述生成单元3d>
这里,说明最终生成的指令集模拟器S的程序描述的最高位函数(main函数)的程序描述。main函数程序描述生成单元3d创建最高位函数(main函数)的程序。
如所述,作为“码元地址”具有执行二进制文件中定义的“入口点”(程序执行时的最初的地址)的“入口码元”与最初执行的子例程对应。因此,从“指令集模拟器”的程序描述的最高位函数,生成调用与“入口码元”对应的子例程的程序描述。
例如,在与入口码元对应的子例程名为″my__mainCRTStartup″的情况下,指令集模拟器S的最高位函数的程序描述如图39那样。图39中,表示指令集模拟器的最高位函数的程序描述例1。
此外,作为另一方法,也可直接调用执行二进制文件中的main函数。这种情况下,将堆栈指针设定为存储器的大小,如果需要,则在将main函数的自变量int argc,char*argv[]写入在CPU的存储器上后调用main函数(图40)。图40中,表示指令集模拟器的最高位函数的程序描述例2。图41中,表示将main函数的自变量信息写入CPU存储器中的程序描述。
<指令集模拟器S进行的程序描述结构的特征>
由以上生成的指令集模拟器程序描述结构具有以下的特征。
(1)如图34所示,“执行二进制文件”中的子例程直接与“程序描述”上的子例程对应,“执行二进制文件”具有的“函数分层结构”被直接反映在指令集模拟器S输出的程序描述中。
此外,简单分支指令中goto语句和标签语句明确地对应,数据依赖分支指令中switch语句和case语句明确地对应,程序控制的流程也容易理解。
因此,程序描述的可读性高,可以高效地进行程序的调试作业和程序的功能扩展等的代码改变作业。
(2)程序控制通过goto语句、call语句、return语句而显式地实现,不存在程序计数器(PC)的更新处理。不使用在以往的静态编译方式指令集模拟器中作为必需的“与PC有关的switch语句和与各指令地址有关的case语句的代码结构”。
因此,程序控制的处理开销比以往大幅度减少。此外,程序控制结构相比现有技术的结构极为简单,所以编译器的优化处理(冗长指令删除等)非常容易有效。
从这些事实来看,指令集模拟器S的处理速度大幅度地提高。
从以上来看,根据第1实施方式的指令集模拟器S的结构,发挥下述效果。
1.根据使用了指令集模拟器S的嵌入式系统用软件开发环境,可进行详细动作的再现。
2.输出与执行二进制具有等价功能的源程序描述文件(指令集模拟器源代码:C语言描述),通过编译和执行该文件,如上述,可以构筑高速的指令集模拟环境。得到具有与本机执行时间(例如,编译目标CPU用的程序源而成为机器语言由CPU执行的时间)大致相当的模拟执行时间的高速的指令集模拟器。
3.进行应用软件开发验证环境中的、用于使目标CPU动作的程序的调试、动作验证和性能验证。
4.可以生成反映了处理器架构开发验证环境中的、用于CPU高性能化的架构变更等的指令集模拟器。
5.可进行平台转换(移植)。从用于某个目标CPU的执行二进制输出等价功能C描述,可以用于对另一CPU进行程序移植。
6.可进行恶意软件分析。由于程序源的分析容易,病毒等的恶意软件分析容易进行,可以有助于病毒驱除软件和防火墙的早期开发。
7.有助于软件知识产权保护。由于具有与执行二进制等价功能的源程序描述文件的分析容易,侵权的取证顺利地进行,可以在著作权侵权和专利侵权的验证中有效地灵活运用。
8.具有“可靠地”进行从执行二进制至源程序复原的完全性。
9.得到可以实现高速性和完全性的简便的工具框架结构的指令集模拟器S。
如所述,供实际使用的非专利文献4、8、9有下述应解决的课题。
作为第1课题,没有判断哪个指令可成为分支目的地地址的信息。
作为第2课题,模拟执行时间相比本地执行花费14倍~54倍的时间。
作为第3课题,非常难以参与编译器中的代码优化。
作为第4课题,缺少分层结构。
作为第5课题,作为源程序,可读性明显较低。
作为第6课题,缺少程序控制流程分析的机制。
如前述,根据第1实施方式的指令集模拟器S的结构,由于分支目的地地址作为标签(识别信息)被附加在分支目的地指令中,有转移表等,所以有判断哪个指令可成为分支目的地地址的信息。
此外,模拟执行时间与本机执行时间基本相同。
此外,二进制文件的分层结构被复原为程序源代码,编译器中的代码优化很容易。
此外,由于二进制文件的各子例程具有函数的结构,并具有分层结构,所以从二进制文件复原的源程序可读性高。
而且,由于分析简单分支指令、数据依赖分支指令、数据依赖子例程等并用转移表等明确表示分支目的地,所以具有程序控制流程分析的机制。
从以上来看,通过第1实施方式(本发明),可以解决非专利文献4、8、9供实际使用的问题。
<<第2实施方式>>
第2实施方式的指令集模拟器2S(参照图43)在第1实施方式的指令集模拟器S中追加了“子例程自变量提取功能”。
其他的结构与第1实施方式的指令集模拟器S是同样的,所以对同样的结构要素附加相同的标号表示,省略详细的说明。
第2实施方式的指令集模拟器2S在第1实施方式的指令集模拟器S中,追加“子例程自变量提取功能”,通过将CPU的寄存器置换为子例程内的局部变量及自变量,谋求指令集模拟的进一步高速化。
图42中,表示第2实施方式的机器语言指令分析单元的功能框图。
第2实施方式的机器语言指令分析单元21是在第1实施方式的码元地址预处理单元1a、码元地址获取单元1b、指令地址获取单元1c、下一指令信息提取单元1d、地址列表更新单元1e,以及在数据依赖分支提取单元2中,新加入子例程自变量提取单元1f的结构。
子例程自变量提取单元1f进行在输出的源代码中将CPU的寄存器内的数据作为局部变量及自变量描述的工作。
图43中,将第2实施方式的指令集模拟器2S的结构与分析对象的执行二进制文件5、指令集模拟器2S输出的指令集模拟器程序源代码4一起表示。
第2实施方式的指令集模拟器2S包括机器语言指令分析单元21和指令集模拟器程序源代码输出单元23。
指令集模拟器2S将执行二进制文件5作为输入,输出高级语言的指令集模拟器程序源代码4。
指令集模拟器程序源代码输出单元23是在子例程程序源生成单元3a、码元地址信息表源生成单元3b、存储器初始化程序描述生成单元3c、以及main函数程序描述生成单元3d中新加入了子例程自变量共用处理单元3e的结构。
再者,在机器语言程序的执行二进制文件5中,仅在有数据依赖子例程调用指令的情况下,使用码元地址信息表源生成单元3b和子例程自变量共用处理单元3e。
以下,说明新加入的子例程自变量提取单元1f(参照图42)。
<子例程自变量提取单元1f>
子例程自变量提取单元1f进行的处理,在指令地址获取单元1c将“当前码元信息”“追加”到“码元信息列表”中之前执行(参照图42、图7)。
<子例程自变量提取单元1f的处理的原理>
子例程的“自变量”是在子例程调用前对CPU寄存器设定的数据,程序的指令执行在进至了子例程后被参照(这里未考虑自变量存储在堆栈存储器中的情况)。为了分析哪个寄存器是“子例程自变量”,找到在指令执行进至了子例程后没有被任何指令更新而参照的寄存器即可。为了该分析,预先分析(掌握)各指令参照哪个寄存器,更新哪个寄存器,通过“反顺序”地追寻指令执行顺序,可以指定“子例程自变量”。
图44中表示图10的ARMv5机器语言指令的“输入输出寄存器”的信息。这里,“输入输出寄存器”是指:机器语言指令作为操作数使用的寄存器(输入寄存器);根据机器语言指令被更新值的寄存器(输出寄存器)。假设输入和输出寄存器的对象除了pc(程序计数器)以外(由于pc与自变量提取处理没有关系),包含“状态寄存器”。此外,为方便起见而将多个“状态寄存器”看作1个寄存器“CC”,将寄存器ID标记“16”。此外,将sp的寄存器ID标记为“13”,将lr的寄存器ID如所述那样标记为“14”。
(1)输入寄存器ID列表(图44中标记为I(..)):机器语言指令作为操作数使用的寄存器ID的列表
(2)输出寄存器ID列表(图44中标记为O(..)):机器语言指令作为操作数使用的寄存器ID的列表
(3)输入输出寄存器的例子:
A)sub r3,r0,_3:由于第1操作数为r0,所以为I(0),由于结果存储寄存器为r3,所以为O(3)。
B)push[lr]:由于基址是堆栈指针(sp:r[13]),写入数据为链路寄存器(lr:r[14]),所以为I(13,14),由于基址寄存器被更新,所以为O(13)。
C)cmp r3,#5:由于第1操作数是r3,所以为I(3),由于状态寄存器(CC)被更新,所以为O(16)。
D)ldrls pc,[pc,r3,lsl_2]:基址为pc(不看作输入)且偏移量是r3,由于是带条件的执行指令,参照状态寄存器(CC),所以为I(3,16)。由于输出寄存器pc被排除,所以为O()(没有输出寄存器)。
(4)“生存输入寄存器分析”:从子例程内的所有的“返回指令”以指令执行的反顺序追寻,更新“生存输入寄存器ID列表”。这里,“生存输入寄存器”是,着眼于某个指令,在该指令执行后子例程内被参照的寄存器,是指在该指令执行前子例程内没有被更新的寄存器。“生存输入寄存器分析”处理按各指令执行以下的过程。
A)对于“输出寄存器ID列表”中包含的各寄存器ID,在“生存输入寄存器ID列表”中存在该寄存器ID的情况下,将该寄存器ID从“生存输入寄存器ID列表”中删除。
B)将“输入寄存器ID列表”的所有寄存器ID(不重复地)“追加”到“生存输入寄存器ID列表”中。
表12中,表示输入输出寄存器的分析例子(从0x8380的返回指令起开始分析)。
[表12]
表12表示从0x8380的返回指令至码元的开始指令(0x8340)为止反顺序地追寻时的“生存输入寄存器ID列表”,从这些分析的结果,可知码元的开始指令中的“生存输入寄存器ID列表”为(0,13,14),“生存输入寄存器”为r0,sp,lr。通过根据其它所有的返回指令进行同样的分析处理,最终得到(0,13,14)作为“生存输入寄存器ID列表”。
(5)子例程自变量寄存器的确定:从由所述分析处理得到的“生存输入寄存器ID列表”中,根据以下的规则,确定“子例程自变量”。
A)链路寄存器(lr:r[14]):不看作“子例程自变量”。因为在程序描述上直接进行有关这些子例程的控制的“本发明的技术”中,不需要用于在CPU动作上实现“子例程调用处理”和“子例程恢复处理”的寄存器的信息。
B)堆栈指针(sp:r[13]):看作“子例程自变量”。通常堆栈指针的更新在子例程调用处理和子例程恢复处理的前后执行,由CPU资源管理,而在本第2实施方式中,是将包含了堆栈指针的所有CPU寄存器作为局部变量或子例程自变量来处理。
C)其他的寄存器:看作“子例程自变量”。
<子例程自变量提取单元1f的处理中使用的数据结构>
在子例程的自变量提取单元1f的处理中,使用以下的数据结构。
(1)指令信息列表:用于分析“生存输入寄存器”的指令信息列表。
“指令信息”由以下的数据项目组成。
A)指令信息ID:各指令信息中固有的ID号
B)指令地址
C)输入寄存器ID列表
D)输出寄存器ID列表
E)生存输入寄存器ID列表(每个指令的“生存输入寄存器”)
F)下一指令信息列表:与所述“下一指令信息临时列表”相同的信息
G)“前方向指令信息ID列表”:将该指令设为“下一指令”的所有的指令的指令信息ID组成的列表(在追寻指令执行的反顺序时需要)
(2)“指令信息ID临时列表”:用于指令执行的反顺序分析处理的指令信息ID的临时列表。
(3)“子例程生存输入寄存器ID临时列表”:“生存输入寄存器”的ID组成的临时列表。
(4)“子例程自变量寄存器ID列表”:最后,存储与子例程自变量对应的寄存器ID的列表
此外,在所述“码元信息”中追加“子例程自变量寄存器ID列表”。
“第2实施方式的码元信息”的数据项目:
A)码元地址
B)指令地址列表
C)码元名字符串
D)数据依赖子例程指令标志
E)子例程自变量寄存器ID列表(第2实施方式中新加入的列表)
<子例程自变量提取单元1f的结构>
图45中表示子例程自变量提取单元1f的功能框图。
子例程自变量提取单元1f具有:输入输出寄存器分析单元1f1;前方向指令分析单元1f2;子例程自变量提取预处理单元1f3、指令信息获取单元1f4、生存输入寄存器ID列表更新单元1f5、以及子例程自变量寄存器确定单元1f6。以下,说明子例程自变量提取单元1f的各单元。
<输入输出寄存器分析单元1f1>
从“当前码元信息”的“指令地址列表”中每次一个地顺序获取“指令地址”,生成与该指令地址对应的“指令信息”。然后,对“指令信息”适当设定(不重复)“指令信息ID”,设定该指令的“指令地址”,创建“输入寄存器ID列表”、“输出寄存器ID列表”、“下一指令信息列表”。再者,在“下一指令信息列表”的创建中使用所述下一指令信息提取单元1d。在这种时候,使各“指令信息”的“生存输入寄存器ID列表”和“前方向指令信息ID列表”为“空”。在对所有的“指令地址”的处理结束后,进至前方向指令分析单元1f2的处理。
<前方向指令分析单元1f2>
在“指令信息列表”的各“指令信息”中(以后将该“指令信息”称为“当前指令信息”),基于“下一指令信息列表”中包含的“紧接型下一指令”和“分支型下一指令”的各“下一指令地址”,搜索相应的“指令信息”。搜索指令信息的指令地址与下一指令地址一致的指令信息。以后将搜索到的“指令信息”称为“下一指令信息”。在该“下一指令信息”的“前方向指令信息ID列表”中(不重复地)“追加”“当前指令信息”的“指令信息ID”。在对所有的“指令信息”的处理结束后,进至子例程自变量提取预处理单元1f3。
<子例程自变量提取预处理单元1f3>
作为子例程自变量提取处理预处理单元1f3的前处理,执行以下处理。
将“指令信息列表”中包含的指令信息之中,与“返回指令”相应的“指令信息”的“指令信息ID”全部(不重复地)“追加”到“指令信息ID临时列表”中。使“子例程生存输入寄存器ID临时列表”为“空”。
之后,进至指令信息获取单元1f4。
<指令信息获取单元1f4>
从“指令信息ID临时列表”“取出”“指令信息ID”,获取相应的“指令信息”,进至生存输入寄存器ID列表更新单元1f5。以后,将它称为“当前指令信息”。在“指令信息ID临时列表”为“空”的情况下,进至子例程自变量寄存器确定单元1f6。
<生存输入寄存器ID列表更新单元1f5>
执行以下的处理,返回到指令信息获取单元1f4的处理。
(1)对于“当前指令信息”的“输出寄存器ID列表”的各“输出寄存器ID”,在包含在“子例程生存输入寄存器ID临时列表”中的情况下,将该寄存器ID从“子例程生存输入寄存器ID临时列表”中删除。
(2)将“当前指令信息”的“输入寄存器ID列表”的各“输入寄存器ID”(不重复地)“追加”到“子例程生存输入寄存器ID临时列表”中。
(3)在“子例程生存输入寄存器ID临时列表”的所有寄存器ID包含在“当前指令信息”的“生存输入寄存器ID列表”中的情况下,跳过后续的处理,直接返回到指令信息获取单元1f4的处理。
(4)在“子例程生存输入寄存器ID临时列表”的某个寄存器ID不包含在“当前指令信息”的“生存输入寄存器ID列表”中的情况下,执行后续的处理。
A)将“子例程生存输入寄存器ID临时列表”的各寄存器ID不重复地“追加”到“当前指令信息”的“生存输入寄存器ID列表”中。即,重复的情况下,寄存器ID不追加到“生存输入寄存器ID列表”中。
B)将“当前指令信息”的“前方向指令信息ID列表”的各“指令信息ID”不重复地“追加”到“指令信息ID临时列表”中。即,重复的情况下,指令信息ID不追加到“指令信息ID临时列表”中。
<子例程自变量寄存器确定单元1f6>
在“子例程生存输入寄存器ID临时列表”中,将除了存储“子例程恢复地址”的“链路寄存器”的寄存器ID以外的寄存器ID写入在“子例程自变量寄存器ID列表”中。
<子例程自变量共用处理单元3e>
接着,说明指令集模拟器程序源代码输出单元23中的子例程自变量共用处理单元3e。
子例程自变量共用处理单元3e,在对于“码元信息列表”中包含的所有的“码元信息”执行了处理之后执行子例程自变量提取单元1f的处理(参照图42)。该处理是“码元信息”的“数据依赖子例程调用指令标志”为“1”的处理,但仅在包含“码元信息列表”中的情况下需要该处理。需要该处理的理由是,因为在将数据依赖子例程以程序描述实现的情况下,全部子例程中需要“共用”的函数指针数据类型(自变量的个数也共用)。
创建“空”的“共用子例程自变量寄存器ID列表”。
对于“码元信息列表”中包含的所有的“码元信息”,将该“子例程自变量寄存器ID列表”中包含的所有的寄存器ID不重复地“追加”到“共用子例程自变量寄存器ID列表”中。即,在共用子例程自变量寄存器ID列表中,寄存器ID不重复存在。
对于“码元信息列表”中包含的所有的“码元信息”,将“共用子例程自变量寄存器ID列表”置换为该“码元信息”的“子例程自变量寄存器ID列表”。
<第2实施方式的其他处理的变更点>
(1)CPU资源参照宏定义:图14的CPU资源参照宏定义,以CPU寄存器变量按CPU资源数据结构体(参照图13)定义为前提,但在“第2实施方式”中,CPU寄存器变量作为子例程自变量或局部变量来定义。因此,如图46那样变更CPU资源参照宏。
(2)“子例程定义描述生成单元”:在第2实施方式中,子例程的函数型与第1实施方式的情况不同。
A)子例程“返回值”:第1实施方式中是没有返回值的(void型)函数,而在第2实施方式中设为取CPU寄存器的数据类型的返回值的函数。(32比特CPU的情况下为U32型、64比特CPU的情况下为U64型)
B)子例程自变量:根据由“子例程自变量提取单元”及(根据需要而执行)“子例程自变量共用处理单元3e”(参照图43)生成的“子例程自变量寄存器ID列表”,确定子例程自变量的个数。各自的自变量的数据类型与“返回值”同样地设为与CPU寄存器的数据类型相同。此外,自变量名基于寄存器号和寄存器别名(r[13]的别名sp等)生成。
C)CPU寄存器的局部变量定义描述:将未出现在“子例程自变量”中的其他的CPU寄存器作为局部变量,定义在子例程的最初的部分中(参照图47)。图47中,表示″jump_test″函数的子例程定义描述输出。
图48中表示第2实施方式的子例程定义描述例子。这里,假定在“子例程自变量共用处理单元3e”执行后子例程自变量的个数也不变化。
(3)简单子例程调用指令程序描述生成单元3a7(参照图24):在第2实施方式中,子例程的函数型不同,所以子例程调用描述改变。
A)子例程自变量移交描述:获取“调用目的地码元信息”的“子例程自变量寄存器ID列表”,使用自变量或局部变量的寄存器,生成调用子例程的自变量移交描述。
B)子例程返回值:生成将子例程返回值存储在寄存器变量中的描述。(即使在没有实际的子例程的返回值的情况下也不发生程序执行上的不便)
图50中表示第2实施方式的子例程调用程序描述。
(4)“码元地址信息表”中的“函数指针数据类型”的变更:在“第1实施方式”中,在码元地址信息的_FP_INFO_结构体(参照图34~图36)中使用了没有返回值、也没有自变量的函数指针数据类型,而在第2实施方式中变更为图49所示的定义。再者,假定“共用子例程自变量寄存器ID列表”与子例程“my_jump_test”的“子例程自变量寄存器ID列表”相同。
(5)数据依赖子例程调用指令程序描述生成单元3a9(参照图24):在第2实施方式中,由于子例程调用描述改变,所以“数据依赖子例程调用程序描述”也变更。这种情况下,根据“共用子例程自变量寄存器ID列表”,使用自变量或局部变量的寄存器生成调用子例程的自变量移交描述。图50中,表示第2实施方式的数据依赖子例程调用指令程序描述。所述同样地假定“共用子例程自变量寄存器ID列表”与子例程“my_jump_test”的“子例程自变量寄存器ID列表”相同。
<<第3实施方式>>
图51中,表示使用了第3实施方式的指令集模拟器的嵌入式系统用软件开发环境。
第3实施方式的指令集模拟器3S包含在第1实施方式和第2实施方式中,没有码元表的情况下的机器语言指令分析单元31。
在第1实施方式和第2实施方式中,将执行二进制文件中包含“码元表”设为前提。这里,说明用于应对不存在“码元表”的情况的第3实施方式。
<不存在“码元表”的情况下的应对方法的概要>
在第3实施方式中,第1实施方式和第2实施方式的机器语言指令分析单元1(21)和指令集模拟器程序源代码输出单元3变更为机器语言指令分析单元31、指令集模拟器程序源代码输出单元33。
(1)机器语言指令分析单元31的变更点如下述。
(ア)机器语言指令分析单元31具有未分析码元地址检测单元31a。
在不存在“码元表”的情况下,指定机器语言指令的位置的唯一的信息是“入口点”(程序起动后最初执行的指令地址)。因此,首先,未分析码元地址检测单元31a只将“入口点”追加到“码元地址临时列表”中。
(ィ)机器语言指令分析单元31具有码元候选地址列表31a1。“码元候选地址列表”是“码元候选”的地址列表。
码元候选地址列表31a1的初始状态为“空”,在发现了“未分析”的码元地址的情况下,未分析码元地址检测单元31a将其追加到码元候选地址中(后述)。将该“码元候选地址列表”的各地址追加到“码元地址临时列表”中。
(2)指令集模拟器程序源代码输出单元33的变更点:将在“数据依赖子例程调用指令”的程序描述中被调用的_GET_FPI_函数的定义变更为图52那样。图52表示返回_FP_INFO_结构体的指针的_GET_FPI_函数的定义。
作为变更点,
在“数据依赖子例程调用指令”的调用目的地地址中没有相应的“码元信息”(该地址的码元为“未分析”)的情况中,有“强制结束”指令集模拟器的机制。
根据该特征,在“未分析”码元被调用时,使指令集模拟器“异常结束”(exit(-1)。然后,使用更新的“码元候选地址列表”,使机器语言指令分析单元31、指令集模拟器程序源代码输出单元33再次执行,将生成的指令集模拟器程序源代码34再次编译和执行。
根据上述结构,在执行二进制文件中没有码元表的情况下,指令集模拟器3S也可以应对。
此外,发挥与第1实施方式同样的作用效果,可再现详细动作,模拟器的处理速度快。
<<其他实施方式>>
1.再者,在所述的实施方式1~3中,作为从执行二进制反编译的高级程序语言,例示了C语言,但当然也可以用C语言以外的高级程序语言替代反编译的语言。
2.再者,权利要求的范围的程序源代码是指,通过实施方式中说明的指令集模拟器S、2S、3S从机器语言转换的C语言等,程序源代码当然也可以是C语言以外的编程语言。
标号说明
1c 指令地址获取单元(子例程检测部件、子例程调用指令检测部件)
1d 下一指令信息提取单元(子例程检测部件、子例程调用指令检测部件、分支指令检测部件、简单分支指令检测部件、简单子例程调用指令检测部件、数据依赖分支指令检测部件、数据依赖子例程调用指令检测部件)
1e 地址列表更新单元(子例程检测部件、简单子例程调用指令检测部件、数据依赖子例程调用指令检测部件)
1f 子例程自变量提取单元(子例程检测部件、寄存器变量展开部件)
2 数据依赖分支信息提取单元(子例程检测部件、分支指令检测部件、数据依赖分支指令检测部件、数据依赖子例程调用指令检测部件、分支目的地地址信息读出单元)
2f (子例程机器语言地址表生成部件、)
2g 转移表信息生成单元(转移表记录部件、子例程机器语言地址表生成部件)
3 指令集模拟器程序源代码输出单元(数据依赖分支指令生成部件)
3a 子例程程序源生成单元(子例程源代码输出部件、子例程调用指令输出部件)
3a4 程序标签描述生成单元(识别符附加部件)
3a5 机器语言指令类别判定单元(无条件分支指令输出部件)
3a6 简单分支指令程序描述生成单元(无条件分支指令输出部件、子例程调用指令输出部件)
3a7 简单子例程调用指令程序描述生成单元(子例程源代码输出部件、子例程调用指令输出部件)
3a8 数据依赖分支指令程序描述生成单元(无条件分支指令输出部件、数据依赖分支指令生成部件、子例程调用指令输出部件、数据依赖子例程调用指令生成部件)
3a9 数据依赖子例程调用指令程序描述生成单元(子例程源代码输出部件、子例程调用指令输出部件、子例程地址检索处理指令生成部件)
3e 子例程自变量共用处理单元(子例程源代码输出部件、寄存器变量展开部件)
23 指令集模拟器程序源代码输出单元(数据依赖分支指令生成部件、寄存器变量展开部件)
33 指令集模拟器程序源代码输出单元(子例程源代码输出部件)
r3 转移表信息列表(转移表信息存储单元、机器语言地址表)
S、2S、3S 指令集模拟器
Claims (12)
1.一种指令集模拟器,其将机器语言程序转换为程序源代码而生成模拟器执行程序,其特征在于,包括:
子例程检测部件,检测所述机器语言程序中包含的子例程;
分支指令检测部件,检测所述机器语言程序中包含的指令字之中具有分支目的地地址的分支指令;
子例程调用指令检测部件,检测所述机器语言程序中包含的指令字之中具有子例程调用目的地地址的子例程调用指令;
子例程源代码输出部件,输出由所述子例程检测部件检测所述机器语言程序所得的各子例程单位的程序源代码;
识别符附加部件,在所述程序源代码的分支目的地的指令中附加表示所述分支目的地地址的识别符;
无条件分支指令输出部件,将所述机器语言程序的所述分支指令作为对具有所述程序源代码的所述识别符的指令的无条件分支指令输出;以及
子例程调用指令输出部件,将所述机器语言程序的子例程调用指令作为所述程序源代码的子例程调用指令输出,
所述分支指令检测部件具有:
简单分支指令检测部件,检测所述机器语言程序中包含的指令字之中可以指定分支目的地地址的简单分支指令;以及
数据依赖分支指令检测部件,检测以寄存器值或存储器值确定所述机器语言程序中包含的分支目的地地址的数据依赖分支指令,
该指令集模拟器还包括:
转移表记录部件,将所述机器语言程序的所述数据依赖分支指令的分支目的地地址记录在转移表信息存储单元中;以及
数据依赖分支指令生成部件,基于所述数据依赖分支指令的所述分支目的地地址,从所述转移表信息存储单元检索相应的转移表信息,使用检索出的转移表信息,生成所述程序源代码的所述无条件分支指令。
2.如权利要求1所述的指令集模拟器,其特征在于,还包括:
寄存器变量展开部件,将所述机器语言程序的寄存器值作为所述程序源代码上的子例程自变量或局部变量来描述。
3.如权利要求1所述的指令集模拟器,其特征在于,
所述程序源代码是C语言的程序,不使用有关程序计数器的switch语句和有关各指令地址的case语句的代码结构,而使用对具有程序源代码上的识别符的指令的无条件分支指令和子例程调用指令,所述机器语言程序的子例程和所述程序源代码的子例程对应,所述机器语言程序中的子例程的分层被复原为所述程序源代码中的子例程的分层,
所述模拟器执行程序通过编译所述程序源代码而生成。
4.一种指令集模拟器,其将机器语言程序转换为程序源代码而生成模拟器执行程序,其特征在于,包括:
子例程检测部件,检测所述机器语言程序中包含的子例程;
分支指令检测部件,检测所述机器语言程序中包含的指令字之中具有分支目的地地址的分支指令;
子例程调用指令检测部件,检测所述机器语言程序中包含的指令字之中具有子例程调用目的地地址的子例程调用指令;
子例程源代码输出部件,输出由所述子例程检测部件检测所述机器语言程序所得的各子例程单位的程序源代码;
识别符附加部件,在所述程序源代码的分支目的地的指令中附加表示所述分支目的地地址的识别符;
无条件分支指令输出部件,将所述机器语言程序的所述分支指令作为对具有所述程序源代码的所述识别符的指令的无条件分支指令输出;以及
子例程调用指令输出部件,将所述机器语言程序的子例程调用指令作为所述程序源代码的子例程调用指令输出,
所述分支指令检测部件具有:
简单分支指令检测部件,检测所述机器语言程序中包含的指令字之中可以指定分支目的地地址的简单分支指令;以及
数据依赖分支指令检测部件,检测以寄存器值或存储器值确定所述机器语言程序中包含的分支目的地地址的数据依赖分支指令,
该指令集模拟器还包括:
子例程机器语言地址表生成部件,生成将与子例程名和子例程机器语言地址形成对的信息有关的子例程机器语言地址表;
子例程地址检索处理指令生成部件,从子例程机器语言地址检索所述程序源代码上的子例程,生成获取所述程序源代码上的子例程地址的子例程地址检索处理的程序;以及
数据依赖子例程调用指令生成部件,根据所述子例程地址检索处理的指令,指定所述程序源代码的数据依赖子例程调用指令的调用目的地子例程,对该子例程进行调用处理。
5.如权利要求4所述的指令集模拟器,其特征在于,
由于机器语言程序中缺少码元信息,所以作为在所述子例程检测部件中无法检测所有的子例程的情况下相应处理的部件,包括:
未注册机器语言地址检测部件,在所述模拟器执行程序的执行中,未注册到所述子例程机器语言地址表中的机器语言地址通过数据依赖子例程指令被调用的情况下,在记录了该未注册机器语言地址后,强制结束所述模拟器执行程序;以及
未注册子例程程序源代码生成部件,对于未注册机器语言地址的子例程,由所述未注册子例程程序源代码生成部件追加生成程序源代码。
6.如权利要求4或5所述的指令集模拟器,其特征在于,还包括:
寄存器变量展开部件,将所述机器语言程序的寄存器值作为所述程序源代码上的子例程自变量或局部变量来描述。
7.如权利要求4或5所述的指令集模拟器,其特征在于,
所述程序源代码是C语言的程序,不使用有关程序计数器的switch语句和有关各指令地址的case语句的代码结构,而使用对具有程序源代码上的识别符的指令的无条件分支指令和子例程调用指令,所述机器语言程序的子例程和所述程序源代码的子例程对应,所述机器语言程序中的子例程的分层被复原为所述程序源代码中的子例程的分层,
所述模拟器执行程序通过编译所述程序源代码而生成。
8.一种指令集模拟器的模拟器执行程序生成方法,其为将机器语言程序转换为程序源代码而生成模拟器执行程序的指令集模拟器的模拟器执行程序生成方法,其特征在于,
所述指令集模拟器包括:子例程检测部件、分支指令检测部件、子例程调用指令检测部件、子例程源代码输出部件、识别符附加部件、无条件分支指令输出部件、以及子例程调用指令输出部件,
所述子例程检测部件检测所述机器语言程序中包含的子例程,
所述分支指令检测部件检测所述机器语言程序中包含的指令字之中具有分支目的地地址的分支指令,
所述子例程调用指令检测部件检测所述机器语言程序中包含的指令字之中具有子例程调用目的地地址的子例程调用指令,
所述子例程源代码输出部件将由所述子例程检测部件检测所述机器语言程序所得的各子例程单位的程序源代码输出,
所述识别符附加部件将表示所述分支目的地地址的识别符附加在所述程序源代码的分支目的地的指令中,并且所述无条件分支指令输出部件将所述机器语言程序的所述分支指令,作为对具有所述程序源代码的所述识别符的指令的无条件分支指令而输出,
所述子例程调用指令输出部件将所述机器语言程序的子例程调用指令,作为所述程序源代码的子例程调用指令输出,
所述指令集模拟器包括转移表记录部件和数据依赖分支指令生成部件,
所述转移表记录部件将以寄存器值或存储器值确定所述机器语言程序中包含的分支目的地地址的数据依赖分支指令的分支目的地地址,记录在转移表信息存储单元中,
所述数据依赖分支指令生成部件,基于所述数据依赖分支指令的所述分支目的地地址,从所述转移表信息存储单元检索相应的转移表信息,使用检索出的转移表信息,生成所述程序源代码的所述无条件分支指令。
9.如权利要求8所述的指令集模拟器的模拟器执行程序生成方法,其特征在于,
所述指令集模拟器包括寄存器变量展开部件,
所述寄存器变量展开部件将所述机器语言程序的寄存器值作为所述程序源代码上的子例程自变量或局部变量来描述。
10.一种指令集模拟器的模拟器执行程序生成方法,其为将机器语言程序转换为程序源代码而生成模拟器执行程序的指令集模拟器的模拟器执行程序生成方法,其特征在于,
所述指令集模拟器包括:子例程检测部件、分支指令检测部件、子例程调用指令检测部件、子例程源代码输出部件、识别符附加部件、无条件分支指令输出部件、以及子例程调用指令输出部件,
所述子例程检测部件检测所述机器语言程序中包含的子例程,
所述分支指令检测部件检测所述机器语言程序中包含的指令字之中具有分支目的地地址的分支指令,
所述子例程调用指令检测部件检测所述机器语言程序中包含的指令字之中具有子例程调用目的地地址的子例程调用指令,
所述子例程源代码输出部件将由所述子例程检测部件检测所述机器语言程序所得的各子例程单位的程序源代码输出,
所述识别符附加部件将表示所述分支目的地地址的识别符附加在所述程序源代码的分支目的地的指令中,并且所述无条件分支指令输出部件将所述机器语言程序的所述分支指令,作为对具有所述程序源代码的所述识别符的指令的无条件分支指令而输出,
所述子例程调用指令输出部件将所述机器语言程序的子例程调用指令,作为所述程序源代码的子例程调用指令输出,
所述指令集模拟器包括:子例程机器语言地址表生成部件;子例程地址检索处理指令生成部件;以及数据依赖子例程调用指令生成部件,
所述子例程机器语言地址表生成部件生成将与子例程名和子例程机器语言地址形成对的信息有关的子例程机器语言地址表,
所述子例程地址检索处理指令生成部件从子例程机器语言地址检索所述程序源代码上的子例程,生成获取所述程序源代码上的子例程地址的子例程地址检索处理的程序,
所述数据依赖子例程调用指令生成部件根据所述子例程地址检索处理的指令,指定所述程序源代码的数据依赖子例程调用指令的调用目的地子例程,对该调用目的地子例程进行调用处理。
11.如权利要求10所述的指令集模拟器的模拟器执行程序生成方法,其特征在于,
所述指令集模拟器包括未注册机器语言地址检测部件和未注册子例程程序源代码生成部件,
所述未注册机器语言地址检测部件在所述模拟器执行程序的执行中,未注册到所述子例程机器语言地址表中的机器语言地址通过数据依赖子例程指令被调用的情况下,具有在记录了该未注册机器语言地址后,强制结束所述模拟器执行程序的功能,
所述未注册子例程程序源代码生成部件对于未注册机器语言地址的子例程,由所述未注册子例程程序源代码生成部件追加生成程序源代码。
12.如权利要求10或11所述的指令集模拟器的模拟器执行程序生成方法,其特征在于,
所述指令集模拟器包括寄存器变量展开部件,
所述寄存器变量展开部件将所述机器语言程序的寄存器值作为所述程序源代码上的子例程自变量或局部变量来描述。
Applications Claiming Priority (3)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
JP2015-145452 | 2015-07-23 | ||
JP2015145452A JP6418696B2 (ja) | 2015-07-23 | 2015-07-23 | 命令セットシミュレータおよびそのシミュレータ生成方法 |
PCT/JP2016/071632 WO2017014318A1 (ja) | 2015-07-23 | 2016-07-22 | 命令セットシミュレータおよびそのシミュレータ生成方法 |
Publications (2)
Publication Number | Publication Date |
---|---|
CN108027748A CN108027748A (zh) | 2018-05-11 |
CN108027748B true CN108027748B (zh) | 2019-09-10 |
Family
ID=57834504
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CN201680055109.2A Active CN108027748B (zh) | 2015-07-23 | 2016-07-22 | 指令集模拟器及其模拟器生成方法 |
Country Status (4)
Country | Link |
---|---|
US (1) | US10459707B2 (zh) |
JP (1) | JP6418696B2 (zh) |
CN (1) | CN108027748B (zh) |
WO (1) | WO2017014318A1 (zh) |
Families Citing this family (8)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
JP2013242700A (ja) * | 2012-05-21 | 2013-12-05 | Internatl Business Mach Corp <Ibm> | コード最適化方法、プログラム及びシステム |
US10884720B2 (en) | 2018-10-04 | 2021-01-05 | Microsoft Technology Licensing, Llc | Memory ordering annotations for binary emulation |
US20200183661A1 (en) * | 2018-12-11 | 2020-06-11 | GM Global Technology Operations LLC | Method and apparatus for cross-execution of binary embedded software |
US10684835B1 (en) * | 2018-12-11 | 2020-06-16 | Microsoft Technology Licensing, Llc | Improving emulation and tracing performance using compiler-generated emulation optimization metadata |
CN110309655B (zh) * | 2019-07-05 | 2021-08-17 | 武汉绿色网络信息服务有限责任公司 | 一种检测app更新过程中安全性的方法以及检测装置 |
CN110659032B (zh) * | 2019-09-24 | 2023-08-22 | 网易(杭州)网络有限公司 | 游戏应用的指令执行方法、装置、终端设备和存储介质 |
US11900136B2 (en) * | 2021-07-28 | 2024-02-13 | Sony Interactive Entertainment LLC | AoT compiler for a legacy game |
CN117407267A (zh) * | 2022-07-07 | 2024-01-16 | 格兰菲智能科技有限公司 | 条件分支覆盖率计算方法、装置、计算机设备、存储介质 |
Citations (4)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
JPH096646A (ja) * | 1995-06-14 | 1997-01-10 | Oki Electric Ind Co Ltd | プログラムシミュレーション装置 |
CN1512334A (zh) * | 2002-12-26 | 2004-07-14 | �Ҵ���˾ | 程序变换装置和程序变换方法 |
CN101216775A (zh) * | 2008-01-03 | 2008-07-09 | 北京深思洛克数据保护中心 | 一种软件程序的保护方法、装置及系统 |
JP5542643B2 (ja) * | 2010-12-10 | 2014-07-09 | 三菱電機株式会社 | シミュレーション装置及びシミュレーションプログラム |
Family Cites Families (12)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
JPH1083311A (ja) * | 1996-09-06 | 1998-03-31 | Mitsubishi Electric Corp | シミュレータ |
JP3495230B2 (ja) * | 1997-06-30 | 2004-02-09 | Necマイクロシステム株式会社 | エミュレーション処理方式 |
WO1999012094A1 (de) * | 1997-09-01 | 1999-03-11 | Siemens Nixdorf Informationssysteme Ag | Verfahren zum umsetzen eines objektcodes in einen programmcode |
WO1999030229A1 (en) * | 1997-12-11 | 1999-06-17 | Digits Corp. | Object code analysis and remediation system and method |
US7356672B2 (en) * | 2004-05-28 | 2008-04-08 | The Regents Of The University Of California | Warp processor for dynamic hardware/software partitioning |
US8621444B2 (en) * | 2004-06-01 | 2013-12-31 | The Regents Of The University Of California | Retargetable instruction set simulators |
US8056138B2 (en) * | 2005-02-26 | 2011-11-08 | International Business Machines Corporation | System, method, and service for detecting improper manipulation of an application |
US20100274755A1 (en) * | 2009-04-28 | 2010-10-28 | Stewart Richard Alan | Binary software binary image analysis |
US8510723B2 (en) * | 2009-05-29 | 2013-08-13 | University Of Maryland | Binary rewriting without relocation information |
US8726255B2 (en) * | 2012-05-01 | 2014-05-13 | Concurix Corporation | Recompiling with generic to specific replacement |
KR102147355B1 (ko) * | 2013-09-27 | 2020-08-24 | 삼성전자 주식회사 | 프로그램 변환 방법 및 장치 |
US20180211046A1 (en) * | 2017-01-26 | 2018-07-26 | Intel Corporation | Analysis and control of code flow and data flow |
-
2015
- 2015-07-23 JP JP2015145452A patent/JP6418696B2/ja active Active
-
2016
- 2016-07-22 WO PCT/JP2016/071632 patent/WO2017014318A1/ja active Application Filing
- 2016-07-22 CN CN201680055109.2A patent/CN108027748B/zh active Active
-
2018
- 2018-01-23 US US15/877,397 patent/US10459707B2/en active Active
Patent Citations (4)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
JPH096646A (ja) * | 1995-06-14 | 1997-01-10 | Oki Electric Ind Co Ltd | プログラムシミュレーション装置 |
CN1512334A (zh) * | 2002-12-26 | 2004-07-14 | �Ҵ���˾ | 程序变换装置和程序变换方法 |
CN101216775A (zh) * | 2008-01-03 | 2008-07-09 | 北京深思洛克数据保护中心 | 一种软件程序的保护方法、装置及系统 |
JP5542643B2 (ja) * | 2010-12-10 | 2014-07-09 | 三菱電機株式会社 | シミュレーション装置及びシミュレーションプログラム |
Also Published As
Publication number | Publication date |
---|---|
CN108027748A (zh) | 2018-05-11 |
WO2017014318A1 (ja) | 2017-01-26 |
US10459707B2 (en) | 2019-10-29 |
JP2017027375A (ja) | 2017-02-02 |
US20180165079A1 (en) | 2018-06-14 |
JP6418696B2 (ja) | 2018-11-07 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
CN108027748B (zh) | 指令集模拟器及其模拟器生成方法 | |
CN108614960B (zh) | 一种基于前端字节码技术的JavaScript虚拟化保护方法 | |
US7146606B2 (en) | General purpose intermediate representation of software for software development tools | |
CN105678169B (zh) | 一种二进制程序漏洞挖掘方法和系统 | |
CN110287702B (zh) | 一种二进制漏洞克隆检测方法及装置 | |
Brooks | Survey of automated vulnerability detection and exploit generation techniques in cyber reasoning systems | |
US20070011664A1 (en) | Device and method for generating an instruction set simulator | |
Watt et al. | Two mechanisations of WebAssembly 1.0 | |
Liang et al. | Deobfuscation of virtualization-obfuscated code through symbolic execution and compilation optimization | |
Lunnikivi et al. | Transpiling python to rust for optimized performance | |
CN105677297B (zh) | 套锁实现方法及装置 | |
Escalada et al. | An efficient platform for the automatic extraction of patterns in native code | |
Cesare et al. | Wire--a formal intermediate language for binary analysis | |
Murawski et al. | A contextual equivalence checker for IMJ | |
Heitman et al. | BARF: a multiplatform open source binary analysis and reverse engineering framework | |
CN114816435A (zh) | 一种基于逆向技术的软件开发方法 | |
CN114816436A (zh) | 一种基于反汇编的源码解析装置 | |
Jeong et al. | A data type inference method based on long short-term memory by improved feature for weakness analysis in binary code | |
CN102866893B (zh) | 基于中间语言il的遗产软件结构析取方法 | |
Ramsey et al. | A transformational approach to binary translation of delayed branches | |
Haijiang et al. | Nightingale: Translating embedded VM code in x86 binary executables | |
McNamara | Rust in Action | |
Shao et al. | A survey of available information recovery of binary programs based on machine learning | |
Vishnyakov et al. | A method for analyzing code-reuse attacks | |
Hai et al. | Multi-threaded on-the-fly model generation of malware with hash compaction |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
PB01 | Publication | ||
PB01 | Publication | ||
SE01 | Entry into force of request for substantive examination | ||
SE01 | Entry into force of request for substantive examination | ||
GR01 | Patent grant | ||
GR01 | Patent grant |