Запишите адреса инструкций ошибок страницы с помощью perf - PullRequest
2 голосов
/ 11 июля 2019

Я хотел бы получить адреса инструкций, которые приводят к основным сбоям страницы, используя perf.У меня есть простая программа:

#include <time.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mman.h>


int main(int argc, char* argv[]) {
    int fd = open("path to large file several Gb", O_RDONLY);
    struct stat st;
    fstat(fd, &st);
    void* ptr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
    const uint8_t* data = (const uint8_t*) ptr;

    srand(time(NULL));
    size_t i1 = ((double) rand() / RAND_MAX) * st.st_size;
    size_t i2 = ((double) rand() / RAND_MAX) * st.st_size;
    size_t i3 = ((double) rand() / RAND_MAX) * st.st_size;

    printf("%x[%lu], %x[%lu], %x[%lu]\n", data[i1], i1, data[i2], i2, data[i3], i3);

    munmap(ptr, st.st_size);
    close(fd);
    return 0;
}

Я компилирую ее с помощью gcc -g -O0 main.c и запускаю perf record -e major-faults -g -d ./a.out

Далее я открываю полученный отчет с помощью perf report -g В отчете говорится, что есть 3основные ошибки страницы (это правильно), но я не могу понять адреса инструкций, которые приводят к ошибкам страницы.Ниже приводится отчет:

# To display the perf.data header info, please use --header/--header-only options.
#
#
# Total Lost Samples: 0
#
# Samples: 3  of event 'major-faults'
# Event count (approx.): 3
#
# Children      Self  Command  Shared Object     Symbol                
# ........  ........  .......  ................  ......................
#
   100.00%     0.00%  a.out    libc-2.23.so      [.] __libc_start_main 
              |
              ---__libc_start_main
                 main

   100.00%   100.00%  a.out    a.out             [.] main              
              |
              ---0x33e258d4c544155
                 __libc_start_main
                 main

   100.00%     0.00%  a.out    [unknown]         [.] 0x033e258d4c544155
              |
              ---0x33e258d4c544155
                 __libc_start_main
                 main

a.out не содержит адрес 0x33e258d4c544155 или что-то, заканчивающееся 155.

Вопрос в том, как получить адреса инструкций, которыеприводит к ошибкам страницы?

1 Ответ

1 голос
/ 11 июля 2019

По какой-то причине я не могу воспроизвести ваш пример, т.е. я не получаю никаких образцов с событием major-faults.Но я могу объяснить другим примером.

Вывод pref report вводит в заблуждение, он не содержит трех событий, он показывает три уровня стека.Это гораздо проще понять, используя perf script - который показывает реальные события (включая их стеки).Записи выглядят так (повторяются для каждого образца):

a.out 22107 14721.378764:   10000000 cycles:u: 
            5653c1afb134 main+0x1b (/tmp/a.out)
            7f58bb1eeee3 __libc_start_main+0xf3 (/usr/lib/libc-2.29.so)
        49564100002cdb3d [unknown] ([unknown])

Теперь вы видите стек функций с адресом виртуальной инструкции, ближайшим символом и смещением от символа.Если вы хотите поиграть с адресами самостоятельно, вы можете запустить perf script --show-mmap-events, который скажет вам:

a.out 22107 14721.372233: PERF_RECORD_MMAP2 22107/22107: [0x5653c1afb000(0x1000) @ 0x1000 00:2b 463469 624179165]: r-xp /tmp/a.out
                                                          ^ Base         ^ size    ^ offset                             ^ file

Затем вы можете сделать математику для 0x5653c1afb134, вычтя основание 0x5653c1afb000 и добавивсмещение 0x1000 - вы получаете адрес инструкции или обратный адрес в файле.

Вы также видите, что 0x49564100002cdb3d не отображается, не может быть разрешен - это просто мусор из основанного на указателе кадрастек раскручивается.Вы можете игнорировать это.Вы также можете использовать --call-graph dwarf или --call-graph lbr, которые, кажется, показывают более разумное происхождение стека.

...