1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
|
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.
|