Механизм, используемый для определения адреса загрузки библиотеки в Perf - PullRequest
1 голос
/ 13 января 2020

Как perf определяет адреса загрузки для каждого загруженного изображения (например, общих библиотек) во время постобработки. Например, perf report использует эту информацию, чтобы сделать каждый символ адресом относительно начала каждого загруженного изображения. Это показано на рисунке ниже (unwind: _int_malloc...): enter image description here

Хранится ли оно где-нибудь в elf двоичном или профилирующем выводе (т. Е. perf.data)?

Ответы [ 2 ]

3 голосов
/ 15 января 2020

Адрес загрузки общих библиотек хранится в файле perf.data, записанном во время команды perf record. Вы можете использовать команду perf script -D для выгрузки данных из perf.data в частично декодированном формате. Когда ваша программа загружается с помощью ld-linux*.so.2 (или когда требуется с dlopen), загрузчик будет искать библиотеку и загружать ее сегменты, используя системный вызов mmap. Эти события mmap записываются ядром и имеют тип PERF_RECORD_MMAP или PERF_RECORD_MMAP2 в файле perf.data. И perf reportperf script) восстановят смещения памяти для декодирования имен символов.

$ perf record  echo 1
$ perf script -D|grep MMAP -c
7
$ perf script -D|less
PERF_RECORD_MMAP2 ... r-xp /bin/echo
...
PERF_RECORD_MMAP2 ... r-xp /lib/x86_64-linux-gnu/libc-2.27.so

Основные c идеи perf описаны в файле https://github.com/torvalds/linux/blob/master/tools/perf/design.txt , Для начала профилирования существует perf_event_open системный вызов , который имеет аргумент perf_event_attr *attr. Справочная страница описывает связанные с mmap поля attr:

   The perf_event_attr structure provides detailed configuration
   information for the event being created.

                 mmap           : 1,   /* include mmap data */
                 mmap_data      : 1,   /* non-exec mmap data */
                 mmap2          :  1,  /* include mmap with inode data */

Linux Ядро в своей подсистеме perf_events (ядро / события) будет записывать необходимые события для профилируемых процессов и экспортировать данные с помощью fd и mmap для профилировщика. perf record обычно выгружает эти данные из ядра в файл perf.data без интенсивной обработки (отметьте отпечатки "10 раз *, чтобы записать данные" вашего вывода perf record). События Mmap в ядре записываются с помощью perf_event_mmap_output, вызываемой с perf_event_mmap_event, которая вызывается с perf_event_mmap. Реализация mmap syscall в mm/mmap.c имеет некоторые безусловные вызовы perf_event_mmap.

perf. design.txt упоминает munmap, но в текущей реализации нет поля или события munmap, код события 2 использовался повторно PERF_RECORD_LOST . Были идеи, что munmap может быть полезен https://www.spinics.net/lists/netdev/msg524414.html со ссылками на https://lkml.org/lkml/2016/12/10/1 и https://lkml.org/lkml/2017/1/27/452

. linux исходных кодов ядра, которые можно просмотреть онлайн на веб-сайте LXR / elixir: https://elixir.bootlin.com/linux/v5.4/source/tools/perf/ Код обработки событий mmap / mmap2 находится в perf / util / machine. c machine__process_mmap_event и machine__process_mmap2_event; зарегистрированные аргументы mmap, возвращенный адрес, смещение и имя файла записываются с помощью map__new и thread__insert_map для процесса (pid / tid) и используются позже для преобразования примера адреса события в имя символа.

PS : Ваш perf.data имеет размер более 300 МБ, он огромен, и обработка может быть медленной. Для программ, работающих долго, вы можете уменьшить частоту дискретизации событий перфоза с опцией -F freq, равной perf record: perf record -F40 или с опцией -c.

2 голосов
/ 13 января 2020

Вы не можете найти его, просто взглянув на исполняемый файл ELF и библиотеки. Это может варьироваться каждый пробег; даже если ASLR был отключен программой perf, как это делает GDB, программа может использовать mmap(MAP_FIXED) перед использованием dlopen некоторой необязательной библиотеки, загруженной позже, поэтому dlopen придется выбирать другой адрес, чем обычно, для сопоставления библиотеки. (Нормальное динамическое связывание c происходит до запуска main, не через dlopen, но, предположительно, perf хочет иметь возможность записывать адреса -> сопоставления файлов для любого сопоставления с файловой поддержкой.)

Возможно, перф сохраняет базовый адрес времени выполнения каждого объекта ELF в perf.data

...