mirror of
				https://gitlab.com/freepascal.org/lazarus/lazarus.git
				synced 2025-11-04 11:00:01 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			188 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			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.
 | 
						|
 |