Debugger: Attach, Darwin, try and get process-list via gdb. Issue #0025302 Patch by Joost van der Sluis

git-svn-id: trunk@43417 -
This commit is contained in:
martin 2013-11-10 23:32:18 +00:00
parent 126c85c628
commit 165fa57622
5 changed files with 102 additions and 37 deletions

View File

@ -9,20 +9,10 @@ interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
ComCtrls, LCLType, Contnrs, LazarusIDEStrConsts;
ComCtrls, LCLType, Contnrs, LazarusIDEStrConsts, BaseDebugManager, Debugger;
type
// Used to enumerate running processes.
TRunningProcessInfo = class
public
PID: Cardinal;
ImageName: string;
constructor Create(APID: Cardinal; const AImageName: string);
end;
TRunningProcessInfoList = TObjectList;
{ TDebugAttachDialogForm }
TDebugAttachDialogForm = class(TForm)
@ -188,6 +178,9 @@ begin
if not Assigned(AList) then
Exit;
// If it is not possible to get the process-list from the debugger,
// use NSRunningApplication as fallback method. This list is not complete,
// though. But better then nothing.
Arr := NSWorkspace.sharedWorkspace.runningApplications;
for I := 0 to Arr.count - 1 do
begin
@ -205,41 +198,34 @@ end;
{$endif}
{$endif}
{ TRunningProcessInfo }
constructor TRunningProcessInfo.Create(APID: Cardinal; const AImageName: string);
begin
self.PID := APID;
self.ImageName := AImageName;
end;
function GetPidForAttach: string;
var
ProcessList: TRunningProcessInfoList;
begin
Result := '';
// Check if we can enumerate processes.
if not EnumerateProcesses(nil) then
begin
// If we can't just ask PID as string.
InputQuery(rsAttachTo, rsEnterPID, Result);
Exit;
end;
// Enumerate.
DebugAttachDialogForm := TDebugAttachDialogForm.Create(nil);
ProcessList := TRunningProcessInfoList.Create(True);
try
ProcessList := TRunningProcessInfoList.Create(True);
// Check if we can enumerate processes.
if not DebugBoss.FillProcessList(ProcessList) then
if not EnumerateProcesses(ProcessList) then
begin
// If we can't just ask PID as string.
InputQuery(rsAttachTo, rsEnterPID, Result);
Exit;
end;
// Enumerate.
DebugAttachDialogForm := TDebugAttachDialogForm.Create(nil);
try
EnumerateProcesses(ProcessList);
if DebugAttachDialogForm.ChooseProcess(ProcessList, Result) <> mrOK then
Result := '';
finally
FreeAndNil(ProcessList);
FreeAndNil(DebugAttachDialogForm);
end;
finally
FreeAndNil(DebugAttachDialogForm);
FreeAndNil(ProcessList);
end;
end;
@ -294,7 +280,9 @@ procedure TDebugAttachDialogForm.btnRefreshClick(Sender: TObject);
begin
lvProcesses.Items.Clear;
FList.Clear;
EnumerateProcesses(FList);
if not DebugBoss.FillProcessList(FList)
then
EnumerateProcesses(FList);
lvProcesses.Items.Count := FList.Count;
end;

View File

@ -39,7 +39,7 @@ interface
uses
TypInfo, Classes, SysUtils, Laz2_XMLCfg, math, FileUtil, LazLoggerBase, LazClasses,
LCLProc, LazConfigStorage, DebugUtils, maps;
LCLProc, LazConfigStorage, DebugUtils, maps, contnrs;
type
// datatype pointing to data on the target
@ -162,6 +162,20 @@ type
EDebuggerException = class(Exception);
EDBGExceptions = class(EDebuggerException);
type
// Used to enumerate running processes.
{ TRunningProcessInfo }
TRunningProcessInfo = class
public
PID: Cardinal;
ImageName: string;
constructor Create(APID: Cardinal; const AImageName: string);
end;
TRunningProcessInfoList = TObjectList;
type
{ TDebuggerConfigStore }
(* TODO: maybe revert relations. Create this in Debugger, and call environmentoptions for the configstore only? *)
@ -2848,6 +2862,7 @@ type
function Evaluate(const AExpression: String; var AResult: String;
var ATypeInfo: TDBGType;
EvalFlags: TDBGEvaluateFlags = []): Boolean; // Evaluates the given expression, returns true if valid
function GetProcessList(AList: TRunningProcessInfoList): boolean; virtual;
function Modify(const AExpression, AValue: String): Boolean; // Modifies the given expression, returns true if valid
function Disassemble(AAddr: TDbgPtr; ABackward: Boolean; out ANextAddr: TDbgPtr;
out ADump, AStatement, AFile: String; out ALine: Integer): Boolean; deprecated;
@ -3155,6 +3170,14 @@ begin
if a > b then Result := a else Result := b;
end;
{ TRunningProcessInfo }
constructor TRunningProcessInfo.Create(APID: Cardinal; const AImageName: string);
begin
self.PID := APID;
self.ImageName := AImageName;
end;
{ TRegistersFormatList }
function TRegistersFormatList.GetFormat(AName: String): TRegisterDisplayFormat;
@ -6528,6 +6551,11 @@ begin
Result := ReqCmd(dcEvaluate, [AExpression, @AResult, @ATypeInfo, Integer(EvalFlags)]);
end;
function TDebugger.GetProcessList(AList: TRunningProcessInfoList): boolean;
begin
result := false;
end;
class function TDebugger.ExePaths: String;
begin
Result := '';

View File

@ -803,6 +803,7 @@ type
procedure Init; override; // Initializes external debugger
procedure Done; override; // Kills external debugger
function GetLocation: TDBGLocationRec; override;
function GetProcessList(AList: TRunningProcessInfoList): boolean; override;
//LockCommandProcessing is more than just QueueExecuteLock
//LockCommandProcessing also takes care to run the queue, if unlocked and not already running
@ -7288,6 +7289,45 @@ begin
Result := FCurrentLocation;
end;
function TGDBMIDebugger.GetProcessList(AList: TRunningProcessInfoList): boolean;
{$ifdef darwin}
var
AResult: TGDBMIExecResult;
ARunningProcessInfo: TRunningProcessInfo;
pname,pid,aLine: string;
s: string;
i: integer;
{$endif}
begin
{$ifdef darwin}
result := State in [dsIdle, dsStop, dsInit];
if not Result then
exit;
ExecuteCommand('info mach-tasks',[],[], AResult);
s := AResult.Values;
i := pos(sLineBreak,s);
while i>0 do
begin
aLine := trim(copy(s,1,i-1));
delete(s,1,i+1);
i := pos(' is ', aLine);
pid := copy(aLine,1,i-1);
pname := copy(aLine,i+4,PosEx(' ',aLine,i+4)-(i+4));
if pid <> '' then
begin
ARunningProcessInfo := TRunningProcessInfo.Create(StrToIntDef(pname,-1), pid);
AList.Add(ARunningProcessInfo);
end;
i := pos(sLineBreak,s);
end;
{$else}
result := false;
{$endif}
end;
procedure TGDBMIDebugger.LockCommandProcessing;
begin
// Keep a different counter than QueueExecuteLock

View File

@ -172,6 +172,7 @@ type
procedure Attach(AProcessID: String); virtual; abstract;
procedure Detach; virtual; abstract;
function FillProcessList(AList: TRunningProcessInfoList): boolean; virtual; abstract;
function Evaluate(const AExpression: String; var AResult: String;
var ATypeInfo: TDBGType;

View File

@ -208,6 +208,7 @@ type
procedure EndDebugging; override;
procedure Attach(AProcessID: String); override;
function FillProcessList(AList: TRunningProcessInfoList): boolean; override;
procedure Detach; override;
function Evaluate(const AExpression: String; var AResult: String;
@ -2640,10 +2641,17 @@ begin
end;
end;
function TDebugManager.FillProcessList(AList: TRunningProcessInfoList): boolean;
begin
Result := (not Destroying)
and (MainIDE.ToolStatus in [itDebugger, itNone])
and (FDebugger <> nil)
and FDebugger.GetProcessList(AList);
end;
procedure TDebugManager.Detach;
begin
FRunTimer.Enabled:=false;
Exclude(FManagerStates,dmsWaitForRun);
FRunTimer.Enabled:=false; Exclude(FManagerStates,dmsWaitForRun);
Exclude(FManagerStates,dmsWaitForAttach);
SourceEditorManager.ClearExecutionLines;