mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-22 06:20:45 +02:00
FpDebugger (pure): Let the memory-manager read memory from within the debugging-thread on Linux.
More fixes for getting the instruction-register on x86_64 Fixxed setting the line-info on Darwin and Linux git-svn-id: trunk@45817 -
This commit is contained in:
parent
a3a3e0ba9a
commit
600fc1036c
@ -38,6 +38,8 @@ interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, FileUtil, FpDbgInfo, FpDbgClasses, FpDbgDisasX86, DbgIntfBaseTypes,
|
||||
FpDbgDwarf,
|
||||
FpdMemoryTools,
|
||||
CustApp;
|
||||
|
||||
type
|
||||
@ -47,17 +49,21 @@ type
|
||||
TFPDLoop = class(TCustomApplication)
|
||||
private
|
||||
FLast: string;
|
||||
FMemReader: TDbgMemReader;
|
||||
FMemManager: TFpDbgMemManager;
|
||||
procedure ShowDisas;
|
||||
procedure ShowCode;
|
||||
procedure GControllerExceptionEvent(var continue: boolean; const ExceptionClass, ExceptionMessage: string);
|
||||
procedure GControllerCreateProcessEvent(var continue: boolean);
|
||||
procedure GControllerHitBreakpointEvent(var continue: boolean; const Breakpoint: TDbgBreakpoint);
|
||||
procedure GControllerProcessExitEvent(ExitCode: DWord);
|
||||
procedure GControllerDebugInfoLoaded(Sender: TObject);
|
||||
procedure OnLog(const AString: string; const ALogLevel: TFPDLogLevel);
|
||||
protected
|
||||
Procedure DoRun; override;
|
||||
public
|
||||
procedure Initialize; override;
|
||||
destructor Destroy; override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
@ -67,11 +73,41 @@ uses
|
||||
FpDbgUtil,
|
||||
FPDGlobal;
|
||||
|
||||
type
|
||||
|
||||
{ TPDDbgMemReader }
|
||||
|
||||
TPDDbgMemReader = class(TDbgMemReader)
|
||||
protected
|
||||
function GetDbgProcess: TDbgProcess; override;
|
||||
public
|
||||
function ReadMemory(AnAddress: TDbgPtr; ASize: Cardinal; ADest: Pointer): Boolean; override;
|
||||
function ReadMemoryEx(AnAddress, AnAddressSpace: TDbgPtr; ASize: Cardinal; ADest: Pointer): Boolean; override;
|
||||
end;
|
||||
|
||||
|
||||
resourcestring
|
||||
sBreakpointReached = 'Breakpoint reached at %s.';
|
||||
sProcessPaused = 'Process paused.';
|
||||
sProcessExited = 'Process ended with exit-code %d.';
|
||||
|
||||
{ TPDDbgMemReader }
|
||||
|
||||
function TPDDbgMemReader.GetDbgProcess: TDbgProcess;
|
||||
begin
|
||||
result := GController.CurrentProcess;
|
||||
end;
|
||||
|
||||
function TPDDbgMemReader.ReadMemory(AnAddress: TDbgPtr; ASize: Cardinal; ADest: Pointer): Boolean;
|
||||
begin
|
||||
result := GetDbgProcess.ReadData(AnAddress, ASize, ADest^);
|
||||
end;
|
||||
|
||||
function TPDDbgMemReader.ReadMemoryEx(AnAddress, AnAddressSpace: TDbgPtr; ASize: Cardinal; ADest: Pointer): Boolean;
|
||||
begin
|
||||
result := GetDbgProcess.ReadData(AnAddress, ASize, ADest^);
|
||||
end;
|
||||
|
||||
{ TFPDLoop }
|
||||
|
||||
procedure TFPDLoop.GControllerExceptionEvent(var continue: boolean; const ExceptionClass, ExceptionMessage: string);
|
||||
@ -95,6 +131,11 @@ begin
|
||||
writeln(format(sProcessExited,[ExitCode]));
|
||||
end;
|
||||
|
||||
procedure TFPDLoop.GControllerDebugInfoLoaded(Sender: TObject);
|
||||
begin
|
||||
TFpDwarfInfo(GController.CurrentProcess.DbgInfo).MemManager := FMemManager;
|
||||
end;
|
||||
|
||||
procedure TFPDLoop.ShowDisas;
|
||||
var
|
||||
a: TDbgPtr;
|
||||
@ -239,11 +280,21 @@ end;
|
||||
procedure TFPDLoop.Initialize;
|
||||
begin
|
||||
inherited Initialize;
|
||||
FMemReader := TPDDbgMemReader.Create;
|
||||
FMemManager := TFpDbgMemManager.Create(FMemReader, TFpDbgMemConvertorLittleEndian.Create);
|
||||
GController.OnLog:=@OnLog;
|
||||
GController.OnHitBreakpointEvent:=@GControllerHitBreakpointEvent;
|
||||
GController.OnCreateProcessEvent:=@GControllerCreateProcessEvent;
|
||||
GController.OnExceptionEvent:=@GControllerExceptionEvent;
|
||||
GController.OnProcessExitEvent:=@GControllerProcessExitEvent;
|
||||
GController.OnDebugInfoLoaded:=@GControllerDebugInfoLoaded;
|
||||
end;
|
||||
|
||||
destructor TFPDLoop.Destroy;
|
||||
begin
|
||||
FMemManager.Free;
|
||||
FMemReader.Free;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
initialization
|
||||
|
@ -115,12 +115,9 @@ type
|
||||
{ TDbgMemReader }
|
||||
|
||||
TDbgMemReader = class(TFpDbgMemReaderBase)
|
||||
private
|
||||
FDbgProcess: TDbgProcess;
|
||||
protected
|
||||
function GetDbgProcess: TDbgProcess; virtual; abstract;
|
||||
public
|
||||
constructor Create(ADbgProcess: TDbgProcess);
|
||||
function ReadMemory(AnAddress: TDbgPtr; ASize: Cardinal; ADest: Pointer): Boolean; override;
|
||||
function ReadMemoryEx(AnAddress, AnAddressSpace: TDbgPtr; ASize: Cardinal; ADest: Pointer): Boolean; override;
|
||||
function ReadRegister(ARegNum: Cardinal; out AValue: TDbgPtr; AContext: TFpDbgAddressContext): Boolean; override;
|
||||
function RegisterSize(ARegNum: Cardinal): Integer; override;
|
||||
end;
|
||||
@ -190,14 +187,12 @@ type
|
||||
private
|
||||
FMode: TFPDMode;
|
||||
FName: String;
|
||||
FOnDebugInfoLoaded: TNotifyEvent;
|
||||
FProcess: TDbgProcess;
|
||||
FDbgInfo: TDbgInfo;
|
||||
FSymbolTableInfo: TFpSymbolInfo;
|
||||
FLoader: TDbgImageLoader;
|
||||
|
||||
protected
|
||||
procedure LoadInfo; virtual;
|
||||
function InitializeLoader: TDbgImageLoader; virtual;
|
||||
procedure SetName(const AValue: String);
|
||||
public
|
||||
@ -208,11 +203,11 @@ type
|
||||
function AddrOffset: Int64; virtual; // gives the offset between the loaded addresses and the compiled addresses
|
||||
function FindSymbol(AAdress: TDbgPtr): TFpDbgSymbol;
|
||||
function RemoveBreak(const AFileName: String; ALine: Cardinal): Boolean;
|
||||
procedure LoadInfo; virtual;
|
||||
|
||||
property Process: TDbgProcess read FProcess;
|
||||
property DbgInfo: TDbgInfo read FDbgInfo;
|
||||
property SymbolTableInfo: TFpSymbolInfo read FSymbolTableInfo;
|
||||
property OnDebugInfoLoaded: TNotifyEvent read FOnDebugInfoLoaded write FOnDebugInfoLoaded;
|
||||
property Mode: TFPDMode read FMode;
|
||||
end;
|
||||
|
||||
@ -239,8 +234,6 @@ type
|
||||
FOnLog: TOnLog;
|
||||
FProcessID: Integer;
|
||||
FThreadID: Integer;
|
||||
FMemReader: TDbgMemReader;
|
||||
FMemManager: TFpDbgMemManager;
|
||||
|
||||
procedure ThreadDestroyed(const AThread: TDbgThread);
|
||||
protected
|
||||
@ -257,7 +250,6 @@ type
|
||||
|
||||
FRunToBreakpoint: TDbgBreakpoint;
|
||||
FMainThread: TDbgThread;
|
||||
procedure LoadInfo; override;
|
||||
function GetHandle: THandle; virtual;
|
||||
procedure SetExitCode(AValue: DWord);
|
||||
function GetLastEventProcessIdentifier: THandle; virtual;
|
||||
@ -295,6 +287,7 @@ type
|
||||
function ResolveDebugEvent(AThread: TDbgThread): TFPDEvent; virtual;
|
||||
|
||||
function AddThread(AThreadIdentifier: THandle): TDbgThread;
|
||||
procedure LoadInfo; override;
|
||||
|
||||
function WriteData(const AAdress: TDbgPtr; const ASize: Cardinal; const AData): Boolean; virtual;
|
||||
|
||||
@ -439,22 +432,6 @@ end;
|
||||
|
||||
{ TDbgMemReader }
|
||||
|
||||
constructor TDbgMemReader.Create(ADbgProcess: TDbgProcess);
|
||||
begin
|
||||
FDbgProcess := ADbgProcess;
|
||||
end;
|
||||
|
||||
function TDbgMemReader.ReadMemory(AnAddress: TDbgPtr; ASize: Cardinal; ADest: Pointer): Boolean;
|
||||
begin
|
||||
result := FDbgProcess.ReadData(AnAddress, ASize, ADest^);
|
||||
end;
|
||||
|
||||
function TDbgMemReader.ReadMemoryEx(AnAddress, AnAddressSpace: TDbgPtr;
|
||||
ASize: Cardinal; ADest: Pointer): Boolean;
|
||||
begin
|
||||
result := FDbgProcess.ReadData(AnAddress, ASize, ADest^);
|
||||
end;
|
||||
|
||||
function TDbgMemReader.ReadRegister(ARegNum: Cardinal; out AValue: TDbgPtr; AContext: TFpDbgAddressContext): Boolean;
|
||||
var
|
||||
ARegister: TDbgRegisterValue;
|
||||
@ -468,12 +445,12 @@ begin
|
||||
StackFrame := 0;
|
||||
if StackFrame = 0 then
|
||||
begin
|
||||
ARegister:=FDbgProcess.MainThread.RegisterValueList.FindRegisterByDwarfIndex(ARegNum);
|
||||
ARegister:=GetDbgProcess.MainThread.RegisterValueList.FindRegisterByDwarfIndex(ARegNum);
|
||||
end
|
||||
else
|
||||
begin
|
||||
FDbgProcess.MainThread.PrepareCallStackEntryList(StackFrame);
|
||||
AFrame := FDbgProcess.MainThread.CallStackEntryList[StackFrame];
|
||||
GetDbgProcess.MainThread.PrepareCallStackEntryList(StackFrame);
|
||||
AFrame := GetDbgProcess.MainThread.CallStackEntryList[StackFrame];
|
||||
if AFrame <> nil then
|
||||
ARegister:=AFrame.RegisterValueList.FindRegisterByDwarfIndex(ARegNum)
|
||||
else
|
||||
@ -492,7 +469,7 @@ function TDbgMemReader.RegisterSize(ARegNum: Cardinal): Integer;
|
||||
var
|
||||
ARegister: TDbgRegisterValue;
|
||||
begin
|
||||
ARegister:=FDbgProcess.MainThread.RegisterValueList.FindRegisterByDwarfIndex(ARegNum);
|
||||
ARegister:=GetDbgProcess.MainThread.RegisterValueList.FindRegisterByDwarfIndex(ARegNum);
|
||||
if assigned(ARegister) then
|
||||
result := ARegister.Size
|
||||
else
|
||||
@ -629,8 +606,6 @@ begin
|
||||
FDbgInfo := TFpDwarfInfo.Create(FLoader);
|
||||
TFpDwarfInfo(FDbgInfo).LoadCompilationUnits;
|
||||
FSymbolTableInfo := TFpSymbolInfo.Create(FLoader);
|
||||
if Assigned(FOnDebugInfoLoaded) then
|
||||
FOnDebugInfoLoaded(Self);
|
||||
end;
|
||||
|
||||
function TDbgInstance.RemoveBreak(const AFileName: String; ALine: Cardinal): Boolean;
|
||||
@ -689,9 +664,6 @@ begin
|
||||
FBreakMap := TMap.Create(MAP_ID_SIZE, SizeOf(TDbgBreakpoint));
|
||||
FCurrentBreakpoint := nil;
|
||||
|
||||
FMemReader := TDbgMemReader.Create(Self);
|
||||
FMemManager := TFpDbgMemManager.Create(FMemReader, TFpDbgMemConvertorLittleEndian.Create);
|
||||
|
||||
FSymInstances := TList.Create;
|
||||
|
||||
SetName(AName);
|
||||
@ -722,8 +694,6 @@ begin
|
||||
FreeAndNil(FThreadMap);
|
||||
FreeAndNil(FLibMap);
|
||||
FreeAndNil(FSymInstances);
|
||||
FreeAndNil(FMemManager);
|
||||
FreeAndNil(FMemReader);
|
||||
inherited;
|
||||
end;
|
||||
|
||||
@ -977,7 +947,9 @@ end;
|
||||
procedure TDbgProcess.LoadInfo;
|
||||
begin
|
||||
inherited LoadInfo;
|
||||
TFpDwarfInfo(FDbgInfo).MemManager := FMemManager;
|
||||
|
||||
if DbgInfo.HasInfo then
|
||||
FSymInstances.Add(Self);
|
||||
end;
|
||||
|
||||
function TDbgProcess.GetLastEventProcessIdentifier: THandle;
|
||||
|
@ -408,7 +408,6 @@ begin
|
||||
if assigned(FCurrentProcess) then
|
||||
begin
|
||||
FProcessMap.Add(FCurrentProcess.ProcessID, FCurrentProcess);
|
||||
FCurrentProcess.OnDebugInfoLoaded := @DoOnDebugInfoLoaded;
|
||||
Log('Got PID: %d, TID: %d', [FCurrentProcess.ProcessID, FCurrentProcess.ThreadID]);
|
||||
result := true;
|
||||
end;
|
||||
@ -538,6 +537,9 @@ begin
|
||||
case FPDEvent of
|
||||
deCreateProcess:
|
||||
begin
|
||||
FCurrentProcess.LoadInfo;
|
||||
DoOnDebugInfoLoaded(self);
|
||||
|
||||
continue:=true;
|
||||
if assigned(OnCreateProcessEvent) then
|
||||
OnCreateProcessEvent(continue);
|
||||
|
@ -572,11 +572,6 @@ var
|
||||
begin
|
||||
inherited Create(AName, AProcessID, AThreadID, AOnLog);
|
||||
|
||||
LoadInfo;
|
||||
|
||||
if DbgInfo.HasInfo
|
||||
then FSymInstances.Add(Self);
|
||||
|
||||
GetDebugAccessRights;
|
||||
aKernResult:=task_for_pid(mach_task_self, AProcessID, FTaskPort);
|
||||
if aKernResult <> KERN_SUCCESS then
|
||||
|
@ -402,11 +402,6 @@ constructor TDbgLinuxProcess.Create(const AName: string; const AProcessID,
|
||||
AThreadID: Integer; AOnLog: TOnLog);
|
||||
begin
|
||||
inherited Create(AName, AProcessID, AThreadID, AOnLog);
|
||||
|
||||
LoadInfo;
|
||||
|
||||
if DbgInfo.HasInfo
|
||||
then FSymInstances.Add(Self);
|
||||
end;
|
||||
|
||||
destructor TDbgLinuxProcess.Destroy;
|
||||
|
@ -876,11 +876,6 @@ begin
|
||||
s := GetProcFilename(Self, AInfo.lpImageName, AInfo.fUnicode, 0);
|
||||
if s <> ''
|
||||
then SetName(s);
|
||||
|
||||
LoadInfo;
|
||||
|
||||
if DbgInfo.HasInfo
|
||||
then FSymInstances.Add(Self);
|
||||
end;
|
||||
|
||||
function TDbgWinProcess.GetInstructionPointerRegisterValue: TDbgPtr;
|
||||
|
@ -18,6 +18,7 @@ uses
|
||||
FpPascalBuilder,
|
||||
DbgIntfBaseTypes,
|
||||
DbgIntfDebuggerBase,
|
||||
FpdMemoryTools,
|
||||
FpPascalParser,
|
||||
FPDbgController, FpDbgDwarfDataClasses;
|
||||
|
||||
@ -65,6 +66,8 @@ type
|
||||
FRaiseExceptionBreakpoint: FpDbgClasses.TDBGBreakPoint;
|
||||
FDbgLogMessageList: array of TFpDbgLogMessage;
|
||||
FLogCritSection: TRTLCriticalSection;
|
||||
FMemReader: TDbgMemReader;
|
||||
FMemManager: TFpDbgMemManager;
|
||||
{$ifdef linux}
|
||||
FCacheLine: cardinal;
|
||||
FCacheFileName: string;
|
||||
@ -240,11 +243,48 @@ uses
|
||||
FpDbgUtil,
|
||||
FpDbgDisasX86;
|
||||
|
||||
type
|
||||
|
||||
{ TFpDbgMemReader }
|
||||
|
||||
TFpDbgMemReader = class(TDbgMemReader)
|
||||
private
|
||||
FFpDebugDebugger: TFpDebugDebugger;
|
||||
protected
|
||||
function GetDbgProcess: TDbgProcess; override;
|
||||
public
|
||||
constructor create(AFpDebugDebuger: TFpDebugDebugger);
|
||||
function ReadMemory(AnAddress: TDbgPtr; ASize: Cardinal; ADest: Pointer): Boolean; override;
|
||||
function ReadMemoryEx(AnAddress, AnAddressSpace: TDbgPtr; ASize: Cardinal; ADest: Pointer): Boolean; override;
|
||||
end;
|
||||
|
||||
procedure Register;
|
||||
begin
|
||||
RegisterDebugger(TFpDebugDebugger);
|
||||
end;
|
||||
|
||||
{ TFpDbgMemReader }
|
||||
|
||||
function TFpDbgMemReader.GetDbgProcess: TDbgProcess;
|
||||
begin
|
||||
result := FFpDebugDebugger.FDbgController.CurrentProcess;
|
||||
end;
|
||||
|
||||
constructor TFpDbgMemReader.create(AFpDebugDebuger: TFpDebugDebugger);
|
||||
begin
|
||||
FFpDebugDebugger := AFpDebugDebuger;
|
||||
end;
|
||||
|
||||
function TFpDbgMemReader.ReadMemory(AnAddress: TDbgPtr; ASize: Cardinal; ADest: Pointer): Boolean;
|
||||
begin
|
||||
result := FFpDebugDebugger.ReadData(AnAddress, ASize, ADest^);
|
||||
end;
|
||||
|
||||
function TFpDbgMemReader.ReadMemoryEx(AnAddress, AnAddressSpace: TDbgPtr; ASize: Cardinal; ADest: Pointer): Boolean;
|
||||
begin
|
||||
result := FFpDebugDebugger.ReadData(AnAddress, ASize, ADest^);
|
||||
end;
|
||||
|
||||
{ TFPCallStackSupplier }
|
||||
|
||||
procedure TFPCallStackSupplier.DoStateLeavePause;
|
||||
@ -385,7 +425,11 @@ begin
|
||||
end
|
||||
else
|
||||
RegList := AController.CurrentProcess.MainThread.RegisterValueList;
|
||||
Reg := RegList.FindRegisterByDwarfIndex(8);
|
||||
{$ifdef i386}
|
||||
Reg := RegList.FindRegisterByDwarfIndex(8);
|
||||
{$else}
|
||||
Reg := RegList.FindRegisterByDwarfIndex(16);
|
||||
{$endif}
|
||||
if Reg <> nil then
|
||||
AContext := AController.CurrentProcess.DbgInfo.FindContext(CurThreadId, CurStackFrame, Reg.NumValue)
|
||||
else
|
||||
@ -913,7 +957,11 @@ begin
|
||||
end
|
||||
else
|
||||
RegList := AController.CurrentProcess.MainThread.RegisterValueList;
|
||||
{$ifdef i386}
|
||||
Reg := RegList.FindRegisterByDwarfIndex(8);
|
||||
{$else}
|
||||
Reg := RegList.FindRegisterByDwarfIndex(16);
|
||||
{$endif}
|
||||
if Reg <> nil then
|
||||
AContext := ADbgInfo.FindContext(ThreadId, StackFrame, Reg.NumValue)
|
||||
else
|
||||
@ -1007,6 +1055,7 @@ end;
|
||||
|
||||
procedure TFpDebugDebugger.FDbgControllerDebugInfoLoaded(Sender: TObject);
|
||||
begin
|
||||
TFpDwarfInfo(FDbgController.CurrentProcess.DbgInfo).MemManager := FMemManager;
|
||||
if LineInfo <> nil then begin
|
||||
TFpLineInfo(LineInfo).DebugInfoChanged;
|
||||
end;
|
||||
@ -1444,6 +1493,8 @@ begin
|
||||
FWatchEvalList := TList.Create;
|
||||
FPrettyPrinter := TFpPascalPrettyPrinter.Create(sizeof(pointer));
|
||||
InitCriticalSection(FLogCritSection);
|
||||
FMemReader := TFpDbgMemReader.Create(self);
|
||||
FMemManager := TFpDbgMemManager.Create(FMemReader, TFpDbgMemConvertorLittleEndian.Create);
|
||||
FDbgController := TDbgController.Create;
|
||||
FDbgController.OnLog:=@OnLog;
|
||||
FDbgController.OnCreateProcessEvent:=@FDbgControllerCreateProcessEvent;
|
||||
@ -1460,6 +1511,8 @@ begin
|
||||
FDbgController.Free;
|
||||
FPrettyPrinter.Free;
|
||||
FWatchEvalList.Free;
|
||||
FMemManager.Free;
|
||||
FMemReader.Free;
|
||||
DoneCriticalsection(FLogCritSection);
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
Loading…
Reference in New Issue
Block a user