Integrated Debugger

HarbourBuilder includes a fully integrated debugger that runs in-process via the .hrb bytecode format. No external debugger process, no inter-process communication overhead — the debugger is part of the Harbour VM itself, providing a seamless debugging experience with full control over execution.

In-Process Debugging

Unlike traditional debuggers that attach to a running process, HarbourBuilder's debugger operates within the same Harbour VM. This means zero latency for variable inspection, instant breakpoint hits, and accurate call stack information at all times.

Architecture

graph TB A["Source Code (.prg)"] --> B["Harbour Compiler\nharbour -gh -b"] B --> C[".hrb Bytecode\n(debug symbols)"] C --> D["Harbour VM\nwith hb_dbg_* API"] D --> E["Debug Hook\nhb_dbg_SetEntry"] E --> F["IDE Debugger UI"] F --> G["Watch Panel"] F --> H["Locals Panel"] F --> I["Call Stack Panel"] F --> J["Breakpoints Panel"] F --> K["Output Panel"] style A fill:#d2a8ff,stroke:#bc8cff,color:#0d1117 style B fill:#58a6ff,stroke:#388bfd,color:#0d1117 style D fill:#3fb950,stroke:#2ea043,color:#0d1117 style F fill:#f0883e,stroke:#db6d28,color:#0d1117

Compilation for Debugging

To generate debuggable bytecode, compile with these flags:

FlagPurpose
-ghGenerate debug symbols (line numbers, variable names, scope info)
-bOutput .hrb bytecode file instead of C source
harbour myapp.prg -gh -b

The .hrb file contains all the information the debugger needs to map bytecode instructions back to source code lines, display variable names, and reconstruct the call stack.

The Debug Hook: hb_dbg_SetEntry

At the core of Harbour's debugging support is the hb_dbg_SetEntry() hook function. This callback is invoked by the Harbour VM on every bytecode instruction when debug mode is active, allowing the IDE to:

How the Hook Works

When Harbour executes a .hrb file compiled with -gh, each instruction triggers a call to hb_dbg_SetEntry. The IDE registers its own callback via hb_dbg_SetEntry(), receiving the current file, line number, function name, and variable context on every step.

Debug Toolbar

The debug toolbar provides five essential execution controls:

IconShortcutActionDescription
F5Run / ContinueStart execution or continue from a breakpoint
F6PausePause execution at the current line
F7Step IntoExecute the current line; if it calls a function, enter it
F8Step OverExecute the current line; skip over function calls
Shift+F5StopTerminate the debug session

Dockable Debug Panels

The debugger provides five dockable tabs that can be arranged to suit your workflow:

TabDescription
WatchAdd expressions to monitor their values in real-time. Supports Harbour expressions like oForm:cTitle, aArray[1], and function calls.
LocalsShows all local variables in the current function scope, including their types and current values. Auto-expands arrays and objects.
Call StackDisplays the full call stack with file names, line numbers, and function names. Click any frame to navigate to that source location.
BreakpointsList of all breakpoints with file, line, condition, and hit count. Enable/disable or delete individual breakpoints.
OutputConsole output from the debugged application, including ? and ?? output, MsgInfo() logs, and debug trace messages.

Setting Breakpoints

Click in the gutter next to any line number to toggle a breakpoint. Breakpoints are indicated by a red dot:

Debug Session Workflow

  1. Compile with debug flags — Press F9 to build; the IDE automatically adds -gh -b when debugging.
  2. Set breakpoints — Click in the gutter on lines you want to pause at.
  3. Start debugging — Press F5 or click the Run button.
  4. Inspect variables — Use the Watch and Locals tabs to examine state.
  5. Step through code — Use F7 (Step Into) or F8 (Step Over) to advance.
  6. Navigate the call stack — Click frames in the Call Stack panel to see context.
  7. Stop — Press Shift+F5 to end the session.
Quick Tip

You can hover over any variable in the source editor while paused to see its current value in a tooltip. This works for local variables, object properties, and array elements.

Unit Test Coverage

The debugger subsystem is covered by 16 unit tests that verify:

#TestVerifies
1Breakpoint set and hitExecution pauses at the correct line
2Step Into function callDebugger enters the called function
3Step Over function callDebugger skips over the function body
4Step Out of functionDebugger returns to the caller
5Local variable inspectionLocals panel shows correct names and values
6Static variable inspectionStatic variables are visible and correct
7Watch expression evaluationExpressions are evaluated accurately
8Call stack accuracyStack frames match actual call chain
9Conditional breakpoint (true)Pauses when condition is met
10Conditional breakpoint (false)Does not pause when condition fails
11Hit count breakpointPauses only after N hits
12Breakpoint enable/disableToggling works correctly
13Multiple breakpointsAll breakpoints are respected
14Array element inspectionArray elements display correctly
15Object property inspectionObject properties are navigable
16Debug session cleanupResources are freed on stop

Debugger Shortcuts Summary

ShortcutAction
F5Run / Continue
F6Pause
F7Step Into
F8Step Over
Shift+F5Stop debugging
F9Toggle breakpoint on current line
Ctrl+Shift+F9Clear all breakpoints
Next Steps

After debugging, use Build & Run to compile a release build without debug symbols for distribution. Release builds are smaller and faster since they omit the -gh -b flags.

On This Page

Getting Started Component Palette IDE Features Tutorials Reference Platforms Architecture Compilation for Debugging The Debug Hook: hb_dbg_SetEntry Debug Toolbar Dockable Debug Panels Setting Breakpoints Debug Session Workflow Unit Test Coverage Debugger Shortcuts Summary