DBG: refactor unit location handling

git-svn-id: trunk@32335 -
This commit is contained in:
martin 2011-09-14 13:48:43 +00:00
parent 7fc60239cb
commit a7100b234c
6 changed files with 557 additions and 151 deletions

View File

@ -197,8 +197,7 @@ function TCallStackDlg.GetImageIndex(Entry: TCallStackEntry): Integer;
begin begin
if BreakPoints = nil then if BreakPoints = nil then
Exit(False); Exit(False);
FileName := Entry.Source; Result := DebugBoss.GetFullFilename(Entry.UnitInfo, FileName, False);
Result := DebugBoss.GetFullFilename(FileName, False);
if Result then if Result then
Result := BreakPoints.Find(FileName, Entry.Line) <> nil; Result := BreakPoints.Find(FileName, Entry.Line) <> nil;
end; end;
@ -439,16 +438,8 @@ begin
// avoid any process-messages, so this proc can not be re-entered (avoid opening one files many times) // avoid any process-messages, so this proc can not be re-entered (avoid opening one files many times)
DebugBoss.LockCommandProcessing; DebugBoss.LockCommandProcessing;
try try
// check the full name first if DebugBoss.GetFullFilename(Entry.UnitInfo, Filename, False) then
Filename := Entry.FullFileName; MainIDE.DoJumpToSourcePosition(Filename, 0, Entry.Line, 0, True, True);
if (Filename = '') or not DebugBoss.GetFullFilename(Filename, False) then
begin
// if fails the check the short file name
Filename := Entry.Source;
if (FileName = '') or not DebugBoss.GetFullFilename(Filename, True) then
Exit;
end;
MainIDE.DoJumpToSourcePosition(Filename, 0, Entry.Line, 0, True, True);
finally finally
DebugBoss.UnLockCommandProcessing; DebugBoss.UnLockCommandProcessing;
end; end;
@ -491,8 +482,7 @@ begin
idx := FViewStart + Item.Index; idx := FViewStart + Item.Index;
if idx >= GetSelectedCallstack.Count then Exit; if idx >= GetSelectedCallstack.Count then Exit;
Entry := GetSelectedCallstack.Entries[idx]; Entry := GetSelectedCallstack.Entries[idx];
FileName := Entry.Source; if not DebugBoss.GetFullFilename(Entry.UnitInfo, FileName, False) then
if (FileName = '') or not DebugBoss.GetFullFilename(FileName, False) then
Exit; Exit;
BreakPoint := BreakPoints.Find(FileName, Entry.Line); BreakPoint := BreakPoints.Find(FileName, Entry.Line);
if BreakPoint <> nil then if BreakPoint <> nil then

View File

@ -190,6 +190,81 @@ type
procedure ReleaseAndNil(var ARefCountedObject); procedure ReleaseAndNil(var ARefCountedObject);
type type
TDebuggerLocationType = (dltUnknown, // not jet looked up
dltUnresolvable, // lookup failed
dltProject,
dltPackage
);
TDebuggerLocationFlags = set of (dlfLoadError // resolved but failed to load
);
{ TDebuggerUnitInfo }
TDebuggerUnitInfo = class(TRefCountedObject)
private
FFileName, FDbgFullName: String;
FFlags: TDebuggerLocationFlags;
FLocationName, FLocationOwnerName, FLocationFullFile: String;
FLocationType: TDebuggerLocationType;
function GetFileName: String;
function GetDbgFullName: String;
function GetLocationFullFile: String;
function GetLocationName: String;
function GetLocationOwnerName: String;
function GetLocationType: TDebuggerLocationType;
procedure SetLocationFullFile(AValue: String);
procedure SetLocationType(AValue: TDebuggerLocationType);
public
constructor Create(const AFileName: String; const AFullFileName: String);
function IsEqual(const AFileName: String; const AFullFileName: String): boolean;
function IsEqual(AnOther: TDebuggerUnitInfo): boolean;
procedure LoadDataFromXMLConfig(const AConfig: TXMLConfig;
const APath: string); virtual;
procedure SaveDataToXMLConfig(const AConfig: TXMLConfig;
const APath: string); virtual;
property FileName: String read GetFileName;
property DbgFullName: String read GetDbgFullName;
property LocationType: TDebuggerLocationType read GetLocationType write SetLocationType;
property LocationOwnerName: String read GetLocationOwnerName;
property LocationName: String read GetLocationName;
property LocationFullFile: String read GetLocationFullFile write SetLocationFullFile;
property Flags: TDebuggerLocationFlags read FFlags write FFlags;
end;
{ TDebuggerUnitInfoList }
TDebuggerUnitInfoList = class(TRefCntObjList)
private
function GetInfo(Index: Integer): TDebuggerUnitInfo;
procedure PutInfo(Index: Integer; AValue: TDebuggerUnitInfo);
public
property Items[Index: Integer]: TDebuggerUnitInfo read GetInfo write PutInfo; default;
end;
{ TDebuggerUnitInfoProvider }
TDebuggerUnitInfoProvider = class
private
FList: TDebuggerUnitInfoList;
FLoader: TDebuggerUnitInfo;
function GetInfo(Index: Integer): TDebuggerUnitInfo;
public
constructor Create;
destructor Destroy; override;
procedure Clear;
function GetUnitInfoFor(const AFileName: String; const AFullFileName: String): TDebuggerUnitInfo;
function IndexOf(AnInfo: TDebuggerUnitInfo; AddIfNotExists: Boolean = False): Integer;
function Count: integer;
property Items[Index: Integer]: TDebuggerUnitInfo read GetInfo; default;
public
// Load/Save all entries with ID
procedure LoadDataFromXMLConfig(const AConfig: TXMLConfig;
const APath: string);
procedure SaveDataToXMLConfig(const AConfig: TXMLConfig;
const APath: string);
end;
{ ---------------------------------------------------------<br> { ---------------------------------------------------------<br>
TDebuggerNotification is a reference counted baseclass TDebuggerNotification is a reference counted baseclass
for handling notifications for locals, watches, breakpoints etc.<br> for handling notifications for locals, watches, breakpoints etc.<br>
@ -1464,31 +1539,34 @@ type
FFunctionName: String; FFunctionName: String;
FLine: Integer; FLine: Integer;
FArguments: TStrings; FArguments: TStrings;
FSource: String; FUnitInfo: TDebuggerUnitInfo;
FFullFileName: String;
FState: TDebuggerDataState; FState: TDebuggerDataState;
function GetArgumentCount: Integer; function GetArgumentCount: Integer;
function GetArgumentName(const AnIndex: Integer): String; function GetArgumentName(const AnIndex: Integer): String;
function GetArgumentValue(const AnIndex: Integer): String; function GetArgumentValue(const AnIndex: Integer): String;
function GetFullFileName: String;
function GetFunctionName: String; function GetFunctionName: String;
function GetSource: String; function GetSource: String;
procedure SetUnitInfo(AUnitInfo: TDebuggerUnitInfo);
protected protected
procedure LoadDataFromXMLConfig(const AConfig: TXMLConfig; procedure LoadDataFromXMLConfig(const AConfig: TXMLConfig;
APath: string); const APath: string;
AUnitInvoPrv: TDebuggerUnitInfoProvider = nil
);
procedure SaveDataToXMLConfig(const AConfig: TXMLConfig; procedure SaveDataToXMLConfig(const AConfig: TXMLConfig;
APath: string); APath: string;
AUnitInvoPrv: TDebuggerUnitInfoProvider = nil
);
public public
constructor Create; constructor Create;
constructor Create(const AIndex:Integer; const AnAdress: TDbgPtr; constructor Create(const AIndex:Integer; const AnAdress: TDbgPtr;
const AnArguments: TStrings; const AFunctionName: String; const AnArguments: TStrings; const AFunctionName: String;
const ASource: String; const AFullFileName: String; const AUnitInfo: TDebuggerUnitInfo;
const ALine: Integer; AState: TDebuggerDataState = ddsValid); const ALine: Integer; AState: TDebuggerDataState = ddsValid);
constructor CreateCopy(const ASource: TCallStackEntry); constructor CreateCopy(const ASource: TCallStackEntry);
destructor Destroy; override; destructor Destroy; override;
procedure Init(const AnAdress: TDbgPtr; procedure Init(const AnAdress: TDbgPtr;
const AnArguments: TStrings; const AFunctionName: String; const AnArguments: TStrings; const AFunctionName: String;
const ASource: String; const AFullFileName: String; const AUnitInfo: TDebuggerUnitInfo;
const ALine: Integer; AState: TDebuggerDataState = ddsValid); const ALine: Integer; AState: TDebuggerDataState = ddsValid);
function GetFunctionWithArg: String; function GetFunctionWithArg: String;
function IsCurrent: Boolean; function IsCurrent: Boolean;
@ -1501,7 +1579,7 @@ type
property Index: Integer read FIndex; property Index: Integer read FIndex;
property Line: Integer read FLine; property Line: Integer read FLine;
property Source: String read GetSource; property Source: String read GetSource;
property FullFileName: String read GetFullFileName; property UnitInfo: TDebuggerUnitInfo read FUnitInfo;
property State: TDebuggerDataState read FState write FState; property State: TDebuggerDataState read FState write FState;
end; end;
@ -1525,9 +1603,13 @@ type
procedure AddEntry(AnEntry: TCallStackEntry); virtual; // must be added in correct order procedure AddEntry(AnEntry: TCallStackEntry); virtual; // must be added in correct order
procedure AssignEntriesTo(AnOther: TCallStack); virtual; procedure AssignEntriesTo(AnOther: TCallStack); virtual;
procedure LoadDataFromXMLConfig(const AConfig: TXMLConfig; procedure LoadDataFromXMLConfig(const AConfig: TXMLConfig;
APath: string); APath: string;
AUnitInvoPrv: TDebuggerUnitInfoProvider = nil
);
procedure SaveDataToXMLConfig(const AConfig: TXMLConfig; procedure SaveDataToXMLConfig(const AConfig: TXMLConfig;
APath: string); APath: string;
AUnitInvoPrv: TDebuggerUnitInfoProvider = nil
);
public public
constructor Create; constructor Create;
constructor CreateCopy(const ASource: TCallStack); constructor CreateCopy(const ASource: TCallStack);
@ -1551,9 +1633,13 @@ type
function GetEntryForThread(const AThreadId: Integer): TCallStack; virtual; function GetEntryForThread(const AThreadId: Integer): TCallStack; virtual;
procedure Add(ACallStack: TCallStack); procedure Add(ACallStack: TCallStack);
procedure LoadDataFromXMLConfig(const AConfig: TXMLConfig; procedure LoadDataFromXMLConfig(const AConfig: TXMLConfig;
APath: string); APath: string;
AUnitInvoPrv: TDebuggerUnitInfoProvider = nil
);
procedure SaveDataToXMLConfig(const AConfig: TXMLConfig; procedure SaveDataToXMLConfig(const AConfig: TXMLConfig;
APath: string); APath: string;
AUnitInvoPrv: TDebuggerUnitInfoProvider = nil
);
public public
constructor Create; constructor Create;
destructor Destroy; override; destructor Destroy; override;
@ -1889,13 +1975,17 @@ type
FThreadState: String; FThreadState: String;
protected protected
procedure LoadDataFromXMLConfig(const AConfig: TXMLConfig; procedure LoadDataFromXMLConfig(const AConfig: TXMLConfig;
const APath: string); reintroduce; const APath: string;
AUnitInvoPrv: TDebuggerUnitInfoProvider = nil
); reintroduce;
procedure SaveDataToXMLConfig(const AConfig: TXMLConfig; procedure SaveDataToXMLConfig(const AConfig: TXMLConfig;
const APath: string); reintroduce; const APath: string;
AUnitInvoPrv: TDebuggerUnitInfoProvider = nil
); reintroduce;
public public
constructor Create(const AIndex:Integer; const AnAdress: TDbgPtr; constructor Create(const AIndex:Integer; const AnAdress: TDbgPtr;
const AnArguments: TStrings; const AFunctionName: String; const AnArguments: TStrings; const AFunctionName: String;
const ASource: String; const AFullFileName: String; const ALocationInfo: TDebuggerUnitInfo;
const ALine: Integer; const ALine: Integer;
const AThreadId: Integer; const AThreadName: String; const AThreadId: Integer; const AThreadName: String;
const AThreadState: String; const AThreadState: String;
@ -1917,9 +2007,13 @@ type
protected protected
procedure Assign(AOther: TThreads); procedure Assign(AOther: TThreads);
procedure LoadDataFromXMLConfig(const AConfig: TXMLConfig; procedure LoadDataFromXMLConfig(const AConfig: TXMLConfig;
APath: string); virtual; APath: string;
AUnitInvoPrv: TDebuggerUnitInfoProvider = nil
);
procedure SaveDataToXMLConfig(const AConfig: TXMLConfig; procedure SaveDataToXMLConfig(const AConfig: TXMLConfig;
APath: string); virtual; APath: string;
AUnitInvoPrv: TDebuggerUnitInfoProvider = nil
);
public public
constructor Create; constructor Create;
destructor Destroy; override; destructor Destroy; override;
@ -2011,9 +2105,13 @@ type
function GetLocationAsText: String; function GetLocationAsText: String;
protected protected
procedure LoadDataFromXMLConfig(const AConfig: TXMLConfig; procedure LoadDataFromXMLConfig(const AConfig: TXMLConfig;
APath: string); virtual; APath: string;
AUnitInvoPrv: TDebuggerUnitInfoProvider = nil
);
procedure SaveDataToXMLConfig(const AConfig: TXMLConfig; procedure SaveDataToXMLConfig(const AConfig: TXMLConfig;
APath: string); virtual; APath: string;
AUnitInvoPrv: TDebuggerUnitInfoProvider = nil
);
public public
constructor Create(ASnapMgr: TSnapshotManager); constructor Create(ASnapMgr: TSnapshotManager);
destructor Destroy; override; destructor Destroy; override;
@ -2054,6 +2152,7 @@ type
FThreads: TThreadsMonitor; FThreads: TThreadsMonitor;
private private
FActive: Boolean; FActive: Boolean;
FUnitInfoProvider: TDebuggerUnitInfoProvider;
FUpdateLock: Integer; FUpdateLock: Integer;
FUpdateFlags: set of (ufSnapChanged, ufSnapCurrent, ufInDebuggerIdle); FUpdateFlags: set of (ufSnapChanged, ufSnapCurrent, ufInDebuggerIdle);
FCurrentState: TDBGState; FCurrentState: TDBGState;
@ -2090,9 +2189,9 @@ type
procedure DoCurrent; procedure DoCurrent;
protected protected
procedure LoadDataFromXMLConfig(const AConfig: TXMLConfig; procedure LoadDataFromXMLConfig(const AConfig: TXMLConfig;
APath: string); virtual; APath: string);
procedure SaveDataToXMLConfig(const AConfig: TXMLConfig; procedure SaveDataToXMLConfig(const AConfig: TXMLConfig;
APath: string); virtual; APath: string);
public public
constructor Create; constructor Create;
destructor Destroy; override; destructor Destroy; override;
@ -2125,6 +2224,7 @@ type
property CallStack: TCallStackMonitor read FCallStack write FCallStack; property CallStack: TCallStackMonitor read FCallStack write FCallStack;
property Threads: TThreadsMonitor read FThreads write FThreads; property Threads: TThreadsMonitor read FThreads write FThreads;
property Debugger: TDebugger read FDebugger write FDebugger; property Debugger: TDebugger read FDebugger write FDebugger;
property UnitInfoProvider: TDebuggerUnitInfoProvider read FUnitInfoProvider write FUnitInfoProvider;
end; end;
{%endregion ^^^^^ Snapshots ^^^^^ } {%endregion ^^^^^ Snapshots ^^^^^ }
@ -2424,6 +2524,7 @@ type
AType: TDBGFeedbackType; AButtons: TDBGFeedbackResults AType: TDBGFeedbackType; AButtons: TDBGFeedbackResults
): TDBGFeedbackResult of object; ): TDBGFeedbackResult of object;
TDebuggerNotifyReason = (dnrDestroy); TDebuggerNotifyReason = (dnrDestroy);
{ TDebuggerProperties } { TDebuggerProperties }
@ -2454,6 +2555,7 @@ type
FFileName: String; FFileName: String;
FLocals: TLocalsSupplier; FLocals: TLocalsSupplier;
FLineInfo: TDBGLineInfo; FLineInfo: TDBGLineInfo;
FUnitInfoProvider, FInternalUnitInfoProvider: TDebuggerUnitInfoProvider;
FOnBeforeState: TDebuggerStateChangedEvent; FOnBeforeState: TDebuggerStateChangedEvent;
FOnConsoleOutput: TDBGOutputEvent; FOnConsoleOutput: TDBGOutputEvent;
FOnFeedback: TDBGFeedbackEvent; FOnFeedback: TDBGFeedbackEvent;
@ -2476,6 +2578,7 @@ type
FDestroyNotificationList: array [TDebuggerNotifyReason] of TMethodList; FDestroyNotificationList: array [TDebuggerNotifyReason] of TMethodList;
procedure DebuggerEnvironmentChanged(Sender: TObject); procedure DebuggerEnvironmentChanged(Sender: TObject);
procedure EnvironmentChanged(Sender: TObject); procedure EnvironmentChanged(Sender: TObject);
function GetUnitInfoProvider: TDebuggerUnitInfoProvider;
function GetState: TDBGState; function GetState: TDBGState;
function ReqCmd(const ACommand: TDBGCommand; function ReqCmd(const ACommand: TDBGCommand;
const AParams: array of const): Boolean; const AParams: array of const): Boolean;
@ -2582,6 +2685,8 @@ type
property IsIdle: Boolean read GetIsIdle; // Nothing queued property IsIdle: Boolean read GetIsIdle; // Nothing queued
property ErrorStateMessage: String read FErrorStateMessage; property ErrorStateMessage: String read FErrorStateMessage;
property ErrorStateInfo: String read FErrorStateInfo; property ErrorStateInfo: String read FErrorStateInfo;
property UnitInfoProvider: TDebuggerUnitInfoProvider // Provided by DebugBoss, to map files to packages or project
read GetUnitInfoProvider write FUnitInfoProvider;
// Events // Events
property OnCurrent: TDBGCurrentLineEvent read FOnCurrent write FOnCurrent; // Passes info about the current line being debugged property OnCurrent: TDBGCurrentLineEvent read FOnCurrent write FOnCurrent; // Passes info about the current line being debugged
property OnDbgOutput: TDBGOutputEvent read FOnDbgOutput write FOnDbgOutput; // Passes all debuggeroutput property OnDbgOutput: TDBGOutputEvent read FOnDbgOutput write FOnDbgOutput; // Passes all debuggeroutput
@ -2744,6 +2849,213 @@ begin
Result:=bpaStop; Result:=bpaStop;
end; end;
{ TDebuggerUnitInfoProvider }
function TDebuggerUnitInfoProvider.GetInfo(Index: Integer): TDebuggerUnitInfo;
begin
Result := FList.Items[Index];
end;
constructor TDebuggerUnitInfoProvider.Create;
begin
FList := TDebuggerUnitInfoList.Create;
FLoader := TDebuggerUnitInfo.Create('', '');
end;
destructor TDebuggerUnitInfoProvider.Destroy;
begin
FList.Clear;
inherited Destroy;
FreeAndNil(FLoader);
FreeAndNil(FList);
end;
procedure TDebuggerUnitInfoProvider.Clear;
begin
FList.Clear;
end;
function TDebuggerUnitInfoProvider.GetUnitInfoFor(const AFileName: String;
const AFullFileName: String): TDebuggerUnitInfo;
var
i: Integer;
begin
i := FList.Count - 1;
while i >= 0 do begin
if FList[i].IsEqual(AFileName, AFullFileName) then begin
{$IFDEF DBG_LOCATION_INFO}
debugln(['TDebuggerLocationProvider.GetLocationInfoFor Found entry for: ', AFileName, ' / ', AFullFileName]);
{$ENDIF}
exit(FList[i])
end;
dec(i);
end;
Result := TDebuggerUnitInfo.Create(AFileName, AFullFileName);
FList.Add(Result);
{$IFDEF DBG_LOCATION_INFO}
debugln(['TDebuggerLocationProvider.GetLocationInfoFor Created new entry (Cnt=',FList.Count,') for: ', AFileName, ' / ', AFullFileName]);
{$ENDIF}
end;
function TDebuggerUnitInfoProvider.IndexOf(AnInfo: TDebuggerUnitInfo;
AddIfNotExists: Boolean): Integer;
begin
Result := FList.Count - 1;
while Result >= 0 do begin
if FList[Result].IsEqual(AnInfo) then begin
exit;
end;
dec(Result);
end;
if AddIfNotExists then
Result := FList.Add(AnInfo);
end;
function TDebuggerUnitInfoProvider.Count: integer;
begin
Result := FList.Count;
end;
procedure TDebuggerUnitInfoProvider.LoadDataFromXMLConfig(const AConfig: TXMLConfig;
const APath: string);
var
i, c: Integer;
Item: TDebuggerUnitInfo;
begin
c := AConfig.GetValue(APath + 'UnitInfoCount', 0);
for i := 0 to c - 1 do begin
Item := TDebuggerUnitInfo.Create('', '');
Item.LoadDataFromXMLConfig(AConfig, APath + 'UnitInfo_' + IntToStr(i) + '/');
FList.Add(Item);
end;
end;
procedure TDebuggerUnitInfoProvider.SaveDataToXMLConfig(const AConfig: TXMLConfig;
const APath: string);
var
i: Integer;
begin
AConfig.SetValue(APath + 'UnitInfoCount', FList.Count);
for i := 0 to FList.Count - 1 do
FList[i].SaveDataToXMLConfig(AConfig, APath + 'UnitInfo_' + IntToStr(i) + '/');
end;
{ TDebuggerUnitInfoList }
function TDebuggerUnitInfoList.GetInfo(Index: Integer): TDebuggerUnitInfo;
begin
Result := TDebuggerUnitInfo(inherited Items[Index]);
end;
procedure TDebuggerUnitInfoList.PutInfo(Index: Integer; AValue: TDebuggerUnitInfo);
begin
inherited Items[Index] := AValue;
end;
{ TDebuggerUnitInfo }
function TDebuggerUnitInfo.GetFileName: String;
begin
Result := FFileName;
end;
function TDebuggerUnitInfo.GetDbgFullName: String;
begin
Result := FDbgFullName;
end;
function TDebuggerUnitInfo.GetLocationFullFile: String;
begin
Result := FLocationFullFile;;
end;
function TDebuggerUnitInfo.GetLocationName: String;
begin
Result := FLocationName;
end;
function TDebuggerUnitInfo.GetLocationOwnerName: String;
begin
Result := FLocationOwnerName;
end;
function TDebuggerUnitInfo.GetLocationType: TDebuggerLocationType;
begin
Result := FLocationType;
end;
procedure TDebuggerUnitInfo.SetLocationFullFile(AValue: String);
begin
FLocationFullFile := AValue;
end;
procedure TDebuggerUnitInfo.SetLocationType(AValue: TDebuggerLocationType);
begin
FLocationType := AValue;
end;
constructor TDebuggerUnitInfo.Create(const AFileName: String; const AFullFileName: String);
begin
FFileName := AFileName;
FDbgFullName := TrimFilename(AFullFileName);
FLocationType := dltUnknown;
end;
function TDebuggerUnitInfo.IsEqual(const AFileName: String;
const AFullFileName: String): boolean;
begin
Result := (FFileName = AFileName) and
(FDbgFullName = AFullFileName);
end;
function TDebuggerUnitInfo.IsEqual(AnOther: TDebuggerUnitInfo): boolean;
begin
Result := (FFileName = AnOther.FFileName);
if not Result then exit;
case LocationType of
dltUnknown, dltUnresolvable:
Result := Result and (FDbgFullName = AnOther.FDbgFullName);
dltProject, dltPackage:
Result := Result and
(FLocationType = AnOther.FLocationType) and
(FLocationOwnerName = AnOther.FLocationOwnerName) and
(FLocationName = AnOther.FLocationName);
end;
end;
procedure TDebuggerUnitInfo.LoadDataFromXMLConfig(const AConfig: TXMLConfig;
const APath: string);
begin
try
ReadStr(AConfig.GetValue(APath + 'Type', 'dltUnknown'), FLocationType);
if LocationType = dltUnresolvable
then LocationType := dltUnknown;
except
FLocationType := dltUnknown;
end;
FFileName := AConfig.GetValue(APath + 'File', '');
FLocationOwnerName := AConfig.GetValue(APath + 'UnitOwner', '');
FLocationName := AConfig.GetValue(APath + 'UnitFile', '');
FDbgFullName := AConfig.GetValue(APath + 'DbgFile', '');
FLocationFullFile := '';
end;
procedure TDebuggerUnitInfo.SaveDataToXMLConfig(const AConfig: TXMLConfig;
const APath: string);
var
s: String;
begin
WriteStr(s, LocationType);
AConfig.SetValue(APath + 'Type', s);
AConfig.SetValue(APath + 'File', FileName);
AConfig.SetValue(APath + 'UnitOwner', LocationOwnerName);
AConfig.SetValue(APath + 'UnitFile', LocationName);
AConfig.SetValue(APath + 'DbgFile', FDbgFullName);
end;
{ TSnapshotList } { TSnapshotList }
function TSnapshotList.Get(Index: Integer): TSnapshot; function TSnapshotList.Get(Index: Integer): TSnapshot;
@ -2797,7 +3109,8 @@ begin
inherited Destroy; inherited Destroy;
end; end;
procedure TSnapshot.LoadDataFromXMLConfig(const AConfig: TXMLConfig; APath: string); procedure TSnapshot.LoadDataFromXMLConfig(const AConfig: TXMLConfig; APath: string;
AUnitInvoPrv: TDebuggerUnitInfoProvider = nil);
begin begin
FLocation.Address := StrToQWordDef(AConfig.GetValue(APath + 'LocationAddress', '0'), 0); FLocation.Address := StrToQWordDef(AConfig.GetValue(APath + 'LocationAddress', '0'), 0);
FLocation.FuncName := AConfig.GetValue(APath + 'LocationFuncName', ''); FLocation.FuncName := AConfig.GetValue(APath + 'LocationFuncName', '');
@ -2810,9 +3123,9 @@ begin
FTimeStamp := 0; FTimeStamp := 0;
end; end;
if FSnapMgr.Threads.Snapshots[Pointer(Self)] <> nil then if FSnapMgr.Threads.Snapshots[Pointer(Self)] <> nil then
FSnapMgr.Threads.Snapshots[Pointer(Self)].LoadDataFromXMLConfig(AConfig, APath + 'SnapThreads/'); FSnapMgr.Threads.Snapshots[Pointer(Self)].LoadDataFromXMLConfig(AConfig, APath + 'SnapThreads/', AUnitInvoPrv);
if FSnapMgr.CallStack.Snapshots[Pointer(Self)] <> nil then if FSnapMgr.CallStack.Snapshots[Pointer(Self)] <> nil then
FSnapMgr.CallStack.Snapshots[Pointer(Self)].LoadDataFromXMLConfig(AConfig, APath + 'SnapCallstack/'); FSnapMgr.CallStack.Snapshots[Pointer(Self)].LoadDataFromXMLConfig(AConfig, APath + 'SnapCallstack/', AUnitInvoPrv);
if FSnapMgr.Locals.Snapshots[Pointer(Self)] <> nil then if FSnapMgr.Locals.Snapshots[Pointer(Self)] <> nil then
FSnapMgr.Locals.Snapshots[Pointer(Self)].LoadDataFromXMLConfig(AConfig, APath + 'SnapLocals/'); FSnapMgr.Locals.Snapshots[Pointer(Self)].LoadDataFromXMLConfig(AConfig, APath + 'SnapLocals/');
if FSnapMgr.Watches.Snapshots[Pointer(Self)] <> nil then if FSnapMgr.Watches.Snapshots[Pointer(Self)] <> nil then
@ -2822,7 +3135,8 @@ begin
if AConfig.GetValue(APath + 'IsHistory', True) then AddToHistory; if AConfig.GetValue(APath + 'IsHistory', True) then AddToHistory;
end; end;
procedure TSnapshot.SaveDataToXMLConfig(const AConfig: TXMLConfig; APath: string); procedure TSnapshot.SaveDataToXMLConfig(const AConfig: TXMLConfig; APath: string;
AUnitInvoPrv: TDebuggerUnitInfoProvider = nil);
begin begin
AConfig.SetValue(APath + 'LocationAddress', IntToStr(FLocation.Address)); AConfig.SetValue(APath + 'LocationAddress', IntToStr(FLocation.Address));
AConfig.SetValue(APath + 'LocationFuncName', FLocation.FuncName); AConfig.SetValue(APath + 'LocationFuncName', FLocation.FuncName);
@ -2834,9 +3148,9 @@ begin
AConfig.SetValue(APath + 'IsSnapshot', IsSnapshot); AConfig.SetValue(APath + 'IsSnapshot', IsSnapshot);
if FSnapMgr.Threads.Snapshots[Pointer(Self)] <> nil then if FSnapMgr.Threads.Snapshots[Pointer(Self)] <> nil then
FSnapMgr.Threads.Snapshots[Pointer(Self)].SaveDataToXMLConfig(AConfig, APath + 'SnapThreads/'); FSnapMgr.Threads.Snapshots[Pointer(Self)].SaveDataToXMLConfig(AConfig, APath + 'SnapThreads/', AUnitInvoPrv);
if FSnapMgr.CallStack.Snapshots[Pointer(Self)] <> nil then if FSnapMgr.CallStack.Snapshots[Pointer(Self)] <> nil then
FSnapMgr.CallStack.Snapshots[Pointer(Self)].SaveDataToXMLConfig(AConfig, APath + 'SnapCallstack/'); FSnapMgr.CallStack.Snapshots[Pointer(Self)].SaveDataToXMLConfig(AConfig, APath + 'SnapCallstack/', AUnitInvoPrv);
if FSnapMgr.Locals.Snapshots[Pointer(Self)] <> nil then if FSnapMgr.Locals.Snapshots[Pointer(Self)] <> nil then
FSnapMgr.Locals.Snapshots[Pointer(Self)].SaveDataToXMLConfig(AConfig, APath + 'SnapLocals/'); FSnapMgr.Locals.Snapshots[Pointer(Self)].SaveDataToXMLConfig(AConfig, APath + 'SnapLocals/');
if FSnapMgr.Watches.Snapshots[Pointer(Self)] <> nil then if FSnapMgr.Watches.Snapshots[Pointer(Self)] <> nil then
@ -2982,8 +3296,11 @@ procedure TSnapshotManager.LoadDataFromXMLConfig(const AConfig: TXMLConfig; APat
var var
c, i: Integer; c, i: Integer;
NewSnap: TSnapshot; NewSnap: TSnapshot;
UIProv: TDebuggerUnitInfoProvider;
begin begin
Clear; Clear;
UIProv := TDebuggerUnitInfoProvider.Create;
UIProv.LoadDataFromXMLConfig(AConfig, APath + 'UnitInfos/');
c := AConfig.GetValue(APath + 'SnapCount', 0); c := AConfig.GetValue(APath + 'SnapCount', 0);
for i := 0 to c - 1 do begin for i := 0 to c - 1 do begin
@ -2992,7 +3309,7 @@ begin
FCallStack.NewSnapshot(NewSnap, True); FCallStack.NewSnapshot(NewSnap, True);
FLocals.NewSnapshot(NewSnap, True); FLocals.NewSnapshot(NewSnap, True);
FWatches.NewSnapshot(NewSnap, True); FWatches.NewSnapshot(NewSnap, True);
NewSnap.LoadDataFromXMLConfig(AConfig, APath + 'SnapEntry' + IntToStr(i) + '/'); NewSnap.LoadDataFromXMLConfig(AConfig, APath + 'SnapEntry' + IntToStr(i) + '/', UIProv);
if not(NewSnap.IsHistory or NewSnap.IsSnapshot) then begin if not(NewSnap.IsHistory or NewSnap.IsSnapshot) then begin
RemoveHistoryEntryFromMonitors(NewSnap); // TODO: add user feedback / warning RemoveHistoryEntryFromMonitors(NewSnap); // TODO: add user feedback / warning
debugln(['************** Snapshot loaded, but not kept']); debugln(['************** Snapshot loaded, but not kept']);
@ -3007,7 +3324,7 @@ begin
FCallStack.NewSnapshot(NewSnap, True); FCallStack.NewSnapshot(NewSnap, True);
FLocals.NewSnapshot(NewSnap, True); FLocals.NewSnapshot(NewSnap, True);
FWatches.NewSnapshot(NewSnap, True); FWatches.NewSnapshot(NewSnap, True);
NewSnap.LoadDataFromXMLConfig(AConfig, APath + 'HistEntry' + IntToStr(i) + '/'); NewSnap.LoadDataFromXMLConfig(AConfig, APath + 'HistEntry' + IntToStr(i) + '/', UIProv);
if not(NewSnap.IsHistory or NewSnap.IsSnapshot) then begin if not(NewSnap.IsHistory or NewSnap.IsSnapshot) then begin
RemoveHistoryEntryFromMonitors(NewSnap); // TODO: add user feedback / warning RemoveHistoryEntryFromMonitors(NewSnap); // TODO: add user feedback / warning
debugln(['************** Snapshot loaded, but not kept']); debugln(['************** Snapshot loaded, but not kept']);
@ -3015,6 +3332,8 @@ begin
NewSnap.ReleaseReference; NewSnap.ReleaseReference;
end; end;
UIProv.Free;
//FThreads.CurrentThreads.SnapShot := nil; //FThreads.CurrentThreads.SnapShot := nil;
//FCallStack.CurrentCallStackList.SnapShot := nil; //FCallStack.CurrentCallStackList.SnapShot := nil;
//FLocals.CurrentLocalsList.SnapShot := nil; //FLocals.CurrentLocalsList.SnapShot := nil;
@ -3026,21 +3345,27 @@ end;
procedure TSnapshotManager.SaveDataToXMLConfig(const AConfig: TXMLConfig; APath: string); procedure TSnapshotManager.SaveDataToXMLConfig(const AConfig: TXMLConfig; APath: string);
var var
c, i: Integer; c, i: Integer;
UIProv: TDebuggerUnitInfoProvider;
begin begin
UIProv := TDebuggerUnitInfoProvider.Create;
c := 0; c := 0;
for i := 0 to FSnapshotList.Count - 1 do begin for i := 0 to FSnapshotList.Count - 1 do begin
if FSnapshotList[i].IsHistory then continue; if FSnapshotList[i].IsHistory then continue;
FSnapshotList[i].SaveDataToXMLConfig(AConfig, APath + 'SnapEntry' + IntToStr(i) + '/'); FSnapshotList[i].SaveDataToXMLConfig(AConfig, APath + 'SnapEntry' + IntToStr(i) + '/', UIProv);
inc(c); inc(c);
end; end;
AConfig.SetValue(APath + 'SnapCount', c); AConfig.SetValue(APath + 'SnapCount', c);
c := 0; c := 0;
for i := 0 to FHistoryList.Count - 1 do begin for i := 0 to FHistoryList.Count - 1 do begin
FHistoryList[i].SaveDataToXMLConfig(AConfig, APath + 'HistEntry' + IntToStr(i) + '/'); FHistoryList[i].SaveDataToXMLConfig(AConfig, APath + 'HistEntry' + IntToStr(i) + '/', UIProv);
inc(c); inc(c);
end; end;
AConfig.SetValue(APath + 'HistCount', c); AConfig.SetValue(APath + 'HistCount', c);
UIProv.SaveDataToXMLConfig(AConfig, APath + 'UnitInfos/');
UIProv.Free;
end; end;
procedure TSnapshotManager.ClearHistory; procedure TSnapshotManager.ClearHistory;
@ -4312,7 +4637,7 @@ begin
Result := nil; Result := nil;
if FEntries.GetData(AIndex, Result) then Exit; if FEntries.GetData(AIndex, Result) then Exit;
Result := TCallStackEntry.Create(AIndex, 0, nil, '', '', '', 0, ddsRequested); Result := TCallStackEntry.Create(AIndex, 0, nil, '', nil, 0, ddsRequested);
if Result = nil then Exit; if Result = nil then Exit;
FEntries.Add(AIndex, Result); FEntries.Add(AIndex, Result);
Result.FOwner := Self; Result.FOwner := Self;
@ -4497,7 +4822,7 @@ begin
end; end;
procedure TCallStackList.LoadDataFromXMLConfig(const AConfig: TXMLConfig; procedure TCallStackList.LoadDataFromXMLConfig(const AConfig: TXMLConfig;
APath: string); APath: string; AUnitInvoPrv: TDebuggerUnitInfoProvider = nil);
var var
c, i: Integer; c, i: Integer;
e: TCallStack; e: TCallStack;
@ -4507,19 +4832,20 @@ begin
APath := APath + 'Entry'; APath := APath + 'Entry';
for i := 0 to c - 1 do begin for i := 0 to c - 1 do begin
e := TCallStack.Create; e := TCallStack.Create;
e.LoadDataFromXMLConfig(AConfig, APath + IntToStr(i) + '/'); e.LoadDataFromXMLConfig(AConfig, APath + IntToStr(i) + '/', AUnitInvoPrv);
Add(e); Add(e);
end; end;
end; end;
procedure TCallStackList.SaveDataToXMLConfig(const AConfig: TXMLConfig; APath: string); procedure TCallStackList.SaveDataToXMLConfig(const AConfig: TXMLConfig; APath: string;
AUnitInvoPrv: TDebuggerUnitInfoProvider = nil);
var var
i: Integer; i: Integer;
begin begin
AConfig.SetDeleteValue(APath + 'Count', Count, 0); AConfig.SetDeleteValue(APath + 'Count', Count, 0);
APath := APath + 'Entry'; APath := APath + 'Entry';
for i := 0 to Count - 1 do for i := 0 to Count - 1 do
Entries[i].SaveDataToXMLConfig(AConfig, APath + IntToStr(i) + '/'); Entries[i].SaveDataToXMLConfig(AConfig, APath + IntToStr(i) + '/', AUnitInvoPrv);
end; end;
procedure TCallStackList.Assign(AnOther: TCallStackList); procedure TCallStackList.Assign(AnOther: TCallStackList);
@ -4878,30 +5204,32 @@ end;
{ TThreadEntry } { TThreadEntry }
procedure TThreadEntry.LoadDataFromXMLConfig(const AConfig: TXMLConfig; const APath: string); procedure TThreadEntry.LoadDataFromXMLConfig(const AConfig: TXMLConfig; const APath: string;
AUnitInvoPrv: TDebuggerUnitInfoProvider = nil);
begin begin
inherited LoadDataFromXMLConfig(AConfig, APath); inherited LoadDataFromXMLConfig(AConfig, APath, AUnitInvoPrv);
FThreadId := AConfig.GetValue(APath + 'ThreadId', -1); FThreadId := AConfig.GetValue(APath + 'ThreadId', -1);
FThreadName := AConfig.GetValue(APath + 'ThreadName', ''); FThreadName := AConfig.GetValue(APath + 'ThreadName', '');
FThreadState := AConfig.GetValue(APath + 'ThreadState', ''); FThreadState := AConfig.GetValue(APath + 'ThreadState', '');
end; end;
procedure TThreadEntry.SaveDataToXMLConfig(const AConfig: TXMLConfig; const APath: string); procedure TThreadEntry.SaveDataToXMLConfig(const AConfig: TXMLConfig; const APath: string;
AUnitInvoPrv: TDebuggerUnitInfoProvider = nil);
begin begin
inherited SaveDataToXMLConfig(AConfig, APath); inherited SaveDataToXMLConfig(AConfig, APath, AUnitInvoPrv);
AConfig.SetValue(APath + 'ThreadId', FThreadId); AConfig.SetValue(APath + 'ThreadId', FThreadId);
AConfig.SetValue(APath + 'ThreadName', FThreadName); AConfig.SetValue(APath + 'ThreadName', FThreadName);
AConfig.SetValue(APath + 'ThreadState', FThreadState); AConfig.SetValue(APath + 'ThreadState', FThreadState);
end; end;
constructor TThreadEntry.Create(const AIndex: Integer; const AnAdress: TDbgPtr; constructor TThreadEntry.Create(const AIndex: Integer; const AnAdress: TDbgPtr;
const AnArguments: TStrings; const AFunctionName: String; const ASource: String; const AnArguments: TStrings; const AFunctionName: String;
const AFullFileName: String; const ALine: Integer; const AThreadId: Integer; const ALocationInfo: TDebuggerUnitInfo; const ALine: Integer; const AThreadId: Integer;
const AThreadName: String; const AThreadState: String; const AThreadName: String; const AThreadState: String;
AState: TDebuggerDataState); AState: TDebuggerDataState);
begin begin
inherited Create(AIndex, AnAdress, AnArguments, AFunctionName, ASource, inherited Create(AIndex, AnAdress, AnArguments, AFunctionName, ALocationInfo,
AFullFileName, ALine, AState); ALine, AState);
FThreadId := AThreadId; FThreadId := AThreadId;
FThreadName := AThreadName; FThreadName := AThreadName;
FThreadState := AThreadState; FThreadState := AThreadState;
@ -4939,7 +5267,8 @@ begin
FList.Add(TThreadEntry.CreateCopy(TThreadEntry(AOther.FList[i]))); FList.Add(TThreadEntry.CreateCopy(TThreadEntry(AOther.FList[i])));
end; end;
procedure TThreads.LoadDataFromXMLConfig(const AConfig: TXMLConfig; APath: string); procedure TThreads.LoadDataFromXMLConfig(const AConfig: TXMLConfig; APath: string;
AUnitInvoPrv: TDebuggerUnitInfoProvider = nil);
var var
c, i: Integer; c, i: Integer;
e: TThreadEntry; e: TThreadEntry;
@ -4950,12 +5279,13 @@ begin
APath := APath + 'Entry'; APath := APath + 'Entry';
for i := 0 to c - 1 do begin for i := 0 to c - 1 do begin
e := TThreadEntry.Create; e := TThreadEntry.Create;
e.LoadDataFromXMLConfig(AConfig, APath + IntToStr(i) + '/'); e.LoadDataFromXMLConfig(AConfig, APath + IntToStr(i) + '/', AUnitInvoPrv);
FList.Add(e); FList.Add(e);
end; end;
end; end;
procedure TThreads.SaveDataToXMLConfig(const AConfig: TXMLConfig; APath: string); procedure TThreads.SaveDataToXMLConfig(const AConfig: TXMLConfig; APath: string;
AUnitInvoPrv: TDebuggerUnitInfoProvider = nil);
var var
i: Integer; i: Integer;
begin begin
@ -4963,7 +5293,7 @@ begin
AConfig.SetDeleteValue(APath + 'Count', Count, 0); AConfig.SetDeleteValue(APath + 'Count', Count, 0);
APath := APath + 'Entry'; APath := APath + 'Entry';
for i := 0 to Count - 1 do for i := 0 to Count - 1 do
Entries[i].SaveDataToXMLConfig(AConfig, APath + IntToStr(i) + '/'); Entries[i].SaveDataToXMLConfig(AConfig, APath + IntToStr(i) + '/', AUnitInvoPrv);
end; end;
constructor TThreads.Create; constructor TThreads.Create;
@ -5093,6 +5423,7 @@ begin
list.OnChange := @EnvironmentChanged; list.OnChange := @EnvironmentChanged;
FEnvironment := list; FEnvironment := list;
FCurEnvironment := TStringList.Create; FCurEnvironment := TStringList.Create;
FInternalUnitInfoProvider := TDebuggerUnitInfoProvider.Create;
FBreakPoints := CreateBreakPoints; FBreakPoints := CreateBreakPoints;
FLocals := CreateLocals; FLocals := CreateLocals;
@ -5191,6 +5522,7 @@ begin
FWatches.Debugger := nil; FWatches.Debugger := nil;
FThreads.Debugger := nil; FThreads.Debugger := nil;
FreeAndNil(FInternalUnitInfoProvider);
FreeAndNil(FExceptions); FreeAndNil(FExceptions);
FreeAndNil(FBreakPoints); FreeAndNil(FBreakPoints);
FreeAndNil(FLocals); FreeAndNil(FLocals);
@ -5353,6 +5685,13 @@ begin
FCurEnvironment.Assign(FEnvironment); FCurEnvironment.Assign(FEnvironment);
end; end;
function TDebugger.GetUnitInfoProvider: TDebuggerUnitInfoProvider;
begin
Result := FUnitInfoProvider;
if Result = nil then
Result := FInternalUnitInfoProvider;
end;
function TDebugger.GetIsIdle: Boolean; function TDebugger.GetIsIdle: Boolean;
begin begin
Result := False; Result := False;
@ -7910,7 +8249,7 @@ end;
constructor TCallStackEntry.Create(const AIndex: Integer; constructor TCallStackEntry.Create(const AIndex: Integer;
const AnAdress: TDbgPtr; const AnArguments: TStrings; const AnAdress: TDbgPtr; const AnArguments: TStrings;
const AFunctionName: String; const ASource: String; const AFullFileName: String; const AFunctionName: String; const AUnitInfo: TDebuggerUnitInfo;
const ALine: Integer; AState: TDebuggerDataState = ddsValid); const ALine: Integer; AState: TDebuggerDataState = ddsValid);
begin begin
inherited Create; inherited Create;
@ -7920,8 +8259,7 @@ begin
if AnArguments <> nil if AnArguments <> nil
then FArguments.Assign(AnArguments); then FArguments.Assign(AnArguments);
FFunctionName := AFunctionName; FFunctionName := AFunctionName;
FSource := ASource; SetUnitInfo(AUnitInfo);
FFullFileName := TrimFilename(AFullFileName);
FLine := ALine; FLine := ALine;
FState := AState; FState := AState;
end; end;
@ -7929,26 +8267,27 @@ end;
constructor TCallStackEntry.CreateCopy(const ASource: TCallStackEntry); constructor TCallStackEntry.CreateCopy(const ASource: TCallStackEntry);
begin begin
Create(ASource.FIndex, ASource.FAdress, ASource.FArguments, Create(ASource.FIndex, ASource.FAdress, ASource.FArguments,
ASource.FFunctionName, ASource.FSource, ASource.FFullFileName, ASource.FFunctionName, ASource.FUnitInfo,
ASource.FLine, ASource.FState); ASource.FLine, ASource.FState);
end; end;
destructor TCallStackEntry.Destroy; destructor TCallStackEntry.Destroy;
begin begin
inherited; inherited;
if FUnitInfo <> nil then FUnitInfo.ReleaseReference;
FreeAndNil(FArguments); FreeAndNil(FArguments);
end; end;
procedure TCallStackEntry.Init(const AnAdress: TDbgPtr; procedure TCallStackEntry.Init(const AnAdress: TDbgPtr;
const AnArguments: TStrings; const AFunctionName: String; const ASource: String; const AnArguments: TStrings; const AFunctionName: String;
const AFullFileName: String; const ALine: Integer; AState: TDebuggerDataState); const AUnitInfo: TDebuggerUnitInfo; const ALine: Integer; AState: TDebuggerDataState);
begin begin
FAdress := AnAdress; FAdress := AnAdress;
if AnArguments <> nil if AnArguments <> nil
then FArguments.Assign(AnArguments); then FArguments.Assign(AnArguments);
FFunctionName := AFunctionName; FFunctionName := AFunctionName;
FSource := ASource;
FFullFileName := AFullFileName; SetUnitInfo(AUnitInfo);
FLine := ALine; FLine := ALine;
FState := AState; FState := AState;
end; end;
@ -7999,13 +8338,6 @@ begin
Result := GetPart('=', '', Result); Result := GetPart('=', '', Result);
end; end;
function TCallStackEntry.GetFullFileName: String;
begin
if FState = ddsValid
then Result := FFullFileName
else Result := '';
end;
function TCallStackEntry.GetFunctionName: String; function TCallStackEntry.GetFunctionName: String;
begin begin
case FState of case FState of
@ -8019,20 +8351,41 @@ end;
function TCallStackEntry.GetSource: String; function TCallStackEntry.GetSource: String;
begin begin
if FState = ddsValid if (FState = ddsValid) and (FUnitInfo <> nil)
then Result := FSource then Result := FUnitInfo.FileName
else Result := ''; else Result := '';
end; end;
procedure TCallStackEntry.LoadDataFromXMLConfig(const AConfig: TXMLConfig; APath: string); procedure TCallStackEntry.SetUnitInfo(AUnitInfo: TDebuggerUnitInfo);
begin
if FUnitInfo <> nil then FUnitInfo.ReleaseReference;
FUnitInfo := AUnitInfo;
if FUnitInfo <> nil then FUnitInfo.AddReference;
end;
procedure TCallStackEntry.LoadDataFromXMLConfig(const AConfig: TXMLConfig; const APath: string;
AUnitInvoPrv: TDebuggerUnitInfoProvider = nil);
var
UInfo: TDebuggerUnitInfo;
i: Integer;
begin begin
FIndex := AConfig.GetValue(APath + 'Index', 0); FIndex := AConfig.GetValue(APath + 'Index', 0);
FAdress := StrToQWordDef(AConfig.GetValue(APath + 'Address', '0'), 0); FAdress := StrToQWordDef(AConfig.GetValue(APath + 'Address', '0'), 0);
FFunctionName := AConfig.GetValue(APath + 'FunctionName', ''); FFunctionName := AConfig.GetValue(APath + 'FunctionName', '');
FLine := AConfig.GetValue(APath + 'Line', 0); FLine := AConfig.GetValue(APath + 'Line', 0);
FArguments.Text := AConfig.GetValue(APath + 'Arguments', ''); FArguments.Text := AConfig.GetValue(APath + 'Arguments', '');
FSource := AConfig.GetValue(APath + 'Source', '');
FFullFileName := AConfig.GetValue(APath + 'FullFileName', ''); i := AConfig.GetValue(APath + 'UnitInfoRef', -1);
UInfo := nil;
if (i >= 0) and (AUnitInvoPrv <> nil) then begin
if i < AUnitInvoPrv.Count then
UInfo := AUnitInvoPrv[i];
end
else begin
UInfo := TDebuggerUnitInfo.Create('','');
UInfo.LoadDataFromXMLConfig(AConfig, APath + 'UnitInfo/');
end;
SetUnitInfo(UInfo);
try try
ReadStr(AConfig.GetValue(APath + 'State', 'ddsUnknown'), FState); ReadStr(AConfig.GetValue(APath + 'State', 'ddsUnknown'), FState);
except except
@ -8040,17 +8393,26 @@ begin
end; end;
end; end;
procedure TCallStackEntry.SaveDataToXMLConfig(const AConfig: TXMLConfig; APath: string); procedure TCallStackEntry.SaveDataToXMLConfig(const AConfig: TXMLConfig; APath: string;
AUnitInvoPrv: TDebuggerUnitInfoProvider = nil);
var var
s: string; s: string;
i: Integer;
begin begin
AConfig.SetValue(APath + 'Index', FIndex); AConfig.SetValue(APath + 'Index', FIndex);
AConfig.SetValue(APath + 'Address', IntToStr(FAdress)); AConfig.SetValue(APath + 'Address', IntToStr(FAdress));
AConfig.SetValue(APath + 'FunctionName', FFunctionName); AConfig.SetValue(APath + 'FunctionName', FFunctionName);
AConfig.SetValue(APath + 'Line', FLine); AConfig.SetValue(APath + 'Line', FLine);
AConfig.SetValue(APath + 'Arguments', FArguments.Text); AConfig.SetValue(APath + 'Arguments', FArguments.Text);
AConfig.SetValue(APath + 'Source', FSource); if FUnitInfo <> nil then begin
AConfig.SetValue(APath + 'FullFileName', FFullFileName); if AUnitInvoPrv <> nil
then begin
i := AUnitInvoPrv.IndexOf(FUnitInfo, True);
AConfig.SetValue(APath + 'UnitInfoRef', i);
end
else
FUnitInfo.SaveDataToXMLConfig(AConfig, APath + 'UnitInfo/');
end;
WriteStr(s, FState); WriteStr(s, FState);
AConfig.SetValue(APath + 'State', s); AConfig.SetValue(APath + 'State', s);
end; end;
@ -8114,7 +8476,8 @@ begin
end; end;
end; end;
procedure TCallStack.LoadDataFromXMLConfig(const AConfig: TXMLConfig; APath: string); procedure TCallStack.LoadDataFromXMLConfig(const AConfig: TXMLConfig; APath: string;
AUnitInvoPrv: TDebuggerUnitInfoProvider = nil);
var var
c, i: Integer; c, i: Integer;
e: TCallStackEntry; e: TCallStackEntry;
@ -8128,12 +8491,13 @@ begin
for i := 0 to c - 1 do begin for i := 0 to c - 1 do begin
e := TCallStackEntry.Create(); e := TCallStackEntry.Create();
e.FOwner := self; e.FOwner := self;
e.LoadDataFromXMLConfig(AConfig, APath + IntToStr(i) + '/'); e.LoadDataFromXMLConfig(AConfig, APath + IntToStr(i) + '/', AUnitInvoPrv);
FList.Add(e); FList.Add(e);
end; end;
end; end;
procedure TCallStack.SaveDataToXMLConfig(const AConfig: TXMLConfig; APath: string); procedure TCallStack.SaveDataToXMLConfig(const AConfig: TXMLConfig; APath: string;
AUnitInvoPrv: TDebuggerUnitInfoProvider = nil);
var var
i: Integer; i: Integer;
begin begin
@ -8143,7 +8507,7 @@ begin
AConfig.SetDeleteValue(APath + 'Count', FList.Count, 0); AConfig.SetDeleteValue(APath + 'Count', FList.Count, 0);
APath := APath + 'Entry'; APath := APath + 'Entry';
for i := 0 to FList.Count - 1 do for i := 0 to FList.Count - 1 do
TCallStackEntry(FList[i]).SaveDataToXMLConfig(AConfig, APath + IntToStr(i) + '/'); TCallStackEntry(FList[i]).SaveDataToXMLConfig(AConfig, APath + IntToStr(i) + '/', AUnitInvoPrv);
end; end;
function TCallStack.IndexError(AIndex: Integer): TCallStackEntry; function TCallStack.IndexError(AIndex: Integer): TCallStackEntry;

View File

@ -1940,7 +1940,9 @@ begin
FThreads[i] := TThreadEntry.Create( FThreads[i] := TThreadEntry.Create(
0, addr, 0, addr,
Arguments, Arguments,
func, filename, fullname, line, func,
FTheDebugger.UnitInfoProvider.GetUnitInfoFor(filename, fullname),
line,
ThrId,ThrName, ThrState ThrId,ThrName, ThrState
); );
@ -5098,8 +5100,7 @@ var
addr, addr,
Arguments, Arguments,
func, func,
filename, FTheDebugger.UnitInfoProvider.GetUnitInfoFor(filename, fullname),
fullname,
StrToIntDef(line, 0) StrToIntDef(line, 0)
); );

View File

@ -154,16 +154,8 @@ begin
// avoid any process-messages, so this proc can not be re-entered (avoid opening one files many times) // avoid any process-messages, so this proc can not be re-entered (avoid opening one files many times)
DebugBoss.LockCommandProcessing; DebugBoss.LockCommandProcessing;
try try
// check the full name first if DebugBoss.GetFullFilename(Entry.UnitInfo, Filename, False) then
Filename := Entry.FullFileName; MainIDE.DoJumpToSourcePosition(Filename, 0, Entry.Line, 0, True, True);
if (Filename = '') or not DebugBoss.GetFullFilename(Filename, False) then
begin
// if fails the check the short file name
Filename := Entry.Source;
if (FileName = '') or not DebugBoss.GetFullFilename(Filename, True) then
Exit;
end;
MainIDE.DoJumpToSourcePosition(Filename, 0, Entry.Line, 0, True, True);
finally finally
DebugBoss.UnLockCommandProcessing; DebugBoss.UnLockCommandProcessing;
end;end; end;end;

View File

@ -148,6 +148,8 @@ type
EvalFlags: TDBGEvaluateFlags = []): Boolean; virtual; abstract; // Evaluates the given expression, returns true if valid EvalFlags: TDBGEvaluateFlags = []): Boolean; virtual; abstract; // Evaluates the given expression, returns true if valid
function Modify(const AExpression: String; const ANewValue: String): Boolean; virtual; abstract; // Modify the given expression, returns true if valid function Modify(const AExpression: String; const ANewValue: String): Boolean; virtual; abstract; // Modify the given expression, returns true if valid
function GetFullFilename(const AUnitinfo: TDebuggerUnitInfo;
out Filename: string; AskUserIfNotFound: Boolean): Boolean; virtual; abstract;
function GetFullFilename(var Filename: string; AskUserIfNotFound: Boolean): Boolean; virtual; abstract; function GetFullFilename(var Filename: string; AskUserIfNotFound: Boolean): Boolean; virtual; abstract;
procedure EvaluateModify(const AExpression: String); virtual; abstract; procedure EvaluateModify(const AExpression: String); virtual; abstract;

View File

@ -95,13 +95,13 @@ type
procedure DebugDialogDestroy(Sender: TObject); procedure DebugDialogDestroy(Sender: TObject);
private private
FDebugger: TDebugger; FDebugger: TDebugger;
FUnitInfoProvider: TDebuggerUnitInfoProvider;
FDialogs: array[TDebugDialogType] of TDebuggerDlg; FDialogs: array[TDebugDialogType] of TDebuggerDlg;
FInStateChange: Boolean; FInStateChange: Boolean;
FPrevShownWindow: HWND; FPrevShownWindow: HWND;
FStepping: Boolean; FStepping: Boolean;
// keep track of the last reported location // keep track of the last reported location
FCurrentLocation: TDBGLocationRec; FCurrentLocation: TDBGLocationRec;
FIgnoreSourceFiles: TStringList; // a list of unfindable sourcefiles, that should not be prompted anymore
// last hit breakpoint // last hit breakpoint
FCurrentBreakpoint: TIDEBreakpoint; FCurrentBreakpoint: TIDEBreakpoint;
FAutoContinueTimer: TTimer; FAutoContinueTimer: TTimer;
@ -203,6 +203,7 @@ type
procedure EvaluateModify(const AExpression: String); override; procedure EvaluateModify(const AExpression: String); override;
procedure Inspect(const AExpression: String); override; procedure Inspect(const AExpression: String); override;
function GetFullFilename(const AUnitinfo: TDebuggerUnitInfo; out Filename: string; AskUserIfNotFound: Boolean): Boolean; override;
function GetFullFilename(var Filename: string; AskUserIfNotFound: Boolean): Boolean; override; function GetFullFilename(var Filename: string; AskUserIfNotFound: Boolean): Boolean; override;
function DoCreateBreakPoint(const AFilename: string; ALine: integer; function DoCreateBreakPoint(const AFilename: string; ALine: integer;
@ -517,6 +518,59 @@ end;
// Menu events // Menu events
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
function TDebugManager.GetFullFilename(const AUnitinfo: TDebuggerUnitInfo;
out Filename: string; AskUserIfNotFound: Boolean): Boolean;
procedure ResolveFromDbg;
begin
Filename := AUnitinfo.DbgFullName;
Result := Filename <> '';
if Result then
Result := GetFullFilename(Filename, False);
if not Result then begin
Filename := AUnitinfo.FileName;
Result := GetFullFilename(Filename, AskUserIfNotFound);
end;
end;
begin
Result := False;
if Destroying or (AUnitinfo = nil) then exit;
Filename := AUnitinfo.LocationFullFile;
Result := Filename <> '';
if Result then exit;
case AUnitinfo.LocationType of
dltUnknown:
begin
ResolveFromDbg;
end;
dltUnresolvable: Result := False;
dltProject:
begin
Filename := TrimFilename(AUnitinfo.LocationName);
Filename:= MainIDE.FindSourceFile(Filename, Project1.ProjectDirectory,
[fsfSearchForProject, fsfUseIncludePaths, fsfUseDebugPath,
fsfMapTempToVirtualFiles, fsfSkipPackages]);
Result := Filename <> '';
if not Result then
ResolveFromDbg;
end;
dltPackage:
begin
ResolveFromDbg;
end;
end;
if Result then
AUnitinfo.LocationFullFile := Filename
else begin
Filename := AUnitinfo.FileName;
if AskUserIfNotFound
then AUnitinfo.LocationType := dltUnresolvable;
end;
end;
function TDebugManager.GetFullFilename(var Filename: string; AskUserIfNotFound: Boolean): Boolean; function TDebugManager.GetFullFilename(var Filename: string; AskUserIfNotFound: Boolean): Boolean;
var var
SrcFile: String; SrcFile: String;
@ -1024,23 +1078,22 @@ procedure TDebugManager.DebuggerCurrentLine(Sender: TObject; const ALocation: TD
end; end;
var var
SrcFile, SrcFullName: String; SrcFullName: String;
NewSource: TCodeBuffer; NewSource: TCodeBuffer;
Editor: TSourceEditor; Editor: TSourceEditor;
SrcLine: Integer; SrcLine: Integer;
i, TId: Integer; i, TId: Integer;
StackEntry: TCallStackEntry; StackEntry: TCallStackEntry;
FocusEditor: Boolean; FocusEditor: Boolean;
InIgnore: Boolean; CurrentSourceUnitInfo: TDebuggerUnitInfo;
begin begin
if (Sender<>FDebugger) or (Sender=nil) then exit; if (Sender<>FDebugger) or (Sender=nil) then exit;
if FDebugger.State = dsInternalPause then exit; if FDebugger.State = dsInternalPause then exit;
if Destroying then exit; if Destroying then exit;
FCurrentLocation := ALocation; FCurrentLocation := ALocation;
SrcFile := ALocation.SrcFile;
SrcFullName := ALocation.SrcFullName;
SrcLine := ALocation.SrcLine; SrcLine := ALocation.SrcLine;
CurrentSourceUnitInfo := nil;
if SrcLine < 1 if SrcLine < 1
then begin then begin
@ -1053,71 +1106,69 @@ begin
StackEntry := CallStack.CurrentCallStackList.EntriesForThreads[TId].Entries[i]; StackEntry := CallStack.CurrentCallStackList.EntriesForThreads[TId].Entries[i];
if StackEntry.Line > 0 if StackEntry.Line > 0
then begin then begin
CurrentSourceUnitInfo := StackEntry.UnitInfo;
CurrentSourceUnitInfo.AddReference;
SrcLine := StackEntry.Line; SrcLine := StackEntry.Line;
SrcFile := StackEntry.Source;
SrcFullName := StackEntry.FullFileName;
StackEntry.MakeCurrent; StackEntry.MakeCurrent;
Break; Break;
end; end;
Inc(i); Inc(i);
end; end;
if SrcLine < 1 end
then begin else begin
ViewDebugDialog(ddtAssembler); CurrentSourceUnitInfo := Debugger.UnitInfoProvider.GetUnitInfoFor(ALocation.SrcFile, ALocation.SrcFullName);
Exit; CurrentSourceUnitInfo.AddReference;
end;
end;
if FDialogs[ddtAssembler] <> nil
then begin
TAssemblerDlg(FDialogs[ddtAssembler]).SetLocation(FDebugger, Alocation.Address);
if SrcLine < 1 then Exit;
end; end;
// TODO: do in DebuggerChangeState / Only currently State change locks execution of gdb // TODO: do in DebuggerChangeState / Only currently State change locks execution of gdb
// Must be after stack frame selection (for inspect)
if FDialogs[ddtAssembler] <> nil
then TAssemblerDlg(FDialogs[ddtAssembler]).SetLocation(FDebugger, Alocation.Address);
if (FDialogs[ddtInspect] <> nil) if (FDialogs[ddtInspect] <> nil)
then TIDEInspectDlg(FDialogs[ddtInspect]).UpdateData; then TIDEInspectDlg(FDialogs[ddtInspect]).UpdateData;
if (SrcFullName = '') or not GetFullFilename(SrcFullName, False) then if (SrcLine > 0) and (CurrentSourceUnitInfo <> nil) and
begin GetFullFilename(CurrentSourceUnitInfo, SrcFullName, True)
SrcFullName := SrcFile;
InIgnore := FIgnoreSourceFiles.IndexOf(FileLocationToId(ALocation)) >= 0;
if not GetFullFilename(SrcFullName, not InIgnore) then begin
if not InIgnore
then FIgnoreSourceFiles.Add(FileLocationToId(ALocation));
ViewDebugDialog(ddtAssembler);
exit;
end;
end;
NewSource := CodeToolBoss.LoadFile(SrcFullName, true, false);
if NewSource = nil
then begin then begin
InIgnore := FIgnoreSourceFiles.IndexOf(FileLocationToId(ALocation)) >= 0; // Load the file
if (FIgnoreSourceFiles.IndexOf(FileLocationToId(ALocation)) < 0) NewSource := CodeToolBoss.LoadFile(SrcFullName, true, false);
if NewSource = nil
then begin then begin
FIgnoreSourceFiles.Add(FileLocationToId(ALocation)); if not (dlfLoadError in CurrentSourceUnitInfo.Flags) then begin
MessageDlg(lisDebugUnableToLoadFile, MessageDlg(lisDebugUnableToLoadFile,
Format(lisDebugUnableToLoadFile2, ['"', SrcFullName, '"']), Format(lisDebugUnableToLoadFile2, ['"', SrcFullName, '"']),
mtError,[mbCancel],0); mtError,[mbCancel],0);
CurrentSourceUnitInfo.Flags := CurrentSourceUnitInfo.Flags + [dlfLoadError];
end;
SrcLine := -1;
end; end;
ViewDebugDialog(ddtAssembler); end
Exit; else
end; SrcLine := -1;
ReleaseAndNil(CurrentSourceUnitInfo);
// clear old error and execution lines // clear old error and execution lines
Editor := nil;
if SourceEditorManager <> nil if SourceEditorManager <> nil
then begin then begin
Editor := SourceEditorManager.SourceEditorIntfWithFilename(NewSource.Filename);
SourceEditorManager.ClearExecutionLines; SourceEditorManager.ClearExecutionLines;
SourceEditorManager.ClearErrorLines; SourceEditorManager.ClearErrorLines;
end; end;
if SrcLine < 1
then begin
ViewDebugDialog(ddtAssembler);
exit;
end;
Editor := nil;
if SourceEditorManager <> nil
then Editor := SourceEditorManager.SourceEditorIntfWithFilename(NewSource.Filename);
// jump editor to execution line // jump editor to execution line
FocusEditor := (FCurrentBreakPoint = nil) or (FCurrentBreakPoint.AutoContinueTime = 0); FocusEditor := (FCurrentBreakPoint = nil) or (FCurrentBreakPoint.AutoContinueTime = 0);
i := SrcLine; i := SrcLine;
if Editor <> nil then if (Editor <> nil) then
i := Editor.DebugToSourceLine(i); i := Editor.DebugToSourceLine(i);
if MainIDE.DoJumpToCodePos(nil,nil,NewSource,1,i,-1,true, FocusEditor)<>mrOk if MainIDE.DoJumpToCodePos(nil,nil,NewSource,1,i,-1,true, FocusEditor)<>mrOk
then exit; then exit;
@ -1380,6 +1431,7 @@ begin
FDialogs[DialogType] := nil; FDialogs[DialogType] := nil;
FDebugger := nil; FDebugger := nil;
FUnitInfoProvider := TDebuggerUnitInfoProvider.Create;
FBreakPoints := TManagedBreakPoints.Create(Self); FBreakPoints := TManagedBreakPoints.Create(Self);
FBreakPointGroups := TIDEBreakPointGroups.Create; FBreakPointGroups := TIDEBreakPointGroups.Create;
FWatches := TWatchesMonitor.Create; FWatches := TWatchesMonitor.Create;
@ -1397,9 +1449,9 @@ begin
FSnapshots.CallStack := FCallStack; FSnapshots.CallStack := FCallStack;
FSnapshots.Watches := FWatches; FSnapshots.Watches := FWatches;
FSnapshots.Locals := FLocals; FSnapshots.Locals := FLocals;
FSnapshots.UnitInfoProvider := FUnitInfoProvider;
FUserSourceFiles := TStringList.Create; FUserSourceFiles := TStringList.Create;
FIgnoreSourceFiles := TStringList.Create;
FAutoContinueTimer := TTimer.Create(Self); FAutoContinueTimer := TTimer.Create(Self);
FAutoContinueTimer.Enabled := False; FAutoContinueTimer.Enabled := False;
@ -1440,9 +1492,9 @@ begin
FreeAndNil(FRegisters); FreeAndNil(FRegisters);
FreeAndNil(FUserSourceFiles); FreeAndNil(FUserSourceFiles);
FreeAndNil(FIgnoreSourceFiles);
FreeAndNil(FHiddenDebugOutputLog); FreeAndNil(FHiddenDebugOutputLog);
FreeAndNil(FHiddenDebugEventsLog); FreeAndNil(FHiddenDebugEventsLog);
FreeAndNil(FUnitInfoProvider);
inherited Destroy; inherited Destroy;
end; end;
@ -1456,7 +1508,9 @@ begin
FExceptions.Reset; FExceptions.Reset;
FSignals.Reset; FSignals.Reset;
FUserSourceFiles.Clear; FUserSourceFiles.Clear;
FIgnoreSourceFiles.Clear; FUnitInfoProvider.Clear;
if FDebugger <> nil
then FDebugger.UnitInfoProvider.Clear;
end; end;
procedure TDebugManager.ConnectMainBarEvents; procedure TDebugManager.ConnectMainBarEvents;
@ -1819,7 +1873,7 @@ begin
end; end;
if (Project1.MainUnitID < 0) or Destroying then Exit; if (Project1.MainUnitID < 0) or Destroying then Exit;
FIgnoreSourceFiles.Clear; FUnitInfoProvider.Clear;
FIsInitializingDebugger:= True; FIsInitializingDebugger:= True;
try try
DebuggerClass := GetDebuggerClass; DebuggerClass := GetDebuggerClass;
@ -2109,7 +2163,9 @@ begin
MainIDE.ToolStatus:=itNone; MainIDE.ToolStatus:=itNone;
end; end;
FIgnoreSourceFiles.Clear; FUnitInfoProvider.Clear; // Maybe keep locations? But clear "not found"/"not loadable" flags?
if FDebugger <> nil
then FDebugger.UnitInfoProvider.Clear;
Result := mrOk; Result := mrOk;
end; end;
@ -2444,6 +2500,7 @@ begin
FSnapshots.Debugger := nil; FSnapshots.Debugger := nil;
end end
else begin else begin
FDebugger.UnitInfoProvider := FUnitInfoProvider;
TManagedBreakpoints(FBreakpoints).Master := FDebugger.BreakPoints; TManagedBreakpoints(FBreakpoints).Master := FDebugger.BreakPoints;
FWatches.Supplier := FDebugger.Watches; FWatches.Supplier := FDebugger.Watches;
FThreads.Supplier := FDebugger.Threads; FThreads.Supplier := FDebugger.Threads;