专利名称:基于代码查询进行源代码插桩的方法
技术领域:
本发明涉及计算机程序动态分析,主要涉及一种基于代码查询的插桩方法。
背景技术:
程序分析通常利用静态程序分析和动态程序分析对程序行为进行自动分析,进而提高软件质量。动态程序分析常借助于插桩方法来收集程序动态运行行为,某些与运行环境相关的程序行为只能通过插桩来收集,而静态程序分析无法进行分析。软件开发过程中, 代码审查者在代码编写阶段完成后使用源代码插桩方法对代码进行审查,通常审查者拥有阅读源代码权限但不便对代码进行修改。通过对程序运行行为的分析尽早发现代码中的错误,进而提高软件质量。源代码插桩能够充分地利用程序语义、可视化地显示插桩代码、并且不会提高代码逻辑复杂性。程序插桩技术,是在保证被测程序原有逻辑完整性的基础上在程序中插入一些探针,通过探针的执行并抛出程序运行的特征数据,通过对这些数据的分析,可以获得程序的控制流和数据流信息,进而得到逻辑覆盖等动态信息,从而实现测试目的的方法。由于程序插桩技术是在被测程序中插入探针,然后通过探针的执行来获得程序的控制流和数据流信息,以此来实现测试的目的。因此,根据探针插入的时间可以分为目标代码插桩和源代码插桩。现有插桩方法主要包括断言机制、字节码插桩、面向方面插桩等三类方法。断言机制直接在写源文件中添加插桩代码,将会降低代码阅读性。字节码插桩则直接对字节码文件进行修改,被插字节码的源代码无法可视化,且无法保证代码插入过程的正确性。面向方面插桩在程序纵向继承关系的基础上增加了横向方面关系,增加了程序的逻辑复杂性。目前插桩技术主要存在的瓶颈主要有插桩点及其代码非可视化、插桩点自动定位困难、难以做到插桩语句上下文敏感、自动插桩性能较低的问题。代码查询技术在软件设计有着十分重要的地位。一些查询工具被设计用于帮助程序员理解程序中大量经常变化和复杂的关系。目前,代码查询技术已经被广泛的用于软件代码查询技术在软件分析和测试工作中发挥着重要的作用,在软件架构分析,逆向工程,一致性验证,代码审查等方面都有广泛的应用。从另一方面看,代码查询已经延伸至系统框架错误检测,识别重构可能,定位项目缺陷,查询横切关注点,监测开发过程,评估设计适量, 跟踪冗余依赖条件等等。通常插桩过程分两步进行(1)定位插桩语句将要插入的位置(2) 构建插桩语句。目前插桩技术主要存在的瓶颈主要有插桩点及其代码非可视化、插桩点自动定位困难、难以做到插桩语句上下文敏感、自动插桩性能较低的问题。
发明内容
本发明目的是,鉴于上述问题,本发明旨在提供一个源代码插桩方法,该方法结合代码查询技术,有效的将代码查询得到的插桩位置以及上下文内容与插桩机制相结合在一起。
本发明是通过以下的技术方案实现的无痕可管理的源代码手动定义标志插桩方法
步骤10 打开一个工程(程序);
步骤11 通过在JSearch编辑器里输入相应的插桩命令; 步骤12 工具运行Jkarch命令,得到所有的插桩点定义
步骤13 审查所有插桩点的定义若发现带有错误的插桩点,则进入步骤14对其进行修改;没有发现带有错误的插桩点,则直接进入步骤15 ; 步骤14 修改插桩的定义至正确; 步骤15 将插桩点与原源文件合并生成新源文件; 其中步骤11和步骤12所使用的JSearch命令符合下面的语法规范 S ; = find Id:T satisfying CS IS T : = object
statement method class interface
CS ; = {exist Id:T}{all Id:T} where CE CE = CE && CE CE I I CE !CE (CE)
Id. Att=' value' Id Rel Id Att : = name
dataType specificType returnType paramsType Rel : = extend use
change
isln
call
IS := insert before Id IN insert after Id IN IS
IN := "STR〃 STR := STR String STR STR %Att% STRNULL
查询命令S以关键字find开始,后跟一个Id: T的声明格式,再接satisfying关键字, 最后以条件语句CS结尾。它的含义是要查询满足查询条件CS的T类型的程序元素。语法规则中的T是指程序元素的类型,它可以是object、statement、function、 interface和class的其中之一,分别对应于变量、语句、方法、接口和类。Id:T声明了一个类型为T,别名为Id的元素。Id作为它声明元素的别名在之后的查询条件表达式CE中被使用。在条件表达式中出现的Id必须先被声明,并且同名的Id不能被重复声明,以免混淆。 紧跟在关键字find之后声明的Id就对应于查询目标元素。条件语句CS描述的是目标元素需要满足的查询条件。它的语法规则在形式上符合带量词的一阶谓词的公式,具体含义是存在Tll类型的元素Idll、T12类型的元素 Idl2……,且对任一 T21类型的元素Id21、T22类型的元素Id22……,使得条件表达式CE成立。其中,Idli (i=l,2…)是紧跟关键字exist之后的元素的别名,并且它声明的类型为 Tli:Id2j (j=l,2…)是紧跟关键字all之后的元素别名,并且它声明的类型为T2j。条件表达式CE是一个布尔逻辑表达式,支持与(‘&&’)、或(‘ I I ’)、非(‘ ! ’) 的逻辑运算符。用户还可以通过在条件表达式中添加括号’(‘和’)’,来改变运算符的运算先后次序。可以看到,在有关CE的语法规则中有两个条件表达式Id. Att=’ value’和Id Rel Id,它们是结构最简单的条件表达式,本文把这两个表达式称作原子表达式。任何一个条件表达式都是在一个或多个原子表达式的基础上添加与&&、或11、非!以及括号(和)等运算符拼接而成的。其中,Id. Att=’value’称为属性条件表达式,本文规定如果元素Id的Att 属性的属性值等于value,则表达式的值为True ;否则表达式的值为i^ilse。Idl Rel Id2 称为关系条件表达式,规定如果元素Idl与Id2间存在关系Rel,则表达式的值为True,否则表达式的值为i^alse。下表定义了针对不同的程序元素定义了一系列的属性(表1),同时也定义了元素间的一系列关系(表2)。 表格1程序元素的属性
权利要求
1.一种基于代码查询进行源代码插桩的方法,其特征是包括步骤 步骤10 打开一个或多个工程(程序);步骤11 通过在Jkarch命令编辑器里输入相应的JSearch插桩命令; 步骤12 工具运行Jkarch命令,得到所有的插桩点定义;步骤13 审查所有插桩点的定义若发现带有错误的插桩点,则进入步骤14对其进行修改;没有发现带有错误的插桩点,则直接进入步骤15 ; 步骤14 修改插桩的定义至正确; 步骤15 将插桩点与原源文件合并生成新源文件。
2.根据权利要求1所述的基于代码查询进行源代码插桩的方法,其特征是所述的输入 JSearch插桩命令即步骤11中,其中输入相应的Jkarch插桩命令过程包括步骤30 打开JSearch命令编辑器;步骤31 判断是否需要在工程中的源文件上定义插桩点,如果是,则跳转到步骤32,如果不是,则跳转到步骤35;步骤32 按照Jkarch命令语法规则给出目标插桩点位置的JSearch命令描述; 步骤33 按照Jkarch命令语法规则给出目标插桩点插桩语句的模板描述; 步骤34 将步骤32和步骤33得到的命令描述和模板描述的字符串输入到JSearch命令编辑器中;步骤35:结束本次插桩定义。
3.根据权利要求1所述的基于代码查询进行源代码插桩的方法,其特征是运行 Jkarch插桩命令即步骤12,其中运行相应的Jkarch插桩命令、得到所有的插桩点定义过程包括步骤40 从JSearch命令编辑器中获得JSearch命令字符串,即命令描述和模板描述的字符串;步骤41 从已经打开工程中的Java源代码中生成相应的代码信息,这些代码信息包括类、接口、方法、对象和语句信息;步骤42 对步骤40中得到的JSearch命令字符串进行语法检测和预处理得到检索指令;步骤43 按照检索指令在步骤41中得到的代码信息中进行目标元素检索,得到相应的目标元素集合和相应的辅助元素集合构成的元素属性值;步骤44 将JSearch命令中插桩模板的参数替换成步骤43中的元素属性值,得到相应的插桩语句集合;步骤45 将步骤44中得到的插桩语句集合生成相应的插桩点。
4.根据权利要求3所述的基于代码查询进行源代码插桩的方法,其特征是生成代码信息即所述步骤41中,从源代码生成与JSearch命令字符串相应的代码信息的方式是首先生成源代码相应的抽象语法树,在将语法树中的类、接口、方法、对象和语句信息依次从语法树中抽取出来,形成表的数据结构。
5.根据权利要求3所述的基于代码查询进行源代码插桩的方法,其特征是语法检查及检索准备工作即步骤42中,其中检测和预处理即检查和检索准备工作的过程包括步骤601 匹配关键字find ;步骤602 匹配Target元素,并将其存放到Query, target中; 步骤603 匹配关键satisfying ;步骤604 当匹配关键字exist成功或者匹配关键字all成功,则跳转步骤605,,否则跳转步骤608 ;步骤605 构造相应的predicate ;PM 606 -M predicatelist Query, predicates ψ ;步骤607 跳转步骤604 ; 步骤608 匹配关键字where ; 步骤609 当扫描完整个字符串,则跳转618 ;步骤610 如果匹配Att表达式成功,则跳转步骤611,否则跳转步骤612 ;步骤611 生成AttrCondition对象,存放到Query. conditionLex队列中,跳转步骤·617 ;步骤612 如果匹配Rel表达式成功,则跳转步骤613,否则跳转步骤614 ;步骤613 生成RelCondition对象,存放到Query. conditionLex队列中,跳转步骤·617 ;步骤614 如果匹配运算符成功,则跳转步骤615,否则跳转步骤616步骤615 生成Operator对象,存放到Query. conditionLex队列中,跳转步骤617 ;步骤616:返回出错状态;步骤617 跳转步骤609 ;步骤618 返回Query单次查询结构。
6.根据权利要求3所述的基于代码查询进行源代码插桩的方法,其特征是目标元素检索即步骤43中,其中检索过程包括步骤701 初始化运算符栈op_stack ; 步骤702 初始化操作数栈r_stack ;步骤703 当conditionLex列表中的所有对象已经处理完,则跳转步骤714 ; 步骤704 从conditionLex列表中取出一个Lex对象1 步骤705 如果1的类型是Attr或者Rel,则跳转步骤706,否者跳转步骤707 ; 步骤706 将1压入操作数栈,跳转步骤703 ;步骤707 如果1的类型是Operator,则跳转步骤708,否则跳转步骤703 ;步骤708 如果1的优先级比top (op_stack)大,则跳转步骤709,否则跳转步骤710 ;步骤709 将1压入op_stack中,跳转步骤703 ;步骤710:如果1的优先级与t0p(0p_stack)相等,则跳转步骤711,否则跳转步骤·712 ;步骤711 弹出op_stack元素,跳转步骤703 ; 步骤712 弹出[stack的元素,计算相应的集合; 步骤713 跳转步骤703 ; 步骤714 返回r_stack弹出元素。
7.根据权利要求1或3所述的基于代码查询进行源代码插桩的方法,其特征是插桩点即步骤12、步骤13、步骤14、步骤15和步骤45中,其实现在源文件编辑器标尺上增加相应的标记,该标记指定了插桩语句应该插入的字符位置、文件行数和插入内容。
8.根据权利要求7所述的基于代码查询进行源代码插桩的方法,其特征是所述的插桩点定义方式,所有插桩标志均随程序(工程)进行插桩标志在程序(工程)关闭后自动进行保存,在下次打开工程时插桩标志依旧能够在源代码编辑器的标尺上进行还原。
全文摘要
一种使用基于代码查询进行源代码插桩的方法,包括步骤步骤10打开一个工程;步骤11通过在JSearch编辑器里输入相应的插桩命令;步骤12工具运行JSearch命令,得到所有的插桩点定义步骤13审查所有插桩点的定义若发现带有错误的插桩点,则进入步骤14对其进行修改;没有发现带有错误的插桩点,则直接进入步骤15;步骤14修改插桩的定义至正确;步骤15将插桩点与原源文件合并生成新源文件;本发明为明确定义的代码查询和插桩命令,参数化的插桩语句模板,插桩代码可视化,自动插桩高效性等。
文档编号G06F11/36GK102298552SQ20111027589
公开日2011年12月28日 申请日期2011年9月19日 优先权日2011年9月19日
发明者张天, 赵建华, 陶永晶 申请人:南京大学