[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: introducing vrc :)
From: |
Stefan Hajnoczi |
Subject: |
Re: introducing vrc :) |
Date: |
Wed, 20 Apr 2022 16:06:47 +0200 |
On Tue, Apr 19, 2022 at 04:39:13PM +0200, Paolo Bonzini wrote:
> 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
Cool, thanks for sharing. I will keep this in mind when I need to
analyze call graphs.
Stefan
signature.asc
Description: PGP signature