piccolo icon indicating copy to clipboard operation
piccolo copied to clipboard

`Feature`: implemented [`Debugger`]

Open reloginn opened this issue 4 months ago • 1 comments

Features

DAP adapter

  • Events support.
  • Multi-session and multi-thread support.
  • Extensions (within the limits of the protocol) have been made to basic requests, for example, launch (name and source have been added), and some custom requests have been added (for example, restart_session).
  • disassemble, read_memory, stack_trace, etc. according to the protocol support.

Debugger

  • Multi-session and multi-thread support.
  • Breakpoints support (data/function/instruction).
  • read_memory support.
  • disassemble support.
  • step_*, read_register, read_global, read_registers, read_upvalues support.
  • stack_snapshot, backtrace support.

Why was the visibility of some piccolo structures changed?

Currently, a significant portion of the piccolo API is closed, without which it's simply impossible to implement any debugger. I made part of the piccolo API public so that the debugger would have access to low-level utilities, structures, and functions of piccolo.

A bit of information about the debugger itself

About [Debugger::disassemble]

[Debugger::disassemble] receives opcodes and converts them into already compiled operations.

What is memory_reference?

memory_reference defines what information we will receive and from where. If you specify "" (empty string) in memory_reference, it takes the last frame for disassembly by default. If the string is "frame:id" or "prototype:id", it searches for the needed FunctionPrototype and disassembles it specifically.

Output format

Approximate output of the [Debugger::disassemble] method looks like this:

  Disassembled { symbol: "  ", index: 0, line: 2, operation: SetUpTable { table: UpValueIndex(0), key: Constant(ConstantIndex8(0)), value: Constant(ConstantIndex8(1)) } }
  Disassembled { symbol: "=>", index: 1, line: 3, operation: LoadConstant { dest: RegisterIndex(0), constant: ConstantIndex16(2) } }
  Disassembled { symbol: "  ", index: 2, line: 4, operation: Closure { dest: RegisterIndex(1), proto: PrototypeIndex(0) } }
  Disassembled { symbol: "  ", index: 3, line: 4, operation: SetUpTable { table: UpValueIndex(0), key: Constant(ConstantIndex8(3)), value: Register(RegisterIndex(1)) } }
  Disassembled { symbol: "  ", index: 4, line: 10, operation: Closure { dest: RegisterIndex(1), proto: PrototypeIndex(1) } }
  Disassembled { symbol: "  ", index: 5, line: 10, operation: SetUpTable { table: UpValueIndex(0), key: Constant(ConstantIndex8(4)), value: Register(RegisterIndex(1)) } }
  Disassembled { symbol: "  ", index: 6, line: 15, operation: GetUpTable { dest: RegisterIndex(1), table: UpValueIndex(0), key: Constant(ConstantIndex8(4)) } }
  Disassembled { symbol: "  ", index: 7, line: 15, operation: Call { func: RegisterIndex(1), args: VarCount(Opt254(Some(0))), returns: VarCount(Opt254(Some(1))) } }
  Disassembled { symbol: "  ", index: 8, line: 15, operation: Jump { offset: 0, close_upvalues: Opt254(Some(0)) } }
  Disassembled { symbol: "  ", index: 9, line: 16, operation: Return { start: RegisterIndex(0), count: VarCount(Opt254(Some(0))) } }

About [Debugger::stack_snapshot] (or stack trace)

[Debugger::stack_snapshot] goes through all frames and collects information about the chunk name, its location, line, and the number of containing registers.

Output format

Approximate output of the [Debugger::stack_snapshot] method looks like this:

test.lua:2 <chunk> (2 regs)

Note: all output is described after data formatting

at the same time, [Debugger] functions completely correctly, see /examples/simple_debug.rs you can also see tests of the main functionality in /examples/simple_debug.rs

reloginn avatar Aug 20 '25 20:08 reloginn

@kyren @Aeledfyr can u review it and #130?

reloginn avatar Aug 24 '25 11:08 reloginn