PikeDebugger

[ Start > PikeDevel > PikeDebugger ] [ Edit this Page | Show Page Versions | Show Raw Source ]


Work on permitting pike code to be debugged interactively is underway, and currently exists as a rough proof of concept in branch bill/debugger-concept.

The minimum requirement to use the new Pike debugger is to have a pike that's been compiled with the --with-debug configure option. For best results, you'll also want to disable machine code generation in the interpreter. While debugging will work, the optimizations that occur in a pike compiled with machine code generation will often cause surprising code execution flows and the appearance some lines of code aren't executing at all.

The debugger is built directly into the pike executable and its functionality runs within a separate thread. The debugger natively speaks the Debug Adapter Protocol (DAP), which is a language and runtime agnostic mecanism for communicating between a debugger and a user interface, such as an IDE.

Once you have a pike compiled from the debugging branch with the appropriate build flags (described above), you can use VSCode as a debugging client using the following plugin. The readme has a good description of what to expect to work (and not). Comments and feedback are welcome!

https://hg.sr.ht/~hww3/vscode-debugger-pike

Current features of the POC

  • Debug Adapter Protocol support for Visual Studio/Visual Studio Code
  • Multiple breakpoints may be set and cleared independently.
  • Backtrace viewing
  • Frame stack browsing (as part of backtrace frames)
  • View locals and globals with variable names (thanks, Grubba!)
  • Logpoints (minus expression evaluation, see to-to list)
  • Modify locals and globals
  • Single stepping/Step In
  • Step Over
  • Step Out
  • Thread Pausing
  • Thread Terminating
  • Continue

    Things that need to be done

  • Expression evaluation within frame context
  • Do we need to evaluate a possible debugger halt for every opcode, or just some?
  • Thread naming
  • Function Breakpoints
  • Conditional Breakpoints?
  • Routing of stderr/stdout through debugger
  • Efficiency improvements?
  • Work to possibly not require RTL debug

Some notes about optimization

Pike is very clever, and will attempt to do whatever you ask in the most efficient way possible. This can create confusion when debugging, though, as code may not be evaluated quite the way you expect.

For example, if you have a breakpoint in a method that has no side-effects and the answer returned would be considered constant (either because it takes no input variables, or those inputs are constant in the context of the call), Pike may opt to evaluate the method once, possibly at compile time, and then simply skip over it during evaluation. If you were to put a breakpoint on a line in this method, you may hit it at an unexpected time (or not at all!), and then never again when the code around it executes.

Needs research: It may be possible to disable certain optimizations to prevent this unexpected behavior, though that could have side effects of its own.

It seems the easiest way to get a debugger that behaves in a reasonable manner is to run pike without machine code. The only behavior that seems less than ideal is that on some code lines, single-stepping causes the debugger to break on the same line multiple times, as there may multiple opcodes that run in an expression or line. It may be possible to cut down on some of this behavior by not actually pausing a thread for certain opcodes.

Example of a debugging session: (Obsolete)

Start up a pike program with the debugger enabled. Pike will wait a few seconds for a debugger to connect, then continue on if one has not.

$ pike --debugger --debugger-wait=5 --debugger-port=4711 /path/to/file.pike

In another terminal, connect to the debugger port.

$ telnet localhost 3333
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Welcome to the Pike Debugger.
> object bp = Debug.Debugger.add_breakpoint("/path/to/file.pike", 22);
> object bp1 = Debug.Debugger.add_breakpoint("/path/to/file.pike", "/path/to/included_file.h", 2);
> bp->enable();
> bp1->enable();
> go
Breakpoint on /path/to/file.pike:22
> backtrace;
(1) Result: ({ /* 4 elements */
                backtrace_frame(/Users/hww3/pike2/build/darwin-16.7.0-x86_64/master.pike:4148, _main(), Args: 1),
                backtrace_frame(-:1, `()(), Args: 1),
                backtrace_frame(/path/to/file.pike:14, doit(), No args),
                backtrace_frame(/path/to/included_file.h:2, whee(), Args: 1)
            })
> backtrace[-1]->locals();
(4) Result: ({ /* 3 elements */
                "rad",
                0,
                0
            })
> backtrace[-1]->set_local(1, "bar");
(5) Result: 0
> backtrace[-1]->locals();
(6) Result: ({ /* 3 elements */
                "rad",
                "bar",
                0
            })
> step
Stepping.
Breakpoint on /path/to/included_file.h:2
> go


Powered by PikeWiki2

 
gotpike.org | Copyright © 2004 - 2009 | Pike is a trademark of Department of Computer and Information Science, Linköping University