博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
开源代码分析技巧之——打印调用逻辑
阅读量:6916 次
发布时间:2019-06-27

本文共 1834 字,大约阅读时间需要 6 分钟。

 

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

 

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

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

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

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

 

        1、从SAMBA源码说起

 

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

       

 

       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:\tmp\samba4.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下的换行符为\r\n,而Linux下的换行符为\n;第二,函数的书写不同比如如下的格式:格式一、格式二都很常用,都应该考虑。

      格式一:

void function( ){}

     格式二:

void function( ){}

 

        5结语

 

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

 

         2013/10/13 am9:55思于家中床前

 

你可能感兴趣的文章
设计模式之状态模式
查看>>
消息中间件(3)-ActiveMQ消息持久化
查看>>
URL Rewrite初认识
查看>>
springboot(六):如何优雅的使用mybatis
查看>>
Spring 3中PropertySourcesPlaceholderConfigurer 的...
查看>>
Python中os和shutil模块实用方法集锦
查看>>
理解Scala的Symbol类型
查看>>
java 日期操作
查看>>
JVM内存区域(基于jdk1.7)
查看>>
float和double运算过程会失去精度,BigDecimal适用于商业计算
查看>>
maven实现依赖的“全局排除”
查看>>
如何快速入门Python
查看>>
New的执行过程
查看>>
prometheus服务发现-不同场景下的service注册参数
查看>>
仿OpenStack开发云计算管理软件”--第1周:熟悉开发环境
查看>>
使用 RandomStringUtils 类来生成随机码/随机数
查看>>
js中怪异的this 指针
查看>>
改变Jsp文件后缀
查看>>
VisualSVN Server+Trac集成安装(图文版)
查看>>
Ubuntu下解决拯救者笔记本无法使用无线网卡
查看>>