To test & explore gcov/lcov functionality for kernel modules, here are the steps I used:
- I wanted to get coverage for two simple kernel modules - character driver with a user space counterpart & a hello LKM. Here is the code: https://github.com/babuneelam/gcov_kspace_tests.
- Re-compile the kernel with GCOV functionality enabled. To enable Gcov functionality in kernel, enable CONFIG_DEBUG_FS, CONFIG_GCOV_KERNEL, CONFIG_GCOV_FORMAT_AUTODETECT and CONFIG_GCOV_PROFILE_ALL (if entire linux kernel requires coverage). If "make menuconfig" is ued, the following screens screens help to enable gcov in kernel:
- To instrument the code with gcov, I enabled gcov compilation flags in the makefile of simple_krn_drv & simple_test_app, but left out hello_lkm. I also turned off any gcc optimization by removing "O" flags :
root@babu-VirtualBox:~/gcov_tests/lkm# grep -irne "-fprofile-arcs" *
simple_krn_drv/Makefile:5:CFLAGS=-ftest-coverage -fprofile-arcs --disable-initfini-array
simple_test_app/Makefile:6:CFLAGS = -fPIC -pedantic -fprofile-arcs -ftest-coverage -march=native -ggdb3
root@babu-VirtualBox:~/gcov_tests/lkm#
simple_krn_drv/Makefile:5:CFLAGS=-ftest-coverage -fprofile-arcs --disable-initfini-array
simple_test_app/Makefile:6:CFLAGS = -fPIC -pedantic -fprofile-arcs -ftest-coverage -march=native -ggdb3
root@babu-VirtualBox:~/gcov_tests/lkm#
- I compiled all the kernel modules & the user space test application.
- After compilation, I see that gcc generated .gcov files in the two kernel modules instrumented with gcov flags:
root@babu-VirtualBox:~/gcov_tests/lkm# find . -type f -name "*.gcno"
./simple_krn_drv/.tmp_simple_dev.gcno
./simple_krn_drv/simple_dev.mod.gcno
./simple_test_app/simple_hello.gcno
root@babu-VirtualBox:~/gcov_tests/lkm#
./simple_krn_drv/.tmp_simple_dev.gcno
./simple_krn_drv/simple_dev.mod.gcno
./simple_test_app/simple_hello.gcno
root@babu-VirtualBox:~/gcov_tests/lkm#
- The gcov run time date is not available before I inserted my kernel modules:
reset usr var
root@babu-VirtualBox:~/gcov_tests/lkm#
- Test modules: Insert LKMs, run the simple_test_app
- Merge run time coverage information from debugfs to build directory.
- I have automated this step using a script tool - https://github.com/babuneelam/gcov_scripts/blob/master/fetch_n_merge_gcov. One can use this script tool on build machine in any build sub-directory to update corresponding directory's run time coverage info from the test machine. Below is the usage info of this script.
root@babu-VirtualBox:~/gcov_tests/lkm# ./fetch_n_merge_gcov
Usage: fetch_n_merge_gcov --[local/remote] --kinfo --uinfo
[--kp <kdir_prefix>] [--up <udir_prefix>]
Execute this script from any build sub-directory to update
corresponding run time coverage info
root@babu-VirtualBox:~/gcov_tests/lkm#
- As my test & build machine are both same, I used this with "--local --kinfo" options.
root@babu-VirtualBox:~/gcov_tests/lkm# ./fetch_n_merge_gcov --local --kinfo
Is /home/babu/gcov_tests/lkm the build sub-directory you want to update run time coverage info with? : (y/n)?y
Deleting old run time runtime info in build directory: /home/babu/gcov_tests/lkm
/home/babu/gcov_tests/lkm/simple_krn_drv/simple_dev.gcda
/home/babu/gcov_tests/lkm/simple_test_app/simple_hello.gcda
Importing new kspace coverage run time info from test device....
Treating /sys/kernel/debug/gcov/ as top level kspace gcov directory in test machine
mount: none already mounted or /sys/kernel/debug/ busy
mount: according to mtab, none is already mounted on /sys/kernel/debug
Merging new kspace coverage run time info to the build directory....
/home/babu/gcov_tests/lkm/simple_krn_drv/simple_dev.gcda
root@babu-VirtualBox:~/gcov_tests/lkm#
- In case the test machine is different from the build machine, use this script with "--remote --kinfo" options.
- Then, from my top build directory, I ran the following lcov commands:
root@babu-VirtualBox:~/gcov_tests/lkm# geninfo . -o ./coverage.info
Found gcov version: 4.8.1
Scanning . for .gcda files ...
Found 2 data files in .
Processing simple_krn_drv/simple_dev.gcda
Cannot open source file include/linux/fs.h
Processing hello_lkm/hello.gcda
Finished .info-file creation
root@babu-VirtualBox:~/gcov_tests/lkm#
root@babu-VirtualBox:~/gcov_tests/lkm# genhtml -o ./lcov_data/ ./coverage.info
Reading data file ./coverage.info
Found 4 entries.
Found common filename prefix "/home/babu/gcov_tests/lkm/simple_krn_drv"
Writing .css and .png files.
Generating output.
Processing file /home/babu/gcov_tests/lkm/hello_lkm/hello.c
Processing file simple_dev.c
Processing file include/linux/fs.h
Processing file /usr/src/linux-3.13.5/arch/x86/include/asm/uaccess.h
Writing directory view page.
Overall coverage rate:
lines......: 23.1% (9 of 39 lines)
functions..: 28.6% (2 of 7 functions)
branches...: 11.1% (1 of 9 branches)
root@babu-VirtualBox:~/gcov_tests/lkm#
- I used firefox to view code coverage information of my tests.
root@babu-VirtualBox:~/gcov_tests# firefox ./lcov_data/index.html
- For reference, I hosted my code coverage results on my google drive - https://googledrive.com/host/0B4xkNcpT6ZbdaEJrelEtTk1uODA/. Here is the top level screen:
- Among the two kernel modules I have, lcov report included only one module instrumented with gcov. So, engineers should NOT be hasty in concluding the coverage information based on just lcov report, but should cautiously check whether all the code expected to be compiled with gocv flags is compiled so. Any code that is not compiled with gcov flags should be categorized "unknown coverage".
Hope this helps.
3 comments:
I have tried similar thing. we got gcno.a created on remote board. But we see issue with linking.
gcno.a links to some directory which referencing build system path. I tried to remove link and recreate, but It doesnt permit to do so.
I have also copied same directory and files at concerned location of symbolic link. But it didnt help.
Can you please advise what might be wrong?
Thanks,
Tejas
tried it on arm target. when kernel modules are loaded into target,simple_dev.gcno and simple_dev.gcda is generated, but both files seems to be empty and no use. So we cannot run the gcov command against the simple_dev.c file to generate coverage data.
I have the same question as Tejas and Chaitanya. Can you help?
Post a Comment