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

Имам голямо работно пространство, което има много изходни файлове на C код. Въпреки че мога да видя функциите, извикани от функция в MS VS2005 с помощта на браузъра на обекти, и в MSVC 6.0 също, това показва само функции, извикани от определена функция в неграфичен вид дисплей. Освен това не показва извиканата функция, започваща от да речем main(), и след това извиканите от нея функции и така нататък, по-навътре до функцията на ниво лист.

Имам нужда от инструмент, който ще ми даде графична графика на извикване на функция с функции callee и caller, свързани със стрелки или нещо подобно, като се започне от main() до последното ниво на функцията или поне показва графика на извикване на всички функции в един C източник файл картинно. Би било чудесно, ако мога да отпечатам тази графика.

Има ли добри инструменти за това (не е необходимо да са безплатни инструменти)?


person goldenmean    schedule 05.02.2009    source източник
comment
Свързани: stackoverflow.com/a/17844310/1959808   -  person Ioannis Filippidis    schedule 03.05.2015
comment
en.wikipedia.org/wiki/Call_graph#Software   -  person 象嘉道    schedule 01.12.2020


Отговори (7)


person philant    schedule 05.02.2009
comment
qusetion относно CodeViz, ако предадете кода си на него, той ще генерира кода или не? Или вие сами трябва да направите графика от codevis? - person Mohammad Reza Rezwani; 05.04.2014
comment
Току-що опитах Египет. Графиката е ужасна. За другите не съм сигурен. - person ar2015; 28.05.2016

Методи за динамичен анализ

Тук описвам няколко метода за динамичен анализ.

Динамичните методи всъщност изпълняват програмата, за да определят графиката на повикванията.

Обратното на динамичните методи са статичните методи, които се опитват да го определят само от източника, без да стартират програмата.

Предимства на динамичните методи:

  • улавя указатели на функции и виртуални 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

Сега сте оставени в една страхотна програма с GUI, която съдържа много интересни данни за производителността.

Долу вдясно изберете раздела „Графика на обажданията“. Това показва интерактивна графика на повикванията, която корелира с показателите за ефективност в други прозорци, докато щракнете върху функциите.

За да експортирате графиката, щракнете с десния бутон върху нея и изберете „Експортиране на графика“. Експортираният 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
comment
Само имайте предвид, че динамичната графика на повикванията обхваща само едно изпълнение на програмата. - person smwikipedia; 30.09.2018
comment
@smwikipedia да, надстроих отговора, за да го направя по-ясно - person Ciro Santilli 新疆再教育营六四事件ۍ 30.09.2018
comment
Също така обяснено тук - stackoverflow.com/questions/311840/ - person tauseef_CuriousGuy; 18.03.2019

Understand върши много добра работа при създаването на графики на обажданията.

person MattK    schedule 05.02.2009

Нашият DMS Software Reengineering Toolkit има static control/dataflow/points-to/call graph анализ, който е приложен към огромни системи (~~25 милиона реда) на C код и създаде такива графики на извиквания, включително функции, извикани чрез указатели на функции.

person Ira Baxter    schedule 04.12.2010
comment
А, хубаво, това е 2016 г. и сега се появява гласуващ против. Сигурен съм, че неговият отрицателен вот се основава на точна оценка, че този инструмент не може да направи това. Е, може би не. Със сигурност прави това, което OP поиска. - person Ira Baxter; 31.03.2016
comment
Гласувайте в подкрепа, за да се противопоставите на това. Не ме интересува дали е вашият софтуер или патентован, стига да върши работата :-) - person Ciro Santilli 新疆再教育营六四事件ۍ 12.04.2016

Можете да опитате CScope + tceetree + Graphviz.

person Fabio Visona'    schedule 21.08.2014
comment
Как да използвате тази комбинация, за да получите графиката, има ли урок или поне някакво обяснение. - person Muhammad Yusuf; 31.12.2018
comment
@Muhammad Yusuf, да, има уики страница. - person BillyJoe; 02.01.2019

Можете да разгледате моя базиран на bash C генератор на дърво за повиквания тук. Позволява ви да посочите една или повече C функции, за които искате информация за повикващия и/или извикания, или можете да посочите набор от функции и да определите графиката на достижимост на извикванията на функции, която ги свързва... Т.е. кажете ми всички начини, по които са свързани main(), foo() и bar(). Той използва graphviz/dot за графичен двигател.

person Jason Nyberg    schedule 03.07.2015

Astrée е най-стабилният и усъвършенстван инструмент, IMHO.

person ЯegDwight    schedule 17.02.2009