lazarus/components/fpdebug/fpdbgdwarffreepascal.pas
martin c4d3a2e866 FpDebug: recognize parentfp and $parentfp
git-svn-id: trunk@44912 -
2014-05-04 19:18:17 +00:00

188 lines
5.4 KiB
ObjectPascal

unit FpDbgDwarfFreePascal;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FpDbgDwarfDataClasses, FpDbgDwarf, FpDbgInfo, FpDbgUtil, DbgIntfBaseTypes,
LazLoggerBase;
type
{ TFpDwarfFreePascalSymbolClassMap }
TFpDwarfFreePascalSymbolClassMap = class(TFpDwarfDefaultSymbolClassMap)
public
class function HandleCompUnit(ACU: TDwarfCompilationUnit): Boolean; override;
//class function GetDwarfSymbolClass(ATag: Cardinal): TDbgDwarfSymbolBaseClass; override;
class function CreateContext(AThreadId, AStackFrame: Integer; AnAddress: TDBGPtr; ASymbol: TFpDbgSymbol;
ADwarf: TFpDwarfInfo): TFpDbgInfoContext; override;
//class function CreateProcSymbol(ACompilationUnit: TDwarfCompilationUnit;
// AInfo: PDwarfAddressInfo; AAddress: TDbgPtr): TDbgDwarfSymbolBase; override;
end;
{ TFpDwarfFreePascalAddressContext }
TFpDwarfFreePascalAddressContext = class(TFpDwarfInfoAddressContext)
private
FOuterNestContext: TFpDbgInfoContext;
FOuterNotFound: Boolean;
protected
function FindLocalSymbol(const AName: String; PNameUpper, PNameLower: PChar;
InfoEntry: TDwarfInformationEntry; out ADbgValue: TFpDbgValue): Boolean; override;
public
destructor Destroy; override;
end;
implementation
{ TFpDwarfFreePascalSymbolClassMap }
class function TFpDwarfFreePascalSymbolClassMap.HandleCompUnit(ACU: TDwarfCompilationUnit): Boolean;
var
s: String;
begin
s := LowerCase(ACU.Producer);
Result := pos('free pascal', s) > 0;
end;
class function TFpDwarfFreePascalSymbolClassMap.CreateContext(AThreadId, AStackFrame: Integer;
AnAddress: TDBGPtr; ASymbol: TFpDbgSymbol; ADwarf: TFpDwarfInfo): TFpDbgInfoContext;
begin
Result := TFpDwarfFreePascalAddressContext.Create(AThreadId, AStackFrame, AnAddress, ASymbol, ADwarf);
end;
{ TFpDwarfFreePascalAddressContext }
function TFpDwarfFreePascalAddressContext.FindLocalSymbol(const AName: String; PNameUpper,
PNameLower: PChar; InfoEntry: TDwarfInformationEntry; out ADbgValue: TFpDbgValue): Boolean;
const
parentfp: string = 'parentfp';
parentfp2: string = '$parentfp';
selfname: string = 'self';
// TODO: get reg num via memreader name-to-num
{$IFDEF cpu64}
RegFp = 6;
RegPc = 16;
{$ELSE}
RegFp = 5;
RegPc = 8;
{$ENDIF}
var
StartScopeIdx: Integer;
ParentFpVal: TFpDbgValue;
SearchCtx: TFpDwarfFreePascalAddressContext;
par_fp, cur_fp, prev_fp, pc: TDbgPtr;
d, i: Integer;
ParentFpSym: TFpDwarfSymbol;
begin
Result := False;
if (Length(AName) = length(selfname)) and (CompareUtf8BothCase(PNameUpper, PNameLower, @selfname[1])) then begin
ADbgValue := GetSelfParameter;
if ADbgValue <> nil then begin
AddRefToVal(ADbgValue);
Result := True;
exit;
end;
end;
StartScopeIdx := InfoEntry.ScopeIndex;
Result := inherited FindLocalSymbol(AName, PNameUpper, PNameLower, InfoEntry, ADbgValue);
if Result then
exit;
if FOuterNotFound then
exit;
if FOuterNestContext <> nil then begin
ADbgValue := FOuterNestContext.FindSymbol(AName); // TODO: pass upper/lower
if ADbgValue <> nil then
AddRefToVal(ADbgValue);
Result := True; // self, global was done by outer
exit;
end;
InfoEntry.ScopeIndex := StartScopeIdx;
if not InfoEntry.GoNamedChildEx(@parentfp[1], @parentfp[1]) then begin
InfoEntry.ScopeIndex := StartScopeIdx;
if not InfoEntry.GoNamedChildEx(@parentfp2[1], @parentfp2[1]) then begin
FOuterNotFound := True;
exit;
end;
end;
ParentFpSym := TFpDwarfSymbol.CreateSubClass(AName, InfoEntry);
ParentFpVal := ParentFpSym.Value;
ApplyContext(ParentFpVal);
//TFpDwarfSymbol(ADbgValue.DbgSymbol).ParentTypeInfo := TFpDwarfSymbolValueProc(FSymbol);
if not (svfOrdinal in ParentFpVal.FieldFlags) then begin
DebugLn('no ordinal for parentfp');
ParentFpSym.ReleaseReference;
FOuterNotFound := True;
exit;
end;
par_fp := ParentFpVal.AsCardinal;
ParentFpSym.ReleaseReference;
DebugLn(['par_fp=',par_fp]);
if par_fp = 0 then begin
DebugLn('no ordinal for parentfp');
FOuterNotFound := True;
exit;
end;
i := StackFrame + 1;
SearchCtx := TFpDwarfFreePascalAddressContext.Create(ThreadId, i, 0, Symbol, Dwarf);
cur_fp := 0;
if MemManager.ReadRegister(RegFp, cur_fp, Self) then begin
if cur_fp > par_fp then
d := -1 // cur_fp must go down
else
d := 1; // cur_fp must go up
while not (cur_fp = par_fp) do begin
SearchCtx.StackFrame := i;
// TODO: get reg num via memreader name-to-num
prev_fp := cur_fp;
if not MemManager.ReadRegister(RegFp, cur_fp, SearchCtx) then
break;
inc(i);
if (cur_fp = prev_fp) or ((cur_fp < prev_fp) xor (d = -1)) then
break; // wrong direction
if i > StackFrame + 200 then break; // something wrong? // TODO better check
end;
dec(i);
end;
if (par_fp <> cur_fp) or (cur_fp = 0) or
not MemManager.ReadRegister(RegPc, pc, SearchCtx)
then begin
FOuterNotFound := True;
SearchCtx.ReleaseReference;
exit;
end;
SearchCtx.ReleaseReference;
FOuterNestContext := Dwarf.FindContext(ThreadId, i, pc);
ADbgValue := FOuterNestContext.FindSymbol(AName); // TODO: pass upper/lower
if ADbgValue <> nil then
AddRefToVal(ADbgValue);
Result := True; // self, global was done by outer
end;
destructor TFpDwarfFreePascalAddressContext.Destroy;
begin
FOuterNestContext.ReleaseReference;
inherited Destroy;
end;
initialization
DwarfSymbolClassMapList.AddMap(TFpDwarfFreePascalSymbolClassMap);
end.