TDebuggerIntf
TDebuggerIntf is the base class of implementing a debugger as Lazarus-IDE plugin package. The package must have DebuggerIntf package as it's requirements. Any debugger plug-in must implement the class and register via RegisterDebugger (called at Register of registering unit).
Implementation notes:
- the class is designed to act as asynchronous object. The interaction is implemented in form of commands sent to the class.
- the command should be put (or not put) into an execution queue. The information about acceptance or denial of the command should be returned as soon as possible.
- Command request is sent from the Main Thread. Thus any actual debugging job should be implemented in a separate thread NOT to impact the user experience.
- once a command has been handled from the queue, the corresponding event should be called and/or debugger state changed
Debugger Workflow
Initialization
IDE does following steps via TDebuggerIntf methods:
- allocate (external debugger executable name is provided) (the state is expected dsNone)
- assign debugger properties
- .Init() (as a result of Init method, the debugger should be in dsIdle state)
- assigning Environment
- assigning debugged process information (WorkingDir, FileName, Arguments, etc...)
Minimal Implementation
The following methods must be implemented for TDebbugerIntf
- GetSupportedCommands (or GetCommands) - returns the set of formats that a debugger can perform
- RequestCommand - the method actually performing commands. Only commands returned by GetSupportedCommands would be passed to this method
- Caption - the method return user-friendly name of the debugger
type
TMiniDebugger = class(TDebuggerIntf)
protected
function RequestCommand(const ACommand: TDBGCommand; const AParams: array of const): Boolean; override;
function GetSupportedCommands: TDBGCommands; override;
public
class function Caption: String; override;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterDebugger(TMiniDebugger);
end;
class function TMiniDebugger.Caption: String;
begin
Result:='Initial Debugger Plug-in';
end;
function TMiniDebugger.GetSupportedCommands: TDBGCommands;
begin
Result := [dcRun, dcStop];
end;
function TMiniDebugger.RequestCommand(const ACommand: TDBGCommand;
const AParams: array of const): Boolean;
begin
case ACommand of
dcRun: begin // the debugger was requested to run
Result:=true; // typically it should set the state into dsIdle (to get more data from IDE)
SetState(dsRun); // the debugger replies as if it started immediately
end;
dcStop: begin // the debugger was requested to stop
Result:=true;
SetState(dsStop); // the debugger replied as if it stopped immediately
end;
else
Result:=false;
end;
end;
Reference
RequestCommand
The method should return false, if the command cannot be executed.
property Environment
property Environment: TStrings read write
Environment variables that should be passed (or updated) in a debugged project. Assigning values to Environment triggers dcEnvironment command.
Commands
The following commands are called via RequestCommand method.
Command | Explanation | Parameters |
---|---|---|
dcRun | Starts (or Restarts) or Resumes the execution of a debugged process.
The debugged process executable and arguments to be used are available through FileName and Arguments properties of TDebuggerIntf object. |
no parameters |
dcPause | no parameters | |
dcStop | no parameters | |
dcStepOver | no parameters | |
dcStepInto | no parameters | |
dcStepOut | no parameters | |
dcRunTo | 0 - AnsiString - file name of the source code to run to
1 - Integer - Line number to run to | |
dcJumpto | 0 - AnsiString - file name of the source code to jump to
1 - Integer - Line number to run to | |
dcAttach | 0 - AnsiString - process ID to attach-to. | |
dcDetach | no parameters | |
dcBreak | ||
dcWatch | ||
dcLocal | ||
dcEvaluate | 0 - AnsiString - expression to be evaluated
1 - pointer to AnsiString - the string where the result should be saved into 2 - pointer to TDBGType - the reference where the information about the result type should be saved to 3 - Integer - TDBGEvaluateFlags casted into Integer | |
dcModify | Modifies the given expression / Assigns a value to a variable/field/property | 0 - AnsiString - identified expression
1 - AnsiString - value to be assigned |
dcEnvironment | Prepares/updates an environmental variable for a debugged process. | 0 - AnsiString - environment variable in %name%=%value% format
1 - Boolean - the flag, if "true" then the variable needs to be set, "false" if needs to be removed |
dcSetStackFrame | ||
dcDisassemble | ||
dcStepOverInstr | ||
dcStepIntoInstr | ||
dcSendConsoleInput |
Development Hints
- it might be helpful to recompile DebuggerIntf package, adding the following Custom Options to the compiler options of the package
- -dDBG_STATE
- -dDBG_EVENTS
- -dDBG_VERBOSE
- -dDBG_WARNINGS
- -dDBG_DATA_MONITORS
- -dDBG_DISASSEMBLER
- these defines provide more logging output of TDebuggerIntf
- it might be helpful to rebuild IDE adding the following defines into build Options:
- -dVerboseDebugger
- VerboseDebugger logs messages debugging calls from IDE itself
See Also
- FpGdbmiDebugger - debugger plug-in, that works over the external GDB debugger, but has a better understanding of Pascal expressions and types