1 (*  This program is free software: you can redistribute it and/or modify
2     it under the terms of the GNU General Public License as published by
3     the Free Software Foundation, either version 2, 3 or any later version
4     of the License (at your option).
5 
6     This program is distributed in the hope that it will be useful,
7     but WITHOUT ANY WARRANTY; without even the implied warranty of
8     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9     GNU General Public License for more details.
10 
11     You should have received a copy of the GNU General Public License
12     along with this program.  If not, see <https://www.gnu.org/licenses/>.
13 *)
14 unit LldbInstructions;
15 
16 {$mode objfpc}{$H+}
17 
18 interface
19 
20 uses
21   SysUtils, Classes, strutils,
22   // LazUtils
23   LazLoggerBase,
24   // DebuggerIntf
25   DbgIntfDebuggerBase, DbgIntfBaseTypes,
26   // CmdLineDebuggerBase
27   DebugInstructions,
28   // LazDebuggerLldb
29   LldbHelper;
30 
31 type
32 
33   (*
34    *  Instructions
35    *)
36 
37   TLldbInstruction = class;
38 
39   { TLldbInstructionQueue }
40 
41   TLldbInstructionQueue = class(TDBGInstructionQueue)
42   private
43   protected
CheckForIgnoredErrornull44     function CheckForIgnoredError(const AData: String): Boolean;
45     procedure DoBeforeHandleLineReceived(var ALine: String); override;
46 
GetSelectFrameInstructionnull47     function GetSelectFrameInstruction(AFrame: Integer): TDBGInstruction; override;
GetSelectThreadInstructionnull48     function GetSelectThreadInstruction(AThreadId: Integer): TDBGInstruction; override;
49   public
50     procedure CancelAllForCommand(ACommand: TObject); // Does NOT include the current or running instruction
51   end;
52 
53   { TLldbInstruction }
54 
55   TLldbInstruction = class(TDBGInstruction)
56   private
57     FDwarfLoadErrors: String;
58     FOwningCommand: TObject;
GetQueuenull59     function GetQueue: TLldbInstructionQueue;
60   protected
MaskQuotedTextnull61     function MaskQuotedText(ALine: String): String;
ProcessInputFromDbgnull62     function ProcessInputFromDbg(const AData: String): Boolean; override;
63     procedure SetContentReceieved; reintroduce;
64 
65     property Queue: TLldbInstructionQueue read GetQueue;
66     property NextInstruction;
67   public
68     property OwningCommand: TObject read FOwningCommand write FOwningCommand;
69     property DwarfLoadErrors: String read FDwarfLoadErrors;
70   end;
71 
72   { TLldbInstructionSettingSet }
73 
74   TLldbInstructionSettingSet = class(TLldbInstruction)
75   protected
ProcessInputFromDbgnull76     function ProcessInputFromDbg(const AData: String): Boolean; override;
77   public
78     constructor Create(AName, AValue: String; AGlobal: Boolean = False; AQuote: Boolean = False);
79   end;
80 
81   { TLldbInstructionSettingRemove }
82 
83   TLldbInstructionSettingRemove = class(TLldbInstruction)
84   protected
ProcessInputFromDbgnull85     function ProcessInputFromDbg(const AData: String): Boolean; override;
86   public
87     constructor Create(AName, AValue: String; AQuote: Boolean = False);
88   end;
89 
90   { TLldbInstructionSettingClear }
91 
92   TLldbInstructionSettingClear = class(TLldbInstruction)
93   protected
ProcessInputFromDbgnull94     function ProcessInputFromDbg(const AData: String): Boolean; override;
95   public
96     constructor Create(AName: String);
97   end;
98 
99   { TLldbInstructionTargetCreate }
100 
101   TLldbInstructionTargetCreate = class(TLldbInstruction)
102   private
103     FRes: String;
104   protected
ProcessInputFromDbgnull105     function ProcessInputFromDbg(const AData: String): Boolean; override;
106   public
107     constructor Create(AFile: String);
108     property Res: String read FRes;
109   end;
110 
111   { TLldbInstructionTargetDelete }
112 
113   TLldbInstructionTargetDelete = class(TLldbInstruction)
114   protected
ProcessInputFromDbgnull115     function ProcessInputFromDbg(const AData: String): Boolean; override;
116   public
117     constructor Create;
118   end;
119 
120   { TLldbInstructionTargetStopHook }
121 
122   TLldbInstructionTargetStopHook = class(TLldbInstruction)
123   protected
ProcessInputFromDbgnull124     function ProcessInputFromDbg(const AData: String): Boolean; override;
125   public
126     constructor Create(const ACmd: String);
127   end;
128 
129   { TLldbInstructionProcessLaunch }
130 
131   TLldbInstructionProcessLaunch = class(TLldbInstruction)
132   protected
ProcessInputFromDbgnull133     function ProcessInputFromDbg(const AData: String): Boolean; override;
134   public
135     constructor Create(AOpenTerminal: Boolean);
136   end;
137 
138   { TLldbInstructionProcessStep }
139 
140   TLldbInstructionProcessStepAction = (saContinue, saOver, saInto, saOut, saInsIn, saInsOver);
141 
142   TLldbInstructionProcessStep = class(TLldbInstruction)
143   protected
ProcessInputFromDbgnull144     function ProcessInputFromDbg(const AData: String): Boolean; override;
145   public
146     constructor Create(AStepAction: TLldbInstructionProcessStepAction; AThread: Integer = -1);
147   end;
148 
149   { TLldbInstructionProcessKill }
150 
151   TLldbInstructionProcessKill = class(TLldbInstruction)
152   protected
ProcessInputFromDbgnull153     function ProcessInputFromDbg(const AData: String): Boolean; override;
154   public
155     constructor Create();
156   end;
157 
158   { TLldbInstructionProcessInterrupt }
159 
160   TLldbInstructionProcessInterrupt = class(TLldbInstruction)
161   protected
ProcessInputFromDbgnull162     function ProcessInputFromDbg(const AData: String): Boolean; override;
163   public
164     constructor Create();
165   end;
166 
167   { TLldbInstructionBreakOrWatchSet }
168 
169   TLldbInstructionBreakOrWatchSet = class(TLldbInstruction)
170   private
171     FBreakId: Integer;
172     FLldbNoDisableError: Boolean;
173     FState: TValidState;
174   protected
ProcessInputFromDbgnull175     function ProcessInputFromDbg(const AData: String): Boolean; override;
176   public
177     property BreakId: Integer read FBreakId;
178     property State: TValidState read FState;
179     property LldbNoDisableError: Boolean read FLldbNoDisableError;
180   end;
181 
182   { TLldbInstructionBreakSet }
183 
184   TLldbInstructionBreakSet = class(TLldbInstructionBreakOrWatchSet)
185   public
186     constructor Create(AFileName: String; ALine: Integer; ADisabled: Boolean = False; AConditon: String = '');
187     constructor Create(AMethod: String; ADisabled: Boolean = False; AConditon: String = '');
188     constructor Create(AMethod: String; ADisabled: Boolean; ABeforePrologue: Boolean);
189     constructor Create(AnAddress: TDBGPtr; ADisabled: Boolean = False; AConditon: String = '');
190   end;
191 
192   { TLldbInstructionBreakModify }
193 
194   TLldbInstructionBreakModify = class(TLldbInstruction)
195   protected
ProcessInputFromDbgnull196     function ProcessInputFromDbg(const AData: String): Boolean; override;
197   public
198     constructor Create(AnId: Integer; ADisabled: Boolean);
199     constructor Create(AnId: Integer; ADisabled: Boolean; AConditon: String);
200   end;
201 
202   { TLldbInstructionBreakAddCommands }
203 
204   TLldbInstructionBreakAddCommands = class(TLldbInstruction)
205   private
206     FCommands: TStringArray;
207   protected
ProcessInputFromDbgnull208     function ProcessInputFromDbg(const AData: String): Boolean; override;
209     procedure SendCommandDataToDbg(); override;
210   public
211     constructor Create(AnId: Integer; ACommands: Array of String);
212   end;
213 
214   { TLldbInstructionBreakDelete }
215 
216   TLldbInstructionBreakDelete = class(TLldbInstruction)
217   protected
ProcessInputFromDbgnull218     function ProcessInputFromDbg(const AData: String): Boolean; override;
219   public
220     constructor Create(AnId: Integer);
221   end;
222 
223   { TLldbInstructionWatchSet }
224 
225   TLldbInstructionWatchSet = class(TLldbInstructionBreakOrWatchSet)
226   public
227     constructor Create(AWatch: String; AKind: TDBGWatchPointKind);
228   end;
229 
230   { TLldbInstructionWatchModify }
231 
232   TLldbInstructionWatchModify = class(TLldbInstruction)
233   protected
ProcessInputFromDbgnull234     function ProcessInputFromDbg(const AData: String): Boolean; override;
235   public
236     constructor Create(AnId: Integer; AConditon: String = '');
237   end;
238 
239   { TLldbInstructionWatchDelete }
240 
241   TLldbInstructionWatchDelete = class(TLldbInstruction)
242   protected
ProcessInputFromDbgnull243     function ProcessInputFromDbg(const AData: String): Boolean; override;
244   public
245     constructor Create(AnId: Integer);
246   end;
247 
248   { TLldbInstructionThreadSelect }
249 
250   TLldbInstructionThreadSelect = class(TLldbInstruction)
251   private
252     FIndex: Integer;
253   protected
ProcessInputFromDbgnull254     function ProcessInputFromDbg(const AData: String): Boolean; override;
255   public
256     constructor Create(AnIndex: Integer);
257   end;
258 
259   { TLldbInstructionFrameSelect }
260 
261   TLldbInstructionFrameSelect = class(TLldbInstruction)
262   private
263     FIndex: Integer;
264   protected
ProcessInputFromDbgnull265     function ProcessInputFromDbg(const AData: String): Boolean; override;
266   public
267     constructor Create(AnIndex: Integer);
268   end;
269 
270   { TLldbInstructionValueBase }
271 
272   TLldbInstructionValueBase = class(TLldbInstruction)
273   private
274     FCurly: Integer;
275   protected
ParseStructnull276     function ParseStruct(ALine: string): Boolean;
277   end;
278 
279   { TLldbInstructionLocals }
280 
281   TLldbInstructionLocals = class(TLldbInstructionValueBase)
282   private
283     FRes: TStringList;
284     FCurVal, FCurName: String;
285   protected
ProcessInputFromDbgnull286     function ProcessInputFromDbg(const AData: String): Boolean; override;
287     procedure SendCommandDataToDbg(); override;
288   public
289     constructor Create(AThread, AFrame: Integer);
290     destructor Destroy; override;
291     property Res: TStringList read FRes;
292   end;
293 
294   { TLldbInstructionExpressionBase }
295 
296   TLldbInstructionExpressionBase = class(TLldbInstructionValueBase)
297   private
298     FRes: String;
299   protected
ProcessInputFromDbgnull300     function ProcessInputFromDbg(const AData: String): Boolean; override;
301   public
302     property Res: String read FRes;
303   end;
304 
305   { TLldbInstructionExpression }
306 
307   TLldbInstructionExpression = class(TLldbInstructionExpressionBase)
308   public
309     constructor Create(AnExpression: String; AThread, AFrame: Integer);
310   end;
311 
312   { TLldbInstructionReadExpression
313     Reads data, if LLDB already printing it
314   }
315 
316   TLldbInstructionReadExpression = class(TLldbInstructionExpressionBase)
317   protected
318     procedure SendCommandDataToDbg(); override;
319   public
320     constructor Create;
321   end;
322 
323   { TLldbInstructionMemory }
324 
325   TArrayOfByte = array of byte;
326 
327   TLldbInstructionMemory = class(TLldbInstruction)
328   private
329     FRes: TArrayOfByte;
330     FReading: Boolean;
331   protected
ProcessInputFromDbgnull332     function ProcessInputFromDbg(const AData: String): Boolean; override;
333     procedure SendCommandDataToDbg(); override;
334   public
335     constructor Create(AnAddress: TDBGPtr; ALen: Cardinal);
336     destructor Destroy; override;
337     property Res: TArrayOfByte read FRes;
338   end;
339 
340   { TLldbInstructionRegister }
341 
342   TLldbInstructionRegister = class(TLldbInstruction)
343   private
344     FRes: TStringList;
345     FReading: Boolean;
346   protected
347     procedure DoFree; override;
ProcessInputFromDbgnull348     function ProcessInputFromDbg(const AData: String): Boolean; override;
349     procedure SendCommandDataToDbg(); override;
350   public
351     constructor Create(AThread, AFrame: Integer);
352     destructor Destroy; override;
353     property Res: TStringList read FRes;
354   end;
355 
356   { TLldbInstructionThreadList }
357 
358   TLldbInstructionThreadList = class(TLldbInstruction)
359   private
360     FRes: TStringArray;
361     FReading: Boolean;
362   protected
363     procedure SendCommandDataToDbg(); override;
ProcessInputFromDbgnull364     function ProcessInputFromDbg(const AData: String): Boolean; override;
365   public
366     constructor Create();
367     destructor Destroy; override;
368     property Res: TStringArray read FRes;
369   end;
370 
371   { TLldbInstructionThreadListReader }
372 
373   TLldbInstructionThreadListReader = class(TLldbInstructionThreadList)
374   protected
375     procedure SendCommandDataToDbg(); override;
ProcessInputFromDbgnull376     function ProcessInputFromDbg(const AData: String): Boolean; override;
377   end;
378 
379   { TLldbInstructionStackTrace }
380 
381   TLldbInstructionStackTrace = class(TLldbInstruction)
382   private
383     FRes: TStringArray;
384     FReading: Boolean;
385   protected
386     procedure SendCommandDataToDbg(); override;
ProcessInputFromDbgnull387     function ProcessInputFromDbg(const AData: String): Boolean; override;
388   public
389     constructor Create(FrameCount: Integer; AThread: Integer);
390     constructor Create(FrameCount, FirstFrame: Integer; AThread: Integer);
391     destructor Destroy; override;
392     property Res: TStringArray read FRes;
393   end;
394 
395   { TLldbInstructionDisassem }
396 
397   TLldbInstructionDisassem = class(TLldbInstruction)
398   private
399     FRes: TStringList;
400     FReading: Boolean;
401   protected
402     procedure SendCommandDataToDbg(); override;
ProcessInputFromDbgnull403     function ProcessInputFromDbg(const AData: String): Boolean; override;
404   public
405     constructor Create(AnAddr: TDBGPtr; NumLines: Cardinal);
406     constructor CreateRange(StartAddr: TDBGPtr; EndAddr: TDBGPtr);
407     destructor Destroy; override;
408     property Res: TStringList read FRes;
409 end;
410 
411 implementation
412 
413 { TLldbInstructionValueBase }
414 
ParseStructnull415 function TLldbInstructionValueBase.ParseStruct(ALine: string): Boolean;
416 var
417   i: Integer;
418 begin
419   i := 1;
420   while i <= Length(ALine) do begin
421     case ALine[i] of
422       '"': break; // string always goes to end of line
423       '{': inc(FCurly);
424       '}': dec(FCurly);
425     end;
426     inc(i);
427     if FCurly<0 then debugln(['ParseStruct curly too low ', FCurly]);
428   end;
429   Result := FCurly <= 0;
430 end;
431 
432 { TLldbInstructionBreakOrWatchSet }
433 
TLldbInstructionBreakOrWatchSet.ProcessInputFromDbgnull434 function TLldbInstructionBreakOrWatchSet.ProcessInputFromDbg(const AData: String
435   ): Boolean;
436 var
437   i: Integer;
438   found, found2: TStringArray;
439 begin
440   Result := True;
441 
442   if StrMatches(AData, ['', 'unrecognized option', 'disable', '']) then begin
443     FLldbNoDisableError := True;
444     //MarkAsFailed; // next line will be error
445     exit;
446   end;
447 
448   if StrMatches(AData, ['Breakpoint ',': ', ''], found) then begin
449     i := StrToIntDef(found[0], -1);
450     if i = -1 then begin
451       MarkAsFailed;
452       exit;
453     end;
454     FBreakId:= i;
455 
456     if StrContains(found[1], 'pending') then
457       FState := vsPending
458     else
459     if StrMatches(found[1], ['', ' locations'], found2) then begin
460       if StrToIntDef(found2[0], 0) > 0 then
461         FState := vsValid;
462     end
463     else
464     if StrStartsWith(found[1], 'where = ') then
465       FState := vsValid;
466 
467     MarkAsSuccess;
468   end
469 //Breakpoint 41: where = lazarus.exe`CREATE + 2029 at synedit.pp:2123, address = 0x00764d2d
470 //Breakpoint 38: no locations (pending).
471 //Breakpoint 34: 3 locations.
472   else
473       Result := inherited;
474 end;
475 
476 { TLldbInstructionQueue }
477 
CheckForIgnoredErrornull478 function TLldbInstructionQueue.CheckForIgnoredError(const AData: String
479   ): Boolean;
480 begin
481   Result := True;
482   if StrStartsWith(AData, 'error: ') then begin // ignore dwarf warnings
483     if StrMatches(AData, ['error', 'unhandled type tag', 'DW_TAG_', '']) then // ignore dwarf warnings
484       exit;
485     if StrStartsWith(AData, 'error: need to add support for DW_TAG_') then // ignore dwarf warnings
486       exit;
487   end;
488   Result := False;
489 end;
490 
491 procedure TLldbInstructionQueue.DoBeforeHandleLineReceived(var ALine: String);
492 begin
493   inherited DoBeforeHandleLineReceived(ALine); // Do first send to DebugOutput window
494 
495   while LeftStr(ALine, 7) = '(lldb) ' do begin
496     Delete(ALine, 1, 7);
497   end;
498 
499   if CheckForIgnoredError(ALine) then begin
500     ALine := '';
501     exit;
502   end;
503 
504   // TODO: detect the echo, and flag if data is for RunningInstruction;
505 
506 //  if LeftStr(ALine, 7) = 'error: ' then begin
507 //    // TODO: late error for previous instruction
508 //    ALine := '';
509 //  end;
510 //
511 //  ALine := '';
512 end;
513 
TLldbInstructionQueue.GetSelectFrameInstructionnull514 function TLldbInstructionQueue.GetSelectFrameInstruction(AFrame: Integer
515   ): TDBGInstruction;
516 begin
517   Result := TLldbInstructionFrameSelect.Create(AFrame);
518 end;
519 
GetSelectThreadInstructionnull520 function TLldbInstructionQueue.GetSelectThreadInstruction(AThreadId: Integer
521   ): TDBGInstruction;
522 begin
523   Result := TLldbInstructionThreadSelect.Create(AThreadId);
524 end;
525 
526 procedure TLldbInstructionQueue.CancelAllForCommand(ACommand: TObject);
527 var
528   Instr, NextInstr: TLldbInstruction;
529 begin
530   NextInstr := TLldbInstruction(FirstInstruction);
531   while NextInstr <> nil do begin
532     Instr := NextInstr;
533     NextInstr := TLldbInstruction(Instr.NextInstruction);
534     if Instr.OwningCommand = ACommand then begin
535       Instr.Cancel;
536     end;
537   end;
538 
539   if (RunningInstruction <> nil) and
540      (TLldbInstruction(RunningInstruction).OwningCommand = ACommand) and
541      (not RunningInstruction.IsCompleted)
542   then begin
543     RunningInstruction.OnFailure := nil;
544     RunningInstruction.OnFinish := nil;
545     RunningInstruction.Cancel;
546   end;
547 end;
548 
549 { TLldbInstruction }
550 
TLldbInstruction.GetQueuenull551 function TLldbInstruction.GetQueue: TLldbInstructionQueue;
552 begin
553   Result := TLldbInstructionQueue(inherited Queue);
554 end;
555 
TLldbInstruction.MaskQuotedTextnull556 function TLldbInstruction.MaskQuotedText(ALine: String): String;
557 var
558   p: PChar;
559   q: Boolean;
560   i: Integer;
561 begin
562   Result := ALine;
563   if Result = '' then
564     Exit;
565   UniqueString(Result);
566   p := @Result[1];
567   q := False;
568   for i := Length(Result) - 1 downto 0 do begin
569     if p^ = '''' then
570       q := not q;
571     if q then
572       p^ := ' ';
573     // The closing ' remains in text...
574     inc(p);
575   end;
576 end;
577 
ProcessInputFromDbgnull578 function TLldbInstruction.ProcessInputFromDbg(const AData: String): Boolean;
579 var
580   s: String;
581 begin
582   Result := False;
583   if LeftStr(AData, 7) = 'error: ' then begin
584     s := MaskQuotedText(LowerCase(AData));
585     if (StrContains(s, 'debug map time') and StrContains(s, 'file will be ignored'))
586     then begin
587       FDwarfLoadErrors := FDwarfLoadErrors + AData + LineEnding;
588       exit;
589     end;
590 
591     Result := True;
592     HandleError(ifeContentError);
593     exit;
594   end;
595 end;
596 
597 procedure TLldbInstruction.SetContentReceieved;
598 begin
599   inherited;
600   MarkAsSuccess;
601 end;
602 
603 { TLldbInstructionSettingSet }
604 
ProcessInputFromDbgnull605 function TLldbInstructionSettingSet.ProcessInputFromDbg(const AData: String
606   ): Boolean;
607 begin
608   Result := inherited ProcessInputFromDbg(AData);
609 
610   if not Result then // if Result=true then self is destroyed;
611     MarkAsSuccess;
612   Result := true;
613 end;
614 
615 constructor TLldbInstructionSettingSet.Create(AName, AValue: String;
616   AGlobal: Boolean; AQuote: Boolean);
617 begin
618   if AQuote then begin
619     AValue := StringReplace(AValue, '\', '\\', [rfReplaceAll]);
620     AValue := StringReplace(AValue, '"', '\"', [rfReplaceAll]);
621     AValue := '"'+AValue+'"';
622   end;
623   if AGlobal then
624     inherited Create(Format('settings set -g -- %s %s', [AName, AValue]))
625   else
626     inherited Create(Format('settings set -- %s %s', [AName, AValue]));
627 end;
628 
629 { TLldbInstructionSettingRemove }
630 
ProcessInputFromDbgnull631 function TLldbInstructionSettingRemove.ProcessInputFromDbg(const AData: String
632   ): Boolean;
633 begin
634   Result := inherited ProcessInputFromDbg(AData);
635 
636   if not Result then // if Result=true then self is destroyed;
637     MarkAsSuccess;
638   Result := true;
639 end;
640 
641 constructor TLldbInstructionSettingRemove.Create(AName, AValue: String;
642   AQuote: Boolean);
643 begin
644   if AQuote then begin
645     AValue := StringReplace(AValue, '\', '\\', [rfReplaceAll]);
646     AValue := StringReplace(AValue, '"', '\"', [rfReplaceAll]);
647     AValue := '"'+AValue+'"';
648   end;
649   inherited Create(Format('settings remove %s %s', [AName, AValue]));
650 end;
651 
652 { TLldbInstructionSettingClear }
653 
ProcessInputFromDbgnull654 function TLldbInstructionSettingClear.ProcessInputFromDbg(const AData: String
655   ): Boolean;
656 begin
657   Result := inherited ProcessInputFromDbg(AData);
658 
659   if not Result then // if Result=true then self is destroyed;
660     MarkAsSuccess;
661   Result := true;
662 end;
663 
664 constructor TLldbInstructionSettingClear.Create(AName: String);
665 begin
666   inherited Create(Format('settings clear %s', [AName]));
667 end;
668 
669 { TLldbInstructionTargetCreate }
670 
ProcessInputFromDbgnull671 function TLldbInstructionTargetCreate.ProcessInputFromDbg(const AData: String
672   ): Boolean;
673 begin
674   Result := True;
675   if LeftStr(AData, 25) = 'Current executable set to' then begin
676     FRes := AData;
677     SetContentReceieved;
678   end
679   else
680     Result := inherited;
681 end;
682 
683 constructor TLldbInstructionTargetCreate.Create(AFile: String);
684 begin
685   if pos(' ', AFile) > 0 then
686     AFile := ''''+AFile+'''';
687   inherited Create('target create '+AFile);
688 end;
689 
690 { TLldbInstructionTargetDelete }
691 
ProcessInputFromDbgnull692 function TLldbInstructionTargetDelete.ProcessInputFromDbg(const AData: String
693   ): Boolean;
694 begin
695   Result := True;
696   if (LeftStr(AData, 27) = 'error: no targets to delete') or
697      (LeftStr(AData, 17) = '1 targets deleted')
698   then begin
699     SetContentReceieved;
700   end
701   else
702     Result := inherited;
703 end;
704 
705 constructor TLldbInstructionTargetDelete.Create;
706 begin
707   inherited Create('target delete 0');
708 end;
709 
710 { TLldbInstructionTargetStopHook }
711 
ProcessInputFromDbgnull712 function TLldbInstructionTargetStopHook.ProcessInputFromDbg(const AData: String
713   ): Boolean;
714 begin
715   Result := True;
716   if StrStartsWith(AData, 'Stop hook ') and (pos(' added', AData) > 8) then begin
717     SetContentReceieved;
718   end
719   else
720     Result := inherited;
721 end;
722 
723 constructor TLldbInstructionTargetStopHook.Create(const ACmd: String);
724 begin
725   inherited Create(Format('target stop-hook add -o "%s"', [ACmd]));
726 end;
727 
728 { TLldbInstructionProcessLaunch }
729 
ProcessInputFromDbgnull730 function TLldbInstructionProcessLaunch.ProcessInputFromDbg(const AData: String
731   ): Boolean;
732 var
733   s: String;
734 begin
735   if StrStartsWith(AData, 'Process ') and (pos(' launched:', AData) > 8) then begin
736     SetContentReceieved;
737   end
738   else
739     inherited;
740   Result := True; // Ignore any "process stopped", before "launched"
741 end;
742 
743 constructor TLldbInstructionProcessLaunch.Create(AOpenTerminal: Boolean);
744 begin
745   if AOpenTerminal then
746     inherited Create('process launch --tty')
747   else
748     inherited Create('process launch -n');
749 end;
750 
751 { TLldbInstructionProcessStep }
752 
ProcessInputFromDbgnull753 function TLldbInstructionProcessStep.ProcessInputFromDbg(const AData: String
754   ): Boolean;
755 begin
756   Result := inherited ProcessInputFromDbg(AData);
757   SetContentReceieved;
758 end;
759 
760 constructor TLldbInstructionProcessStep.Create(
761   AStepAction: TLldbInstructionProcessStepAction; AThread: Integer);
762 begin
763   case AStepAction of
764   	saContinue: inherited Create('process continue');
765   (*
766     saOver: inherited Create('thread step-over', AThread);
767   	saInto: inherited Create('thread step-in', AThread);
768     saOut: inherited Create('thread step-out', AThread);
769     saInsIn: inherited Create ('thread step-inst', AThread);
770     saInsOver: inherited Create('thread step-inst-over', AThread);
771   // *)
772   //(*
773     saOver: inherited Create(Format('thread step-over %d', [AThread]));
774   	saInto: inherited Create(Format('thread step-in %d', [AThread]));
775     saOut: inherited Create(Format('thread step-out %d', [AThread]));
776     saInsIn: inherited Create (Format('thread step-inst %d', [AThread]));
777     saInsOver: inherited Create(Format('thread step-inst-over %d', [AThread]));
778   // *)
779   end;
780 end;
781 
782 { TLldbInstructionProcessKill }
783 
ProcessInputFromDbgnull784 function TLldbInstructionProcessKill.ProcessInputFromDbg(const AData: String
785   ): Boolean;
786 begin
787   Result := True;
788   if (LeftStr(AData, 8) = 'Process ') and (pos(' exited with status = ', AData) > 7) then begin
789     SetContentReceieved;
790   end
791   else
792       Result := inherited;
793 end;
794 
795 constructor TLldbInstructionProcessKill.Create();
796 begin
797   inherited Create('process kill');
798 end;
799 
800 { TLldbInstructionProcessInterrupt }
801 
ProcessInputFromDbgnull802 function TLldbInstructionProcessInterrupt.ProcessInputFromDbg(
803   const AData: String): Boolean;
804 begin
805   Result := True;
806   SetContentReceieved;
807 end;
808 
809 constructor TLldbInstructionProcessInterrupt.Create();
810 begin
811   inherited Create('process interrupt');
812 end;
813 
814 { TLldbInstructionBreakSet }
815 
816 constructor TLldbInstructionBreakSet.Create(AFileName: String; ALine: Integer;
817   ADisabled: Boolean; AConditon: String);
818 begin
819   FState := vsInvalid;
820   if AConditon <> '' then AConditon := ' --condition ''' + AConditon + '''';
821   if ADisabled then AConditon := AConditon + ' -d ';
822   if pos(' ', AFileName) > 0 then
823     AFileName := ''''+AFileName+'''';
824   inherited Create(Format('breakpoint set --file %s --line %d', [AFileName, ALine]) + AConditon);
825 end;
826 
827 constructor TLldbInstructionBreakSet.Create(AMethod: String;
828   ADisabled: Boolean; AConditon: String);
829 begin
830   FState := vsInvalid;
831   if AConditon <> '' then AConditon := ' --condition ''' + AConditon + '''';
832   if ADisabled then AConditon := AConditon + ' -d ';
833   inherited Create(Format('breakpoint set --func %s', [AMethod]) + AConditon);
834 end;
835 
836 constructor TLldbInstructionBreakSet.Create(AMethod: String;
837   ADisabled: Boolean; ABeforePrologue: Boolean);
838 var
839   s: String;
840 begin
841   FState := vsInvalid;
842   s := '';
843   if ABeforePrologue then s := ' -K false ';
844   if ADisabled then s := s + ' -d ';
845   inherited Create(Format('breakpoint set --func %s', [AMethod]) + s);
846 end;
847 
848 constructor TLldbInstructionBreakSet.Create(AnAddress: TDBGPtr;
849   ADisabled: Boolean; AConditon: String);
850 begin
851   FState := vsInvalid;
852   if AConditon <> '' then AConditon := ' --condition ''' + AConditon + '''';
853   if ADisabled then AConditon := AConditon + ' -d ';
854   inherited Create(Format('breakpoint set --address %u', [AnAddress]) + AConditon);
855 end;
856 
857 { TLldbInstructionBreakModify }
858 
ProcessInputFromDbgnull859 function TLldbInstructionBreakModify.ProcessInputFromDbg(const AData: String
860   ): Boolean;
861 begin
862   Result := inherited ProcessInputFromDbg(AData);
863   if not Result then
864     MarkAsSuccess;
865 end;
866 
867 constructor TLldbInstructionBreakModify.Create(AnId: Integer; ADisabled: Boolean
868   );
869 begin
870   if ADisabled
871   then inherited Create(Format('breakpoint modify --disable %d', [AnId]))
872   else inherited Create(Format('breakpoint modify --enable %d', [AnId]));
873 end;
874 
875 constructor TLldbInstructionBreakModify.Create(AnId: Integer;
876   ADisabled: Boolean; AConditon: String);
877 begin
878   AConditon := ' --condition ''' + AConditon + '''';
879   if ADisabled
880   then AConditon := ' --disable' + AConditon
881   else AConditon := ' --enable' + AConditon;
882   inherited Create(Format('breakpoint modify %s %d', [AConditon, AnId]));
883 end;
884 
885 { TLldbInstructionBreakAddCommands }
886 
ProcessInputFromDbgnull887 function TLldbInstructionBreakAddCommands.ProcessInputFromDbg(const AData: String
888   ): Boolean;
889 begin
890   if StrStartsWith(AData, 'version') then begin
891     Result := True;
892     MarkAsSuccess;
893     Exit;
894   end;
895   Result := inherited ProcessInputFromDbg(AData);
896 end;
897 
898 procedure TLldbInstructionBreakAddCommands.SendCommandDataToDbg();
899 var
900   i: Integer;
901 begin
902   inherited SendCommandDataToDbg();
903   for i := 0 to length(FCommands) - 1 do
904     Queue.SendDataToDBG(Self, FCommands[i]);
905   Queue.SendDataToDBG(Self, 'DONE');
906   Queue.SendDataToDBG(Self, 'version'); // end marker // do not sent before new prompt
907 end;
908 
909 constructor TLldbInstructionBreakAddCommands.Create(AnId: Integer;
910   ACommands: array of String);
911 var
912   i: Integer;
913 begin
914   inherited Create(Format('breakpoint command add %d', [AnId]));
915   SetLength(FCommands, Length(ACommands));
916   for i := 0 to Length(ACommands) - 1 do
917     FCommands[i] := ACommands[i];
918 end;
919 
920 { TLldbInstructionBreakDelete }
921 
ProcessInputFromDbgnull922 function TLldbInstructionBreakDelete.ProcessInputFromDbg(const AData: String
923   ): Boolean;
924 begin
925   Result := inherited ProcessInputFromDbg(AData);
926   if Result then exit;  // if Result=true then self is destroyed;
927 
928   //ReadLn "1 breakpoints deleted; 0 breakpoint locations disabled."
929   if StrMatches(AData, ['', 'breakpoint', 'deleted', '']) then
930     MarkAsSuccess;
931   Result := true;
932 
933   //TODO: "error: No breakpoints exist to be deleted."
934   // prevent from failing other instruction
935 end;
936 
937 constructor TLldbInstructionBreakDelete.Create(AnId: Integer);
938 begin
939   inherited Create(Format('breakpoint delete %d', [AnId]));
940 end;
941 
942 { TLldbInstructionWatchSet }
943 
944 constructor TLldbInstructionWatchSet.Create(AWatch: String;
945   AKind: TDBGWatchPointKind);
946 begin
947   case AKind of
948   	wpkWrite:     inherited Create(Format('watchpoint set variable -w write %s', [AWatch]));
949     wpkRead:      inherited Create(Format('watchpoint set variable -w read %s', [AWatch]));
950     wpkReadWrite: inherited Create(Format('watchpoint set variable -w read_write %s', [AWatch]));
951   end;
952 end;
953 
954 { TLldbInstructionWatchModify }
955 
ProcessInputFromDbgnull956 function TLldbInstructionWatchModify.ProcessInputFromDbg(const AData: String
957   ): Boolean;
958 begin
959   Result := inherited ProcessInputFromDbg(AData);
960   if not Result then
961     MarkAsSuccess;
962 end;
963 
964 constructor TLldbInstructionWatchModify.Create(AnId: Integer; AConditon: String
965   );
966 begin
967   inherited Create(Format('watchpoint modify --condition ''%s'' %d', [AConditon, AnId]));
968 end;
969 
970 { TLldbInstructionWatchDelete }
971 
ProcessInputFromDbgnull972 function TLldbInstructionWatchDelete.ProcessInputFromDbg(const AData: String
973   ): Boolean;
974 begin
975   Result := inherited ProcessInputFromDbg(AData);
976 
977   if not Result then // if Result=true then self is destroyed;
978     MarkAsSuccess;
979   Result := true;
980 
981   //TODO: "error: No breakpoints exist to be deleted."
982   // prevent from failing other instruction
983 end;
984 
985 constructor TLldbInstructionWatchDelete.Create(AnId: Integer);
986 begin
987   inherited Create(Format('watchpoint delete %d', [AnId]));
988 end;
989 
990 { TLldbInstructionThreadSelect }
991 
ProcessInputFromDbgnull992 function TLldbInstructionThreadSelect.ProcessInputFromDbg(const AData: String
993   ): Boolean;
994 begin
995   Result := inherited ProcessInputFromDbg(AData);
996 
997   if not Result then begin // if Result=true then self is destroyed;
998     Queue.SetKnownThread(FIndex);
999     MarkAsSuccess;
1000   end;
1001   Result := true;
1002 end;
1003 
1004 constructor TLldbInstructionThreadSelect.Create(AnIndex: Integer);
1005 begin
1006   FIndex := AnIndex;
1007   inherited Create(Format('thread select %d', [AnIndex]));
1008 end;
1009 
1010 { TLldbInstructionFrameSelect }
1011 
ProcessInputFromDbgnull1012 function TLldbInstructionFrameSelect.ProcessInputFromDbg(const AData: String
1013   ): Boolean;
1014 begin
1015   Result := inherited ProcessInputFromDbg(AData);
1016 
1017   if not Result then begin // if Result=true then self is destroyed;
1018     Queue.SetKnownThreadAndFrame(Queue.CurrentThreadId, FIndex);
1019     MarkAsSuccess;
1020   end;
1021   Result := true;
1022 (* TODO: ?
1023 ReadLn "* thread #3"
1024 ReadLn "    frame #0: 0x7700eb6c ntdll.dll`NtDelayExecution + 12"
1025 
1026 This falls through to TLldbDebugger.DoAfterLineReceived
1027 and sets the current location in the editor.
1028 *)
1029 end;
1030 
1031 constructor TLldbInstructionFrameSelect.Create(AnIndex: Integer);
1032 begin
1033   FIndex := AnIndex;
1034   inherited Create(Format('frame select %d', [AnIndex]));
1035 end;
1036 
1037 { TLldbInstructionLocals }
1038 
ProcessInputFromDbgnull1039 function TLldbInstructionLocals.ProcessInputFromDbg(const AData: String
1040   ): Boolean;
1041 var
1042   found: TStringArray;
1043 begin
1044   Result := True;
1045 
1046   if StrStartsWith(AData, 'version') then begin
1047     MarkAsSuccess;
1048     Exit;
1049   end;
1050 
1051   if FCurVal <> '' then begin
1052     FCurVal := FCurVal + AData;
1053     if ParseStruct(AData) then begin
1054       FRes.Values[FCurName] := FCurVal;
1055       FCurName := '';
1056       FCurVal := '';
1057     end;
1058     exit;
1059   end;
1060 
1061   if StrMatches(AData, ['(', ')', ' = ', ''], found) then begin
1062     FCurName := found[1];
1063     FCurVal := found[2];
1064     FCurly := 0;
1065     if ParseStruct(found[2]) then begin
1066       FRes.Values[FCurName] := FCurVal;
1067       FCurName := '';
1068       FCurVal := '';
1069     end;
1070     exit;
1071   end;
1072 
1073   Result := inherited ProcessInputFromDbg(AData);
1074 end;
1075 
1076 procedure TLldbInstructionLocals.SendCommandDataToDbg();
1077 begin
1078   inherited SendCommandDataToDbg();
1079   Queue.SendDataToDBG(Self, 'version'); // end marker // do not sent before new prompt
1080 end;
1081 
1082 constructor TLldbInstructionLocals.Create(AThread, AFrame: Integer);
1083 begin
1084   inherited Create('frame variable -P 1 -D 5', AThread, AFrame); // TODO: make -D 5 configurable
1085   FRes := TStringList.Create;
1086 end;
1087 
1088 destructor TLldbInstructionLocals.Destroy;
1089 begin
1090   inherited Destroy;
1091   FRes.Free;
1092 end;
1093 
1094 { TLldbInstructionExpressionBase }
1095 
ProcessInputFromDbgnull1096 function TLldbInstructionExpressionBase.ProcessInputFromDbg(const AData: String
1097   ): Boolean;
1098 var
1099   found: TStringArray;
1100 begin
1101   Result := True;
1102 
1103   if FRes <> '' then begin
1104     FRes := FRes + AData;
1105     if ParseStruct(AData) then
1106       SetContentReceieved;
1107     exit;
1108   end;
1109 
1110   if StrMatches(AData, ['(', ')', ' = ', ''], found) then begin
1111     FRes := AData;
1112     FCurly := 0;
1113     if ParseStruct(found[2]) then
1114       SetContentReceieved;
1115     exit;
1116   end;
1117 // error: use of undeclared identifier 'i'
1118 // (int) $0 = 133
1119 // (LONGINT) I = 99
1120 // (ANSISTRING) $1 = 0x005aac80
1121   Result := inherited ProcessInputFromDbg(AData);
1122 end;
1123 
1124 { TLldbInstructionExpression }
1125 
1126 constructor TLldbInstructionExpression.Create(AnExpression: String; AThread,
1127   AFrame: Integer);
1128 begin
1129 //  inherited Create(Format('expression -R -- %s', [UpperCase(AnExpression)]));
1130   inherited Create(Format('expression -T -- %s', [UpperCase(AnExpression)]), AThread, AFrame);
1131 end;
1132 
1133 { TLldbInstructionReadExpression }
1134 
1135 procedure TLldbInstructionReadExpression.SendCommandDataToDbg();
1136 begin
1137   // do not sent data
1138   SetStateRunning;
1139 end;
1140 
1141 constructor TLldbInstructionReadExpression.Create;
1142 begin
1143   inherited Create('');
1144 end;
1145 
1146 { TLldbInstructionMemory }
1147 
ProcessInputFromDbgnull1148 function TLldbInstructionMemory.ProcessInputFromDbg(const AData: String
1149   ): Boolean;
1150 var
1151   found: TStringArray;
1152   n, l, i: Integer;
1153   s: String;
1154 begin
1155   Result := False;
1156   if StrStartsWith(AData, Command) then begin
1157     FReading := True;
1158   end;
1159 
1160   if not FReading then
1161     exit;
1162 
1163   Result := True;
1164 
1165 
1166   if StrMatches(AData, ['0x', ': ', ''], found) then begin
1167     // todo check the address
1168     l := Length(FRes);
1169     s := found[1];
1170     n := (Length(s)+1) div 5;
1171     SetLength(FRes, l+n);
1172     for i := l to l + n-1 do begin
1173       FRes[i] := StrToIntDef(copy(s,1,4), 0);
1174       delete(s,1,5);
1175     end;
1176     exit;
1177   end;
1178 //<< << TCmdLineDebugger.ReadLn "0x005ff280: 0x60 0x10 0x77 0x04"
1179 
1180 
1181   if StrStartsWith(AData, 'version') then begin
1182     MarkAsSuccess;
1183     Exit;
1184   end;
1185 
1186   Result := inherited ProcessInputFromDbg(AData);
1187 end;
1188 
1189 procedure TLldbInstructionMemory.SendCommandDataToDbg();
1190 begin
1191   inherited SendCommandDataToDbg();
1192   Queue.SendDataToDBG(Self, 'version'); // end marker // do not sent before new prompt
1193 end;
1194 
1195 constructor TLldbInstructionMemory.Create(AnAddress: TDBGPtr; ALen: Cardinal);
1196 begin
1197   inherited Create(Format('memory read --force --size 1 --format x --count %u %u', [ALen, AnAddress]));
1198 end;
1199 
1200 destructor TLldbInstructionMemory.Destroy;
1201 begin
1202   inherited Destroy;
1203   FRes := nil;
1204 end;
1205 
1206 { TLldbInstructionRegister }
1207 
1208 procedure TLldbInstructionRegister.DoFree;
1209 begin
1210   FreeAndNil(FRes);
1211   inherited DoFree;
1212 end;
1213 
ProcessInputFromDbgnull1214 function TLldbInstructionRegister.ProcessInputFromDbg(const AData: String
1215   ): Boolean;
1216 var
1217   found: TStringArray;
1218   i: Integer;
1219   s, reg, val: String;
1220 begin
1221   Result := False;
1222   if StrStartsWith(AData, Command) then begin
1223     FReading := True;
1224   end;
1225 
1226   if not FReading then
1227     exit;
1228 
1229   Result := True;
1230 
1231   if StrStartsWith(AData, 'General Purpose Registers:') then
1232     exit;
1233 
1234   if StrMatches(AData, ['  ', ' = ', ''], found) then begin
1235     if FRes = nil then FRes := TStringList.Create;
1236       reg := UpperCase(trim(found[0]));
1237       i := pos(' ', found[1]);
1238       if i < 1 then i := Length(found[1]);
1239       val := copy(found[1], 1, i);
1240       FRes.Values[reg] := val;
1241     exit;
1242   end;
1243 
1244   if StrStartsWith(AData, 'version') then begin
1245     MarkAsSuccess;
1246     Exit;
1247   end;
1248 
1249   Result := inherited ProcessInputFromDbg(AData);
1250 
1251 (*
1252    << Finished Instruction: register read --all // True
1253   << Current Instruction:
1254   TDBGInstructionQueue.RunQueue nil / nil
1255   << << TCmdLineDebugger.ReadLn "General Purpose Registers:"
1256   << << TCmdLineDebugger.ReadLn "       eax = 0x00000000"
1257   << << TCmdLineDebugger.ReadLn "       ebx = 0x005AF750  VMT_$UNIT1_$$_TFORM1"
1258   << << TCmdLineDebugger.ReadLn "       ecx = 0x04696C7C"
1259   << << TCmdLineDebugger.ReadLn "       edx = 0x00000002"
1260   << << TCmdLineDebugger.ReadLn "       edi = 0x005AF750  VMT_$UNIT1_$$_TFORM1"
1261   << << TCmdLineDebugger.ReadLn "       esi = 0x046F1060"
1262   << << TCmdLineDebugger.ReadLn "       ebp = 0x0262FDF8"
1263   << << TCmdLineDebugger.ReadLn "       esp = 0x0262FDA8"
1264   << << TCmdLineDebugger.ReadLn "       eip = 0x004294A8  project1.exe`FORMCREATE + 104 at unit1.pas:39"
1265   << << TCmdLineDebugger.ReadLn "    eflags = 0b00000000000000000000001001000110"
1266   << << TCmdLineDebugger.ReadLn ""
1267 < TLldbDebugger.UnlockRelease 1
1268 *)
1269 end;
1270 
1271 procedure TLldbInstructionRegister.SendCommandDataToDbg();
1272 begin
1273   inherited SendCommandDataToDbg();
1274   Queue.SendDataToDBG(Self, 'version'); // end marker // do not sent before new prompt
1275 end;
1276 
1277 constructor TLldbInstructionRegister.Create(AThread, AFrame: Integer);
1278 begin
1279   inherited Create('register read --all', AThread, AFrame);
1280 end;
1281 
1282 destructor TLldbInstructionRegister.Destroy;
1283 begin
1284   inherited Destroy;
1285   FRes.Free;
1286 end;
1287 
1288 { TLldbInstructionThreadList }
1289 
1290 procedure TLldbInstructionThreadList.SendCommandDataToDbg();
1291 begin
1292   inherited SendCommandDataToDbg();
1293   Queue.SendDataToDBG(Self, 'version'); // end marker // do not sent before new prompt
1294 end;
1295 
ProcessInputFromDbgnull1296 function TLldbInstructionThreadList.ProcessInputFromDbg(const AData: String
1297   ): Boolean;
1298 var
1299   l: Integer;
1300 begin
1301   Result := False;
1302   if StrStartsWith(AData, Command) then begin
1303     FReading := True;
1304     exit;
1305   end;
1306 
1307   if not FReading then
1308     exit;
1309 
1310   Result := True;
1311 
1312   if StrStartsWith(AData, 'Process ') then
1313     exit;
1314 
1315 
1316   if StrStartsWith(AData, '* thread #') or StrStartsWith(AData, '  thread #') then begin
1317 DebugLn(['######### add ',AData]);
1318     l := Length(FRes);
1319     SetLength(FRes, l+1);
1320     FRes[l] := AData;
1321     exit;
1322   end;
1323 
1324   if StrStartsWith(AData, 'version') then begin
1325     MarkAsSuccess;
1326     Exit;
1327   end;
1328 
1329   Result := inherited ProcessInputFromDbg(AData);
1330 end;
1331 
1332 constructor TLldbInstructionThreadList.Create();
1333 begin
1334   inherited Create('thread list');
1335 end;
1336 
1337 destructor TLldbInstructionThreadList.Destroy;
1338 begin
1339   inherited Destroy;
1340   FRes := nil;
1341 end;
1342 
1343 { TLldbInstructionThreadListReader }
1344 
1345 procedure TLldbInstructionThreadListReader.SendCommandDataToDbg();
1346 begin
1347   // send nothing
1348   SetStateRunning;
1349   FReading := True;
1350 end;
1351 
ProcessInputFromDbgnull1352 function TLldbInstructionThreadListReader.ProcessInputFromDbg(
1353   const AData: String): Boolean;
1354 begin
1355   if StrStartsWith(AData, '    frame ') then begin
1356     MarkAsFailed;
1357     Result := False;
1358     exit;
1359   end;
1360 
1361   Result := inherited ProcessInputFromDbg(AData);
1362 
1363   if StrMatches(AData, ['Process ', 'stopped']) then begin
1364     MarkAsSuccess;
1365     Exit;
1366   end;
1367 end;
1368 
1369 { TLldbInstructionStackTrace }
1370 
1371 procedure TLldbInstructionStackTrace.SendCommandDataToDbg();
1372 begin
1373   inherited SendCommandDataToDbg();
1374   Queue.SendDataToDBG(Self, 'version'); // end marker // do not sent before new prompt
1375 end;
1376 
ProcessInputFromDbgnull1377 function TLldbInstructionStackTrace.ProcessInputFromDbg(const AData: String
1378   ): Boolean;
1379 var
1380   l: Integer;
1381 begin
1382   Result := False;
1383   if StrStartsWith(AData, Command) then begin
1384     FReading := True;
1385     exit;
1386   end;
1387 
1388   if not FReading then
1389     exit;
1390 
1391   Result := True;
1392 
1393   if StrStartsWith(AData, '* thread ') then
1394     exit;
1395 
1396 
1397   if StrStartsWith(AData, '  * frame ') or StrStartsWith(AData, '    frame ') then begin
1398     l := Length(FRes);
1399     SetLength(FRes, l+1);
1400     FRes[l] := AData;
1401     exit;
1402   end;
1403 
1404   if StrStartsWith(AData, 'version') then begin
1405     MarkAsSuccess;
1406     Exit;
1407   end;
1408 
1409   Result := inherited ProcessInputFromDbg(AData);
1410 end;
1411 
1412 constructor TLldbInstructionStackTrace.Create(FrameCount: Integer;
1413   AThread: Integer);
1414 begin
1415   inherited Create(Format('thread backtrace -c %d', [FrameCount]), AThread);
1416 end;
1417 
1418 constructor TLldbInstructionStackTrace.Create(FrameCount, FirstFrame: Integer;
1419   AThread: Integer);
1420 begin
1421   inherited Create(Format('thread backtrace -s %d -c %d', [FirstFrame, FrameCount]), AThread);
1422 end;
1423 
1424 destructor TLldbInstructionStackTrace.Destroy;
1425 begin
1426   inherited Destroy;
1427   FRes := nil;
1428 end;
1429 
1430 constructor TLldbInstructionDisassem.Create(AnAddr: TDBGPtr; NumLines: Cardinal);
1431 var AddressString: String;
1432 begin
1433   FRes := TStringList.Create;
1434   AddressString := IntToHex(AnAddr, 16);
1435   inherited Create(Format('disassemble -b --start-address  0x%s --count %d', [AddressString, NumLines]));
1436 end;
1437 
1438 constructor TLldbInstructionDisassem.CreateRange(StartAddr: TDBGPtr;
1439   EndAddr: TDBGPtr);
1440 var StartAddressString, EndAddressString: String;
1441 begin
1442   FRes := TStringList.Create;
1443   StartAddressString := IntToHex(StartAddr, 16);
1444   EndAddressString := IntToHex(EndAddr, 16);
1445   inherited Create(Format('disassemble -b --start-address  0x%s --end-address 0x%s', [StartAddressString, EndAddressString]));
1446 end;
1447 
1448 
1449 destructor TLldbInstructionDisassem.Destroy;
1450 begin
1451   FRes.Free;
1452   inherited Destroy;
1453 end;
1454 
ProcessInputFromDbgnull1455 function TLldbInstructionDisassem.ProcessInputFromDbg(const AData: String): Boolean;
1456 var i: Integer;
1457     Address: TDBGPtr;
1458 begin
1459   Result := False;
1460   if StrStartsWith(AData, Command) then begin
1461     FReading := True;
1462     exit;
1463   end;
1464 
1465   if not FReading then
1466     exit;
1467 
1468   Result := True;
1469 
1470   if StrStartsWith(AData, 'version') then begin
1471     MarkAsSuccess;
1472     Exit;
1473   end;
1474 
1475   Result := inherited ProcessInputFromDbg(AData);
1476 
1477   if not Result then
1478     FRes.Add(StringReplace(AData, '->', '  ',[]));
1479 
1480 end;
1481 
1482 procedure TLldbInstructionDisassem.SendCommandDataToDbg();
1483 begin
1484   inherited SendCommandDataToDbg();
1485   Queue.SendDataToDBG(Self, 'version'); // end marker // do not sent before new prompt
1486 end;
1487 
1488 
1489 end.
1490 
1491