Alat untuk mendapatkan grafik panggilan fungsi bergambar dari kode [tertutup]


107

Saya memiliki ruang kerja besar yang memiliki banyak file sumber kode C. Meskipun saya dapat melihat fungsi yang dipanggil dari fungsi di MS VS2005 menggunakan browser Objek, dan di MSVC 6.0 juga, ini hanya menampilkan fungsi yang dipanggil dari fungsi tertentu dalam jenis tampilan non-grafis. Selain itu, ia tidak menunjukkan fungsi yang dipanggil mulai dari say main(), lalu fungsi yang dipanggil darinya, dan seterusnya, lebih dalam ke fungsi tingkat daun.

Saya membutuhkan alat yang akan memberi saya grafik panggilan fungsi secara bergambar dengan fungsi calleedan callerdihubungkan oleh panah atau sesuatu seperti itu, mulai dari main()tingkat fungsi terakhir, atau setidaknya menunjukkan grafik panggilan semua fungsi dalam satu file sumber C secara bergambar. Akan sangat bagus jika saya bisa mencetak grafik ini.

Adakah alat yang bagus untuk melakukan itu (tidak perlu alat gratis)?


Jawaban:



29

Metode analisis dinamis

Di sini saya menjelaskan beberapa metode analisis dinamis.

Metode dinamis sebenarnya menjalankan program untuk menentukan grafik panggilan.

Kebalikan dari metode dinamis adalah metode statis, yang mencoba menentukannya dari sumber saja tanpa menjalankan program.

Keuntungan metode dinamis:

  • menangkap pointer fungsi dan panggilan C ++ virtual. Ini ada dalam jumlah besar di perangkat lunak non-sepele.

Kekurangan metode dinamis:

  • Anda harus menjalankan program, yang mungkin lambat, atau memerlukan pengaturan yang tidak Anda miliki, misalnya kompilasi silang
  • hanya fungsi yang benar-benar dipanggil yang akan ditampilkan. Misalnya, beberapa fungsi dapat dipanggil atau tidak, bergantung pada argumen baris perintah.

KcacheGrind

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

Program tes:

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;
}

Pemakaian:

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

Anda sekarang tertinggal di dalam program GUI yang luar biasa yang berisi banyak data kinerja yang menarik.

Di kanan bawah, pilih tab "Grafik panggilan". Ini menunjukkan grafik panggilan interaktif yang berkorelasi dengan metrik kinerja di jendela lain saat Anda mengeklik fungsi.

Untuk mengekspor grafik, klik kanan dan pilih "Export Graph". PNG yang diekspor terlihat seperti ini:

Dari situ kita dapat melihat bahwa:

  • node root adalah _start, yang merupakan titik masuk ELF sebenarnya, dan berisi boilerplate inisialisasi glibc
  • f0, f1dan f2dipanggil seperti yang diharapkan dari satu sama lain
  • pointedjuga ditampilkan, meskipun kami memanggilnya dengan penunjuk fungsi. Ini mungkin tidak akan dipanggil jika kita telah memberikan argumen baris perintah.
  • not_called tidak ditampilkan karena tidak dipanggil saat proses, karena kami tidak meneruskan argumen baris perintah tambahan.

Hal yang keren tentang itu valgrindadalah tidak memerlukan opsi kompilasi khusus.

Oleh karena itu, Anda dapat menggunakannya bahkan jika Anda tidak memiliki kode sumber, hanya yang dapat dieksekusi.

valgrindberhasil melakukannya dengan menjalankan kode Anda melalui "mesin virtual" yang ringan. Ini juga membuat eksekusi menjadi sangat lambat dibandingkan dengan eksekusi asli.

Seperti yang dapat dilihat pada grafik, informasi pengaturan waktu tentang setiap pemanggilan fungsi juga diperoleh, dan ini dapat digunakan untuk membuat profil program, yang kemungkinan merupakan kasus penggunaan asli dari pengaturan ini, tidak hanya untuk melihat grafik panggilan: Bagaimana saya dapat membuat profil Kode C ++ berjalan di Linux?

Diuji di Ubuntu 18.04.

gcc -finstrument-functions + etrace

https://github.com/elcritch/etrace

-finstrument-functions menambahkan callback , etrace mem-parsing file ELF dan mengimplementasikan semua callback.

Sayangnya, saya tidak bisa membuatnya berfungsi: Mengapa `-finstrument-functions` tidak berfungsi untuk saya?

Output yang diklaim dalam format:

\-- 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

Mungkin metode yang paling efisien selain dukungan penelusuran perangkat keras tertentu, tetapi memiliki sisi negatif bahwa Anda harus mengkompilasi ulang kode.


2
Perhatikan bahwa grafik panggilan dinamis hanya mencakup satu kali jalannya program.
smwikipedia

1
@smwikipedia ya, saya telah meningkatkan jawaban untuk membuatnya lebih jelas
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功



9

Perangkat Rekayasa Ulang Perangkat Lunak DMS kami memiliki analisis grafik kontrol / aliran data / titik-ke / panggilan statis yang telah diterapkan pada sistem besar (~~ 25 juta baris) kode C, dan menghasilkan grafik panggilan tersebut, termasuk fungsi yang dipanggil melalui penunjuk fungsi .


1
Ah, bagus, ini tahun 2016 dan sekarang ada downvoter yang muncul. Saya yakin downvote-nya didasarkan pada penilaian yang akurat bahwa alat ini tidak dapat melakukan ini. Mungkin tidak. Itu pasti melakukan apa yang diminta OP.
Ira Baxter

1
Ambil suara positif untuk melawannya. Saya tidak peduli itu perangkat lunak atau hak milik Anda selama itu menyelesaikan pekerjaan :-)
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功


5

Anda dapat melihat generator pohon panggilan C berbasis bash saya di sini . Ini memungkinkan Anda menentukan satu atau lebih fungsi C yang Anda ingin pemanggil dan / atau disebut informasinya, atau Anda dapat menentukan sekumpulan fungsi dan menentukan grafik jangkauan panggilan fungsi yang menghubungkannya ... Yaitu beri tahu saya semua cara main ( ), foo (), dan bar () terhubung. Ini menggunakan graphviz / dot untuk mesin grafik.


Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.