如何用LLVM的c++filt对opt生成的函数名进行反解析,以及如何发出一些中间节点?

问题描述 投票:0回答:1

我正在阅读这个答案,以使用 clang++-13 和 opt-13 生成一个美观的调用图

❯ clang++-13 --version
Homebrew clang version 13.0.1
Target: x86_64-apple-darwin22.5.0
Thread model: posix
InstalledDir: /usr/local/bin
❯ opt-13 --version
Homebrew LLVM version 13.0.1
  Optimized build.
  Default target: x86_64-apple-darwin22.5.0
  Host CPU: westmere

这是示例代码:

#include <vector>

struct A { 
  A(int);
  void f(); // not defined, prevents inlining it!
};

int main() {
  std::vector<A> v;
  v.push_back(42);
  v[0].f();
}

这是我正在使用的命令:

clang++-13 -S -emit-llvm main1.cpp -o - |
   opt-13 -analyze -std-link-opts -dot-callgraph -enable-new-pm=0

这里有一条消息,但我不明白:

Writing '<stdin>.callgraph.dot'...
Printing analysis 'Print call graph to 'dot' file':
Pass::print not implemented for pass: 'Print call graph to 'dot' file'!

由于仍然生成点文件,因此我运行了以下命令:

cat \<stdin\>.callgraph.dot |
   c++filt |
   sed 's,>,\\>,g; s,-\\>,->,g; s,<,\\<,g' |
   gawk '/external node/{id=$1} $1 != id' |
   dot -Tpng -ocallgraph.png

这就是结果:

这与我的预期相去甚远:

What I expected

我看不出答案和我的有什么区别,但输出不同。我明白我的输出中显示的是装饰函数名称,但阅读和理解它们是令人痛苦的。

我想知道是否有方法可以改进我的输出,或者更有效地阅读和理解输出?


更新

我在下面的回答中概述了进展。然而,这个问题还没有完全得到解答:

  1. 有没有办法在 MacOS 上解析修饰函数名称?
  2. 生成的图仍然很大,但我们可以通过省略一些过于详细的节点来希望它变得更小。但是,怎么办?
c++ static-analysis call-graph
1个回答
0
投票

函数名称重组问题是 LLVM 的

c++filt
。这是一个小演示:

您可以在 MacOS 或 Linux 上使用

clang
opt
生成点文件。具体说明可能会因您的
clang
opt
的版本而有所不同,但通常是相同的。我在原来的问题中使用了
clang++-13
opt-13
,这里我使用
clang++-14
opt-14

clang++-14 -S -emit-llvm main1.cpp -o - |
   opt-14 -analyze -dot-callgraph -enable-new-pm=0

修饰后的函数名称如下:

_ZNSt3__14pairINS_16reverse_iteratorIP1AEES4_EC2B6v15006IS4_S4_LPv0EEEOT_OT0_

如果我们使用LLVM的

c++filt
,它无法解析它:

❯ c++filt --version
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++filt
Apple LLVM version 14.0.3 (clang-1403.0.22.14.1)
  Optimized build.
  Default target: arm64-apple-darwin22.5.0
  Host CPU: apple-m1
❯ c++filt _ZNSt3__14pairINS_16reverse_iteratorIP1AEES4_EC2B6v15006IS4_S4_LPv0EEEOT_OT0_
_ZNSt3__14pairINS_16reverse_iteratorIP1AEES4_EC2B6v15006IS4_S4_LPv0EEEOT_OT0_

但是,如果我们使用 GNU 的

c++filt
:

➜  ~ c++filt --version
GNU c++filt (GNU Binutils for Ubuntu) 2.38
Copyright (C) 2022 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) any later version.
This program has absolutely no warranty.
➜  ~ c++filt _ZNSt3__14pairINS_16reverse_iteratorIP1AEES4_EC2B6v15006IS4_S4_LPv0EEEOT_OT0_
std::__1::reverse_iterator<A*>&& std::__1::pair<std::__1::reverse_iterator<A*>, std::__1::reverse_iterator<A*> >::pair[abi:v15006]<std::__1::reverse_iterator<A*>, std::__1::reverse_iterator<A*>, (void*)0>(std::__1::reverse_iterator<A*>&&)

一切正常

© www.soinside.com 2019 - 2024. All rights reserved.