Wednesday, March 02, 2011

Test Code Coverage with Objdump and Valgrind

I was working on a C++ project recently where gcov inexplicitly failed to report correct results, especially for template files. Some templated code was incorrectly being reported as not-covered by my tests. Instead of doing the right thing by finding out why gcov was not working with my source code, I decided to write a python script that combined the outputs of objdump and valgrind into a test coverage report. It worked well enough and I thought I would share it.  Here is an extract of a test coverage report:

---------------------------------
File: HTTPmsg.h
Code not executed in: HTTPmsg<TCPfragmsg>::getContentEncoding() const
line no: 110

Code not executed in: HTTPmsg<TCPfragmsg>::DJBHash(char const*, char const*)
line no: 271

Code not executed in: HTTPmsg<TCPmsg>::isCandidateRequest() const
line no: 215

Code not executed in: HTTPmsg<TCPfragmsg>::isCandidateResponse() const
line no: 236 238 239 242 248 251 252

Code not executed in: HTTPmsg<TCPfragmsg>::getContentDirection() const
line no: 105

Compiled lines: 82, Not executed: 11
Code coverage:  86%
---------------------------------

The script can be found here: coverage

Tested on objdump (GNU Binutils for Ubuntu) 2.20.1 and valgrind-3.6.0.SVN-Debian.


Below, you can see the output of objdump and valgrind's for the 'isCandidateRequest' member function. The objdump output describes what code was compiled and the output of callgrind describes what code was executed. The script works by checking for common line numbers between them. Line numbers that appear in the object dump and not in the valgrind output are marked as non-executed source code.

objdump:  'isCandidateRequest' member function:

080e9498 <HTTPmsg<TCPmsg>::isCandidateRequest() const>:
_ZNK7HTTPmsgI6TCPmsgE18isCandidateRequestEv():
/projects/conduits/conduits/HTTPmsg.h:203
 80e9498:       55                       push   %ebp
 80e9499:       89 e                    mov    %esp,%ebp
 80e949b:       83 e28                sub    $0x28,%esp
/projects/conduits/conduits/HTTPmsg.h:205
 80e949e:       8b 45 08              mov    0x8(%ebp),%eax
 80e94a1:       8b 80 e0 00         mov    0xe0(%eax),%eax
 80e94a7:       85 c0                   test   %eax,%eax
 80e94a9:       75 26                   jne    80e94d1 <HTTPmsg<TCPmsg>::isCandidateRequest() const+0x39>
/projects/conduits/conduits/HTTPmsg.h:206
 80e94ab:       b9 00 00 00 00    mov    $0x0,%ecx
 80e94b0:       a1 e8 7e 26 08    mov    0x8267ee8,%eax
 80e94b5:       8b 15 ec 7e 26    mov    0x8267eec,%edx
 80e94bb:       83 c0 01              add    $0x1,%eax
 80e94be:       83 d2 00              adc    $0x0,%edx
/projects/conduits/conduits/HTTPmsg.h:215
 80e9624:       b9 00 00 00 00    mov    $0x0,%ecx
 80e9629:       a1 20 7f 26 08     mov    0x8267f20,%eax
 80e962e:       8b 15 24 7f 26     mov    0x8267f24,%edx
 80e9634:       83 c0 01              add    $0x1,%eax
 80e9637:       83 d2 00              adc    $0x0,%edx
 80e963a:       a3 20 7f 26 08     mov    %eax,0x8267f20


Callgrind: 'isCandidateRequest' member function:

fn=HTTPmsg<TCPmsg>::isCandidateRequest() const
203 87
205 116
jcnd=29/29 206
205
206 174

Socializer Widget By Blogger Yard
SOCIALIZE IT →
FOLLOW US →
SHARE IT →

0 comments:

Post a Comment