开源代码分析技巧之一——打印调用逻辑

简介: 打印调用逻辑源码分析技巧

前言

在研究开源代码时,大家或许都有这样的感慨:

(1)代码太庞大,少则几万行代码,多则几百万行代码,不知道如何入手

(2)相关的帮助文档有限,很难短时间内理清头绪

(3)有了代码在手,但代码之间的调用相当复杂,一层一层追踪总是理不清调用逻辑顺序。

1、从SAMBA源码说起

笔者在研究kerberos认证时,需要开源的samba软件。如下是samba的官网:http://www.samba.org/

image.png

Samba最新版本为4.1.10,统计得出其中.c及.cpp的文件有近4000个,累计代码近百万行。所以对其的全面分析有一定难度。当然,我们可以根据所需,缩小范围,从指定所需的指令对应的代码追溯代码调用逻辑。

2、给源码插入“调用逻辑线索”代码

即便如此,有时还是想直观看下某个模块的调用顺序,能不能直观的打印出来?而如何打印调用逻辑呢?如果每个函数的头部都加上:文件名、函数名、行号的打印语句,这样不就解决了我们的问题了吧。

而编译器里内置了宏,如下几个编译器内置的宏定义,这些宏定义不仅可以帮助我们完成跨平台的源码编写,灵活使用也可以巧妙地帮我们输出非常有用的调试信息。

ANSI C标准中有几个标准预定义宏(也是常用的):

     __LINE__:在源代码中插入当前源代码行号;
 
     __FILE__:在源文件中插入当前源文件名;
 
     __DATE__:在源文件中插入当前的编译日期
 
     __TIME__:在源文件中插入当前编译时间;
 
     __STDC__:当要求程序严格遵循ANSI C标准时该标识被赋值为1;
 
     __cplusplus__:当编写C++程序时该标识符被定义;
 
     __FUNCTION__:在源文件中插入函数名。

编译器在进行源码编译的时候,会自动将这些宏替换为相应内容。

于是,printf(“File: %s, Function: %s, Line: %s.\n”, __FILE__, __FUNCTION__, __LINE__);这个C的语句就是我们所需的。

于是,问题就有所转嫁:给指定文件夹下的所有.c及.cpp文件下的所有函数的第一行插入“printf(“File: %s, Function: %s, Line: %s.n”, __FILE__, __FUNCTION__, __LINE__);”标记打印语句(以下统称)。

 

3、思路分析

完成任务:给指定文件夹下的所有.c及.cpp文件下的所有函数的首行插入指定代码。

输入:包含源码的文件夹路径名,如:存储samba源码的路径名——C:tmpsamba4.0.9。

中间处理:遍历、处理、添加标记打印语句。

输出:无。

任务分解如下:

Step1:遍历指定文件夹及其所有子文件夹,将所有文件路径存入容器vector_all_dir;

Step2:遍历容器vector_all_dir,将后缀为.c及.cpp的文件存入容器vector_ctype_dir;

Step3:遍历容器vector_ctype_dir的每一个路径,打开路径对应的每个文件—>读取文件内容存入buffer-->清空原有文件内容;

Step4:读取buffer的内容,循环遍历buffer,找到函数头开始的标记“)\n{”,并记录其对应位置position,在poisition+strlen(“)\n{”)后插入标记打印语句。这样就生成了新的buffer——buffer_after_newadd;

Step5:将新的添加标记打印语句的buffer_after_newadd重新写入源路径,关闭文件。

笔者已经完毕代码,在samba4.0.9测试,能够实现预想的调用顺序逻辑打印。

 

4、尚待改进点

(1)读取buffer部分是按照字符串处理,并且是废弃以前的文件,将添加标记打印语句的新buffer写入文件的方法。效率较低,有待改进。

(2)以“)\n{”判定函数不具有一般性。第一,Windows下的换行符为rn,而Linux下的换行符为n;第二,函数的书写不同比如如下的格式:格式一、格式二都很常用,都应该考虑。

格式一:

void function( )
{
 
}

格式二:

void function( ){
}

5、结语

权当是分析开源的小技巧吧,确实对自己分析开源软件提供了帮助。后续有了新的心得,会持续分享。

推荐阅读:

【2】开源代码分析技巧之二——gdb单步调试

http://blog.csdn.net/laoyang360/article/details/14102181

【3】开源代码分析技巧之三——老外如是说

http://blog.csdn.net/laoyang360/article/details/16897117

【4】开源代码分析技巧之四——国外技术社区提问

http://blog.csdn.net/laoyang360/article/details/16897827

【5】开源代码分析技巧之四——高效Windows源码分析

http://blog.csdn.net/laoyang360/article/details/18186529


作者:铭毅天下
转载请标明出处,原文地址:http://blog.csdn.net/laoyang360/article/details/12676131

相关文章
|
6月前
|
存储 算法 Swift
Swift开发——循环执行方式
Swift语言中的循环主要包括`for-in`和`while`结构。`for-in`适用于遍历数字区间、字符串和字典,支持使用`stride`函数定制步进。字典遍历时,可以用二元元组`(k, v)`访问键值对。`while`循环有标准形式和`repeat-while`形式,确保至少执行一次循环体。程序示例展示了`for-in`和不同`while`结构的用法,包括计算阶乘、奇数和、加密字符串以及最大公约数和最小公倍数。
42 0
Swift开发——循环执行方式
|
开发工具
游戏开发实战教程(5):重复执行和逻辑循环的区别
将循环分为重复执行和逻辑循环,应该是微信小游戏开发工具中所特有的。因为之前做游戏,无论是使用哪种工具或者哪种编程语言,对于循环来说,都只有一种,不会存在歧义或者误用。但是这里将循环分为了两种,如果误用的话会导致出现一些奇怪的问题。所以需要单独拿出来区分一下,避免掉进这个“坑”。
157 0
|
开发工具
微信小游戏开发实战5-重复执行和逻辑循环的区别
本篇主要内容包括了解帧的概念,以及理解重复执行和逻辑循环这两种循环积木块之间的区别。 如果你没有任何的游戏开发经验,欢迎阅读我的“人人都能做游戏”系列教程,它会手把手的教你做出自己的第一个小游戏。
116 0
|
芯片
查询方式的按键驱动程序
查询方式的按键驱动程序
141 0
|
小程序 开发工具 开发者
【小程序】第一个小程序——创建小程序项目
【小程序】第一个小程序——创建小程序项目
145 0
【小程序】第一个小程序——创建小程序项目
|
C#
C# 判断当前控制台程序是否重复运行
C# 判断当前控制台程序是否重复运行
174 0
|
前端开发
前端hook项目pc总结笔记-打印实现局部打印
前端hook项目pc总结笔记-打印实现局部打印
96 0
|
API 开发工具 芯片
扩展知识---中断程序的实现
扩展知识---中断程序的实现
114 1
|
Java Maven
编写一个 spootboot 程序,有二个方法,一个问早上好,一个说再见
编写一个 spootboot 程序,有二个方法,一个问早上好,一个说再见
|
存储 编译器 C语言
Win知识 - 程序是怎样跑起来的——函数调用机制
Win知识 - 程序是怎样跑起来的——函数调用机制
111 0
Win知识 - 程序是怎样跑起来的——函数调用机制