|
| 1 | +# gcov Demo |
| 2 | + |
| 3 | +[gcov](https://gcc.gnu.org/onlinedocs/gcc/Gcov.html) is a tool for coverage testing, i.e. showing whether a given line in a program was called and how many times. |
| 4 | +It's used to profile the program and let you know what are the hot areas in the program that could be made more efficient. |
| 5 | + |
| 6 | +This is a demo of using gcov on an implementation of the [IDEA encryption algorithm](https://en.wikipedia.org/wiki/International_Data_Encryption_Algorithm). |
| 7 | +The original source code is [here](https://github.com/bgreenlee/PassKeeper). |
| 8 | +Minor updates were added to fix compiling errors and warnings. A `Makefile` was added. |
| 9 | + |
| 10 | +To test gcov, run `make` to build the program into the `idea` executable file: |
| 11 | + |
| 12 | +``` |
| 13 | +$ make |
| 14 | +cc -Wall -m32 -fprofile-arcs -ftest-coverage -DTEST -c -o idea.o idea.c |
| 15 | +cc -m32 -fprofile-arcs -ftest-coverage idea.o -o idea |
| 16 | +$ ls |
| 17 | +idea idea.c idea.gcno idea.h idea.o Makefile README.md |
| 18 | +``` |
| 19 | + |
| 20 | +An `idea.gcno` file is also generated (gcov notes). |
| 21 | +As told in the [official documentation](https://gcc.gnu.org/onlinedocs/gcc/Gcov-Data-Files.html), the `.gcno file` is a platform-independent static representation of the program, i.e. the control flow graph: basic blocks and arcs between basic blocks. |
| 22 | + |
| 23 | +Running the program provides the runtime information in the `idea.gcda` file: |
| 24 | + |
| 25 | +``` |
| 26 | +$ ./idea |
| 27 | +[...] |
| 28 | +$ ls |
| 29 | +idea idea.c idea.gcda idea.gcno idea.h idea.o Makefile README.md |
| 30 | +``` |
| 31 | + |
| 32 | +The `.gcda` file is a platform-independent representation of the runtime profiling information, i.e. arc transition counts between basic blocks. |
| 33 | + |
| 34 | +gcov then provides a human-readable view of the profiling information based on the two files (`.gcno` and `.gcda`), resulting in a `.gcov` file. |
| 35 | + |
| 36 | +``` |
| 37 | +razvan@yggdrasil:~/projects/snippets.git/gcov$ gcov idea.c |
| 38 | +File 'idea.c' |
| 39 | +Lines executed:97.32% of 149 |
| 40 | +Creating 'idea.c.gcov' |
| 41 | +
|
| 42 | +razvan@yggdrasil:~/projects/snippets.git/gcov$ ls |
| 43 | +idea idea.c idea.c.gcov idea.gcda idea.gcno idea.h idea.o Makefile README.md |
| 44 | +razvan@yggdrasil:~/projects/snippets.git/gcov$ less idea.c.gcov |
| 45 | +``` |
| 46 | + |
| 47 | +The `idea.c.gcov` file lists the program source code together with the number of times each line was called. |
| 48 | + |
| 49 | +Additional information is provided by using certain options to the `gcov` command: |
| 50 | + |
| 51 | +``` |
| 52 | +razvan@yggdrasil:~/projects/snippets.git/gcov$ gcov -acf idea.c |
| 53 | +Function 'main' |
| 54 | +Lines executed:96.00% of 50 |
| 55 | +
|
| 56 | +Function 'ideaCipher' |
| 57 | +Lines executed:100.00% of 38 |
| 58 | +
|
| 59 | +Function 'ideaInvertKey' |
| 60 | +Lines executed:100.00% of 33 |
| 61 | +
|
| 62 | +Function 'ideaExpandKey' |
| 63 | +Lines executed:100.00% of 10 |
| 64 | +
|
| 65 | +Function 'mulInv' |
| 66 | +Lines executed:88.89% of 18 |
| 67 | +
|
| 68 | +File 'idea.c' |
| 69 | +Lines executed:97.32% of 149 |
| 70 | +Creating 'idea.c.gcov' |
| 71 | +``` |
| 72 | + |
| 73 | +[gcovr](https://github.com/gcovr/gcovr) can be used to present coverage information in different formats. |
| 74 | + |
| 75 | +## Custom Coverage |
| 76 | + |
| 77 | +It may be the case that coverage / profile information for only certain functions is of interest. |
| 78 | +gcov offers an API to reset and dump the coverage information (as told in the [official documentation](https://gcc.gnu.org/onlinedocs/gcc/Gcov-and-Optimization.html#Gcov-and-Optimization), thereby restricting colected information to the program sequence between `__gcov_reset()` and `__gcov_dump()` function calls. |
| 79 | + |
| 80 | +Update the `CPPFLAGS` variabile in the `Makefile` to use the `-DCUSTOM_GCOV` flag, i.e. the first two lines of the `Makefile` should be: |
| 81 | + |
| 82 | +``` |
| 83 | +#CPPFLAGS = -DTEST |
| 84 | +CPPFLAGS = -DTEST -DCUSTOM_GCOV |
| 85 | +``` |
| 86 | + |
| 87 | +The `CUSTOM_GCOV` flag will restrict the coverage information to the following program sequence: |
| 88 | + |
| 89 | +``` |
| 90 | + 340 #ifdef CUSTOM_GCOV |
| 91 | + 341 __gcov_reset(); |
| 92 | + 342 #endif |
| 93 | + 343 for (l = 0; l < BLOCKS; l++) |
| 94 | + 344 ideaCipher(YY, YY, EK); /* repeated encryption */ |
| 95 | + 345 #ifdef CUSTOM_GCOV |
| 96 | + 346 __gcov_dump(); |
| 97 | + 347 #endif |
| 98 | +``` |
| 99 | + |
| 100 | +Now rebuild and rerun the program: |
| 101 | +``` |
| 102 | +$ make clean |
| 103 | +$ make |
| 104 | +$ ./idea |
| 105 | +``` |
| 106 | + |
| 107 | +The coverage information will now be limited to the calls of the `ideaCipher()` function in the loop in lines `343` and `344`. |
| 108 | + |
| 109 | +## Internals |
| 110 | + |
| 111 | +The `.gcda` file is by default created at runtime in the current working directory. |
| 112 | +This can be changed by using the `-fprofile-dir` command line option to `gcc`. |
| 113 | + |
| 114 | +The `.gcno` file is created by the compiler when using the `-ftest-coverage` command line option to `gcc`. |
| 115 | +It is technically not required for coverage information, as is the case with the `.gcda` file; the `.gcno` file is used as a support file by `gcov` to provide a human-readable view of the profiling information. |
| 116 | +PGO (*Profile Guided Optimization*) uses only `.gcda` files. |
| 117 | + |
| 118 | +The format of the `.gcda` and `.gcno` files is documented in the [gcov-io.h file](http://src.gnu-darwin.org/src/contrib/gcc/gcov-io.h.html) and parsed and used in the [gcov-io.c file](http://src.gnu-darwin.org/src/contrib/gcc/gcov-io.c.html). |
0 commit comments