I want to know if there are any tools/tool-kits which aid in building source level debuggers for domain specific languages ? (I work on a proprietary DSL, which doesn't have any tools and sometimes debugging will become difficult, so, if in case there are any such tool-kits, wanted to try)
This is an indirect answer to your question. In 1982 I wrote the first commercial C source-level debugger, CDB (also possibly the first remote debugger, kernel debugger, and multi-process/multi-thread debugger). I initially wrote it because I needed it (the only other option was
sdb on a VAX, except I didn't have a VAX, and
sdb sucked planetoids). This situation was in perfect harmony with The Cathedral and the Bazaar's first rule: Every good work of software starts by scratching a developer's personal itch.
Since you are the person with the itch, you are also quite possibly the best person to embark on this journey.
The following things are needed to create a source-level debugger:
- A way of starting & stopping execution without killing the target process. Given your environment this may be trivial or it might be a deal killer.
ptrace(2)was the key in UN*X-land.
- A way of querying the current execution state of the target process. e.g Program Counter (PC) (or equivalent), Stack Pointer (SP), registers, and data/instruction memory. Like #1, trivial or deal killer.
- A way of mapping the PC => file:line and vice versa—file:line => PC. This is critical because it's what differentiates a source-level debugger from an assembly-level debugger (or whatever the equivalent would be in your world). Compiled languages often generate additional symbols in the
.ofile that makes this mapping possible (although not always in a straightforward way).
- A way of inserting and removing a breakpoint. How this is accomplished can vary wildly across environments. It needs to be done in such a way as to be as non-disruptive of the execution state as possible so that you can avoid the debugger equivalent of the Heisenberg uncertainty principle—i.e. the bug reacts differently depending on where you set the break. Note: You can't avoid this with timing-related bugs.
Once you have these things nailed down, your actual command processing should be pretty straightforward. For example, when you hit a breakpoint, you read the PC, map it to file:line and display that line (normally with +/-5 lines of context). For a stack trace, you get the SP and print each frame using the additional symbol info that gives local variable offset from the SP, etc., etc.
What commands make sense will be driven by how you (and your future users) think when using the language. Things that make sense for one language are nonsense when applied to another. For example, given the C declaration
struct FOO *pfoo;, it's nice if typing
*pfoo at the command prompt gives you a formatted dump of the structure pointed to. This might not make sense when debugging something like SQL, but there are often analogues.
The Devil is in the Details on these 4 items, so let me know if you would like any more help offline. My email is in my profile.