Инструменты для получения графического графика вызовов функций кода

Методы динамического анализа

Здесь я описываю несколько call-graph методов динамического анализа.

Динамические def методы фактически запускают c программу для определения call-graph графа вызовов.

Противоположностью call-graph динамических методов являются functions статические методы, которые function пытаются определить его только c из источника без запуска call-graph программы.

Преимущества динамических c методов:

  • перехватывает указатели на функции и виртуальные вызовы C++. Они присутствуют в большом количестве в любом нетривиальном программном обеспечении.

Недостатки динамических functions методов:

  • вам необходимо запустить программу, которая может быть медленной или требовать установки, которой у вас нет, например кросс-компиляция
  • будут показаны только те функции, которые действительно были вызваны. Например, некоторые функции могут быть вызваны или нет, в зависимости от аргументов командной строки.

KcacheGrind

https://kcachegrind.github.io/html/Home.html

Тестовая программа:

int f2(int i) { return i + 2; }
int f1(int i) { return f2(2) + i + 1; }
int f0(int i) { return f1(1) + f2(2); }
int pointed(int i) { return i; }
int not_called(int i) { return 0; }

int main(int argc, char **argv) {
    int (*f)(int);
    f0(1);
    f1(1);
    f = pointed;
    if (argc == 1)
        f(1);
    if (argc == 2)
        not_called(1);
    return 0;
}

Использование:

sudo apt-get install -y kcachegrind valgrind

# Compile the program as usual, no special flags.
gcc -ggdb3 -O0 -o main -std=c99 main.c

# Generate a callgrind.out. file.
valgrind --tool=callgrind ./main

# Open a GUI tool to visualize callgrind data.
kcachegrind callgrind.out.1234

Теперь def вы остались внутри замечательной call-graph программы с графическим интерфейсом, которая def содержит много интересных functions данных о производительности.

В function правом нижнем углу выберите def вкладку «График звонков». Это functions показывает интерактивный functions график вызовов, который коррелирует call-graph с показателями производительности def в других окнах, когда вы function щелкаете по функциям.

Чтобы c экспортировать график, щелкните c его правой кнопкой мыши и def выберите «Экспорт графика». Экспортированный functions PNG выглядит так:

Инструменты для получения графического графика вызовов функций кода_call-graph

Из этого functions мы видим, что:

  • корневой узел - это _start, который является фактической точкой входа ELF и содержит шаблон инициализации glibc.
  • f0, f1 и f2 вызываются, как и ожидалось друг от друга.
  • pointed также отображается, хотя мы вызывали его с помощью указателя на функцию. Возможно, он не был бы вызван, если бы мы передали аргумент командной строки.
  • not_called не отображается, потому что он не был вызван при выполнении, потому что мы не передали дополнительный аргумент командной строки.

Самое замечательное function в valgrind заключается в том, что call-graph он не требует каких-либо c специальных параметров компиляции.

Следовательно, вы call-graph можете использовать его, даже def если у вас нет исходного call-graph кода, только исполняемый def файл.

valgrind удается это сделать, запустив function ваш код через легкую «виртуальную functions машину». Это также делает functions выполнение чрезвычайно медленным c по сравнению с собственным functions исполнением.

Как видно на def графике, также получается c информация о времени для c каждого вызова функции, и function ее можно использовать для functions профилирования программы, что, вероятно, является c исходным вариантом использования function этой настройки, а не только def для просмотра графиков вызовов: How can I profile C++ code running on Linux?

Проверено functions в Ubuntu 18.04.

gcc -finstrument-functions + etrace

https://github.com/elcritch/etrace

-finstrument-functions adds callbacks, etrace functions анализирует файл ELF и реализует functions все обратные вызовы.

К сожалению, мне call-graph не удалось заставить его function работать: Why doesn't `-finstrument-functions` work for me?

Заявленный вывод functions имеет формат:

\-- main
|   \-- Crumble_make_apple_crumble
|   |   \-- Crumble_buy_stuff
|   |   |   \-- Crumble_buy
|   |   |   \-- Crumble_buy
|   |   |   \-- Crumble_buy
|   |   |   \-- Crumble_buy
|   |   |   \-- Crumble_buy
|   |   \-- Crumble_prepare_apples
|   |   |   \-- Crumble_skin_and_dice
|   |   \-- Crumble_mix
|   |   \-- Crumble_finalize
|   |   |   \-- Crumble_put
|   |   |   \-- Crumble_put
|   |   \-- Crumble_cook
|   |   |   \-- Crumble_put
|   |   |   \-- Crumble_bake

Вероятно, это function наиболее эффективный метод, помимо functions поддержки конкретной аппаратной function трассировки, но имеет обратную functions сторону, заключающуюся в functions необходимости перекомпилировать c код.

c

function

call-graph

2022-11-12T23:37:36+00:00