mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-09-12 14:00:38 +02:00
FPDebug/GDBMI: memreader via gdb
git-svn-id: trunk@43567 -
This commit is contained in:
parent
fc6bd246ea
commit
100ac0c220
@ -26,6 +26,21 @@ type
|
|||||||
constructor Create(ATextExpression: String; ADebugger: TFpGDBMIDebugger; AThreadId, AStackFrame: Integer);
|
constructor Create(ATextExpression: String; ADebugger: TFpGDBMIDebugger; AThreadId, AStackFrame: Integer);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TFpGDBMIDbgMemReader }
|
||||||
|
|
||||||
|
TFpGDBMIDbgMemReader = class(TFpDbgMemReaderBase)
|
||||||
|
private
|
||||||
|
// TODO
|
||||||
|
//FThreadId: Integer;
|
||||||
|
//FStackFrame: Integer;
|
||||||
|
FDebugger: TFpGDBMIDebugger;
|
||||||
|
public
|
||||||
|
constructor Create(ADebugger: TFpGDBMIDebugger);
|
||||||
|
function ReadMemory(AnAddress: FpDbgInfo.TDbgPtr; ASize: Cardinal; ADest: Pointer): Boolean; override;
|
||||||
|
function ReadMemoryEx(AnAddress, AnAddressSpace: FpDbgInfo.TDbgPtr; ASize: Cardinal; ADest: Pointer): Boolean; override;
|
||||||
|
function ReadRegister(ARegNum: Integer; out AValue: FpDbgInfo.TDbgPtr): Boolean; override;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TFpGDBPTypeRequestCache }
|
{ TFpGDBPTypeRequestCache }
|
||||||
|
|
||||||
TFpGDBPTypeRequestCache = class(TGDBPTypeRequestCache)
|
TFpGDBPTypeRequestCache = class(TGDBPTypeRequestCache)
|
||||||
@ -48,6 +63,7 @@ type
|
|||||||
private
|
private
|
||||||
FImageLoader: TDbgImageLoader;
|
FImageLoader: TDbgImageLoader;
|
||||||
FDwarfInfo: TDbgDwarf;
|
FDwarfInfo: TDbgDwarf;
|
||||||
|
FMemReader: TFpGDBMIDbgMemReader;
|
||||||
// cache last context
|
// cache last context
|
||||||
FlastStackFrame, FLastThread: Integer;
|
FlastStackFrame, FLastThread: Integer;
|
||||||
FLastContext: array [0..MAX_CTX_CACHE-1] of TDbgInfoAddressContext;
|
FLastContext: array [0..MAX_CTX_CACHE-1] of TDbgInfoAddressContext;
|
||||||
@ -65,6 +81,7 @@ type
|
|||||||
function GetLocationForContext(AThreadId, AStackFrame: Integer): TDBGPtr;
|
function GetLocationForContext(AThreadId, AStackFrame: Integer): TDBGPtr;
|
||||||
function GetInfoContextForContext(AThreadId, AStackFrame: Integer): TDbgInfoAddressContext;
|
function GetInfoContextForContext(AThreadId, AStackFrame: Integer): TDbgInfoAddressContext;
|
||||||
function CreateTypeRequestCache: TGDBPTypeRequestCache; override;
|
function CreateTypeRequestCache: TGDBPTypeRequestCache; override;
|
||||||
|
property CurrentCommand;
|
||||||
public
|
public
|
||||||
class function Caption: String; override;
|
class function Caption: String; override;
|
||||||
public
|
public
|
||||||
@ -116,6 +133,85 @@ type
|
|||||||
procedure Cancel(const ASource: String); override;
|
procedure Cancel(const ASource: String); override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TFpGDBMIDbgMemReader }
|
||||||
|
|
||||||
|
constructor TFpGDBMIDbgMemReader.Create(ADebugger: TFpGDBMIDebugger);
|
||||||
|
begin
|
||||||
|
FDebugger := ADebugger;
|
||||||
|
end;
|
||||||
|
|
||||||
|
type TGDBMIDebuggerCommandHack = class(TGDBMIDebuggerCommand) end;
|
||||||
|
|
||||||
|
function TFpGDBMIDbgMemReader.ReadMemory(AnAddress: FpDbgInfo.TDbgPtr; ASize: Cardinal;
|
||||||
|
ADest: Pointer): Boolean;
|
||||||
|
var
|
||||||
|
cmd: TGDBMIDebuggerCommandHack;
|
||||||
|
R: TGDBMIExecResult;
|
||||||
|
MemDump: TGDBMIMemoryDumpResultList;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
Result := False;
|
||||||
|
|
||||||
|
cmd := TGDBMIDebuggerCommandHack(TFpGDBMIDebugger(FDebugger).CurrentCommand);
|
||||||
|
if cmd = nil then exit;
|
||||||
|
|
||||||
|
if not cmd.ExecuteCommand('-data-read-memory %u x 1 1 %u', [AnAddress, ASize], R, [cfNoThreadContext, cfNoStackContext])
|
||||||
|
then
|
||||||
|
exit;
|
||||||
|
if R.State = dsError then exit;
|
||||||
|
|
||||||
|
MemDump := TGDBMIMemoryDumpResultList.Create(R);
|
||||||
|
|
||||||
|
for i := 0 to MemDump.Count - 1 do begin
|
||||||
|
PByte(ADest + i)^ := Byte(MemDump.ItemNum[i]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
debugln(['TFpGDBMIDbgMemReader.ReadMemory ', dbgs(AnAddress), ' ', dbgMemRange(ADest, ASize)]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TFpGDBMIDbgMemReader.ReadMemoryEx(AnAddress, AnAddressSpace: FpDbgInfo.TDbgPtr;
|
||||||
|
ASize: Cardinal; ADest: Pointer): Boolean;
|
||||||
|
begin
|
||||||
|
Result := False;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TFpGDBMIDbgMemReader.ReadRegister(ARegNum: Integer; out
|
||||||
|
AValue: FpDbgInfo.TDbgPtr): Boolean;
|
||||||
|
var
|
||||||
|
rname: String;
|
||||||
|
v: String;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
Result := False;
|
||||||
|
// 32 bit gdb dwarf names
|
||||||
|
case ARegNum of
|
||||||
|
0: rname := 'EAX'; // RAX
|
||||||
|
1: rname := 'ECX'; // RDX
|
||||||
|
2: rname := 'EDX'; // RCX
|
||||||
|
3: rname := 'EBX'; // RBX
|
||||||
|
4: rname := 'ESP';
|
||||||
|
5: rname := 'EBP';
|
||||||
|
6: rname := 'ESI';
|
||||||
|
7: rname := 'EDI';
|
||||||
|
8: rname := 'EIP';
|
||||||
|
else
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
for i := 0 to FDebugger.Registers.Count - 1 do
|
||||||
|
if UpperCase(FDebugger.Registers.Names[i]) = rname then
|
||||||
|
begin
|
||||||
|
v := FDebugger.Registers.Values[i];
|
||||||
|
debugln(['TFpGDBMIDbgMemReader.ReadRegister ',rname, ' ', v]);
|
||||||
|
Result := true;
|
||||||
|
try
|
||||||
|
AValue := StrToQWord(v);
|
||||||
|
except
|
||||||
|
Result := False;
|
||||||
|
end;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TFpGDBMIPascalExpression }
|
{ TFpGDBMIPascalExpression }
|
||||||
|
|
||||||
function TFpGDBMIPascalExpression.GetDbgTyeForIdentifier(AnIdent: String): TDbgSymbol;
|
function TFpGDBMIPascalExpression.GetDbgTyeForIdentifier(AnIdent: String): TDbgSymbol;
|
||||||
@ -607,8 +703,21 @@ DebugLn(['######## '+ARequest.Request, ' ## FOUND: ', dbgs(Result)]);
|
|||||||
if IdentName <> '' then begin
|
if IdentName <> '' then begin
|
||||||
PasExpr := TFpGDBMIPascalExpression.Create(IdentName, FDebugger, AThreadId, AStackFrame);
|
PasExpr := TFpGDBMIPascalExpression.Create(IdentName, FDebugger, AThreadId, AStackFrame);
|
||||||
if PasExpr.Valid then begin
|
if PasExpr.Valid then begin
|
||||||
|
(*
|
||||||
|
if (TFpPascalExpressionHack(PasExpr).ExpressionPart <> nil) and
|
||||||
|
(TFpPascalExpressionHack(PasExpr).ExpressionPart is TFpPascalExpressionPartIdentifer)
|
||||||
|
then begin
|
||||||
|
PasExpr.ResultType;
|
||||||
|
rt := TFpPascalExpressionPartIdentifer(TFpPascalExpressionHack(PasExpr).ExpressionPart).FDbgType;
|
||||||
|
if (rt <> nil) then begin
|
||||||
|
debugln(['@@@@@ ',rt.ClassName]);
|
||||||
|
if (rt <> nil) and (rt is TDbgDwarfIdentifierVariable) then begin
|
||||||
|
DebugLn(['########### ', rt.Address ]);
|
||||||
|
end;end;
|
||||||
|
end;
|
||||||
|
*)
|
||||||
rt := PasExpr.ResultType;
|
rt := PasExpr.ResultType;
|
||||||
if (rt = nil) and (TFpPascalExpressionHack(PasExpr).ExpressionPart <> nil) then
|
if (rt = nil) and (TFpPascalExpressionHack(PasExpr).ExpressionPart <> nil) then
|
||||||
rt := TFpPascalExpressionHack(PasExpr).ExpressionPart.ResultTypeCast;
|
rt := TFpPascalExpressionHack(PasExpr).ExpressionPart.ResultTypeCast;
|
||||||
if rt <> nil then begin
|
if rt <> nil then begin
|
||||||
AddType(IdentName, rt);
|
AddType(IdentName, rt);
|
||||||
@ -763,8 +872,11 @@ begin
|
|||||||
if not FImageLoader.IsValid then begin
|
if not FImageLoader.IsValid then begin
|
||||||
FreeAndNil(FImageLoader);
|
FreeAndNil(FImageLoader);
|
||||||
exit;
|
exit;
|
||||||
end;;
|
end;
|
||||||
|
FMemReader := TFpGDBMIDbgMemReader.Create(Self);
|
||||||
|
|
||||||
FDwarfInfo := TDbgDwarf.Create(FImageLoader);
|
FDwarfInfo := TDbgDwarf.Create(FImageLoader);
|
||||||
|
FDwarfInfo.MemReader := FMemReader;
|
||||||
FDwarfInfo.LoadCompilationUnits;
|
FDwarfInfo.LoadCompilationUnits;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -773,6 +885,7 @@ begin
|
|||||||
debugln(['TFpGDBMIDebugger.UnLoadDwarf ']);
|
debugln(['TFpGDBMIDebugger.UnLoadDwarf ']);
|
||||||
FreeAndNil(FDwarfInfo);
|
FreeAndNil(FDwarfInfo);
|
||||||
FreeAndNil(FImageLoader);
|
FreeAndNil(FImageLoader);
|
||||||
|
FreeAndNil(FMemReader);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TFpGDBMIDebugger.RequestCommand(const ACommand: TDBGCommand;
|
function TFpGDBMIDebugger.RequestCommand(const ACommand: TDBGCommand;
|
||||||
|
@ -817,6 +817,45 @@ type
|
|||||||
function NeedReset: Boolean; override;
|
function NeedReset: Boolean; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{%region ***** TGDBMINameValueList and Parsers ***** }
|
||||||
|
|
||||||
|
{ TGDBMINameValueBasedList }
|
||||||
|
|
||||||
|
TGDBMINameValueBasedList = class
|
||||||
|
protected
|
||||||
|
FNameValueList: TGDBMINameValueList;
|
||||||
|
procedure PreParse; virtual; abstract;
|
||||||
|
public
|
||||||
|
constructor Create;
|
||||||
|
constructor Create(const AResultValues: String);
|
||||||
|
constructor Create(AResult: TGDBMIExecResult);
|
||||||
|
destructor Destroy; override;
|
||||||
|
procedure Init(AResultValues: string);
|
||||||
|
procedure Init(AResult: TGDBMIExecResult);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TGDBMIMemoryDumpResultList }
|
||||||
|
|
||||||
|
TGDBMIMemoryDumpResultList = class(TGDBMINameValueBasedList)
|
||||||
|
private
|
||||||
|
FAddr: TDBGPtr;
|
||||||
|
function GetItem(Index: Integer): TPCharWithLen;
|
||||||
|
function GetItemNum(Index: Integer): Integer;
|
||||||
|
function GetItemTxt(Index: Integer): string;
|
||||||
|
protected
|
||||||
|
procedure PreParse; override;
|
||||||
|
public
|
||||||
|
// Expected input format: 1 row with hex values
|
||||||
|
function Count: Integer;
|
||||||
|
property Item[Index: Integer]: TPCharWithLen read GetItem;
|
||||||
|
property ItemTxt[Index: Integer]: string read GetItemTxt;
|
||||||
|
property ItemNum[Index: Integer]: Integer read GetItemNum;
|
||||||
|
property Addr: TDBGPtr read FAddr;
|
||||||
|
function AsText(AStartOffs, ACount: Integer; AAddrWidth: Integer): string;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{%endregion *^^^* TGDBMINameValueList and Parsers *^^^* }
|
||||||
|
|
||||||
|
|
||||||
resourcestring
|
resourcestring
|
||||||
gdbmiErrorOnRunCommand = 'The debugger encountered an error when trying to '
|
gdbmiErrorOnRunCommand = 'The debugger encountered an error when trying to '
|
||||||
@ -903,45 +942,6 @@ type
|
|||||||
type
|
type
|
||||||
TGDBMIEvaluationState = (esInvalid, esRequested, esValid);
|
TGDBMIEvaluationState = (esInvalid, esRequested, esValid);
|
||||||
|
|
||||||
{%region ***** TGDBMINameValueList and Parsers ***** }
|
|
||||||
|
|
||||||
{ TGDBMINameValueBasedList }
|
|
||||||
|
|
||||||
TGDBMINameValueBasedList = class
|
|
||||||
protected
|
|
||||||
FNameValueList: TGDBMINameValueList;
|
|
||||||
procedure PreParse; virtual; abstract;
|
|
||||||
public
|
|
||||||
constructor Create;
|
|
||||||
constructor Create(const AResultValues: String);
|
|
||||||
constructor Create(AResult: TGDBMIExecResult);
|
|
||||||
destructor Destroy; override;
|
|
||||||
procedure Init(AResultValues: string);
|
|
||||||
procedure Init(AResult: TGDBMIExecResult);
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ TGDBMIMemoryDumpResultList }
|
|
||||||
|
|
||||||
TGDBMIMemoryDumpResultList = class(TGDBMINameValueBasedList)
|
|
||||||
private
|
|
||||||
FAddr: TDBGPtr;
|
|
||||||
function GetItem(Index: Integer): TPCharWithLen;
|
|
||||||
function GetItemNum(Index: Integer): Integer;
|
|
||||||
function GetItemTxt(Index: Integer): string;
|
|
||||||
protected
|
|
||||||
procedure PreParse; override;
|
|
||||||
public
|
|
||||||
// Expected input format: 1 row with hex values
|
|
||||||
function Count: Integer;
|
|
||||||
property Item[Index: Integer]: TPCharWithLen read GetItem;
|
|
||||||
property ItemTxt[Index: Integer]: string read GetItemTxt;
|
|
||||||
property ItemNum[Index: Integer]: Integer read GetItemNum;
|
|
||||||
property Addr: TDBGPtr read FAddr;
|
|
||||||
function AsText(AStartOffs, ACount: Integer; AAddrWidth: Integer): string;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{%endregion *^^^* TGDBMINameValueList and Parsers *^^^* }
|
|
||||||
|
|
||||||
const
|
const
|
||||||
// priorities for commands
|
// priorities for commands
|
||||||
GDCMD_PRIOR_IMMEDIATE = 999; // run immediate (request without callback)
|
GDCMD_PRIOR_IMMEDIATE = 999; // run immediate (request without callback)
|
||||||
|
Loading…
Reference in New Issue
Block a user