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