코드의 그림 함수 호출 그래프를 얻는 도구 [닫힘]


107

C 코드의 소스 파일이 많은 작업 공간이 넓습니다. 개체 브라우저를 사용하여 MS VS2005 및 MSVC 6.0의 함수에서 호출 된 함수를 볼 수 있지만 이것은 그래픽이 아닌 종류의 디스플레이에서 특정 함수에서 호출 된 함수 만 표시합니다. 또한 say main()에서 시작하여 호출 된 함수를 표시하지 않고 리프 수준 함수의 내부에서 호출되는 함수 등을 표시하지 않습니다 .

함수가있는 함수 호출 그래프를 그림으로 제공 callee하고 함수 의 마지막 수준 caller에서 시작하여 화살표 등으로 연결 main()하거나 적어도 하나의 C 소스 파일에있는 모든 함수의 호출 그래프를 그림으로 표시하는 도구가 필요합니다. 이 그래프를 인쇄 할 수 있다면 좋을 것입니다.

이를위한 좋은 도구가 있습니까 (무료 도구가 필요하지 않음)?


답변:



29

동적 분석 방법

여기에서는 몇 가지 동적 분석 방법을 설명합니다.

동적 메서드는 실제로 프로그램을 실행하여 호출 그래프를 결정합니다.

동적 메서드의 반대는 프로그램을 실행하지 않고 소스에서만 확인하려고하는 정적 메서드입니다.

동적 방법의 장점 :

  • 함수 포인터와 가상 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경량 "가상 머신"을 통해 코드를 실행하여이를 관리합니다. 이로 인해 기본 실행에 비해 실행 속도가 매우 느립니다.

그래프에서 볼 수 있듯이 각 함수 호출에 대한 타이밍 정보도 얻을 수 있으며, 이는 호출 그래프를 보는 것뿐만 아니라이 설정의 원래 사용 사례 인 프로그램을 프로파일 링하는 데 사용할 수 있습니다. 프로파일 링 방법 Linux에서 실행되는 C ++ 코드?

Ubuntu 18.04에서 테스트되었습니다.

gcc -finstrument-functions + etrace

https://github.com/elcritch/etrace

-finstrument-functions 콜백을 추가 하고 etrace는 ELF 파일을 구문 분석하고 모든 콜백을 구현합니다.

하지만 안타깝게도 작동하지 못했습니다. 왜`-finstrument-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

특정 하드웨어 추적 지원 외에 가장 효율적인 방법 일 수 있지만 코드를 다시 컴파일해야한다는 단점이 있습니다.


2
동적 호출 그래프는 프로그램의 한 번만 실행된다는 점에 유의하십시오.
smwikipedia

1
@smwikipedia 예, 나는 명확하게 답을 업그레이드 한
치로 틸리郝海东冠状病六四事件法轮功



9

우리의 DMS 소프트웨어 리엔지니어링 툴킷 은 거대한 C 코드 시스템 (~~ 2500 만 라인)에 적용된 정적 제어 / 데이터 흐름 / 포인트-투 / 호출 그래프 분석을 포함 하고 있으며 함수 포인터를 통해 호출되는 함수를 포함하여 이러한 호출 그래프를 생성했습니다 .


1
아, 좋네요, 2016 년과 이제 다운 보터가 나타납니다. 나는 그의 반대표가이 도구가 이것을 할 수 없다는 정확한 평가를 기반으로했다고 확신합니다. 글쎄, 아닐 수도 있습니다. OP가 요청한 것을 확실히 수행합니다.
Ira Baxter

1
반박하기 위해 찬성 투표를하십시오. 나는 그것이 일을 끝내는 한 그것이 당신의 소프트웨어이거나 독점적이라는 것을 신경 쓰지 않습니다 :-)
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功


5

여기에서 bash 기반 C 호출 트리 생성기를 확인할 수 있습니다 . 호출자 및 / 또는 호출 된 정보를 원하는 하나 이상의 C 함수를 지정하거나 함수 집합을 지정하고 이들을 연결하는 함수 호출의 도달 가능성 그래프를 결정할 수 있습니다. 즉, main ( ), foo (), bar ()가 연결됩니다. 그래프 엔진에 graphviz / dot를 사용합니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.