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