perf展示每个ELF节段的事件

3

有没有办法让perf report(或任何其他perf分析工具)按elf-section显示偶数计数?

例如,标准的perf record echo "hi"; perf report结果为:

# Overhead  Command  Shared Object     Symbol                
# ........  .......  ................  ......................
#
    20.62%  echo     [unknown]         [k] 0xffffffffaafa7fbb
    20.59%  echo     [unknown]         [k] 0xffffffffaa88996a
    18.12%  echo     libc.so.6         [.] __GI___getrandom
    17.68%  echo     [unknown]         [k] 0xffffffffaa52af74
    16.52%  echo     [unknown]         [k] 0xffffffffaa8a5d57
     5.51%  echo     [unknown]         [k] 0xffffffffaafb6c1c
     0.83%  perf-ex  [unknown]         [k] 0xffffffffaafb10f0
     0.11%  perf-ex  [unknown]         [k] 0xffffffffaa249286
     0.02%  perf-ex  [unknown]         [k] 0xffffffffaa210b39
     0.00%  perf-ex  [unknown]         [k] 0xffffffffaa296106
     0.00%  perf-ex  [unknown]         [k] 0xffffffffaa296104

有没有办法让Symbol不是函数(或者如果符号解析失败则为地址),而只是成为elf节(例如.text.text.<任意其他节>)。

?

编辑: 动机是在使用-ffunction-sections编译时获取可靠的符号信息。

1个回答

3
有没有办法只获取它作为 ELF 段(例如 .text 或 ...)的方式?
我怀疑这样的选项不存在——这似乎是一个非常奇怪的要求(可能适用于 http://xyproblem.info)。 perf 是一个开源程序;您可以构建一个新副本,将地址解析为节名称而不是符号名称。
一个更简单的解决方案可能是使用perf script -D,它会产生类似于以下输出:
655100227667001 0x4d0 [0x68]: PERF_RECORD_MMAP2 991807/991807: [0x557bfc80c000(0x1000) @ 0x1000 fe:00 22546274 180651332]: r-xp /tmp/a.out
...
655100231257619 0x918 [0x28]: PERF_RECORD_SAMPLE(IP, 0x4002): 991807/991807: 0x557bfc80c38d period: 1965769 addr: 0
...
           a.out 991807 655100.228914:    2945520 cycles:      557bfc80c38d MyClass::~MyClass+0x19 (/tmp/a.out)
...
           a.out 991807 655100.238353:    1115949 cycles:      557bfc80c38d MyClass::~MyClass+0x19 (/tmp/a.out)
...

您可以使用PERF_RECORD_MMAP2来确定感兴趣的内存部分所在的位置,然后将PERF_RECORD_SAMPLE记录中的地址转换为部分名称(并丢弃符号名称)。
找到了一个更简单的解决方案。
假设你有一个未经剥离的二进制文件 `a.out`。执行命令 `perf record ./a.out; perf report` 会生成一个 "正常" 的报告:
  99.88%  a.out    a.out                 [.] MyClass::~MyClass
   0.03%  a.out    ld-linux-x86-64.so.2  [.] _dl_relocate_object
   0.02%  a.out    [unknown]             [k] 0xffffffffb005b01b
...

让我们运行几个命令:

mv a.out a.out.orig
strip a.out.orig -o a.out.stripped
cp a.out.stripped a.out
perf report

现在报告看起来像这样:

  60.44%  a.out    a.out                 [.] 0x000000000000138d
  21.88%  a.out    a.out                 [.] 0x0000000000001389
  17.56%  a.out    a.out                 [.] 0x0000000000001391
   0.03%  a.out    ld-linux-x86-64.so.2  [.] _dl_relocate_object
...

不完全是你想要的。但是让我们在.text的开头添加一个符号:

objcopy a.out.stripped  a.out  --add-symbol .text=.text:0x0,function,global

现在运行perf report会产生以下结果:

  99.88%  a.out    a.out                 [.] .text
   0.03%  a.out    ld-linux-x86-64.so.2  [.] _dl_relocate_object

这正是您想要的(您可以为其他感兴趣的部分添加更多符号)。


我想要能够获取可靠的每个函数的性能分析数据,而不会省略帧指针。使用“-ffunction-sections”编译可以提供所有函数的信息 -> 事件,无需考虑开销。编辑问题以反映这一点。 - Noah
1
@Noah 现在你的问题变得更加毫无意义了——帧指针与 perf 几乎没有任何关系(除非你用 -g 标志记录调用堆栈)。使用 -ffunction-sections,函数名和节名之间已经是1:1的关系,所以你应该已经得到了你想要的输出。 - Employed Russian
你说得对,帧指针的事情并不是很重要。但例如,perf展示中断发生在0xffffffffaafa7fbb,有没有办法从运行时实际地址转到ELF节段呢? - Noah
1
@Noah:那是一个内核地址。你打算使用-ffunction-sections重新构建你的内核吗?为什么不构建一个非剥离的内核,这样你就可以有每个函数的符号,或者将内核符号表放在perf可以找到的地方呢? - Peter Cordes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接