Perf показывает искаженные имена функций

Я хотел попробовать сделать некоторые программы после того, как увидел этот доклад из CppCon 2015. Я загрузил ту же библиотеку тестов 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 ++?

9

Решение

когда perf report дает вам искаженные имена, такие как _Z*, _ZN*, _ZL* и т. д., это означает, что ваш perf Инструмент был скомпилирован без доступа к функции разборки или с отключенным. В Makefiles есть код для обнаружения деманглера:

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 (<libelf.h> заголовок пакета elfutils, -lelf связывание) доступно (и возвращает что-то? есть ли run test? как насчет кросс-сборок, когда машина ядра не может запустить двоичные файлы elf целевой машины напрямую с ./test-libelf.bin и должен использовать ssh для реальной машины или какой-нибудь пользователь / системный qemu?).

И код в реализации Perf, чтобы сделать demangling (используя cplus_demangle если определено HAVE_CPLUS_DEMANGLE_SUPPORT, не использовать demangle, если после Makefiles установлено NO_DEMANGLE, используя bfd.h и bfd_demangle функция документы — 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 до сих пор нет стандартной функции разборки c ++ в мире Linux?). А также ваш перф был неверно скомпилирован или неверно настроен — это причина, почему он не разоблачает имена. billyw связанный ответ от Михал Фапсо который говорит, что это ошибка 1396654 Ubuntu — https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1396654.

Вы можете взломать фильтрацию вывода perf с помощью c++filt программа, но она не позволяет использовать интерактивный интерфейс по умолчанию 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

Или вы можете обновить / перекомпилировать свой перф как предложено billyw в его комментарий

4 ^ Похоже, вы на Ubuntu. Я подозреваю, что это ваша проблема и решение: https://stackoverflow.com/a/34061874/2166274 — Billyw 3 марта ’16 в 17:31

5

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]