上学期间研究了下软件执行网络的动态拓扑特性,实验了一些在函数粒度上可行的网络构造方法,这里总结下,感觉对分析开源软件代码有一定帮助。废话不多说,主要分为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”安装项目。其中CFLAGS和LDFLAGLS分别是编译和链接标志,它们都需要加入-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函数分别调用了a和c函数。由于例子中的函数只是简单地输出一个字符串,所以每个函数的消耗时间都是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等
- 大小: 21.3 KB
- 大小: 3.8 KB
- 大小: 10.5 KB
- 大小: 4.7 KB
- 大小: 40.6 KB
- 大小: 52.8 KB
分享到:
相关推荐
总之,`cpp-ftrace`是利用`ftrace`功能来对C++程序进行函数调用追踪的一种方法,它可以帮助开发者深入了解程序的执行流程,定位性能瓶颈,或用于系统级别的调试。正确地使用`cpp-ftrace`,可以显著提升软件开发和...
通过遍历这个堆栈,我们可以逆序地查看函数调用的顺序,从而得知哪些函数调用了目标函数。 在C++中,实现堆栈追踪通常有两种方法: 1. **利用编译器支持**:一些编译器如GCC和Visual C++提供了内置的函数来获取...
函数调用关系图是一种图形表示法,它以节点代表函数,边则表示函数间的调用关系。这种图可以帮助我们识别函数的依赖性,理解控制流程,尤其是在大型复杂项目中,这样的可视化工具尤为重要。通过这种方式,开发者可以...
在Android开发中,理解应用程序的函数调用图(Call Graph)至关重要,因为它揭示了程序内部各个组件、方法间的相互作用。通过生成函数调用图,开发者可以更深入地洞察代码的执行流程,从而发现潜在的安全漏洞、性能...
【标题】:“方法调用序列追踪工具” 在软件开发中,理解程序的运行流程和方法间的调用关系是至关重要的,特别是在调试、性能优化和问题定位时。"方法调用序列追踪工具"就是为了帮助开发者实现这一目标而设计的。这...
在Android开发中,理解函数调用顺序和各个函数的执行时间是优化应用性能的关键步骤。一个非侵入式的Android库可以提供这样的功能,无需修改原始代码就能追踪到这些信息,这对于开发者来说是一大福音。这样的工具通常...
通过对上述C语言源代码的反汇编分析,我们不仅了解了函数调用的一般流程,还学习了如何在汇编级别上追踪函数调用的具体细节。这种能力对于理解和分析二进制程序至关重要,尤其是在安全领域中进行漏洞挖掘或恶意软件...
这个框架不仅能够生成函数调用图,还能提供可视化的界面,方便研究人员探索和追踪调用关系。此外,它还可能包含自动化检测机制,能够自动发现潜在的不安全调用模式或者异常行为。 总的来说,这个分析框架为Android...
标题 "Babel插件用于带任何函数调用" 指的是在JavaScript开发过程中,使用Babel这个转换工具时,特定的插件可以处理带有任意函数调用的代码。Babel是一个广泛使用的JavaScript编译器,它允许开发者使用最新版本的...
这种方法能够实时地追踪内核中的函数调用链路,从而帮助开发者更好地理解内核的执行流程和性能瓶颈。 1. 动态监视技术 动态监视工具,如SystemTap、Kprobes或Ftrace,允许用户在内核运行时插入探针,捕获特定事件...
在编程领域,递归函数是一种强大的工具...总的来说,理解和计算递归函数调用次数是编程中的重要技能,它涉及到算法分析、性能优化和问题解决策略等多个方面。通过熟练掌握递归,程序员能更好地应对各种复杂的编程挑战。
Linux C用户态调试追踪函数调用堆栈以及定位段错误是指在 Linux 平台上使用 C 语言编写的程序中,如何追踪函数调用堆栈并定位段错误的方法。 在 Linux 平台上,使用 GDB 调试器是最常用的方法来追踪函数调用堆栈。...
收集一个函数调用的踪迹,一种方法是通过在函数的入口处和出口处插入一个打印语句来检测。这个过程非常繁琐,而且很容易出错,通常需要对源代码进行大量的修改。 幸运的是,GNU 编译器工具链(也称为 gcc)提供了一...
函数调用堆栈(也称为调用栈或执行栈)记录了程序中函数调用的顺序,这对于追踪代码执行流程,特别是错误定位非常有用。在x86架构的处理器上,通常使用两个寄存器——EBP(扩展基址寄存器)和EIP(指令指针寄存器)...
对于分布式追踪,主要有以下的几个概念: 追踪 Trace:就是由分布的微服务协作所支撑的一个事务。一个追踪,包含为该事务提供服务的各个服务请求。...我实现了一种简单的调用追踪。 import uuid impo
在PHP编程语言中,动态调用函数是一种高级技术,允许开发者在程序运行时根据实际情况来决定调用哪个函数...上述的代码实例也已经表明了动态函数调用实现的简洁性和直接性,这在很多场景下都能提供非常便利的编程支持。
标题中的“Android-一个能让你了解所有函数调用顺序的Android库无需侵入式代码”指的是一种在Android开发中用于追踪和理解函数调用顺序的技术或库。这个库的独特之处在于它允许开发者无须修改应用程序的源代码,即...
总之,C#中获取调用函数的参数名称主要依赖于反射机制,通过`StackTrace`、`StackFrame`和`MethodBase`来追踪和解析调用信息。然而,获取参数值通常需要更复杂的策略,如使用AOP或对代码进行特殊处理。在实际开发中...
在编程领域,有时候我们需要追踪和记录某个函数在程序运行过程中的调用次数,这有助于我们理解和优化代码...在实际开发中,根据项目的具体需求和所使用的语言特性,选择最适合的方法来实现函数调用计数是非常重要的。