Tuesday, September 15, 2009

CDT-EDC Breakpoints


Finally a break in our long hot Austin summer with some rain and slightly cooler temps last weekend. In the eight hot weeks since my last post our team has been adding a bunch of new stuff to the EDC debugger we're preparing to contribute to CDT:

Symbian Device Connectivity - In addition to the our reference implementations on Windows and Linux we're now also debugging on a variety of Nokia phones. This has included supporting a new TCF debug agent and adding support for ARM to the existing x86 support in EDC. After using the existing TCF file system service to download everything we also created a new TCF service for installing applications on Symbian phones.

Breakpoints - Software breakpoints are now supported in a couple ways. If the TCF agent implements support for the TCF breakpoints service we'll use it, otherwise support is implemented in the DSF breakpoints service by writing memory to insert break instructions.

Disassembly - EDC now includes disassemblers for x86 and ARM that are built on a common disassembly framework. The disassemblers are used to populate the Disassembly View and to assist other operations like stepping.

Stepping - Stepping over/in/out of a range of code is now working both for TCF agents that know how to step over a range and those that can't. The Symbols service is used to determine the range of instructions to step over and then passes that to the agent. But if the agent doesn't support range stepping then the Run Control service will use the Disassembly service to find all the branch instructions and then set temporary breakpoints to perform the step.

One reason the breakpoint support was really interesting to implement was the interaction between several of EDC's DSF services. To support source level breakpoints you need to be able to get an address in some code from a source file it was built with and you need to know when and where the code is loaded. In EDC this begins when the debug agent sends a TCF context suspended event when a new code module is loaded. EDC's DSF Run Control service handles the event by sending a module loaded event to the other DSF services. The Module service adds a new entry to it's module list and then tells the Breakpoint service about the new module. The Breakpoint service asks the Symbol service if symbols are available for the new module. If so the Symbol service determines if the module was built using any of the source files that contain breakpoints. The Breakpoint service then asks the Symbol and Module services to provide memory addresses for the breakpoints, then installs them. Finally it tells the Run Control service to resume execution of the suspended context and your program begins running again. None of this is visible to the user except for a subtle change in the breakpoint marker to indicate it was installed successfully.

2 comments:

Pawel Piech said...

Nice! Ican't believe how far you've come already in this implementation. I'm also impressed that you managed to implement so much of the debugger logic in Java and with DSF services. Given that I haven't seen any bugs to extend the DSF service interfaces, they must have been good enough for what you're doing with them, which makes me quite happy.

Cheers
Pawel

Torkild U. Resheim said...

Very interesting Ken! I can hardly wait to get my hands on it and implement AVR/AVR32 support. :-)