如何为 Perl 制作静态分析调用图?
我正在开发一个中等复杂的 Perl 程序。 作为其开发的一部分,它必须经过修改和测试。 由于某些环境限制,频繁运行该程序并不是一个容易练习的选择。
我想要的是 Perl 的静态调用图生成器。 它不必涵盖所有边缘情况(例如,在 eval 中将变量重新定义为函数,反之亦然)。
(是的,我知道 Devel::DprofPP 有一个运行时调用图生成工具,但运行时并不能保证调用每个函数。我需要能够查看每个函数功能。)
I am working on a moderately complex Perl program. As a part of its development, it has to go through modifications and testing. Due to certain environment constraints, running this program frequently is not an option that is easy to exercise.
What I want is a static call-graph generator for Perl. It doesn't have to cover every edge case(e,g., redefining variables to be functions or vice versa in an eval).
(Yes, I know there is a run-time call-graph generating facility with Devel::DprofPP, but run-time is not guaranteed to call every function. I need to be able to look at each function.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
在一般情况下无法完成:
但是,获得大量情况应该相当容易(针对自身运行此程序):
注意,这会错过
print "foo\n";
)$coderef->()
)$obj- >$method()
)它错误地捕获了
#foo()
)“foo()”
)如果您想要一个比毫无价值的黑客更好的解决方案,那么是时候开始研究
PPI
,但即使它也会遇到诸如$obj 之类的问题->$method()
。只是因为我很无聊,这里有一个使用
PPI
。 它只查找函数调用(而不是方法调用)。 它也不尝试保持子例程名称的唯一性(即,如果您多次调用同一个子例程,它将多次显示)。
Can't be done in the general case:
However, it should be fairly easy to get a large number of the cases (run this program against itself):
Note, this misses
print "foo\n";
)$coderef->()
)$obj->$method()
)It incorrectly catches
#foo()
)"foo()"
)If you want a better solution than that worthless hack, it is time to start looking into
PPI
, but even it will have problems with things like$obj->$method()
.Just because I was bored, here is a version that uses
PPI
. It only finds function calls (not method calls). It also makes no attempt to keep the names of the subroutines unique (i.e. if you call the same subroutine more than once it will show up more than once).我不确定它是否 100% 可行(因为 Perl 代码理论上无法静态分析,由于
BEGIN
块等 - 请参阅 最近的 SO 讨论)。 此外,即使在BEGIN
块不发挥作用的地方,子例程引用也可能使其变得非常困难。然而,显然有人做出了尝试 - 我只知道但从未使用过,所以买家要小心。
I'm not sure it is 100% feasible (since Perl code can not be statically analyzed in theory, due to
BEGIN
blocks and such - see very recent SO discussion). In addition, subroutine references may make it very difficult to do even in places whereBEGIN
blocks don't come into play.However, someone apparently made the attempt - I only know of it but never used it so buyer beware.
我最近在尝试解决同一问题的答案时偶然发现了一个脚本。 该脚本(链接到下面)使用 GraphViz 创建 Perl 程序或模块的调用图。 输出可以是多种图像格式。
http://www.teragridforum.org/mediawiki/index.php?title=Perl_Static_Source_Code_Analysis
I recently stumbled across a script while trying to solve find an answer to this same question. The script (linked to below) uses GraphViz to create a call graph of a Perl program or module. The output can be in a number of image formats.
http://www.teragridforum.org/mediawiki/index.php?title=Perl_Static_Source_Code_Analysis
我认为 Perl 没有“静态”调用图生成器。
下一个最接近的东西是
Devel::NYTProf
。主要目标是进行分析,但它的输出可以告诉您子例程被调用的次数以及从何处调用。
如果您需要确保调用每个子例程,您还可以使用
Devel::Cover
,它会检查以确保您的测试套件涵盖每个子例程。I don't think there is a "static" call-graph generator for Perl.
The next closest thing would be
Devel::NYTProf
.The main goal is for profiling, but it's output can tell you how many times a subroutine has been called, and from where.
If you need to make sure every subroutine gets called, you could also use
Devel::Cover
, which checks to make sure your test-suite covers every subroutine.我最近解决了类似的问题,想分享我的解决方案。
这个工具是在绝望中诞生的,它解开了 30,000 行遗留脚本中未记录的部分,以实现紧急的错误修复。
它读取源代码,使用 GraphViz 生成 png,然后在屏幕上显示图像。
由于它使用简单的逐行正则表达式,因此格式必须“合理”,以便可以确定嵌套。
如果目标代码格式错误,请先通过 linter 运行它。
另外,不要指望诸如解析动态函数调用之类的奇迹。
简单的正则表达式引擎的一线希望是它可以轻松扩展到其他语言。
该工具现在还支持 awk、bash、basic、dart、fortran、go、lua、javascript、kotlin、matlab、pascal、perl、php、python、r、raku、ruby、rust、scala、swift 和 tcl。
https://github.com/koknat/callGraph
I solved a similar problem recently, and would like to share my solution.
This tool was born out of desperation, untangling an undocumented part of a 30,000-line legacy script, in order to implement an urgent bug fix.
It reads the source code(s), uses GraphViz to generate a png, and then displays the image on-screen.
Since it uses simple line-by-line regexes, the formatting must be "sane" so that nesting can be determined.
If the target code is badly formatted, run it through a linter first.
Also, don't expect miracles such as parsing dynamic function calls.
The silver lining of a simple regex engine is that it can be easily extended for other languages.
The tool now also supports awk, bash, basic, dart, fortran, go, lua, javascript, kotlin, matlab, pascal, perl, php, python, r, raku, ruby, rust, scala, swift, and tcl.
https://github.com/koknat/callGraph