~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/Documentation/translations/zh_TW/dev-tools/gcov.rst

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 .. include:: ../disclaimer-zh_TW.rst
  2 
  3 :Original: Documentation/dev-tools/gcov.rst
  4 :Translator: 趙軍奎 Bernard Zhao <bernard@vivo.com>
  5 
  6 在Linux內核裏使用gcov做代碼覆蓋率檢查
  7 =====================================
  8 
  9 gcov分析核心支持在Linux內核中啓用GCC的覆蓋率測試工具 gcov_ ,Linux內核
 10 運行時的代碼覆蓋率數據會以gcov兼容的格式導出到“gcov”debugfs目錄中,可
 11 以通過gcov的 ``-o`` 選項(如下示例)獲得指定文件的代碼運行覆蓋率統計數據
 12 (需要跳轉到內核編譯路徑下並且要有root權限)::
 13 
 14     # cd /tmp/linux-out
 15     # gcov -o /sys/kernel/debug/gcov/tmp/linux-out/kernel spinlock.c
 16 
 17 這將在當前目錄中創建帶有執行計數註釋的源代碼文件。
 18 在獲得這些統計文件後,可以使用圖形化的gcov前端工具(比如 lcov_ ),來實現
 19 自動化處理Linux內核的覆蓋率運行數據,同時生成易於閱讀的HTML格式文件。
 20 
 21 可能的用途:
 22 
 23 * 調試(用來判斷每一行的代碼是否已經運行過)
 24 * 測試改進(如何修改測試代碼,儘可能地覆蓋到沒有運行過的代碼)
 25 * 內核最小化配置(對於某一個選項配置,如果關聯的代碼從來沒有運行過,
 26   是否還需要這個配置)
 27 
 28 .. _gcov: https://gcc.gnu.org/onlinedocs/gcc/Gcov.html
 29 .. _lcov: http://ltp.sourceforge.net/coverage/lcov.php
 30 
 31 
 32 準備
 33 ----
 34 
 35 內核打開如下配置::
 36 
 37         CONFIG_DEBUG_FS=y
 38         CONFIG_GCOV_KERNEL=y
 39 
 40 獲取整個內核的覆蓋率數據,還需要打開::
 41 
 42         CONFIG_GCOV_PROFILE_ALL=y
 43 
 44 需要注意的是,整個內核開啓覆蓋率統計會造成內核鏡像文件尺寸的增大,
 45 同時內核運行也會變慢一些。
 46 另外,並不是所有的架構都支持整個內核開啓覆蓋率統計。
 47 
 48 代碼運行覆蓋率數據只在debugfs掛載完成後纔可以訪問::
 49 
 50         mount -t debugfs none /sys/kernel/debug
 51 
 52 
 53 定製化
 54 ------
 55 
 56 如果要單獨針對某一個路徑或者文件進行代碼覆蓋率統計,可以在內核相應路
 57 徑的Makefile中增加如下的配置:
 58 
 59 - 單獨統計單個文件(例如main.o)::
 60 
 61     GCOV_PROFILE_main.o := y
 62 
 63 - 單獨統計某一個路徑::
 64 
 65     GCOV_PROFILE := y
 66 
 67 如果要在整個內核的覆蓋率統計(開啓CONFIG_GCOV_PROFILE_ALL)中單獨排除
 68 某一個文件或者路徑,可以使用如下的方法::
 69 
 70     GCOV_PROFILE_main.o := n
 71 
 72 和::
 73 
 74     GCOV_PROFILE := n
 75 
 76 此機制僅支持鏈接到內核鏡像或編譯爲內核模塊的文件。
 77 
 78 
 79 相關文件
 80 --------
 81 
 82 gcov功能需要在debugfs中創建如下文件:
 83 
 84 ``/sys/kernel/debug/gcov``
 85     gcov相關功能的根路徑
 86 
 87 ``/sys/kernel/debug/gcov/reset``
 88     全局復位文件:向該文件寫入數據後會將所有的gcov統計數據清0
 89 
 90 ``/sys/kernel/debug/gcov/path/to/compile/dir/file.gcda``
 91     gcov工具可以識別的覆蓋率統計數據文件,向該文件寫入數據後
 92           會將本文件的gcov統計數據清0
 93 
 94 ``/sys/kernel/debug/gcov/path/to/compile/dir/file.gcno``
 95     gcov工具需要的軟連接文件(指向編譯時生成的信息統計文件),這個文件是
 96     在gcc編譯時如果配置了選項 ``-ftest-coverage`` 時生成的。
 97 
 98 
 99 針對模塊的統計
100 --------------
101 
102 內核中的模塊會動態的加載和卸載,模塊卸載時對應的數據會被清除掉。
103 gcov提供了一種機制,通過保留相關數據的副本來收集這部分卸載模塊的覆蓋率數據。
104 模塊卸載後這些備份數據在debugfs中會繼續存在。
105 一旦這個模塊重新加載,模塊關聯的運行統計會被初始化成debugfs中備份的數據。
106 
107 可以通過對內核參數gcov_persist的修改來停用gcov對模塊的備份機制::
108 
109         gcov_persist = 0
110 
111 在運行時,用戶還可以通過寫入模塊的數據文件或者寫入gcov復位文件來丟棄已卸
112 載模塊的數據。
113 
114 
115 編譯機和測試機分離
116 ------------------
117 
118 gcov的內核分析插樁支持內核的編譯和運行是在同一臺機器上,也可以編譯和運
119 行是在不同的機器上。
120 如果內核編譯和運行是不同的機器,那麼需要額外的準備工作,這取決於gcov工具
121 是在哪裏使用的:
122 
123 .. _gcov-test_zh:
124 
125 a) 若gcov運行在測試機上
126 
127     測試機上面gcov工具的版本必須要跟內核編譯機器使用的gcc版本相兼容,
128     同時下面的文件要從編譯機拷貝到測試機上:
129 
130     從源代碼中:
131       - 所有的C文件和頭文件
132 
133     從編譯目錄中:
134       - 所有的C文件和頭文件
135       - 所有的.gcda文件和.gcno文件
136       - 所有目錄的鏈接
137 
138     特別需要注意,測試機器上面的目錄結構跟編譯機器上面的目錄機構必須
139     完全一致。
140     如果文件是軟鏈接,需要替換成真正的目錄文件(這是由make的當前工作
141     目錄變量CURDIR引起的)。
142 
143 .. _gcov-build_zh:
144 
145 b) 若gcov運行在編譯機上
146 
147     測試用例運行結束後,如下的文件需要從測試機中拷貝到編譯機上:
148 
149     從sysfs中的gcov目錄中:
150       - 所有的.gcda文件
151       - 所有的.gcno文件軟鏈接
152 
153     這些文件可以拷貝到編譯機的任意目錄下,gcov使用-o選項指定拷貝的
154     目錄。
155 
156     比如一個是示例的目錄結構如下::
157 
158       /tmp/linux:    內核源碼目錄
159       /tmp/out:      內核編譯文件路徑(make O=指定)
160       /tmp/coverage: 從測試機器上面拷貝的數據文件路徑
161 
162       [user@build] cd /tmp/out
163       [user@build] gcov -o /tmp/coverage/tmp/out/init main.c
164 
165 
166 關於編譯器的注意事項
167 --------------------
168 
169 GCC和LLVM gcov工具不一定兼容。
170 如果編譯器是GCC,使用 gcov_ 來處理.gcno和.gcda文件,如果是Clang編譯器,
171 則使用 llvm-cov_ 。
172 
173 .. _gcov: https://gcc.gnu.org/onlinedocs/gcc/Gcov.html
174 .. _llvm-cov: https://llvm.org/docs/CommandGuide/llvm-cov.html
175 
176 GCC和Clang gcov之間的版本差異由Kconfig處理的。
177 kconfig會根據編譯工具鏈的檢查自動選擇合適的gcov格式。
178 
179 問題定位
180 --------
181 
182 可能出現的問題1
183     編譯到鏈接階段報錯終止
184 
185 問題原因
186     分析標誌指定在了源文件但是沒有鏈接到主內核,或者客製化了鏈接程序
187 
188 解決方法
189     通過在相應的Makefile中使用 ``GCOV_PROFILE := n``
190     或者 ``GCOV_PROFILE_basename.o := n`` 來將鏈接報錯的文件排除掉
191 
192 可能出現的問題2
193     從sysfs複製的文件顯示爲空或不完整
194 
195 問題原因
196     由於seq_file的工作方式,某些工具(例如cp或tar)可能無法正確地從
197     sysfs複製文件。
198 
199 解決方法
200     使用 ``cat`` 讀取 ``.gcda`` 文件,使用 ``cp -d`` 複製鏈接,或者使用附錄B
201     中所示的機制。
202 
203 
204 附錄A:collect_on_build.sh
205 --------------------------
206 
207 用於在編譯機上收集覆蓋率元文件的示例腳本
208 (見 :ref:`編譯機和測試機分離 a. <gcov-test_zh>` )
209 
210 .. code-block:: sh
211 
212     #!/bin/bash
213 
214     KSRC=$1
215     KOBJ=$2
216     DEST=$3
217 
218     if [ -z "$KSRC" ] || [ -z "$KOBJ" ] || [ -z "$DEST" ]; then
219       echo "Usage: $0 <ksrc directory> <kobj directory> <output.tar.gz>" >&2
220       exit 1
221     fi
222 
223     KSRC=$(cd $KSRC; printf "all:\n\t@echo \${CURDIR}\n" | make -f -)
224     KOBJ=$(cd $KOBJ; printf "all:\n\t@echo \${CURDIR}\n" | make -f -)
225 
226     find $KSRC $KOBJ \( -name '*.gcno' -o -name '*.[ch]' -o -type l \) -a \
227                      -perm /u+r,g+r | tar cfz $DEST -P -T -
228 
229     if [ $? -eq 0 ] ; then
230       echo "$DEST successfully created, copy to test system and unpack with:"
231       echo "  tar xfz $DEST -P"
232     else
233       echo "Could not create file $DEST"
234     fi
235 
236 
237 附錄B:collect_on_test.sh
238 -------------------------
239 
240 用於在測試機上收集覆蓋率數據文件的示例腳本
241 (見 :ref:`編譯機和測試機分離 b. <gcov-build_zh>` )
242 
243 .. code-block:: sh
244 
245     #!/bin/bash -e
246 
247     DEST=$1
248     GCDA=/sys/kernel/debug/gcov
249 
250     if [ -z "$DEST" ] ; then
251       echo "Usage: $0 <output.tar.gz>" >&2
252       exit 1
253     fi
254 
255     TEMPDIR=$(mktemp -d)
256     echo Collecting data..
257     find $GCDA -type d -exec mkdir -p $TEMPDIR/\{\} \;
258     find $GCDA -name '*.gcda' -exec sh -c 'cat < $0 > '$TEMPDIR'/$0' {} \;
259     find $GCDA -name '*.gcno' -exec sh -c 'cp -d $0 '$TEMPDIR'/$0' {} \;
260     tar czf $DEST -C $TEMPDIR sys
261     rm -rf $TEMPDIR
262 
263     echo "$DEST successfully created, copy to build system and unpack with:"
264     echo "  tar xfz $DEST"
265 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php