静态分析C语言生成函数调用关系的利器——GCC

大纲

  • 准备工作
  • GCC生成单文件调用关系VCG
  • 将VCG转为Dot
  • 绘制图片
  • 绘制全景图
  • 代码
  • 参考资料

在《静态分析C语言生成函数调用关系的利器——cally和egypt》中我们介绍了如何使用GCC生成RTL文件,然后再借助cally和egypt来分析出调用关系的方法。GCC自身有命令可以生成代码内部的调用关系,即-fcallgraph-info参数。

Makes the compiler output callgraph information for the program, on a per-object-file basis. The information is generated in the common VCG format.

gcc some.c -fcallgraph-info

它会生成后缀是ci的VCG格式文件。然后我们使用graph-easy将其转换为dot格式,最后使用graphviz将其绘制出来。
我们还是以libevent的为例。

准备工作

graph-easy 用于将vcg文件转换为dot格式

sudo apt install libgraph-easy-perl

因为脚本是Python写的,且会依赖第三方库,于是会使用《管理Python虚拟环境的脚本》介绍的工具构建一个虚拟环境并安装相应依赖。

source env.sh init
soure env.sh enter
source env.sh install pydot

GCC生成单文件调用关系VCG

gcc `find . -regextype posix-extended -regex '^./[^/]*\.c$' ! -name 'wepoll.c' ! -name 'win32select.c' ! -name 'evthread_win32.c' ! -name 'buffer_iocp.c' ! -name 'bufferevent_async.c' ! -name 'arc4random.c' ! -name 'event_iocp.c' ! -name 'bufferevent_mbedtls.c'` \
 ./test/test-time.c \
 -I./build/include/ -I./include -I./ \
 -L./build/lib/ -lcrypto -lssl \
 -DLITTLE_ENDIAN -D__clang__ \
 -UD_WIN32 -UDMBEDTLS_SSL_RENEGOTIATION \
 -fcallgraph-info

在这里插入图片描述

将VCG转为Dot

graph-easy a-test-time.ci --as_dot > a-test-time.dot

绘制图片

dot -Grankdir=LR -T png a-test-time.dot -o test_time.png  

在这里插入图片描述

绘制全景图

因为GCC生成VCG文件只是针对单个文件的,不能构成全景图。这个时候就需要我们自己手撸一点代码,让这些信息合并。

import pydot

class CallgraphInfoCombiner(object):
    def __init__(self, dot_folder, function_name, output_file) -> None:
        self._dot_folder = dot_folder
        self._funciont_name = function_name
        self._output_file = output_file
        self._callee = dict()
        self._graph = pydot.Dot("callgraph-info-combiner", graph_type="graph", bgcolor="white")
        pass
    
    def analyze(self, include_private=False):
        for file in os.listdir(self._dot_folder):
            self._read_dot(self._dot_folder + "/" + file)
            
        nodes_in_graph = set()
        if self._funciont_name in self._callee:
            self._add_node_and_edge(self._funciont_name, nodes_in_graph, include_private)
        self._graph.write_dot(self._output_file + ".dot")
        self._graph.write_png(self._output_file + ".png")
        
    def _add_node_and_edge(self, node_name, nodes_in_graph, include_private=False):
        if include_private and node_name.startswith('"') and node_name.endswith('"'):
            return
        
        if node_name not in nodes_in_graph:
            print("add node: " + node_name)
            self._graph.add_node(pydot.Node(node_name))
            nodes_in_graph.add(node_name)
            
        if node_name in self._callee:
            for callee in self._callee[node_name]:
                if include_private == False and callee.startswith('"') and callee.endswith('"'):
                    continue
        
                if callee not in nodes_in_graph:
                    self._add_node_and_edge(callee, nodes_in_graph, include_private)
                self._graph.add_edge(pydot.Edge(node_name, callee))
                print("add edge: " + node_name + " -> " + callee)
        
    
    def _read_dot(self, dot_file):
        graphs = pydot.graph_from_dot_file(dot_file)
        for graph in graphs:                    
            for edge in graph.get_edges():
                if edge.get_source() in self._callee:
                    self._callee[edge.get_source()].add(edge.get_destination())
                else:
                    self._callee[edge.get_source()] = {edge.get_destination()}

上面的代码会分析DOT文件,所以在使用前需要将VCG转换成DOT文件。

import os
import sys
import subprocess

class Vcg2Dot(object):
    def __init__(self, vcg_file, dot_file):
        self.vcg_file = vcg_file
        self.dot_file = dot_file

    def vcg_to_dot(self):
        print("graph-easy --input=" + self.vcg_file + " -as=dot --output=" + self.dot_file)
        subprocess.run("graph-easy --input=" + self.vcg_file + " -as=dot --output=" + self.dot_file, shell=True)
        
class VcgFiles2Dot(object):
    def __init__(self, vcg_folder, dot_folder):
        self.vcg_folder = vcg_folder
        self.dot_folder = dot_folder

    def vcg_to_dot(self):
        if not os.path.exists(self.dot_folder):
            os.makedirs(self.dot_folder)
        
        for file in os.listdir(self.vcg_folder):
            vcg_to_dot = Vcg2Dot(self.vcg_folder + file, self.dot_folder + file + ".dot")
            vcg_to_dot.vcg_to_dot()

然后我们只要针对这个脚本传vcg文件目录、起始函数和输出的文件名,即可整合出调用关系。

python callgraph-info-combiner.py ./sample/ci/ main libevent

在这里插入图片描述
局部图如下
在这里插入图片描述

代码

https://github.com/f304646673/tools/tree/main/callgraph-info-combiner

参考资料

  • https://gcc.gnu.org/onlinedocs/gcc/Developer-Options.html
  • https://pypi.org/project/pydot/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/347448.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

YOLOv7全网独家首发:Powerful-IoU更好、更快的收敛IoU,效果秒杀CIoU、GIoU等 | 2024年最新IoU

💡💡💡本文独家改进:Powerful-IoU更好、更快的收敛IoU,是一种结合了目标尺寸自适应惩罚因子和基于锚框质量的梯度调节函数的损失函数 💡💡💡MS COCO和PASCAL VOC数据集实现涨点 收录 YOLOv7原创自研 https://blog.csdn.net/m0_63774211/category_12511937.htm…

记一次SPI机制导致的BUG定位【不支持:http://javax.xml.XMLConstants/property/accessExternalDTD】

1、前因 今天在生产环境启用了某个功能,结果发现有个文件上传华为云OBS失败了,报错如下: Caused by: java.lang.IllegalArgumentException: 不支持:http://javax.xml.XMLConstants/property/accessExternalDTDat org.apache.xal…

js中的内置对象、数学对象、日期对象、数组对象、字符串对象

js中的对象(三种): 自定义对象 car、computer DOM对象 div、p BOM对象 window、console 内置对象 数学对象 Math (object类型) 1、圆周率 Math.PI 2、向下取整(返回值) Math.floor() 3、向上取整(返回值) M…

实现自己的mini-react

实现自己的mini-react 创建运行环境实现最简单mini-react渲染dom封装创建虚拟dom节点封装函数封装render函数对齐react 调用方式使用 jsx 任务调度器&fiber架构封装一个workLoop方法 统一提交&实现 function component统一提交实现支持 function component 进军 vdom 的…

6轴机器人运动正解-逆解控制【1】——三种控制位姿的方式

概览: 通过运动学正解控制机器人运动通过运动学逆解控制机器人运动一个简单的物体搬运(沿轨迹运动) 后续会陆续更新(本例仅供学习交流用) 一、6轴机器人 二、运动正解控制 通过修改各个轴的角度,实现末…

目标检测数据集 - 人脑肿瘤检测数据集下载「包含VOC、COCO、YOLO三种格式」

数据集介绍:人脑肿瘤检测数据集,真实 CT 场景高质量图片数据,涉及人脑 CT 图片数据集丰富;适用实际项目应用:CT 图片场景下人脑肿瘤检测项目,以及作为通用人脑检测数据集场景数据的补充;标注说明…

Linux 一键部署influxd2-telegraf 二进制方式

influxd2前言 influxd2 是 InfluxDB 2.x 版本的后台进程,是一个开源的时序数据库平台,用于存储、查询和可视化时间序列数据。它提供了一个强大的查询语言和 API,可以快速而轻松地处理大量的高性能时序数据。 telegraf 是一个开源的代理程序,它可以收集、处理和传输各种不…

数据分析 - python 数据处理

数据处理 去除重复数据 # 删除重复值 保留重复行 第一行的数据 data.drop_duplicates(inplaceTrue, keepfirst)数据格式转化 日期格式化 data[order_date] pd.to_datetime(data[order_dt], format%Y%m%d)data[销售时间] pd.to_datetime(data[销售时间]) # 交货时间 销售…

JS进阶-深入面向对象(三)

看文章可以得到的收获: 1.在日常开发中,我们在声明一个数组对象后,没有声明有map,filter等方法,为什么可以调用这些方法呢? 2. 什么是面向过程思想,什么是面向对象思想呢? 3.JS中…

算法基础之线段树

文章目录 线段树 线段树 线段树的原理十分简单,但是在代码上会相对复杂一点 他也是用来维护一个序列,是一个完全二叉树的形状 对于每一个节点是一个结构体 struct Node {int L,R; int sum; // 以和为例 };假设序列为1到7,那么根节点存的…

EasyCVR视频融合平台雪亮工程视频智能监控方案设计与应用

随着科技的不断发展,视频监控已经成为城市安全防范的重要手段之一。为了提高城市安全防范水平,各地纷纷开展“雪亮工程”,即利用视频智能监控技术,实现对城市各个角落的全方位、全天候监控。本文将介绍一种雪亮工程视频智能监控方…

Windows本地如何部署Jupyter+Notebook并结合内网穿透实现远程访问?

文章目录 1.前言2.Jupyter Notebook的安装2.1 Jupyter Notebook下载安装2.2 Jupyter Notebook的配置2.3 Cpolar下载安装 3.Cpolar端口设置3.1 Cpolar云端设置3.2.Cpolar本地设置 4.公网访问测试5.结语 1.前言 在数据分析工作中,使用最多的无疑就是各种函数、图表、…

2212电机 与 Simonk 30A 电调 调速测试记录

硬件信息 一、2212电机 适配 F330、F450、F550机架 重量:52克 尺寸:28mm*24mm 支持锂电:3s~4s锂电池 电调:20~40A 二、Simonk 30A 电调 重量:25克 尺寸:40 * 23 * 8mm 输入电压:2s~4s&…

使用__missing__方法实现映射表多格式主键

背景介绍 在python中,我们经常使用字典类型实现映射表的功能,通过字典的主键遍历获取对应的值,从而实现从一个值映射到另一个值的功能 但是这种映射是十分硬性的,例如,假如我的映射表为{‘1’:one&#x…

C#学习(十)——WPF重构与美化

一、Entity Framework Core 特点:【跨平台】,【建模】,【查询、更改、保存】,【并发】,【事务】,【缓存】,【数据迁移】 EF的组件 二、重构:构建数据模型 项目延续C#学习(九)的 项…

Unity通用渲染管线升级URP、HDRP

Unity通用渲染管线升级URP、HDRP 一、Build-in Pipline升级到 URP 一、Build-in Pipline升级到 URP 安装URP包 升级所有材质(升级完成后材质会变成紫红色,Shader丢失,此为正常现象) 创建 UniversalRenderPipelineAsset 配置文…

java web 校园健康管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java Web校园健康管理系统是一套完善的java web信息管理系统 ,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发,数据库为Mysq…

深入理解工厂模式:创建可复用的对象实例

这里写目录标题 前言简单工厂模式工厂方法模式抽象工厂模式总结 前言 工厂模式是一种常用的设计模式,它可以帮助我们更好地组织和管理代码,将对象的创建和使用分离开来,提高代码的可维护性和扩展性。 在软件开发中,我们经常会遇到…

C++拷贝构造函数、赋值学习整理:

拷贝构造函数: 概念: 构造函数的第一个参数,是类本身的const引用(一般情况下没有其他参数,少数情况:其他参数必须有默认值!)称此类构造函数为拷贝构造函数 特征: 1&am…

使用Animate.css动画库

1.网站:Animate.css | A cross-browser library of CSS animations. 样式:Animate.css 一款强大的预设css3动画库 (jq22.com) 一、引入 命令提示符/终端: npm install animate.css --save 二、 全局导入(在main.js&#xff0…