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