[发明专利]适用于虚函数和函数指针的静态函数调用图构建方法有效
申请号: | 201910492850.0 | 申请日: | 2019-06-06 |
公开(公告)号: | CN110187988B | 公开(公告)日: | 2021-08-13 |
发明(设计)人: | 顾乃杰;张帆;苏俊杰 | 申请(专利权)人: | 中国科学技术大学 |
主分类号: | G06F9/54 | 分类号: | G06F9/54 |
代理公司: | 安徽省合肥新安专利代理有限责任公司 34101 | 代理人: | 陆丽莉;何梅生 |
地址: | 230026 安*** | 国省代码: | 安徽;34 |
权利要求书: | 查看更多 | 说明书: | 查看更多 |
摘要: | |||
搜索关键词: | 适用于 函数 指针 静态 调用 构建 方法 | ||
1.一种适用于虚函数和函数指针的静态函数调用图构建方法,其特征是按如下步骤进行:
步骤1、获取源程序的中间代码;
步骤2、获取中间代码中的关键信息,所述关键信息包括基本块顺序队列以及虚函数相关信息;其中,获取基本块顺序队列的过程如下:
步骤2A_1、获取所述中间代码中第i个函数Fi所对应的控制流图CFGi,并根据所述控制流图CFGi得到CFGi所对应的入口基本块EntryBBi;i=1,2,…,FN,FN为中间代码中函数的总个数;
设置所述入口基本块EntryBBi为当前基本块,并将所述控制流图CFGi中所有循环的标识符记为“False”,表示未遍历到相应循环;
步骤2A_2、如果当前基本块为循环L的头基本块,则执行步骤2A_3,否则执行步骤2A_6;
步骤2A_3、如果所述当前基本块所在的循环L的标识符为“False”,则执行步骤2A_4,否则执行步骤2A_5;
步骤2A_4、将当前基本块加入第i个基本块顺序队列BBOrderQi,并将当前基本块的后继基本块中处于循环L中的后继基本块设为当前基本块,将未处于循环L中的后继基本块压入第i个未处理栈UnProcessSi中,再将所述循环L的标识符置为“True”后,返回执行步骤2A_2;
步骤2A_5、如果所述第i个未处理栈UnProcessSi为非空栈,则弹出所述第i个未处理栈UnProcessSi中栈顶的基本块,并将栈顶的基本块设置当前基本块后,执行步骤2A_2;
步骤2A_6、将当前基本块加入所述第i个基本块顺序队列BBOrderQi中,如果当前基本块存在后继基本块,且后续基本块满足先序条件,则将满足先序条件的任意一个后继基本块为当前基本块,将其余后继基本块依次压入所述第i个未处理栈UnProcessSi中,再返回步骤2A_2执行,否则,执行步骤2A_5;
所述先序条件为:后继基本块的前驱基本块均在所述第i个基本块顺序队列BBOrderQi中;
获取所述虚函数相关信息的过程如下:
步骤2B_1、定义中间代码中第j个虚表结构体变量为Vj,Vj[k]表示第j个虚表结构体变量Vj中第k个成员数组,且每个成员数组均对应一个类,Vj[k][t]表示第j个虚表结构体变量Vj中第k个成员数组的第t个元素,其中j=1,2,…,N;N为虚表结构体变量的总个数,k=1,2,…,Mj,Mj为第j个虚表结构体变量Vj中成员数组的总个数,t=1,2,…,Mjk,Mjk为第j个虚表结构体变量Vj中第k个成员数组的元素总个数;
步骤2B_2、将第j个虚表结构体变量Vj中第k个成员数组的第1个元素Vj[k][1]转换成整型变量VPtrOffsetjk,以第j个虚表结构体变量Vj对应的类为键,以所述整型变量VPtrOffsetjk为值,构建键值对Pair1,并将键值对Pair1加入第j个虚表结构体变量Vj对应的虚表指针偏移表VirtualPtrj中,其中所述整型变量VPtrOffsetjk表示第k个虚表指针在所述第j个虚表结构体变量Vj所对应的类创建出的对象的内存布局中的偏移字节数;
步骤2B_3、将第j个虚表结构体变量Vj中第k个成员数组的第t个元素Vj[k][t]转换成函数指针类型变量Vfunjkt,以偏移字节数Vj[k][1]为键,以所述指针类型变量Vfunjkt为值,构建键值对Pair2,并将键值对Pair2加入第j个虚表结构体变量Vj中第k个成员数组对应类的虚函数相关信息表VirtualTabjk中,其中,所述指针类型变量Vfunjkt表示第j个虚表结构体变量Vj中第k个成员数组对应类的虚表中的第t-1个虚函数,t=2,…,Mjk;
步骤3、指定静态分析入口函数,并基于所述关键信息,对所述中间代码进行模拟执行,分析出所述中间代码中的函数调用指令调用的实际函数,同时记录下函数调用关系;
步骤3_1、根据所述静态分析入口函数的基本块顺序队列,将队头基本块设置为当前基本块;
步骤3_2、设置当前基本块中的第一条指令为当前指令;
步骤3_3、对所述当前指令进行仿真地址分析,获得中间代码模拟执行至所述当前指令过程中,仿真地址上存放的变量指针、函数指针、虚函数信息,并依次存放至变量指针关系表R1、函数指针关系表R2、虚函数关系表R3中;
在模拟执行过程开始时,给未处理过的指令分配仿真内存后,按如下方式进行仿真地址分析:
如果当前指令为取元素地址指令,则针对取元素地址指令的每个维度,获取每个维度上的操作数数值,并分别与相应操作数的内存对齐后所得到的字节数相乘,再将所有维度上的乘积求和,从而获得总的仿真地址偏移量,并存入仿真内存访存列表中;
如果当前指令为存指令,则判断存指令的第一操作数是否为普通变量指针,若是,则将存指令的第一操作数的仿真内存仿真列表中每个仿真地址和第二操作数的仿真内存访问列表中每个仿真地址进行两两组合后,加入变量指针关系表R1,否则,判断存指令的第一操作数是否为函数指针,若是,则将存指令的第二操作数的仿真内存访问列表中的每个仿真地址,与所述函数指针进行组合后,加入所述 函数指针关系表R2;否则,不操作;
如果当前指令为取指令,则获取所述取指令的操作数仿真地址在所述变量指针关系表R1中对应的仿真地址,并将对应的仿真地址加入取指令的仿真内存访问列表中;
如果当前指令为类型转换指令,则将类型转换后的变量的仿真内存访问列表置为类型转换前的变量的仿真内存访问列表;
如果当前指令为PHI指令,则判断当前指令所处基本块是否为循环头的基本块,若是,则将PHI指令的仿真内存访问列表置为进入循环的基本块所对应变量的仿真内存访问列表,否则,将PHI指令的仿真内存访问列表置为PHI指令中所有操作数的基本块所对应变量的仿真内存访问列表的组合;
如果当前指令为返回指令,则判断返回值是否为指针,若是,则将函数调用指令的仿真内存访问表置为返回值的仿真内存访问列表;否则,不操作;
如果当前指令为函数调用指令,则判断所述函数调用是否为虚函数调用形式,若是,则根据步骤2获得的虚函数相关信息来获取虚函数,并将函数调用指令的操作数的仿真地址与所述虚函数进行组合,并加入虚函数关系表R3,否则,不操作;
如果当前指令为函数调用指令,则判断函数调用指令的参数是否为指针类型,若是,将函数调用指令的实参变量的仿真内存访问列表置为形参变量的仿真内存访问列表;否则,不操作;
步骤3_4、如果所述当前指令为函数调用指令,则根据所述变量指针关系表R1、函数指针关系表R2、虚函数关系表R3,分析出所述函数调用指令实际调用的函数,并记录下函数的调用关系,再将所述静态分析入口函数设置为所述实际调用的函数后,递归执行步骤3_1至步骤3_4模拟执行过程;否则,执行步骤3_5;
步骤3_5、如果所述当前基本块中仍存在未处理的指令,将当前指令的下一条指令置为当前指令,再执行步骤3_3;否则,执行步骤3_6;
步骤3_6、如果所述静态分析入口函数的基本块顺序队列中仍存在未处理的基本块,则将当前基本块的下一个基本块置为当前基本块,再执行步骤3_1;
步骤4、根据所述函数调用关系,构建出静态函数调用图。
该专利技术资料仅供研究查看技术是否侵权等信息,商用须获得专利权人授权。该专利全部权利属于中国科学技术大学,未经中国科学技术大学许可,擅自商用是侵权行为。如果您想购买此专利、获得商业授权和技术合作,请联系【客服】
本文链接:http://www.vipzhuanli.com/pat/books/201910492850.0/1.html,转载请声明来源钻瓜专利网。