Граф вызовов (также известный как мультиграф вызовов [1] [2] ) — это граф потока управления , [3] который представляет отношения вызова между подпрограммами в компьютерной программе . Каждый узел представляет процедуру, а каждое ребро (f, g) указывает, что процедура f вызывает процедуру g . Таким образом, цикл в графе указывает на рекурсивные вызовы процедур.
Основные понятия
Графы вызовов могут быть динамическими или статическими. [4] Динамический граф вызовов — это запись выполнения программы, например, как вывод профилировщика. Таким образом, динамический граф вызовов может быть точным, но описывает только один запуск программы. Статический граф вызовов — это граф вызовов, предназначенный для представления каждого возможного запуска программы. Точный статический граф вызовов — это неразрешимая проблема , поэтому алгоритмы статических графов вызовов, как правило, являются переприближениями. То есть, каждая возникающая связь вызовов представлена в графе, и, возможно, также некоторые связи вызовов, которые никогда не возникнут в реальных запусках программы.
Графы вызовов могут быть определены для представления различных степеней точности. Более точный граф вызовов более точно аппроксимирует поведение реальной программы, за счет более длительного вычисления и большего объема памяти для хранения. Самый точный граф вызовов полностью контекстно-зависим , что означает, что для каждой процедуры граф содержит отдельный узел для каждого стека вызовов , с которым процедура может быть активирована. Полностью контекстно-зависимый граф вызовов называется деревом контекста вызовов. Его можно легко вычислить динамически, хотя он может занять большой объем памяти. Деревья контекста вызовов обычно не вычисляются статически, потому что это заняло бы слишком много времени для большой программы. Наименее точный граф вызовов неконтекстно-зависим , что означает, что для каждой процедуры есть только один узел.
В языках, которые имеют динамическую диспетчеризацию (например, Java или C++ ), [5] функции первого класса (например, Python или Racket ) или указатели функций (например, C ), точное вычисление статического графа вызовов требует результатов анализа псевдонимов . И наоборот, вычисление точного псевдонимизации требует графа вызовов. Многие системы статического анализа решают кажущуюся бесконечную регрессию, вычисляя оба одновременно.
Обычаи
Графы вызовов можно использовать по-разному. Одним из простых применений графов вызовов является поиск процедур, которые никогда не вызываются. Графы вызовов могут служить документацией для понимания программ людьми . [6] Графы вызовов также можно использовать для обнаружения аномалий выполнения программ или атак с внедрением кода. [7]
KCachegrind: мощный инструмент для создания и анализа графиков вызовов на основе данных, сгенерированных callgrind
Mac OS X Activity Monitor: Монитор процессов Apple GUI Activity Monitor имеет встроенный генератор графа вызовов, который может выбирать процессы и возвращать граф вызовов. Эта функция доступна только в Mac OS X Leopard
makeppgraph — это генератор графа зависимостей (на уровне модуля) для сборок, выполняемых с помощью makepp .
Intel(R) Single Event API (бесплатно, с открытым исходным кодом)
Статика для получения графиков вызовов без запуска приложения
С/С++
Sourcetrail создает статический граф вызовов, который может динамически исследоваться пользователем. Также поддерживает Python и Java
doxygen : использует Graphviz для генерации статических диаграмм вызовов/наследования
Cally: инструмент, который использует файлы языка передачи регистров (RTL) GCC для построения графов вызовов вызывающего или вызываемого объекта для проектов на языке C.
cflow : GNU cflow способен генерировать прямой и инвертированный граф вызовов программы на языке C.
egypt: небольшой скрипт Perl , который использует gcc и Graphviz для генерации статического графа вызовов программы на языке C.
CCTree: Собственный плагин Vim , который может отображать статические графики вызовов, считывая базу данных cscope . Работает для программ на языке C.
codeviz : статический генератор графа вызовов (программа не запущена). Реализован как патч к gcc ; работает для программ на C и C++.
calltree.sh : Функции оболочки Bash, которые объединяют cscope, graphviz и выборку инструментов рендеринга точек для отображения отношений «вызывающий» и «вызываемый» выше, ниже и/или между указанными вами функциями C.
tceetree: как и calltree.sh, он соединяет Cscope и Graphviz , но это исполняемый файл, а не скрипт bash.
Идти
go-callvis: интерактивный генератор графа вызовов для программ Go, вывод которых можно нарисовать с помощью Graphviz
Многоязычный
callGraph: генератор графов вызовов с открытым исходным кодом для awk, bash, basic, dart, fortran, go, lua, javascript, julia, kotlin, matlab, perl, pascal, php, python, R, raku, ruby, rust, scala, swift, tcl и typescript.
.СЕТЬ
NDepend : инструмент статического анализа для кода .NET. Этот инструмент поддерживает большое количество метрик кода, позволяет визуализировать зависимости с помощью направленных графов и матрицы зависимостей.
PHP, Perl и Python
Devel::NYTProf: анализатор производительности Perl и генератор диаграмм вызовов
phpCallGraph : генератор графа вызовов для программ PHP, использующий Graphviz . Он написан на PHP и требует как минимум PHP 5.2.
pycallgraph Архивировано 25.05.2007 на Wayback Machine : генератор графа вызовов для программ на Python, использующий Graphviz .
pyan: статический генератор графа вызовов для программ на Python, использующий Graphviz .
gprof2dot: Генератор графа вызовов, написанный на Python, который преобразует данные профилирования для многих языков/сред выполнения в граф вызовов Graphviz .
code2flow: Генератор графа вызовов для программ Python и Javascript, использующий Graphviz
rcviz : Модуль Python для рендеринга графов вызовов, сгенерированных во время выполнения, с помощью Graphviz . Каждый узел представляет собой вызов функции с переданными ей параметрами и возвращаемым значением.
XQuery
Графы вызовов XQuery из XQuery Wikibook: Генератор графа вызовов для функционального модуля XQuery, использующего Graphviz
^ Каллахан, Д.; Карл, А.; Холл, М.В.; Кеннеди, К. (апрель 1990 г.). «Построение мультиграфа вызовов процедур». Труды IEEE по программной инженерии . 16 (4): 483–487. doi :10.1109/32.54302.
^ Удай Кхедкер; Амитабха Саньял; Багешри Сатхе (2009). Анализ потока данных: теория и практика . CRC Press. стр. 234. ISBN978-0-8493-3251-7.
^ Панкадж Джалоте (1997). Комплексный подход к программной инженерии . Springer Science & Business Media. стр. 372. ISBN978-0-387-94899-7.
^ Райдер, Б. Г. (май 1979 г.). «Построение графа вызовов программы». Труды IEEE по программной инженерии . SE-5 (3): 216–226. doi :10.1109/tse.1979.234183. S2CID 16527042.
^ Гроув, Дэвид; ДеФоу, Грег; Дин, Джеффри; Чемберс, Крейг; Гроув, Дэвид; ДеФоу, Грег; Дин, Джеффри; Чемберс, Крейг (9 октября 1997 г.). «Построение графа вызовов в объектно-ориентированных языках». ACM SIGPLAN Notices . 32 (10). ACM: 108, 108–124, 124. doi : 10.1145/263700.264352 .
^ Эйзенбарт, Т.; Кошке, Р.; Саймон, Д. (2001). «Помощь в понимании программ с помощью статического и динамического анализа признаков». Труды Международной конференции IEEE по обслуживанию программного обеспечения. ICSM 2001. С. 602–611. doi :10.1109/icsm.2001.972777. ISBN0-7695-1189-9. S2CID 5934718.
^ Гао, Дебин; Рейтер, Майкл К.; Сонг, Дон (25 октября 2004 г.). «Извлечение графов выполнения методом серого ящика для обнаружения аномалий». Труды 11-й конференции ACM по компьютерной и коммуникационной безопасности — CCS '04. ACM. стр. 318–329. doi :10.1145/1030083.1030126. ISBN1581139616. S2CID 1189805.