Skip to content

GDB Debugging Support

opencode-agent[bot] edited this page May 11, 2026 · 1 revision

GDB Debugging Support

JNode's in-kernel debugger with keyboard-driven state machine and future GDB protocol integration support.

Overview

JNode provides debugging capabilities through an in-kernel debugger (org.jnode.debugger) that can be activated via keyboard input or system triggers. The debugger offers thread inspection, stack trace viewing, and thread interruption capabilities. The architecture uses a state machine pattern (DebugState hierarchy) to manage debugger interaction flow.

The issue mentions "GDB protocol" support for future integration with the GNU Debugger, but the current implementation provides an internal keyboard-driven debugging interface. The infrastructure could be extended to support remote GDB protocol connections.

Key Components

Class/File Purpose
Debugger.java Main debugger entry point, implements keyboard listener and system trigger handler
DebuggerPlugin.java JNode plugin that registers the debugger to keyboard and system trigger events
DebugState.java Abstract base class for debugger state machine
RootState.java Root state of the debugger, shows main menu (thread listing, running/waiting threads)
ThreadListState.java Displays list of threads with filtering by state
ThreadState.java Displays detailed thread information including stack trace
ThreadHelper.java Utility for thread operations
DebuggerUtils.java Common utility functions for debugger

How It Works

Debugger Activation

The debugger can be entered through two mechanisms:

  1. System Trigger: A system trigger event (e.g., from a panic or breakpoint) activates the debugger via SystemTriggerListener.systemTrigger()
  2. Keyboard: Pressing a specific key while the debugger is enabled triggers debugger interaction
// From Debugger.java:55-67
public void systemTrigger(SystemEvent event) {
    event.consume();
    if (!enabled) {
        // Entering debugger
        reset();
        setPreferredListener();
        VmSystem.getOut().println("[Debugger ('h' for help)]");
    } else {
        // Exiting debugger
        System.out.println();
    }
    enabled = !enabled;
}

State Machine Pattern

The debugger uses a hierarchical state machine (DebugState hierarchy):

RootState
├── ThreadListState (filter: ALL/RUNNING/WAITING)
│   └── ThreadState (per-thread detail view)

Each state:

  • Implements print(PrintStream) to display information
  • Implements process(KeyboardEvent) to handle keyboard input
  • Maintains parent state for navigation

Thread Inspection

From RootState, users can list threads:

  • t - List all threads
  • r - List running threads only
  • w - List waiting threads

From ThreadListState, selecting a thread shows:

  • Thread name and state
  • Stack trace (up to 10 frames)

From ThreadState, users can:

  • i - Interrupt the thread

Plugin Integration

DebuggerPlugin extends Plugin and registers the debugger to device events:

// From DebuggerPlugin.java:99-116
private void addListeners(Device device) {
    if (device.implementsAPI(SystemTriggerAPI.class)) {
        final SystemTriggerAPI api = device.getAPI(SystemTriggerAPI.class);
        api.addSystemTriggerListener(debugger);
    }
    if (device.implementsAPI(KeyboardAPI.class)) {
        final KeyboardAPI api = device.getAPI(KeyboardAPI.class);
        api.addKeyboardListener(debugger);
    }
}

The debugger receives priority keyboard access through KeyboardAPI.setPreferredListener().

Gotchas

  1. No GDB Protocol Implementation: The current implementation is an in-kernel keyboard debugger. GDB protocol support would require additional implementation for remote debugger connectivity.

  2. Stack Trace Limitation: Thread stack traces are limited to 10 frames (ThreadState.java:83).

  3. Priority Keyboard Access: The debugger uses setPreferredListener() to intercept keyboard events, which may affect other keyboard handling.

  4. No Persistent Breakpoints: The current debugger does not support persistent breakpoints - it's primarily for runtime inspection.

  5. No Source-Level Debugging: The debugger shows method names but does not provide source-level debugging information.

Related Pages

Clone this wiki locally