views:

187

answers:

1

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!

+1  A: 

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).

André
Not all code lines are executable code. For example the System._LStrToPChar function has data (@@zeroByte) in the code segment.
Andreas Hausladen
Andreas and André - thanks for answering. If the unit does not contain any ASM code would each line be valid? Even if I exclude all units with ASM code, it still crashes... Do you know of any way of determining if the code at the address is the start of an instruction?
Christer Fahlgren
And I have tried to figure out where it is crashing - but so far the root cause has eluded me... I would be happy to zip it up and let you guys look at it if you have the time. I intend to share it with the community with open source license if I get it to work.
Christer Fahlgren
You can easely make a Google Code project and upload your code there, I can take a look then.
André
André - accepting your answer - I managed to isolate the issue which was related to the map file having lines and addresses pointing to a different unit. My approach now works for non-assember code. I will upload to Google code as soon as I have some spare cycles. I'll let you know.
Christer Fahlgren