I am trying to create a code coverage tool using Delphi 2007.
My general approach is to use the Win32 Debug API to insert breakpoints for each source line and then remove the breakpoints as I pass them – thus I would be able to track each executed source line.
Outline of my approach:
- parse the detailed MAP file (as generated by Delphi 2007) to find all the addresses for each source line (only for .text segments)
- open the application in debug mode using the OpenProcess API call
- iterate over each source line and insert an Int3 instruction (one $cc byte using WriteProcessMemory + FlushInstructionCache) at the address of each line
- continue executing and as each breakpoint is triggered, remove the corresponding breakpoint and mark the line as covered
- After either each breakpoint is passed or program exists I generate a report on what lines were covered and which lines were not for each source module
Now on to my question:
Is each source line address in a detailed MAP file a valid address to insert an Int3 breakpoint?
While the approach was successful for some simple units, I run in to access violations for some larger applications where the violated address includes a $cc – which would lead me to think that my approach needs some modification to work.
Hints on better approaches also very welcome!
Well, in theory: yes. And practical, I think yes too. If Delphi can place a breakpoint on every line, so can you :-).
Probably you need some specific handling for some case (for example: first line of a procedure is initialization of local vars, setting EBP etc).
So can you find out in which case it fails?
Btw: nice project! Is it open source?
P.S. if you need some assembly code handling: look at koldetours.pas (use google search).