一种基于硬件的程序动态函数调用序列追踪方法和装置

专利2023-06-15  112



1.本发明涉及基于硬件的函数调用追踪。


背景技术:

2.程序追踪技术在软件测试、调试、性能分析等方面发挥着重要的作用。程序追踪技术分软件追踪和硬件追踪。软件追踪通常会对用户源代码进行插桩,通常依赖于编译器架构并且具有高昂的运行开销。硬件追踪相较于软件追踪,利用硬件追踪模块,具有更小的运行开销和通用性,并且不需要对源代码进行插桩修改。程序的硬件追踪需要执行程序的主体本身的支持,即处理器的支持。而处理器对硬件追踪的支持也是最近几年的事情,相比于软件追踪技术几十年的历史,硬件追踪则是一项全新技术,在实际的应用中存在很多问题。
3.比如,在对高级程序语言进行动态控制流跟踪时,存在机器指令与程序指令对应关系匹配的问题。由高级程序语言所编写的程序比如java、go等语言,是一种需要通过虚拟机进行解释执行的语言。程序被执行时,对应的程序指令并非为机器指令而是一种虚拟机的虚拟指令,需要由虚拟机将虚拟指令转换成机器指令才能被处理器所执行。而处理器硬件追踪所输出的追踪数据对应的是机器指令,故此,机器指令对应至虚拟指令需要进一步对应匹配处理。专利文献cn112905474 a公开了一种基于硬件的高级程序动态控制流追踪方法和装置。该专利文献正是解决了机器指令如何对应至虚拟指令的这道关卡。
4.另一方面,硬件追踪还存在追踪数据记录与处理器执行速度不匹配的问题。处理器硬件跟踪所产生的追踪数据通常需要存储记录才能进行分析。追踪数据存储记录速度与处理器执行速度往往无法匹配。在对程序基本块进行控制流跟踪的情况下,处理器硬件追踪所产生的追踪数据的速度往往高于追踪数据通过存储记录的速度。这往往缓存溢出,导致大量的追踪数据被抛弃丢失,由此记录得到的追踪数据往往不完整。
5.为了解决处理器硬件追踪中追踪数据记录与处理器执行速度不匹配的问题,一种思路是将追踪的粒度扩大化,以降低处理器硬件追踪所产生的追踪数据的速度,比如将追踪的粒度由程序基本块扩大至函数模块,仅对函数的调用进行追踪。


技术实现要素:

6.本发明所要解决的问题:为了解决处理器硬件追踪中追踪数据记录与处理器执行速度不匹配的问题,将追踪的粒度由程序基本块扩大至函数,从而降低处理器硬件追踪所产生的追踪数据的速度。
7.为解决上述问题,本发明采用的方案如下:根据本发明的一种基于硬件的程序动态函数调用序列追踪方法,包括如下步骤:步骤s1,用于:获取待测目标程序;步骤s2,用于:对所述待测目标程序进行插桩形成插桩程序,通过插桩构建函数调用跳转跟踪块,使得所述待测目标程序的各目标函数的入口和出口跳转至所述函数调用跳转跟踪块内再返回;
步骤s3,用于:执行插桩程序时,配置硬件跟踪,使得硬件跟踪仅跟踪所述函数调用跳转跟踪块的执行;步骤s4,用于:根据执行插桩程序跟踪所输出的追踪数据,分析所述待测目标程序的函数调用关系。
8.进一步,根据本发明的基于硬件的程序动态函数调用序列追踪方法,所述待测目标程序为可执行代码。
9.进一步,根据本发明的基于硬件的程序动态函数调用序列追踪方法,所述待测目标程序为源代码程序;所述步骤s2插桩所形成的插桩程序为源代码程序;所述函数调用跳转跟踪块为具有输入参数为函数识别码和出入口标识的函数;所述步骤s2还包括将插桩所形成的插桩程序编译成插桩后的可执行代码,然后分析所述函数调用跳转跟踪块的地址范围;所述步骤s3中,执行插桩程序时,为执行编译而成的插桩后的可执行代码。
10.进一步,根据本发明的基于硬件的程序动态函数调用序列追踪方法,所述待测目标程序为源代码程序;所述步骤s2包括如下步骤:步骤s21,用于:将所述待测目标程序编译成中间代码;步骤s22,用于:对所述中间代码进行插桩形成插桩后的中间代码;所述函数调用跳转跟踪块为中间代码指令块;步骤s23,用于:对插桩后的中间代码进行编译,生成插桩后的可执行代码,然后分析所述函数调用跳转跟踪块的地址范围。
11.根据本发明的一种基于硬件的程序动态函数调用序列追踪装置,包括如下模块:模块m1,用于:获取待测目标程序;模块m2,用于:对所述待测目标程序进行插桩形成插桩程序,通过插桩构建函数调用跳转跟踪块,使得所述待测目标程序的各目标函数的入口和出口跳转至所述函数调用跳转跟踪块内再返回;模块m3,用于:执行插桩程序时,配置硬件跟踪,使得硬件跟踪仅跟踪所述函数调用跳转跟踪块的执行;模块m4,用于:根据执行插桩程序跟踪所输出的追踪数据,分析所述待测目标程序的函数调用关系。
12.进一步,根据本发明的基于硬件的程序动态函数调用序列追踪装置,所述待测目标程序为可执行代码。
13.进一步,根据本发明的基于硬件的程序动态函数调用序列追踪装置,所述待测目标程序为源代码程序;所述模块m2插桩所形成的插桩程序为源代码程序;所述函数调用跳转跟踪块为具有输入参数为函数识别码和出入口标识的函数;所述模块m2还包括将插桩所形成的插桩程序编译成插桩后的可执行目标程序,然后分析所述函数调用跳转跟踪块的地址范围;所述模块m3中,执行插桩程序时,为执行编译而成的插桩后的可执行目标程序。
14.进一步,根据本发明的基于硬件的程序动态函数调用序列追踪装置,所述待测目标程序为源代码程序;所述模块m2包括如下模块:模块m21,用于:将所述待测目标程序编译成中间代码;模块m22,用于:对所述中间代码进行插桩形成插桩后的中间代码;所述函数调用跳转跟踪块为中间代码指令块;
模块m23,用于:对插桩后的中间代码进行编译,生成插桩后的可执行目标程序,然后分析所述函数调用跳转跟踪块的地址范围。
15.本发明的技术效果如下:本发明通过将追踪粒度由原始的程序基本块扩大至函数,从而降低处理器硬件追踪所产生的追踪数据的速度,使得所产生的追踪数据能够与追踪数据存储的速度匹配,减少追踪数据的丢失。
附图说明
16.图1是本发明实施例的流程示意图。
17.图2是本发明实施例的示例代码。
具体实施方式
18.下面结合附图对本发明做进一步详细说明。
19.如图1所示本实施例的一种基于硬件的程序动态函数调用序列追踪方法包括程序插桩步骤、硬件追踪下的程序执行步骤以及追踪数据分析步骤。本发明的输入是待测目标程序,输出为程序执行时的函数调用序列。如前所述,本发明的目的是为了将处理器硬件追踪的粒度由程序基本块扩大至函数,从而实现对程序函数调用的追踪。或者该目的可以表述成如何通过处理器硬件追踪实现对函数调用追踪。为实现上述目的,本发明采用如下方法:程序插桩步骤,通过插桩构建函数调用跳转跟踪块,使得待测目标程序的各目标函数的入口和出口跳转至函数调用跳转跟踪块内再返回;其中,函数调用跳转跟踪块全部由跳转指令所组成;硬件追踪下的程序执行步骤,执行插桩程序时,配置硬件跟踪,使得硬件跟踪仅跟踪函数调用跳转跟踪块的执行;追踪数据分析步骤,根据执行插桩程序跟踪所输出的追踪数据,分析待测目标程序的函数调用关系。上述方法步骤分别对应了前述的步骤s2、s3和s4。
20.程序插桩步骤更为具体的可以描述为:插入函数调用跳转跟踪块,并在函数入口和出口处插入跳转指令,使得函数被调用而进入函数后或者离开函数时,跳转至函数调用跳转跟踪块内,再由函数调用跳转跟踪块内的跳转指令返回。也就是说程序插桩步骤对待测目标程序的目标函数需要进行两步插桩:第一步插桩是函数入口和出口处插入跳转指令,第二步插桩是函数调用跳转跟踪块内与函数入口和出口处插入跳转指令相对应的返回原函数的跳转指令。其中,第一步插桩是函数内的插桩,第二步插桩是函数外的函数调用跳转跟踪块的构建。
21.如图2所示,图2示例了一个插桩后的待测目标程序。该待测目标程序是以机器指令组成的可执行代码。图2中,左侧虚线框标记的是所插入的函数调用跳转跟踪块,右侧是函数被插入跳转指令后的代码。其中,左侧虚线框标记的函数调用跳转跟踪块中在地址区间401000~40101e内定义了6条跳转指令,其跳转指令的首地址分别为:401000,401005,40100a,40100f,401014,401019。右侧的函数被插入跳转指令后的代码中定义了三个函数,其中第一个函数的地址区间为:4004d0~400510,其中4004d0为该函数的入口地址,40050f为该函数的出口地址;第二个函数的地址区间为:400520~40065a,其中400520为该函数的
入口地址,400559为该函数的出口地址;第三个函数的地址区间为:400670~4006c6,其中,400670为该函数的入口地址,4006c5为该函数的出口地址。这三个函数的入口处和出口处均被插入了跳转至函数调用跳转跟踪块的跳转指令,并与函数调用跳转跟踪块的跳转指令一一对应:第一个函数在地址4004d0的入口处插入了跳转至401000的跳转指令,在地址40050f的出口处之前插入了首地址为40050a的跳转至401005的跳转指令,跳转至401000的跳转指令和跳转至401005的跳转指令分别对应函数调用跳转跟踪块中首地址为401000和401005的返回第一个函数的跳转指令;第二个函数在地址400520的入口处插入了跳转至40100a的跳转指令,在地址400559的出口处之前插入了首地址为400554的跳转至40100f的跳转指令,跳转至40100a的跳转指令和跳转至40100f的跳转指令分别对应函数调用跳转跟踪块中首地址为40100a和40100f的返回第一个函数的跳转指令;第三个函数在地址400670的入口处插入了跳转至401014的跳转指令,在地址4006c5的出口处之前插入了首地址为4006c0的跳转至401019的跳转指令,跳转至401014的跳转指令和跳转至401019的跳转指令分别对应函数调用跳转跟踪块中首地址为401014和401019的返回第三个函数的跳转指令;此外,第三个函数中在首地址400688和4006a8的函数调用指令中调用了第二个函数,在首地址400698的函数调用指令中调用了第一个函数。
22.本发明中,硬件追踪下的程序执行步骤,通过配置硬件跟踪,使得硬件跟踪仅跟踪函数调用跳转跟踪块的执行。具体到上述插桩后的待测目标程序中,当执行上述插桩后的待测目标程序时,配置硬件跟踪仅限于地址区间401000~40101e即可。由此,当第三个函数被调用时,首先通过首地址400670的跳转指令跳转至函数调用跳转跟踪块内地址401014,然后执行函数调用跳转跟踪块内地址401014上的返回至第三个函数的跳转指令,当首地址401014上跳转指令被执行时,处理器硬件跟踪输出追踪数据;此后,程序返回地址400675执行插桩前的第三个函数所定义的程序指令集;当程序执行至地址400688时,通过首地址400688的函数调用指令,程序跳转至地址400520而进入第二个函数;进入第二个函数后,通过首地址400520的跳转指令跳转至至函数调用跳转跟踪块内地址40100a,然后执行函数调用跳转跟踪块内地址40100a上的返回至第二个函数的跳转指令,当首地址40100a上跳转指令被执行时,处理器硬件跟踪输出追踪数据;此后,程序返回地址400525执行插桩前的第二个函数所定义的程序指令集,执行至第二个函数出口前,通过首地址400554的跳转指令再跳转至函数调用跳转跟踪块内地址40100f,然后执行函数调用跳转跟踪块内地址40100f上的跳转指令返回第二个函数的地址400559,当首地址40100f上跳转指令被执行时,处理器硬件跟踪输出追踪数据;返回第二个函数后通过400559的函数返回指令返回第三个函数,以此反复,直到程序执行结束。也就是说,通过上述程序插桩,构建函数调用跳转跟踪块,使得待测目标程序的各目标函数的入口和出口跳转至函数调用跳转跟踪块内再返回;然后在执行插桩程序时,配置硬件跟踪,使得硬件跟踪仅跟踪函数调用跳转跟踪块的执行;由此即可通过处理器硬件追踪跟踪函数的调用过程,比如上述图2示例的插桩程序,处理器硬件追踪输出的跟踪数据对应的跳转指令序列为:jmp 400675,jmp 400525,jmp 400559,jmp 4004d5,jmp 40050f,jmp 400525,jmp 400559,jmp 4006c5,这些跳转指令对应函数调用过
程:进入第三个函数,进入第二个函数,第二个函数结束返回,进入第一个函数,第一个函数结束返回,进入第二个函数,第二个函数结束返回,第三个函数结束返回。
23.图2示例中,待测目标程序为机器指令所组成的可执行代码,步骤s2的插桩直接基于可执行代码的插桩,对本领域技术人员而言,实现上述插桩并不困难。但基于可执行代码的插桩存在,插入指令后其他各个指令的地址以及指令所需涉及地址的参数均需要进行相应的匹配修改。比如图2示例中,第一个函数原始的地址区间范围为:4004d0~400506;第二个函数原始的地址区间范围为:400516~400546;第三个函数原始的地址区间范围为:40065c~4006a8;各函数插入跳转指令后,各个函数的入口地址和出口地址发生变化,由此带来的函数调用指令比如,图2示例中地址400688,400698以及4006a8函数调用的地址参数需要进行适配性地修改。显而易地,这种地址即指令的地址参数的匹配性修改复杂且容易出错。为此,本领域技术人员理解,可以将上述针对可执行代码的插桩修改为对源代码程序的插桩或者对中间代码程序的插桩。
24.对源代码程度的插桩意味着本发明所输入的待测目标程序为源程序。比如下述c语言撰写的源程序如下:intfuna(inta,intb){intk=(a*(a-1))+b;returnk;}intfuncb(inta){returna/2;}intmain(){inta=funb(6)a=funa(a,2)a=funb(a)return0;}插桩后的源代码如下:001voidtracefunction(intssid)002{003switch(ssid)004{005case0:006__asm{jmptracestart}007break;008case1:009__asm{jmptraces1}
010break;011case2:012__asm{jmptraces2}013break;014case3:015__asm{jmptraces3}016break;017case4:018__asm{jmptraces4}019break;020case5:021__asm{jmptraces5}022break;023case6:024__asm{jmptraces6}025break;026default:027__asm{jmptraceend}028break;029}030__asm031{032tracestart:033traces1:jmptraced1034traces2:jmptraced2035traces3:jmptraced3036traces4:jmptraced4037traces5:jmptraced5038traces6:jmptraced6039traceend:040traced1:jmpend041traced2:jmpend042traced3:jmpend043traced4:jmpend044traced5:jmpend045traced6:jmpend046end:047}048}
049intfuna(inta,intb)050{051tracefunction(1);052intt=(a*(a-1))+b;053tracefunction(2);054returnt;055}056intfuncb(inta)057{058tracefunction(3);059intt=a/2;060tracefunction(4);061returnt;062}063intmain(){064tracefunction(5);065inta=funb(6)066a=funa(a,2)067a=funb(a)068tracefunction(6);069return0;070}上述插桩后的源代码中,tracefunction(1),tracefunction(2),tracefunction(3),tracefunction(4),tracefunction(5),tracefunction(6)为插桩后插入至函数的函数调用指令;函数tracefunction为插桩后插入的程序;函数调用跳转跟踪块为所插桩函数tracefunction中所定义的区间:tracestart至traceend的范围。根据函数tracefunction的定义,当原函数funa,funb,main被调用或者离开函数时,将分别执行tracestart至traceend的范围定义的各个跳转指令:当jmptraced1被执行时,表示进入函数funa,当jmptraced2被执行时,表示离开函数funa,当jmptraced3被执行时,表示进入函数funb,当jmptraced4被执行时,表示离开函数funb,当jmptraced5被执行时,表示进入函数main,当jmptraced6被执行时,表示离开函数main。
25.显而易见地,上述在源代码级别上的插桩在形式上与前述在可执行代码级别的插桩虽然有所不同,但两者实质相同。
26.此外,显而易见地,上述源代码层面上的插桩,在函数中直接插入汇编的跳转指令需要编程语言和编译器的支持。对于此类情形,本领域技术人员理解,也可以在中间代码层面上实现插桩。中间代码层面上的插桩要求输入的待测目标程序为源代码程序,此时上述
程序插桩步骤可以分解为以下步骤:步骤s21,用于:将待测目标程序编译成中间代码;步骤s22,用于:对中间代码进行插桩形成插桩后的中间代码;函数调用跳转跟踪块为中间代码指令块;步骤s23,用于:对插桩后的中间代码进行编译,生成插桩后的可执行代码,然后分析所述函数调用跳转跟踪块的地址范围。
27.比如,前述示例的c语言代码撰写的源程序通过llvm编译器编译后可以得到如下中间代码:definedso_locali32@funa(i32noundef%0,i32noundef%1)#0{%3=allocai32,align4%4=allocai32,align4%5=allocai32,align4storei32%0,i32*%3,align4storei32%1,i32*%4,align4%6=loadi32,i32*%3,align4%7=loadi32,i32*%3,align4%8=subnswi32%7,1%9=mulnswi32%6,%8%10=loadi32,i32*%4,align4%11=addnswi32%9,%10storei32%11,i32*%5,align4%12=loadi32,i32*%5,align4reti32%12}definedso_locali32@funb(i32noundef%0)#0{%2=allocai32,align4storei32%0,i32*%2,align4%3=loadi32,i32*%2,align4%4=sdivi32%3,2reti32%4}definedso_locali32@main()#0{%1=allocai32,align4%2=allocai32,align4storei320,i32*%1,align4%3=calli32@funb(i32noundef6)storei32%3,i32*%2,align4%4=loadi32,i32*%2,align4%5=calli32@funa(i32noundef%4,i32noundef2)
store i32 %5, i32* %2, align 4%6 = load i32, i32* %2, align 4%7 = call i32 @funb(i32 noundef %6)store i32 %7, i32* %2, align 4ret i32 0}对上述中间代码插桩后可以得到以下插桩后的中间代码程序:001define dso_local i32 @funa(i32 noundef %0, i32 noundef %1) #0 {002call void @"__main.c_@_funa_entry_stub__"()003%3 = alloca i32, align 4004%4 = alloca i32, align 4005%5 = alloca i32, align 4006store i32 %0, i32* %3, align 4007store i32 %1, i32* %4, align 4008%6 = load i32, i32* %3, align 4009%7 = load i32, i32* %3, align 4010%8 = sub nsw i32 %7, 1011%9 = mul nsw i32 %6, %8012%10 = load i32, i32* %4, align 4013%11 = add nsw i32 %9, %10014store i32 %11, i32* %5, align 4015%12 = load i32, i32* %5, align 4016call void @"__main.c_@_funa_exit_stub_0__"()017ret i32 %12018}019define dso_local i32 @funb(i32 noundef %0) #0 {020call void @"__main.c_@_funb_entry_stub__"()021%2 = alloca i32, align 4022store i32 %0, i32* %2, align 4023%3 = load i32, i32* %2, align 4024%4 = sdiv i32 %3, 2025call void @"__main.c_@_funb_exit_stub_0__"()026ret i32 %4027}028define dso_local i32 @main() #0 {029call void @"__main.c_@_main_entry_stub__"()030%1 = alloca i32, align 4033%2 = alloca i32, align 4034store i32 0, i32* %1, align 4
035%3=calli32@funb(i32noundef6)036storei32%3,i32*%2,align4037%4=loadi32,i32*%2,align4038%5=calli32@funa(i32noundef%4,i32noundef2)039storei32%5,i32*%2,align4040%6=loadi32,i32*%2,align4041%7=calli32@funb(i32noundef%6)042storei32%7,i32*%2,align4043callvoid@"__main.c_@_main_exit_stub_0__"()044reti320045}046definevoid@"__main.c_@_funa_entry_stub__"()#1section".entry_exit_stub"{047retvoid048}049definevoid@"__main.c_@_funa_exit_stub_0__"()#1section".entry_exit_stub"{050retvoid051}052definevoid@"__main.c_@_funb_entry_stub__"()#1section".entry_exit_stub"{053retvoid054}055definevoid@"__main.c_@_funb_exit_stub_0__"()#1section".entry_exit_stub"{056retvoid057}058definevoid@"__main.c_@_main_entry_stub__"()#1section".entry_exit_stub"{059retvoid060}061definevoid@"__main.c_@_main_exit_stub_0__"()#1section".entry_exit_stub"{062retvoid063}上述插桩生成的中间代码中,第002、016、020、025、029、043行中的call指令为插入至目标函数内的跳转指令;第046行至第063行所定义的区间为函数调用跳转跟踪块。第046行至第063行所定义的函数调用跳转跟踪块中定义了6个函数,分别与第002、016、020、025、029、043行中的call指令相对应,并对应源程序中三个函数的入口和出口。第046行至
第063行所定义的函数调用跳转跟踪块中定义了6个函数都定义在".entry_exit_stub"程序段中。上述插桩代码经编译器编译后即可生成如图2所示的可执行目标程序,其中,第046行至第063行所定义的".entry_exit_stub"程序段中的6个函数的返回指令被编译成图2左侧虚线框内的6个jmp跳转指令。第002、016、020、025、029、043行中的call指令同样被编译成相应的jmp跳转指令。
28.显而易见地,本发明的方法之下,处理器硬件追踪跳过了函数内部的各种跳转指令,从而可以大大减少硬件追踪输出的数据量,从而使得硬件追踪产生的速度能够跟上追踪数据存储的速度,减少存储数据的丢失。
29.另一方面,本发明的方法通常应用于程序测试中,故此,实际执行待测目标程序时,通常需要测试用例,故此,步骤s1中获取待测目标程序时,通常还包括获取其对应的测试用例。
30.此外,根据本发明的上述方法,对待测目标程序的函数调用进行硬件追踪时,未必需要对待测目标程序中所有的函数调用都进行硬件追踪,故此,步骤s1获取目标程序时,还可以获取目标函数列表。由此在插桩时,仅对目标函数列表所列的目标函数进行插桩,由此,使得硬件追踪时,仅对目标函数列表所列的目标函数进行跟踪。
31.此外,本发明所指的装置与前述方法相对应的虚装置,其包含的模块是与方法对应的步骤,不再赘述。

技术特征:
1.一种基于硬件的程序动态函数调用序列追踪方法,其特征在于,包括如下步骤:步骤s1,用于:获取待测目标程序;步骤s2,用于:对所述待测目标程序进行插桩形成插桩程序,通过插桩构建函数调用跳转跟踪块,使得所述待测目标程序的各目标函数的入口和出口跳转至所述函数调用跳转跟踪块内再返回;所述函数调用跳转跟踪块全部由跳转指令所组成;步骤s3,用于:执行插桩程序时,配置硬件跟踪,使得硬件跟踪仅跟踪所述函数调用跳转跟踪块的执行;步骤s4,用于:根据执行插桩程序跟踪所输出的追踪数据,分析所述待测目标程序的函数调用关系。2.如权利要求1所述的基于硬件的程序动态函数调用序列追踪方法,其特征在于,所述待测目标程序为可执行代码。3.如权利要求1所述的基于硬件的程序动态函数调用序列追踪方法,其特征在于,所述待测目标程序为源代码程序;所述步骤s2插桩所形成的插桩程序为源代码程序;所述函数调用跳转跟踪块为插桩所形成的一个函数内的跳转指令块;所述步骤s2还包括将插桩所形成的插桩程序编译成插桩后的可执行代码,然后分析所述函数调用跳转跟踪块的地址范围;所述步骤s3中,执行插桩程序时,为执行编译而成的插桩后的可执行代码。4.如权利要求1所述的基于硬件的程序动态函数调用序列追踪方法,其特征在于,所述待测目标程序为源代码程序;所述步骤s2包括如下步骤:步骤s21,用于:将所述待测目标程序编译成中间代码;步骤s22,用于:对所述中间代码进行插桩形成插桩后的中间代码;所述函数调用跳转跟踪块为中间代码指令块;步骤s23,用于:对插桩后的中间代码进行编译,生成插桩后的可执行代码,然后分析所述函数调用跳转跟踪块的地址范围。5.一种基于硬件的程序动态函数调用序列追踪装置,其特征在于,包括如下模块:模块m1,用于:获取待测目标程序;模块m2,用于:对所述待测目标程序进行插桩形成插桩程序,通过插桩构建函数调用跳转跟踪块,使得所述待测目标程序的各目标函数的入口和出口跳转至所述函数调用跳转跟踪块内再返回;所述函数调用跳转跟踪块全部由跳转指令所组成;模块m3,用于:执行插桩程序时,配置硬件跟踪,使得硬件跟踪仅跟踪所述函数调用跳转跟踪块的执行;模块m4,用于:根据执行插桩程序跟踪所输出的追踪数据,分析所述待测目标程序的函数调用关系。6.如权利要求5所述的基于硬件的程序动态函数调用序列追踪装置,其特征在于,所述待测目标程序为可执行代码。7.如权利要求5所述的基于硬件的程序动态函数调用序列追踪装置,其特征在于,所述待测目标程序为源代码程序;所述模块m2插桩所形成的插桩程序为源代码程序;所述函数调用跳转跟踪块为插桩所形成的一个函数内的跳转指令块;所述模块m2还包括将插桩所形成的插桩程序编译成插桩后的可执行目标程序,然后分析所述函数调用跳转跟踪块的地址范围;所述模块m3中,执行插桩程序时,为执行编译而成的插桩后的可执行目标程序。
8.如权利要求5所述的基于硬件的程序动态函数调用序列追踪装置,其特征在于,所述待测目标程序为源代码程序;所述模块m2包括如下模块:模块m21,用于:将所述待测目标程序编译成中间代码;模块m22,用于:对所述中间代码进行插桩形成插桩后的中间代码;所述函数调用跳转跟踪块为中间代码指令块;模块m23,用于:对插桩后的中间代码进行编译,生成插桩后的可执行目标程序,然后分析所述函数调用跳转跟踪块的地址范围。

技术总结
本发明公开了一种基于硬件的程序动态函数调用序列追踪方法和装置。该方法在执行硬件跟踪前对目标程序进行插桩形成插桩程序,通过插桩构建函数调用跳转跟踪块,使得目标程序的各目标函数的入口和出口跳转至函数调用跳转跟踪块内再返回,然后在执行硬件跟踪时,仅对函数调用跳转跟踪块的程序块进行跟踪,由此,根据硬件跟踪所输出的追踪数据即可分析出目标程序执行的函数调用关系和调用序列。本发明通过将追踪粒度由原始的程序基本块扩大至函数,从而降低处理器硬件追踪所产生的追踪数据的速度,使得所产生的追踪数据能够与追踪数据存储的速度匹配,减少追踪数据的丢失。减少追踪数据的丢失。减少追踪数据的丢失。


技术研发人员:左志强 戚赟 李宣东
受保护的技术使用者:南京大学
技术研发日:2022.07.21
技术公布日:2022/11/1
转载请注明原文地址: https://tieba.8miu.com/read-3288.html

最新回复(0)