Chicken » Debugging

## Debugging

### Introduction

This document describes "Feathers", a debugger for compiled CHICKEN programs.

"Feathers" is a Tcl/Tk script, installed together with all other components of the CHICKEN system. To use the debugger, Tcl/Tk version 8.5 or later must be installed.

Once the debugger is started, it waits for a client program to connect to it. You can also run a program explicitly by pressing the `F1` key and selecting an executable to run. If the executable has been compiled with debugging information, it will connect to the debugger and the source code of the program will be shown in the debugger window, if the original source files of the program are available in the search path (see below for more details on this.)

To enable debugging in compiled programs a number of requirements must be met:

- The program must be compiled with debug-level 3 or higher (option `-d3`) or by providing the `-debug-info` option.
- The environment variable `CHICKEN_DEBUGGER` must be set to the address and port of a running instance of the debugger, e.g. `CHICKEN_DEBUGGER=localhost:9999` (port 9999 is the default port). If you start a program directly out of the debugger, then this variable does not need to be set.
- The source code files must be in the current directory, or in the current "search path" of the debugger. The search path defaults to the current directory, the directory of the debugged program and any additional directories selected by pressing the `F3` key.

You can also run the debugger from the command line and directly pass the program to be debugged, including any additional arguments that the program should receive:

`% feathers myprogram 1 2 3`

The debugger understands a number of command-line options: `-port PORT` changes the port on which the debugger listens (the default is 9999), `-dir DIRECTORY` adds `DIRECTORY` to the search path (this option can be given multiple times), and `-n` disables loading of a custom init file (`~/.feathers` or `./.feathers`).

Debug-level 3 adds intrumentation to the compiled code to allow interacting with it from the debugger. This has a slight performance cost, so it should not be enabled with performance sensitive code.

Debugging is mostly unintrusive: timing and dynamic (nursery) allocation may be influenced by the debugging, but otherwise the program will behave exactly as it would without embedded debugging-information: no additional heap allocation takes place, and no Scheme library code will be invoked.

User-interrupts triggered from the debugger use `SIGUSR2` to indicate that the program should be suspended. Be aware of that in case your program implements a signal handler for `SIGUSR2`.

Remote debugging should be no problem: all communication between debugger and the client program takes place over TCP sockets. Note that the source files for the debugged program need to be available on the machine that does the debugging.

### Usage

Initially a single window is shown, holding the contents of the source file that contains the currently executing code. When the execution changes to another file, the contents of the window will be automatically updated. The combo-box at the top shows all source-files for which debug-information is currently available. Note that this may change during the execution of the program, as files are dynamically loaded or statically linked units are not yet initialized.

The "focus" (a line marked blue) shows at what location the program is currently suspended. You can move the focus up and down with the `Up` and `Down` arrow keys.

Lines that contain "debug events" are highlighted: these lines can be used to set breakpoints by clicking with the left mouse button or by pressing `Enter` while the focus is on that line. Clicking a line that contains a breakpoint will disable the breakpoint. Note that a single line can contain multiple "debug events". Setting a breakpoint on such a line will interrupt the program on any event that exists on that line.

The following debug events exist:

- Procedure call
- Procedure entry
- Assignment to global variable
- Signal (an error or interrupt)

The topmost line shows the current file and also displays "events" as the debugged program runs and interacts with the debugger.

At the bottom the following buttons are visible, each of them can also be activated by pressing the function-key shown on the button:

F1
  Run an executable under the debugger. If a program is already debugged, then the current program will be terminated and the debugger is reinitialized.
F2
  Move focus back to location where the debugged program has been suspended.
F3
  Add another directory to the current search path.
F4
  Open the "data" view (see below.)
F5
  Continue execution of the program until the next breakpoint is hit, an error occurs, or the program terminates.
F6
  Execute a single "step", until the next debug-event occurs. You can also press the `Space` key to single-step.
F7
  If text is marked in the current window, search backwards and show the most previous occurrence of the marked text that is not already visible.

: F8 : Search for next occurrence of marked text.

: F9 : Open "C" view (see below.)

: F10 : Terminate the currently debugged program and exit the debugger.

Pressing the `Esc` key while the program is executing will suspend it on the next debug-event (so this may not take place instantly.)

The keys `+` (plus) and `-` (minus) increase and decrease the current font-size, respectively.

### The "Data" View

When `F4` is pressed, a window appears that allows inspection of the current arguments of a suspended procedure, together with any additional global variables that have been marked for inspection. By opening value items in the shown tree view, values can be inspected to arbitrary depth. Note that the values are retrieved from the debug-client on-demand, so the textual representation of a value shown will only reflect its currently inspected contents.

The entry-field below the view for variables and arguments can be used to add global variables to the list of watched variables. Double-clicking on a variable (or pressing `Enter` while it is selected) sets a "watchpoint" - a breakpoint that is trigged when the variable is assigned a new value.

The bars indicate current heap-, scratchspace- and nursery utilization. These bars update only when the program is suspended.

At the bottom the current call-trace of the executing program is shown. Note that this is not a "stack-trace", but a list of recently performed calls, ordered from top (earlier) to bottom (later).

### The "C" View

Pressing `F9` opens another text-window which shows the current location where the program is suspended, but in the compiled C code generated by the `chicken` compiler. The contents of the window are automatically updated on every suspension of the debugged program. This may be useful when you want to understand how CHICKEN compiles Scheme to C, or when you are doing low-level debugging.

Text can be marked and searched as in the source-code window with `F7` and `F8`.

Previous: Extensions to the standard

Next: Interface to external functions and variables