[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
introducing vrc :)
From: |
Paolo Bonzini |
Subject: |
introducing vrc :) |
Date: |
Tue, 19 Apr 2022 16:39:13 +0200 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.8.0 |
Hi all,
a while ago I looked at tools that could be used too build a call graph.
The simplest but most effective that I found was a small Perl program
(called "egypt", which is rot13 for "rtlcg" aka RTL call graph) that
used the GCC dumps to build the graph.
I have now rewritten it in Python and extended it with a lot of new
functionality:
- consult compile_commands.json to find/build dumps automatically
- virtual (manually created) nodes and edges
- query call graph in addition to generating DOT file
- interactive mode with readline + completion
The name is unfortunately not rot13 anymore, it stands for visit RTL
callgraph.
Here is an example (run vrc from the root build directory of QEMU):
# load files
load libblock.fa.p/*.c.o
# introduce virtual edges corresponding to function pointers
node BlockDriverState.bdrv_co_flush
edge bdrv_co_flush BlockDriverState.bdrv_co_flush
edge BlockDriverState.bdrv_co_flush blk_log_writes_co_do_file_flush
edge BlockDriverState.bdrv_co_flush preallocate_co_flush
edge BlockDriverState.bdrv_co_flush raw_co_invalidate_cache
edge BlockDriverState.bdrv_co_flush cbw_co_flush
edge BlockDriverState.bdrv_co_flush quorum_co_flush
edge BlockDriverState.bdrv_co_flush throttle_co_flush
edge BlockDriverState.bdrv_co_flush blkdebug_co_flush
edge BlockDriverState.bdrv_co_flush blkverify_co_flush
edge BlockDriverState.bdrv_co_flush bdrv_mirror_top_flush
# apply filter
only --callees bdrv_co_flush
# draw graph
dotty --files
The filtering functionality is a bit rough in the presence of mutual
recursion, but hopefully this can be already useful to find the root
calls of bdrv_*, which are the places where the graph lock has to be
taken for read. Continuing the previous example:
# apply another filter
reset
omit --callees bdrv_co_flush
keep bdrv_co_flush
# example of query
callers bdrv_co_flush
already gives a reasonable answer (not entirely correct, but the actual
analysis must be done on all callbacks at once):
qed_co_request -> bdrv_co_flush
qed_need_check_timer_entry -> bdrv_co_flush
blk_log_writes_co_log -> bdrv_co_flush
bdrv_co_flush_entry -> bdrv_co_flush
bdrv_co_flush -> bdrv_co_flush
blk_co_do_flush -> bdrv_co_flush
bdrv_driver_pwritev -> bdrv_co_flush
blk_co_flush -> bdrv_co_flush
bdrv_flush -> bdrv_co_flush
bdrv_co_do_pwrite_zeroes -> bdrv_co_flush
blk_aio_flush_entry -> bdrv_co_flush
Paolo
vrc
Description: Text document
- introducing vrc :),
Paolo Bonzini <=