【问题标题】:Perf shows mangled function namesPerf 显示损坏的函数名称
【发布时间】:2016-03-18 00:06:53
【问题描述】:

在看到来自 CppCon 2015 的 this 演讲后,我想试一试性能来分析一些程序。我下载了该人在演讲中使用的同一个 Google 基准测试库,使用适当的开关编译了我的程序,并将其链接到它,然后使用 perf 记录运行。报告选项给了我这个:

如您所见,函数名称不是很易读。我认为这与 C++ 名称修改有关。有趣的是,所有的函数名称都正确地显示在了演讲者的视频中,但对我来说却不是。我不认为这是完全丢失符号信息的情况,因为在这种情况下我只会看到内存地址。出于某种原因,perf 无法为我“撤消” C++ 名称重整,这令人沮丧。

我使用的是 gcc (g++) 版本 5.2.1,perf 是版本 4.2.6,我在编译时使用了这些开关:

-I<my own include path> -L<path to the benchmark library> -O3 -std=c++14 -gdwarf-2 -fno-rtti -Wall -pedantic -lbenchmark -pthread

我不使用-fno-omit-frame-pointer 的原因是我改用-gdwarf-2 选项,它将调试信息保留在dwarf 可执行文件中,这是在这种情况下保留帧指针的替代方法。这也意味着我将--call-graph "dwarf" 传递给perf record。反正我也试过帧指针的方法,结果一样,没关系。

那么在这种情况下,为什么不执行“撤消”C++ 名称修改呢?这和使用GCC有什么关系,当然是说我使用的是libstdc++?

【问题讨论】:

  • 我使用的是 Arch Linux,perf report 显示正确的符号去管理。 perf 的手册页还显示有一个默认启用的--demangle 选项。由于我没有看到与您相同的行为,因此我没有答案,但您看到的不是预期的默认行为。
  • 我也尝试手动添加该开关,但没有任何改变
  • @GabrielSouthern 你也在使用 gcc 吗?
  • gcc --version gcc (GCC) 5.2.0
  • 看来您使用的是 Ubuntu。我怀疑这是您的问题和解决方案:stackoverflow.com/a/34061874/2166274

标签: c++ profiling perf name-mangling


【解决方案1】:

perf report 给你的名字像_Z*_ZN*_ZL* 等时,这意味着你的perf 工具在编译时没有使用去重合功能或被禁用。 Makefile 中有检测 demangler 的代码:

http://elixir.free-electrons.com/linux/v4.2.6/source/tools/perf/Makefile.perf

# Define NO_DEMANGLE if you do not want C++ symbol demangling.
# Define NO_LIBELF if you do not want libelf dependency (e.g. cross-builds)

http://elixir.free-electrons.com/linux/v4.2.6/source/tools/perf/config/Makefile

ifdef NO_LIBELF
...
  NO_DEMANGLE := 1
...
else
  ifeq ($(feature-libelf), 0)
    ifeq ($(feature-glibc), 1)
      LIBC_SUPPORT := 1
    endif
    ...
    ifeq ($(LIBC_SUPPORT),1)
      ...
      NO_DEMANGLE := 1
    ...

测试位于tools/build/feature 目录中:http://elixir.free-electrons.com/linux/v4.2.6/source/tools/build/feature 并且如果使用 libelf 的 elf_begin 函数(<libelf.h> header of elfutils package-lelf 链接)的测试程序可用(并返回一些东西?是否运行),则启用 libelf 功能测试?当内核构建器机器无法直接使用./test-libelf.bin 运行目标机器精灵二进制文件并且必须使用 ssh 到真机或某些用户/系统 qemu 时,交叉构建会怎样?)。

在 perf 实现中的代码进行去修饰(如果定义了 HAVE_CPLUS_DEMANGLE_SUPPORT,则使用 cplus_demangle,不使用 demangle 是在 Makefile 之后设置 NO_DEMANGLE,使用 bfd.h 和 bfd_demangle 函数 docs - 2.3.1.24 bfd_demangle): http://elixir.free-electrons.com/linux/v4.2.6/source/tools/perf/util/symbol-elf.c#L19

#ifdef HAVE_CPLUS_DEMANGLE_SUPPORT
extern char *cplus_demangle(const char *, int);

static inline char *bfd_demangle(void __maybe_unused *v, const char *c, int i)
{
    return cplus_demangle(c, i);
}
#else
#ifdef NO_DEMANGLE
static inline char *bfd_demangle(void __maybe_unused *v,
                 const char __maybe_unused *c,
                 int __maybe_unused i)
{
    return NULL;
}
#else
#define PACKAGE 'perf'
#include <bfd.h>
#endif

这一切都有些奇怪(在 C++11 后的时代,Linux 世界中仍然没有标准的 c++ demangle 函数吗?)。并且您的性能被错误编译或配置错误 - 这就是它不会对名称进行解码的原因。 billyw linked answer by Michal Fapso 说这是 ubuntu 的错误 1396654 - https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1396654

您可以使用c++filt 程序过滤 perf 的输出,但它会阻止您使用 perf 的交互式默认 TUI 界面(添加 less 或写入文本文件以使用正常的 pageDown/pageUp 查看非常长的列表) :

perf report | c++filt | less
perf annotate function_name | c++filt | less
# or: perf annotate -s function_name | c++filt | less

或者您可以按照billywhis comment 中的建议更新/重新编译您的性能

4^ 看来您使用的是 Ubuntu。我怀疑这是您的问题和解决方案:https://stackoverflow.com/a/34061874/2166274 – billyw 2016 年 3 月 3 日 17:31

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-09
    • 1970-01-01
    • 2022-10-21
    • 2011-01-31
    • 1970-01-01
    相关资源
    最近更新 更多