Page 123 - 《软件学报》2024年第6期
P. 123

谢汶兵 等: 二进制翻译技术综述                                                                2699


                 存模型的内存映射. Risotto    很好解决了    QEMU  在不同内存模型的硬件平台之间正确翻译并发程序的难题.

                 3.5   代码挖掘
                    与代码挖掘相关的两个问题包括代码自修改和自生成. 代码自修改在                        Adobe Premiere、Doom  以及嵌入式应
                 用中较为常见, 代码自生成则随着           JavaScript、PHP、C#等脚本语言的流行变得更加普遍           [103] . 为了保证缓存代码
                 的及时更新, 当发生代码自修改和代码自生成时, 二进制翻译需要满足: (1) 及时发现被修改代码块. (2) 重新翻译
                 被修改代码并更新缓存. 目前, 静态翻译无法预知代码自修改和自生成, 动态翻译虽然能够及时发现变化的代码,
                 但是在代码块的发现和缓存更新方面开销较大.
                    在修改代码块的发现上, 动态翻译主要是基于信号探测和代码注释的方法实现. QEMU                           采用  mprotect 方法将
                 所有代码设置为不可写, 通过监测          SIGSEGV  异常来发现自修改情况. Strata     [104] 基于内存读写保护和信号探测来发
                 现自修改行为. Liu    等人  [105] 通过比较源代码和备份源代码的异同, 进而确定代码是否被修改. Hawkins 等人                 [103] 基
                                                                               [4]
                                                                                        [6]
                 于代码注释的方式来发现自生成的代码区域; 当代码发生变化时, Transmeta CMS 、DAISY 、QEMU                       等丢弃所
                 有受影响的缓存代码, 开展重新翻译. 这种做法可能会导致大量未修改代码被淘汰和重复翻译. 文献                              [105] 设计精
                 确化自修改代码更新机制, 如果修改后的基本块小于原基本块, 则直接使用修改后的基本块替换原基本块. 如果修
                 改后的基本块大于原基本块, 则为修改后的基本块新开辟代码空间. Wang                     等人  [106] 提出最大化复用基本块代码, 发
                 生页故障时, 启动代码备份机制保存该页代码到新开辟的一个代码空间, 然后逐项比较被修改源代码块与备份块,
                 仅在实际修改源代码块时才会重新翻译代码块.
                    冯·诺伊曼结构的机器中代码和数据以相同形式表示, 重定位、指令跳转、空指令填充等特征导致代码边
                 界模糊, 难以区分代码段和数据段. 静态翻译自身的局限性导致其在自修改代码的发现上存在很大挑战. 最常用
                 的代码发现方法是从可执行文件的执行入口处逐条解码挖掘文件中的可执行指令, 但是间接转移这类指令的存
                 在增加了静态翻译中代码发现的难度. Cifuentes 等人            [107] 提出基于分割和表达式替换方法恢复跳转表目标地址
                 的技术, 改善了静态翻译对代码发现不足的问题. Chen               等人  [108] 提出采用多轮线性扫描的方法明确代码边界, 精
                 确区分数据段和代码段的自修改情况. 但是在发生自修改之后需要对缓存代码及时更新, 这对于静态翻译来说
                 依旧是个难题.
                    在软件测试研究中, 为了提高翻译代码功能点的覆盖率, Guo
                 3.6   功能等价性研究
                    二进制翻译过程是软件功能在新平台环境的再实现, 翻译过程以源程序逻辑等价性为前提. 逻辑的等价性包
                 括翻译前后程序行为的一致性、性能表现的等效性等. 然而, 逻辑等价性验证面临着大量挑战: (1) 二进制翻译技
                 术的跨平台特性导致大量测试集依赖于处理器架构                  [109] , 不同平台之间的回归测试集难以直接复用          [110] . (2) 二进制
                 翻译系统对自身的代码改动极其敏感, 开发过程中需要频繁的引入测试. 然而, 当前业界普遍采用                                SPEC2006、
                 SPEC2017、LTP  等大型测试集进行测试, 测试过程十分耗时             [111] . (3) 二进制翻译系统的功能设计复杂, 测试过程
                 中很难保证对于功能点的全覆盖. 研究发现即使采用大型测试集进行测试, 依旧有                          30%  的二进制翻译系统代码功
                 能点无法被覆盖      [112] . (4) 等价性测试主要是基于特定测试集的白盒与黑盒测试, 而要验证翻译程序的功能等价性
                 是极具困难的. 我们将二进制翻译的功能等价性研究归纳为软件测试和验证研究.
                                                                   等人  [112] 提出基于翻译平台指令和操作数随机生
                 成测试用例的方法, 有效提升了测试代码覆盖率. Zhi 等人               [110] 提出基于  LLVM IR  中间表示变换将程序统一转换
                 为  x86 平台二进制代码, 进而复用      x86 现有的程序测试工具, 弥补了其他目标平台测试工具匮乏的不足. Wu 等人                   [113]
                 提出基于   PerfDBT  构建小型回归测试集, 运行分析已有测试集的基本块, 将热路径代码规模缩减后形成新的基准
                 回归测试集, 有效提升了已有回归测试集的使用效率. Wu                等人  [111] 提出了  FADATest 框架, 首先利用动态二进制翻
                 译执行已有标准测试集程序并捕获测试程序运行特征信息, 然后基于此特征信息生成新的测试代码, 用以模拟原
                 始基准程序行为. FADATest 弥补了      PerfDBT [113] 测试集在跨平台和多线程应用方面支持的不足缺陷. 此外, Wagstaff
                 等人  [114] 提出支持跨平台全系统模拟的基准测试          SimBench, 支持全系统翻译中的性能评估、中断和异常处理、内
                 存访问、I/O   以及其他性能敏感的代码测试.
   118   119   120   121   122   123   124   125   126   127   128