`
luoshi0801
  • 浏览: 146078 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

动态函数调用追踪方法

阅读更多

 

 

上学期间研究了下软件执行网络的动态拓扑特性,实验了一些在函数粒度上可行的网络构造方法,这里总结下,感觉对分析开源软件代码有一定帮助。废话不多说,主要分为c/c++和java两种:

(1) 基于Gnu/Gprof运行时剖析工具

Gnu/Gprof是类Unix平台下对c/c++开源项目的一个profile分析工具,它能在程序运行过程中记录下函数间的调用关系,每个函数被调用的次数,每个函数消耗的时间等代码级信息。它的实现原理是通过编译和链接源程序的时候在gcc编译器的命令行参数中加入“-pg”调试选项,gcc编译器就会在程序的每个函数中加入一个名为“mcout(或“_mcount”,依赖于编译器或操作系统)的函数,该函数在内存中保存了一张函数调用图,可利用函数调用堆栈的形式查找子函数和父函数的地址,从而获得函数间的调用关系,以及每个函数调用次数、运行时间等信息。

下面给出一个小例子,说明如何利用Gnu/Gprof工具追踪程序运行过程中的函数调用,源程序文件名为test.c,其内容如下。


 【步骤1】使用gcc编译器的-pg选项对源程序进行编译和链接,输入如下命令:


 其中test.c文件存放在路径为/home/test,运行命令后会在该路径下生成一个默认名为“a.out”的可执行文件,当然也可以利用-o选项指定可执行文件的名字。本例的调试编译如上所示很简单,但对包含成千上万个源文件的大型开源项目进行编译时会相对复杂一些。首先需要进入项目主文件输入“./configure”命令进行编译配置检查,然后输入“make CFLAGS=-pg LDFLAGS=-pg”进行编译,最后还要输入“make install”安装项目。其中CFLAGSLDFLAGLS分别是编译和链接标志,它们都需要加入-pg选项,否则有可能无法追踪成功。

【步骤2】执行程序,使之生成一个名为“gmon.out”的二进制数据文件,输入如下命令:


 除上述运行结果外,还会在当前目录中生成一个名为“gmon.out”的文件。

【步骤3】使用gprof工具对步骤2中生成的数据文件进行分析,输入如下命令:


 

执行后会在控制台输出分析结果,下面是从中摘抄的一些详细信息。


 Gprof产生的字段信息解释如下所示:

 

字段

含义

时间统计信息中信息

% time

函数消耗的时间占所有时间的百分比

cumulative seconds

函数累计执行的时间(单位秒)

self seconds

函数本身所执行的时间(单位秒)

calls

函数被调用的次数

self Ts/call

调用一次函数的平均时间(不包括调用的函数,单位毫秒)

total Ts/call

调用一次函数的平均时间(包括调用的函数,单位毫秒)

name

函数名

Call graph中信息

index

索引值

% time

函数消耗的时间占所有时间的百分比

self

函数本身所执行的时间

children

父函数调用子函数时所花费的时间或执行子函数花费的时间

called

调用次数

name

函数名

从输出能明显看出,main函数调用了b函数,而b函数分别调用了ac函数。由于例子中的函数只是简单地输出一个字符串,所以每个函数的消耗时间都是0

 (2) 基于AOP面向程序切面编程

AOP(Aspect-Oriented Programming,面向切面编程),是OOP(Object-Oriented Programming,面向对象编程)的补充和完善。OOP引入封装、继续和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当需要对分散对象引入公共行为时,OOP就显得无能为力。也就是说,OOP适合描述从上到下的关系而不适合描述从左到右的关系。例如日志功能,记录代码需要水平分散在所有对象中,而与各对象的核心功能无关,在OOP中这些散布的代码导致了大量的重复,不利于模块的重用。AOP则是该类问题的良好解决方案,它使用一种“横切”技术,剖开对象的内部,将那些影响多个类的公共行为封装到一个可重用模块,即“切面”(Aspect)。所谓“切面”,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,以减少系统的重复代码,降低模块间的耦合度,并有利于未来的操作和维护。AOP的典型应用还包括安全性控制、性能统计、事务和异常处理等。

 

AspectJ是一个扩展Java语言并实现了上述技术的AOP框架,它作为Eclipse的一个插件可编程实现对Java项目中函数调用的动态追踪。具体的方法是在开源项目中定义如下的“切面”。


 在自定义切面中,切入点匹配那些在“com.example”及其子包中的所有公共函数,但排除类“CallLogger”和切面自身中的。通知“before”封装了在每个匹配切入点的函数执行之前的逻辑处理,即将函数压入堆栈并记录下函数的调用关系。通知“after”则在匹配函数执行后进行简单的出栈处理。类“CallLogger”维护了记录函数调用的堆栈并实现了动态生成函数调用关系等操作,源码参见附件。

相对于动态追踪,还有针对函数静态关系的分析工具,如Cflow、CodeViz(依赖于GraphViz)、Doxygen等

 

 

 

  • CallLogger.rar (705 Bytes)
  • 描述: CallLogger源码
  • 下载次数: 34
  • 大小: 21.3 KB
  • 大小: 3.8 KB
  • 大小: 10.5 KB
  • 大小: 4.7 KB
  • 大小: 40.6 KB
  • 大小: 52.8 KB
0
2
分享到:
评论

相关推荐

    追踪谁调用了函数

    追踪谁调用了函数 堆栈追踪 StackWalk 追踪谁调用了函数 堆栈追踪 StackWalk

    cpp-ftrace简单函数调用示踪器

    ftrace - 简单函数调用示踪器

    方法调用序列追踪工具

    我的毕业设计,一个基于符号执行的方法调用序列追踪工具。

    gcc 函数调用探测功能

    收集一个函数调用的踪迹,一种方法是通过在函数的入口处和出口处插入一个打印语句来检测。这个过程非常繁琐,而且很容易出错,通常需要对源代码进行大量的修改。 幸运的是,GNU 编译器工具链(也称为 gcc)提供了一...

    Python函数调用追踪实现代码

    对于分布式追踪,主要有以下的几个概念: 追踪 Trace:就是由分布的微服务协作所支撑的一个事务。一个追踪,包含为该事务提供服务的各个服务请求。...我实现了一种简单的调用追踪。 import uuid impo

    linux C用户态调试追踪函数调用堆栈以及定位段错误.docx

    linux C用户态调试追踪函数调用堆栈以及定位段错误.docx

    Linux下追踪函数调用,打印栈帧

    也是是Pop出来的对象没有Push回去,情况很难复现,所以在Pop里的打印日志,跟踪是谁调用了它,我想在GDB调试里可以追踪调用的栈帧,那也一定有方法实现。首先上网搜索了一下,并没有结果!还好代码量不是很多,只能...

    构造函数和析构函数程序(c++)

    构造函数的调用可以追踪。。。。由于构造函数和析构函数都是自动吊桶的或者更不饿,我们可以自己设立函数来追踪构造函数的调用过称。

    PHP执行流程跟踪工具phptrace.zip

    其实,phptrace是类strace的一个实现,不同的是,strace用来追踪系统调用,而phptrace用来追踪PHP函数调用。无论是开发测试 还是线上追查问题,代码执行流程往往会提供许多有用的信息,大大提高了开发人员的工作...

    详解Linux驱动中,probe函数何时被调用

    以前搞PCI驱动时用pci驱动注册函数就可以调用它,搞s3c2410驱动时只要在mach-smdk2410.c中的struct platform_device *smdk2410_devices {}中加入设备也会调用。但从来就没有想过具体的驱动注册并调用probe的过程。 ...

    跟踪Swift和Objective-C方法调用-Swift开发

    SwiftTrace跟踪应用程序捆绑包或框架中非最终类的Swift和Objective-C方法调用。 考虑使用Xtrace,但要使用Swift和Objective-C。 您还可以将“方面”添加到非最终Swift类的成员函数中。t SwiftTrace跟踪应用程序捆绑...

    iOS逆向教程之跟踪函数调用详解

    主要给大家介绍了关于iOS逆向教程之跟踪函数调用的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。

    易语言纯汇编无DLL命令调用核心功能/找图/图像处理源码

    能达到免申明dll命令,直接调用,里面很多函数是基本跳过dll本身的函数入口,直接push参数call到驱动入口处(当初为了追踪这些dll特意用虚拟机windbg了xp系统大部分函数,有懂的可以去看看里面的 KiZwOpenProcess函数 ),...

    最短路径法弯曲射线追踪的MATLAB代码

    1、代码运行速度非常快,适合新手使用,可建立一些简单模型来进行数值模拟,也可用做其他程序的子函数调用,对认识曲射线追踪非常有帮助。 2、资源中给出了两个模型用以实例代码的用法,其中一个是包含空洞的高速...

    基于stm32和openmv的色块追踪云台+源代码+文档说明

    并通过调用pyb写入串口发送函数,将blob.cx和blob.cy实时发送至Stm32。 串口通信协议:串口通信协议采用的数据帧格式,即帧头、数据、校验位、帧尾。这样可以保证数据的准确性和效率性。由于数据可能大于8位,所以我...

    tstack:跟踪正在运行的程序的函数调用堆栈

    它记录正在运行的程序的指定断点的调用堆栈。 ##如何开始 只需使用tstack命令,如下所示: ./tstack $PID $BREAKPOINT 其中$ PID是程序的pid。 $ BREAKPOINT是要跟踪的点。 它可以是函数名称或代码位置,与gdb中...

    是一款针对 ARM Cortex-M 系列 MCU 的错误代码自动追踪、定位,错误原因自动分析的开源

    输出错误现场的 函数调用栈(需配合 addr2line 工具进行精确定位),还原发生错误时的现场信息,定位问题代码位置、逻辑更加快捷、精准。也可以在正常状态下使用该库,获取当前的函数调用栈;支持 裸机 及以下操作...

    基于C++与MATLAB混合编程的露头表面裂缝识别及矢量化方法.pdf

    调用MATLAB中的图像裂缝识别函数快速提取露头裂缝,同时采用一种改进的八邻域追踪算法实现裂缝线状要素的矢量化。实验结果表明,该方法将C++与MATLAB二者优势互补,兼顾了程序的开发效率与执行效率;改进的八邻域追踪...

    Java 零基础方法递归.md

    掌握如何编写递归函数和调用自身的方法。 理解递归终止条件的重要性。 学习通过递归计算阶乘等常见问题。 阅读建议: 阅读前建议已具备基本的Java语法知识和编程经验。 请按顺序阅读文档中的内容,从概念讲解到示例...

Global site tag (gtag.js) - Google Analytics