-
Notifications
You must be signed in to change notification settings - Fork 0
GDB Debugging Support
JNode's in-kernel debugger with keyboard-driven state machine and future GDB protocol integration support.
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.
| 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 |
The debugger can be entered through two mechanisms:
-
System Trigger: A system trigger event (e.g., from a panic or breakpoint) activates the debugger via
SystemTriggerListener.systemTrigger() - 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;
}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
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
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().
-
No GDB Protocol Implementation: The current implementation is an in-kernel keyboard debugger. GDB protocol support would require additional implementation for remote debugger connectivity.
-
Stack Trace Limitation: Thread stack traces are limited to 10 frames (
ThreadState.java:83). -
Priority Keyboard Access: The debugger uses
setPreferredListener()to intercept keyboard events, which may affect other keyboard handling. -
No Persistent Breakpoints: The current debugger does not support persistent breakpoints - it's primarily for runtime inspection.
-
No Source-Level Debugging: The debugger shows method names but does not provide source-level debugging information.