Files
2026-09-01 12:15:35 +08:00

3.3 KiB

Debugger — GDB server and Qdb

Goal

Let users debug emulated targets: a GDB remote-serial-protocol server so any GDB/IDA/lldb front end can attach cross-architecture, and Qdb — a built-in interactive CLI debugger with stepping, branch prediction, and record/replay reverse debugging. Mature released infrastructure; maturity-based status.

Status

done — Qdb covered by tests/test_qdb.py; the GDB server by tests/test_debugger.py (spawns a real client session).

Code Structure

File Role
qiling/debugger/debugger.py Base QlDebugger
qiling/debugger/gdb/gdb.py QlGdb: GDB remote-serial-protocol server, plus the GdbSerialConn transport
qiling/debugger/gdb/utils.py QlGdbUtils: breakpoint table and the per-instruction dbg_hook that services breakpoints, stepping, and async interrupts
qiling/debugger/gdb/xmlregs.py, gdb/xml/ Target-description XML per arch for modern GDB clients
qiling/debugger/qdb/qdb.py QlQdb: interactive Cmd-based debugger
qiling/debugger/qdb/arch/ Per-arch Qdb support (arm, intel, mips)
qiling/debugger/qdb/branch_predictor/ Predicts branch targets for step/next
qiling/debugger/qdb/render/ Register/stack/disasm view rendering

Key Types and Entry Points

  • qiling/debugger/debugger.py:13 - QlDebugger - base; run() starts the session.
  • qiling/debugger/gdb/gdb.py:84 - QlGdb(QlDebugger) - listens on ip:port, translates RSP packets to Qiling hook/mem/reg operations; run() (:139) serves the session.
  • qiling/debugger/gdb/gdb.py:817 - GdbSerialConn - the socket transport; poll_interrupt() (:856) is a non-blocking check for a client \x03, wired into QlGdbUtils.check_interrupt (qiling/debugger/gdb/gdb.py:145) so a running guest can be broken into asynchronously.
  • qiling/debugger/gdb/utils.py:16 - QlGdbUtils - dbg_hook (:48) runs per instruction to service breakpoints, single-step, and interrupts; bp_insert/bp_remove (:81/:94); resume_emu (:107).
  • Stop replies report SIGTRAP (qiling/debugger/gdb/gdb.py:49) for both single-step (:243) and async-interrupt stops (:262).
  • qiling/debugger/qdb/qdb.py:59 - QlQdb(Cmd, QlDebugger) - CLI loop; rr mode enables record/replay reverse debugging.
  • Activation: set ql.debugger = True | "gdb" | "gdb:0.0.0.0:9999" | "qdb" | "qdb:rr" (qiling/core.py:437); instantiated lazily in Qiling.run via select_debugger (qiling/utils.py:332).
  • qltool flags: --gdb and --qdb (see cli.md).

Interactions

  • Instantiated by core.md at Qiling.run time, not construction.
  • Reads/writes state exclusively through public APIs: registers via arch.md, memory via os-base.md, breakpoints via hook_address (core.md).
  • The IDA plugin in extensions.md offers an alternative front end over the same public API.

How to Test

cd tests && python3 test_qdb.py   # pass = unittest "OK", exit 0
  • GDB server: cd tests && python3 test_debugger.py — starts QlGdb and drives a scripted client.

Open Gaps / Roadmap

  • Qdb per-arch support covers arm/cortex-m/mips/intel; RISC-V and PPC lack Qdb arch modules (qiling/debugger/qdb/arch/).
  • Record/replay (qdb:rr) stores full state per step — memory-heavy on long runs.