Методы динамического анализа
Здесь я описываю несколько методов динамического анализа.
Динамические методы фактически запускают программу для определения графа вызовов.
Противоположностью динамическим методам являются статические методы, которые пытаются определить его только из источника без запуска программы.
Преимущества динамических методов:
- перехватывает указатели на функции и виртуальные вызовы C ++. Они присутствуют в большом количестве в любом нетривиальном программном обеспечении.
Недостатки динамических методов:
- вам нужно запустить программу, которая может быть медленной или требовать установки, которой у вас нет, например кросс-компиляция
- будут показаны только те функции, которые действительно были вызваны. Например, некоторые функции могут быть вызваны или нет, в зависимости от аргументов командной строки.
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.<PID> file.
valgrind --tool=callgrind ./main
# Open a GUI tool to visualize callgrind data.
kcachegrind callgrind.out.1234
Теперь вы остались внутри великолепной программы с графическим интерфейсом, которая содержит много интересных данных о производительности.
В правом нижнем углу выберите вкладку «График звонков». Это показывает интерактивный график вызовов, который коррелирует с показателями производительности в других окнах, когда вы щелкаете по функциям.
Чтобы экспортировать график, щелкните его правой кнопкой мыши и выберите «Экспорт графика». Экспортированный PNG выглядит так:
![](https://i.stack.imgur.com/s7dYK.png)
Из этого мы видим, что:
- корневой узел
_start
, который является фактической точкой входа в ELF и содержит шаблон инициализации glibc
f0
, f1
и f2
вызываются, как и ожидалось друг от друга
pointed
также отображается, хотя мы вызывали его с помощью указателя на функцию. Возможно, он не был бы вызван, если бы мы передали аргумент командной строки.
not_called
не отображается, потому что он не был вызван при выполнении, потому что мы не передали дополнительный аргумент командной строки.
В valgrind
замечательно то, что он не требует каких-либо специальных параметров компиляции.
Следовательно, вы можете использовать его, даже если у вас нет исходного кода, только исполняемый файл.
valgrind
удается это сделать, запустив ваш код через легкую «виртуальную машину». Это также делает выполнение чрезвычайно медленным по сравнению с собственным исполнением.
Как видно на графике, также получается информация о времени для каждого вызова функции, и ее можно использовать для профилирования программы, что, вероятно, является исходным вариантом использования этой настройки, а не только для просмотра графиков вызовов: Как я могу профилировать код C ++, работающий в Linux?
Проверено на Ubuntu 18.04.
gcc -finstrument-functions
+ etrace
https://github.com/elcritch/etrace
-finstrument-functions
добавляет обратные вызовы, etrace анализирует файл ELF и реализует все обратные вызовы.
К сожалению, мне не удалось заставить его работать: Почему не работает `-finstrument- у меня работают функции?
Заявленный вывод имеет формат:
\-- 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
Вероятно, это наиболее эффективный метод, помимо поддержки конкретной аппаратной трассировки, но имеет обратную сторону: вам придется перекомпилировать код.
person
Ciro Santilli 新疆再教育营六四事件ۍ
schedule
02.07.2015