简简单单的生活,简简单单的我
分类: C/C++
2017-04-12 09:32:01
linux下查看C语言函数的调用关系,可以通过如下工具进行:使用方法:
1、将附件中的文件修改为sh格式
2、执行如下命令:
bash callgraph.sh [ 関数名 ] [ calls | is_called ]
※calls : [関数名]が呼んでいる関数を、再起検索。
※is_called : [関数名]の呼び出し元を、再起検索。
★使用附件中的工具时,需要配置一下cscope,配置方法请参考:
http://blog.csdn.net/daofengdeba/article/details/7606616
当然,网上也有好多其他的类似的配置手顺
配置完成cscope之后,就可以在linux上通过vi工具查看代码时
达到eclipse或者sourceInsight工具的效果
callgraph.sh 的脚本请参考如下:
=========================================================================
=========================================================================:
# callgraph.sh V1.1
#
# callgraph generation tool produced by shibata
#
# [history]
# V1.0 初版作成 柴田
# V1.1 下記の修正 谷口(康)
# ヘルプの不具合若干修正
# コマンド名称をcallgraph.shに変更
# 動作モードパラメタをcalls, is_calledでも指定可能に
# #ifdef defined()が不当に認識されるcscopeの問題対応
# プログレスドット表示
# V1.2 正規表現時に出力ファイルを削除する現象の修正 柴田
#第一引数に与えられた関数が呼び出す関数を再帰的にリスト化。
#
#使い方
#1、cscopeが利用できるディレクトリ(ソース配置ディレクトリ)に、本スクリプトを配置。
#2、cscope -RでDB作成済みであることを確認。
#3、callgraph.sh [検索対象関数名] を実行。しばし待つ。※上位層の関数の場合完了まで30min程度かかる場合があり。
# 自動的に、同ディレクトリに、callgraphディレクトリ callgraph/[関数名].csvが作成されます。
#おまけ、
# 事前にcallgraphディレクトリを作成し、callgraph/reject_list.txtに検索から除外したい関数名を一行ずつ列挙することで、
# 検索対象外とすることが出来ます。
# 例えば、エラー後の処理は考慮しなくていいや。といったときには、
# callgraph/reject_list.txtにCcrIErrFindを記述しておく
# OS関数より低い情報はいらないや。といったときには、
# printf
# write
# read
# :などなどを記述しておく。
#
#注意事項:?再起呼び出しの検索による、無限ループ防止のため、
# 一度検索を始めた関数は検索対象から外します。
# (枝分かれ先で、同一の関数を重複して呼び出した場合、
# 先に検索を始めた方しか、追検索されません)
# ?一時的に、ファイル容量をがっぽり使います。
if [ $# -ne 2 ];then
echo "usage: callgraph.sh [function_name] [is_called | calls]"
exit
fi
OPT=$2
if [ "$2" = "calls" ];then
OPT=2
elif [ "$2" = "is_called" ];then
OPT=3
fi
if [ $OPT -ne 2 ] && [ $OPT -ne 3 ];then
echo "usage: callgraph.sh [function_name] [is_called | calls]"
exit
fi
BASENAME=callgraph
DIRNAME=${BASENAME}
# 前回の実行で途中で処理をkillした場合の対処
rm -rf ${DIRNAME}/$1
#大元(入力された関数)のディレクトリ作成&csope
mkdir -p ${DIRNAME}/$1
# エントリ関数の検索を実施
# ifdefディレクティブで使われる"defined"演算子はcscopeに誤認識
# されるので除外
cscope -d -L -$OPT $1 |awk '{print $2}'|sort -u | grep -v "^defined$">${DIRNAME}/$1.txt
cat ${DIRNAME}/reject_list.txt >${DIRNAME}/tmp.txt >& /dev/null
echo "It may take 30 minutes or more in the worst case."
while true
do
printf "."
#DIRNAME配下に、ファイルが無くなったら、終わる。
ls ${DIRNAME}/*.txt > /dev/null /dev/null 2>&1
if [ $? -ne 0 ];then
find ${BASENAME}/$1 -name "*.txt" -exec rm {} \; > /dev/null 2>&1
find ${BASENAME}/$1 -type d -links 2|sed -e "s/\//\,/g" 1>${BASENAME}/${1}.csv 2>/dev/null
tree ${BASENAME}/$1 >${BASENAME}/$1_tree.log
rm ${BASENAME}/${1}.txt > /dev/null 2>&1
rm -rf ${BASENAME}/${1}/ > /dev/null 2>&1
exit
fi
#DIRNAME配下の、ファイルpath付きを変数fileに格納
ls ${DIRNAME}/*.txt|grep -v "tmp.txt\|reject_list.txt" \
| while true
do
read file ||exit
#DIRNAME2に、ファイル名(.txt)省きを格納
DIRNAME2=${file%.txt}
printf "."
#ファイルの中身を一行ずつ読む
cat "$file" \
| while true
do
read line || exit
#関数名ディレクトリ作成
mkdir -p ${DIRNAME2}/${line}
printf "."
#既検索または除外リストにあるかチェック
grep "^$line$" ${BASENAME}/tmp.txt > /dev/null 2>&1
if [ $? -eq 0 ]
then
:
else
#チェックではじかれなければ、cscope実行
# ifdefディレクティブで使われる"defined"演算子はcscopeに誤認識
# されるので除外
cscope -d -L -$OPT $line |awk '{print $2}'|sort -u | grep -v "^defined$" >${DIRNAME2}/$line.txt
fi
done
#既検索リスト更新(再起呼び出し対応)
(cat ${file} ${BASENAME}/reject_list.txt ${BASENAME}/tmp.txt|sort -u >${BASENAME}/tmp2.txt ) >& /dev/null
mv ${BASENAME}/tmp2.txt ${BASENAME}/tmp.txt
done
#調査対象を一階層掘り下げる
DIRNAME="${DIRNAME}/*"
done