将 C Callergraph 与 Doxygen 合并或确定所有调用的并集

发布于 2024-07-12 19:57:12 字数 631 浏览 9 评论 0原文

我有一组遗留的 C 代码,我正在对其进行重构,以将 C 计算代码从 GUI 中分离出来。 由于 K&R 风格声明的高度递归数学核心代码使情况变得复杂。 由于函数参数的嵌套使用,我已经放弃了将它们转换为 ANSI 声明的尝试(只是无法消除最后 4 个编译器错误)。

我需要将一些文件移至纯 DLL 中并确定要公开的最小接口,这将需要编写包装函数来发布类型化接口。

我已使用 Doxygen @callergraph 标记标记了关键源文件,以便为各个函数生成信息图表。 除此之外,我想做的就是合并这些图表,这样我就可以确定暴露给外界的函数的最窄边界。

原始头文件没有用——它们将所有内容公开为非类型化 C 函数。

有数百个函数,因此对生成的调用者图进行简单检查是很痛苦的。

我正在考虑编写某种 DOT 合并工具 - 设置 DOT_CLEANUP=NO 使 Doxygen 将中间 DOT 文件保留在那里,而不是只保留它们生成的 png 文件。

我并不痴迷于这是一个图形解决方案 - 如果有人可以建议一种替代分析工具(免费或相对便宜)或使用 Doxygen 的 XML 输出来实现相同目标的技术,我会非常高兴。

在文件级别合并的调用者图确实对客户端文档(而不是简单的列表)具有一定的吸引力:-)

I have a collection of legacy C code which I'm refactoring to split the C computational code from the GUI. This is complicated by the heavily recursive mathematical core code being K&R style declarations. I've already abandoned an attempt to convert these to ANSI declarations due to nested use of function parameters (just couldn't get those last 4 compiler errors to go).

I need to move some files into a pure DLL and determine the minimal interface to make public, which is going to require wrapper functions writing to publish a typed interface.

I've marked up the key source files with the Doxygen @callergraph markup so informative graphs are generated for individual functions. What I'd like to do beyond that is amalgamate these graphs so I can determine the narrowest boundary of functions exposed to the outside world.

The original header files are no use - they expose everything as untyped C functions.

There are hundreds of functions so simple inspection of the generated callergraphs is painful.

I'm considering writing some kind of DOT merge tool - setting DOT_CLEANUP=NO makes Doxygen leave the intermediate DOT files there rather then just retaining the png files they generated.

I'm not obsessed by this being a graphical solution - I'd be quite happy if someone could suggest an alternative analysis tool (free or relatively cheap) or technique using Doxygen's XML output to achieve the same goal.

A callergraph amalgamated at the file level does have a certain appeal for client documentation rather than a plain list :-)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

静谧 2024-07-19 19:57:19

您可以使用 Scientific Toolworks 查看系统范围的调用图。

如果您想自动化分析和切割,您可以考虑
DMS 软件重组工具包。 它可以计算 C 的完整调用图
(完成了函数指针的指向分析),并且已经
经过 3500 万行代码的系统验证。 它会
生成完整的系统 DOT 文件进行检查; 它们很大,但是你可以
挑选出子集来查看。 请参阅流分析和调用图

You could use Scientific Toolworks to see your system-wide call graph.

If you want to automate the analysis and the cutting, you might consider
the DMS Software Reengineering Toolkit. It can compute full call graphs for C
(complete with points-to analysis for function pointers), and has been
proven for systems of 35 million lines of code. It will
produce full system DOT files to inspect; they are pretty big but you can
pick out subsets to look at. See flow analysis and call graphs.

寻找一个思念的角度 2024-07-19 19:57:18

我有类似的要求。
编写了一个 perl 脚本,将一组点文件合并为一个点文件。

https://github.com/bharanis/scripts/blob/master/doxygen_dot_merge.pl

合并多个 doxygen 生成的点文件。
这对于生成一个文件或一组文件的调用映射非常有用。

1) 该命令要从 html 目录外部运行,doxygen 放置所有 html、dot 和 map 文件。

2) 该命令假定 doxygen 中使用平面目录结构
CREATE_SUBDIRS = NO

3) doxygen 将源文件名作为输出点文件名的前缀。 每个函数生成一个点文件

4) 提供要合并的 doxygen 生成的点文件列表。
例如:

./doxydotmerge.pl  `ls html/ssd_*_8c*_cgraph.dot  | grep -v test | grep -v buf`

I had a similar requirement.
Wrote a perl script to merge a set of dot files into a single dot file.

https://github.com/bharanis/scripts/blob/master/doxygen_dot_merge.pl

merge multiple doxygen generated dot files.
This is useful for generating a call map for a file or a bunch of files.

1) This command is to be run from outside the html directory where doxygen puts all the html, dot and map files.

2) This command assumes flat directory structure used in doxygen
CREATE_SUBDIRS = NO

3) doxygen prefixes the source filename to the name of the output dot files. One dot file is generated per function

4) provide the list of doxygen generated dot files to be merged.
eg:

./doxydotmerge.pl  `ls html/ssd_*_8c*_cgraph.dot  | grep -v test | grep -v buf`
夏花。依旧 2024-07-19 19:57:17

在 Doxyfile 中进行设置

GENERATE_XML = YES

,然后您可以在 XML 文件中找到您的调用图。 对于标有调用者图的每个函数,您将在输出中找到可以使用的 元素。 这是我的一个 C 文件中的一个示例:

  <memberdef kind="function" id="spfs_8c_1a3"
             prot="public" static="yes" const="no" explicit="no"
             inline="no" virt="non-virtual">
    <type>svn_error_t *</type>
    <definition>svn_error_t * init_apr</definition>
    <argsstring>(apr_pool_t **ppool, int *argc, char const *const **argv)</argsstring>
    <name>init_apr</name>
    <!-- param and description elements clipped for brevity ... -->
    <location file="src/spfs.c" line="26" bodystart="101" bodyend="120"/>
    <referencedby refid="spfs_8c_1a13" compoundref="spfs_8c"
                  startline="45" endline="94">main</referencedby>
  </memberdef>

因此,对于每个 memberdef/referencedby 对,您都有一个调用者-被调用者关系,您可以通过 XSLT 获取该关系:

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="text"/>

    <xsl:template match="/">
        <xsl:apply-templates select="//memberdef[@kind eq 'function']"/>
    </xsl:template>

    <xsl:template match="memberdef">
        <xsl:variable name="function-name"
                      select="concat(definition, argsstring)"/>
        <xsl:for-each select="referencedby">
            <xsl:value-of select="concat(./text(), ' calls ', $function-name, '
')"/>
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>

这为每个调用者-被调用者提供了一行,如下所示

main calls svn_error_t * init_apr(apr_pool_t **ppool, int *argc, char const *const **argv)

:调整该 XSLT,然后以跨越最少边的方式对该有向图进行分区。 哇哦,一个 NP 完全问题! 幸运的是,有很多关于这个主题的论文,其中一些在这里:http://www. sandia.gov/~bahendr/partitioning.html

In your Doxyfile, set

GENERATE_XML = YES

and then you can find your call graph in the XML files. For each function marked with the callergraph, you'll find <referencedby> elements in the output that you can use. Here's a sample from one of my C files:

  <memberdef kind="function" id="spfs_8c_1a3"
             prot="public" static="yes" const="no" explicit="no"
             inline="no" virt="non-virtual">
    <type>svn_error_t *</type>
    <definition>svn_error_t * init_apr</definition>
    <argsstring>(apr_pool_t **ppool, int *argc, char const *const **argv)</argsstring>
    <name>init_apr</name>
    <!-- param and description elements clipped for brevity ... -->
    <location file="src/spfs.c" line="26" bodystart="101" bodyend="120"/>
    <referencedby refid="spfs_8c_1a13" compoundref="spfs_8c"
                  startline="45" endline="94">main</referencedby>
  </memberdef>

So for every memberdef/referencedby pair, you have a caller-callee relationship, which you can grab via XSLT:

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="text"/>

    <xsl:template match="/">
        <xsl:apply-templates select="//memberdef[@kind eq 'function']"/>
    </xsl:template>

    <xsl:template match="memberdef">
        <xsl:variable name="function-name"
                      select="concat(definition, argsstring)"/>
        <xsl:for-each select="referencedby">
            <xsl:value-of select="concat(./text(), ' calls ', $function-name, '
')"/>
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>

Which gives you a line per caller-callee like this:

main calls svn_error_t * init_apr(apr_pool_t **ppool, int *argc, char const *const **argv)

You'll want to tweak that XSLT and then partition that directed graph in the way that cuts across the fewest edges. Woo hoo, an NP-complete problem! Luckily, there are lots of papers on the subject, some are here: http://www.sandia.gov/~bahendr/partitioning.html

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文