四、程序插桩
程序插桩是指在程序中设置断点或打印语句,在执行中了解程序中的一些动态特性。
程序插桩技术的研究涉及的问题:
探测哪些信息。
程序的什么位置设置探测点
需要多少探测点
*
程序插桩技术最早是由J.C. Huang 教授提出的, 它是在保证被测程序原有逻辑完整性的基础上在程序中插入一些探针(又称为“探测仪”),通过探针的执行并抛出程序运行的特征数据,通过对这些数据的分析,可以获得程序的控制流和数据流信息,进而得到逻辑覆盖等动态信息,从而实现测试目的的方法。 由于程序插桩技术是在被测程序中插入探针,然后通过探针的执行来获得程序的控制流和数据流信息,以此来实现测试的目的。因此,根据探针插入的时间可以分为目标代码插桩和源代码插桩。
(1)目标代码插桩的前提是对目标代码进行必要的分析以确定需要插桩的地点和内容。由于目标代码的格式主要和操作系统相关,和具体的编程语言及版本无关,所以得到了广泛的应用,尤其是在需要对内存进行监控的软件中。但是由于目标代码中语法、语义信息不完整,而插桩技术需要对代码词法语法的分析有较高的要求,故在覆盖测试工具中多采用源代码插桩。
(2)源代码插桩是在对源文件进行完整的词法分析和语法分析的基础上进行的,这就保证对源文件的插桩能够达到很高的准确度和针对性。但是源代码插桩需要接触到源代码,使得工作量较大,而且随着编码语言和版本的不同需要做一定的修改。在后面我们所提到的程序插桩均指源代码插桩。
程序插桩:是借助往被测程序中插入操作,来实现测试目的的方法。 程序插桩的基本原理是在不破坏被测试程序原有逻辑完整性的前提下,在程序的相应位置上插入一些探针。这些探针本质上就是进行信息采集的代码段,可以是赋值语句或采集覆盖信息的函数调用。通过探针的执行并输出程序的运行特征数据。基于对这些特征数据的分析,揭示程序的内部行为和特征。
代码插桩设计
(1)插桩位置:
探针的植入要做到紧凑精干,才能保证在做到收集的信息全面而无冗余,减少代码的膨胀率。因此,在确定插桩位置时,要将程序划分,基本的划分方法是基于“块”结构。
按照块结构的划分,探针的植入位置有以下几种情况:
a. 程序的第一条语句;b. 分支语句的开始;c. 循环语句的开始;d. 下一个入口语句之前的语句;e. 程序的结束语句;f. 分支语句的结束;g. 循环语句的结束;除此之外,根据覆盖测试要求的不同,插桩的位置除了上面所说的几种情况外,也会随着覆盖测试要求的不同有所变化。
(2)插桩策略:
插桩策略是解决“如何插”的问题。传统的插桩策略是在所有需要插桩的位置插入探针,在程序运行过程收集所有可能用到得程序信息,将其写入数据库进行分析和处理。这种方法对于大型的程序来说,将会造成相当大的工作量,效率很低,且会造成很大的代码膨胀率。而我们会根据不同的测试要求,每次插入不同的探针,采用相应的插桩策略,这样就减少了代码的膨胀率,保证了程序执行的效率。下面简单介绍几种探针的插桩策略。
语句覆盖探针(基本块探针):在基本块的入口和出口处,分别植入相应的探针,以确定程序执行时该基本块是否被覆盖。
分支覆盖探针:C/C++语言中,分支由分支点确定。对于每个分支,在其开始处植入一个相应的探针,以确定程序执行时该分支是否被覆盖。
条件覆盖探针:C/C++语言中,if, swich,while, do-while, for 几种语法结构都支持条件判定,在每个条件表达式的布尔表达式处植入探针,进行变量跟踪取值,以确定其被覆盖情况。
根据不同测试要求采用不用的插桩策略,每次在不同的位置植入相应的探针,使得每次只是植入有限的探针,这就更大大减少了代码的膨胀率和插桩的速度。
代码插桩实验
采用了一个 1000 行的程序作为被测程序,分别采用使用整体插桩的工具和我们自己开发的工具进行测试,结果发现前者插桩的时间和代码膨胀率分别为3s 和35%,后者插桩的平均时间和平均的代码膨胀率为1s 和8%,插桩时间得到明显提升,代码膨胀率明显减少。
采用以上的程序插桩技术,除了常用的覆盖测试策略外,我们还可以实现MC/DC 和LCSAJ 测试。
2022-07-01 03:46:28
4.42MB
软件
测试
1