mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-18 15:49:27 +02:00
FpDebug: Read the symbol-table on OS/X
git-svn-id: trunk@45038 -
This commit is contained in:
parent
5829cc4e89
commit
69a51cde62
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -1282,6 +1282,8 @@ components/fpdebug/fpdbginfo.pas svneol=native#text/pascal
|
||||
components/fpdebug/fpdbgloader.pp svneol=native#text/pascal
|
||||
components/fpdebug/fpdbgpetypes.pp svneol=native#text/pascal
|
||||
components/fpdebug/fpdbgsymbols.pas svneol=native#text/pascal
|
||||
components/fpdebug/fpdbgsymtable.pas svneol=native#text/plain
|
||||
components/fpdebug/fpdbgsymtablecontext.pas svneol=native#text/plain
|
||||
components/fpdebug/fpdbgutil.pp svneol=native#text/pascal
|
||||
components/fpdebug/fpdbgwinclasses.pas svneol=native#text/pascal
|
||||
components/fpdebug/fpdbgwinextra.pp svneol=native#text/pascal
|
||||
|
@ -40,6 +40,7 @@ uses
|
||||
Classes, SysUtils, Maps, FpDbgDwarf, FpDbgUtil, FpDbgWinExtra, FpDbgLoader,
|
||||
FpDbgInfo, FpdMemoryTools, LazLoggerBase, LazClasses, DbgIntfBaseTypes, fgl,
|
||||
FpDbgDisasX86,
|
||||
fpDbgSymTableContext,
|
||||
FpDbgDwarfDataClasses;
|
||||
|
||||
type
|
||||
@ -205,6 +206,7 @@ type
|
||||
FOnDebugInfoLoaded: TNotifyEvent;
|
||||
FProcess: TDbgProcess;
|
||||
FDbgInfo: TDbgInfo;
|
||||
FSymbolTableInfo: TFpSymbolInfo;
|
||||
FLoader: TDbgImageLoader;
|
||||
|
||||
protected
|
||||
@ -222,6 +224,7 @@ type
|
||||
|
||||
property Process: TDbgProcess read FProcess;
|
||||
property DbgInfo: TDbgInfo read FDbgInfo;
|
||||
property SymbolTableInfo: TFpSymbolInfo read FSymbolTableInfo;
|
||||
property OnDebugInfoLoaded: TNotifyEvent read FOnDebugInfoLoaded write FOnDebugInfoLoaded;
|
||||
end;
|
||||
|
||||
@ -601,6 +604,7 @@ end;
|
||||
destructor TDbgInstance.Destroy;
|
||||
begin
|
||||
FreeAndNil(FDbgInfo);
|
||||
FreeAndNil(FSymbolTableInfo);
|
||||
FreeAndNil(FLoader);
|
||||
inherited;
|
||||
end;
|
||||
@ -608,6 +612,8 @@ end;
|
||||
function TDbgInstance.FindSymbol(AAdress: TDbgPtr): TFpDbgSymbol;
|
||||
begin
|
||||
Result := FDbgInfo.FindSymbol(AAdress + AddrOffset);
|
||||
if not assigned(Result) then
|
||||
result := FSymbolTableInfo.FindSymbol(AAdress + AddrOffset);
|
||||
end;
|
||||
|
||||
procedure TDbgInstance.LoadInfo;
|
||||
@ -615,6 +621,7 @@ begin
|
||||
FLoader := InitializeLoader;
|
||||
FDbgInfo := TFpDwarfInfo.Create(FLoader);
|
||||
TFpDwarfInfo(FDbgInfo).LoadCompilationUnits;
|
||||
FSymbolTableInfo := TFpSymbolInfo.Create(FLoader);
|
||||
if Assigned(FOnDebugInfoLoaded) then
|
||||
FOnDebugInfoLoaded(Self);
|
||||
end;
|
||||
|
@ -42,6 +42,7 @@ interface
|
||||
uses
|
||||
LCLType,
|
||||
FpImgReaderBase, FpImgReaderWinPE, FpImgReaderElf, FpImgReaderMacho,
|
||||
fpDbgSymTable,
|
||||
Classes, SysUtils;
|
||||
|
||||
type
|
||||
@ -65,6 +66,7 @@ type
|
||||
public
|
||||
constructor Create; virtual;
|
||||
constructor Create(AFileName: String);
|
||||
procedure ParseSymbolTable(AFpSymbolInfo: TfpSymbolList);
|
||||
{$ifdef USE_WIN_FILE_MAPPING}
|
||||
constructor Create(AFileHandle: THandle);
|
||||
{$endif}
|
||||
@ -100,6 +102,11 @@ begin
|
||||
FImgReader := GetImageReader(FFileLoader, True);
|
||||
end;
|
||||
|
||||
procedure TDbgImageLoader.ParseSymbolTable(AFpSymbolInfo: TfpSymbolList);
|
||||
begin
|
||||
FImgReader.ParseSymbolTable(AFpSymbolInfo);
|
||||
end;
|
||||
|
||||
{$ifdef USE_WIN_FILE_MAPPING}
|
||||
constructor TDbgImageLoader.Create(AFileHandle: THandle);
|
||||
begin
|
||||
|
16
components/fpdebug/fpdbgsymtable.pas
Normal file
16
components/fpdebug/fpdbgsymtable.pas
Normal file
@ -0,0 +1,16 @@
|
||||
unit fpDbgSymTable;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes;
|
||||
|
||||
type
|
||||
TfpSymbolList= TStringList;
|
||||
|
||||
implementation
|
||||
|
||||
end.
|
||||
|
145
components/fpdebug/fpdbgsymtablecontext.pas
Normal file
145
components/fpdebug/fpdbgsymtablecontext.pas
Normal file
@ -0,0 +1,145 @@
|
||||
unit fpDbgSymTableContext;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes,
|
||||
SysUtils,
|
||||
FpDbgLoader,
|
||||
FpImgReaderBase,
|
||||
DbgIntfBaseTypes,
|
||||
fpDbgSymTable,
|
||||
FpdMemoryTools,
|
||||
FpDbgInfo;
|
||||
|
||||
type
|
||||
|
||||
TFpSymbolInfo = class;
|
||||
|
||||
{ TFpSymbolContext }
|
||||
|
||||
TFpSymbolContext = class(TFpDbgInfoContext)
|
||||
private
|
||||
FFpSymbolInfo: TFpSymbolInfo;
|
||||
protected
|
||||
function GetAddress: TDbgPtr; override;
|
||||
function GetStackFrame: Integer; override;
|
||||
function GetThreadId: Integer; override;
|
||||
function GetSizeOfAddress: Integer; override;
|
||||
public
|
||||
constructor Create(AFpSymbolInfo: TFpSymbolInfo);
|
||||
function FindSymbol(const AName: String): TFpDbgValue; override;
|
||||
end;
|
||||
|
||||
{ TFpSymbolInfo }
|
||||
|
||||
TFpSymbolInfo = class(TDbgInfo)
|
||||
private
|
||||
FSymbolList: TfpSymbolList;
|
||||
FContext: TFpSymbolContext;
|
||||
public
|
||||
constructor Create(ALoader: TDbgImageLoader); override;
|
||||
destructor Destroy; override;
|
||||
function FindContext(AThreadId, AStackFrame: Integer; AAddress: TDbgPtr = 0): TFpDbgInfoContext; override;
|
||||
function FindContext(AAddress: TDbgPtr): TFpDbgInfoContext; override;
|
||||
function FindSymbol(AAddress: TDbgPtr): TFpDbgSymbol; override;
|
||||
function FindSymbol(const AName: String): TFpDbgSymbol; override;
|
||||
function GetLineAddress(const AFileName: String; ALine: Cardinal): TDbgPtr; override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
{ TFpSymbolContext }
|
||||
|
||||
function TFpSymbolContext.GetAddress: TDbgPtr;
|
||||
begin
|
||||
result := 0;
|
||||
end;
|
||||
|
||||
function TFpSymbolContext.GetStackFrame: Integer;
|
||||
begin
|
||||
result := 0;
|
||||
end;
|
||||
|
||||
function TFpSymbolContext.GetThreadId: Integer;
|
||||
begin
|
||||
result := 1;
|
||||
end;
|
||||
|
||||
function TFpSymbolContext.GetSizeOfAddress: Integer;
|
||||
begin
|
||||
result := 4;
|
||||
end;
|
||||
|
||||
constructor TFpSymbolContext.Create(AFpSymbolInfo: TFpSymbolInfo);
|
||||
begin
|
||||
inherited create;
|
||||
FFpSymbolInfo:=AFpSymbolInfo;
|
||||
end;
|
||||
|
||||
function TFpSymbolContext.FindSymbol(const AName: String): TFpDbgValue;
|
||||
var
|
||||
i: integer;
|
||||
val: TFpDbgMemLocation;
|
||||
begin
|
||||
i := FFpSymbolInfo.FSymbolList.IndexOf(AName);
|
||||
if i > -1 then
|
||||
begin
|
||||
val.Address:=TDbgPtr(pointer(FFpSymbolInfo.FSymbolList.Objects[i]));
|
||||
val.MType:=mlfTargetMem;
|
||||
result := TFpDbgValueConstAddress.Create(val);
|
||||
end
|
||||
else
|
||||
result := nil;
|
||||
end;
|
||||
|
||||
{ TFpSymbolInfo }
|
||||
|
||||
constructor TFpSymbolInfo.Create(ALoader: TDbgImageLoader);
|
||||
|
||||
begin
|
||||
inherited Create(ALoader);
|
||||
FContext := TFpSymbolContext.Create(self);
|
||||
|
||||
FSymbolList := TfpSymbolList.Create;
|
||||
ALoader.ParseSymbolTable(FSymbolList);
|
||||
end;
|
||||
|
||||
destructor TFpSymbolInfo.Destroy;
|
||||
begin
|
||||
FSymbolList.Free;
|
||||
FContext.Free;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function TFpSymbolInfo.FindContext(AThreadId, AStackFrame: Integer;
|
||||
AAddress: TDbgPtr): TFpDbgInfoContext;
|
||||
begin
|
||||
Result:=FContext;
|
||||
end;
|
||||
|
||||
function TFpSymbolInfo.FindContext(AAddress: TDbgPtr): TFpDbgInfoContext;
|
||||
begin
|
||||
Result:=FContext;
|
||||
end;
|
||||
|
||||
function TFpSymbolInfo.FindSymbol(AAddress: TDbgPtr): TFpDbgSymbol;
|
||||
begin
|
||||
Result:=inherited FindSymbol(AAddress);
|
||||
end;
|
||||
|
||||
function TFpSymbolInfo.FindSymbol(const AName: String): TFpDbgSymbol;
|
||||
begin
|
||||
result := nil;
|
||||
//Result:=FContext.FindSymbol(AName);
|
||||
end;
|
||||
|
||||
function TFpSymbolInfo.GetLineAddress(const AFileName: String; ALine: Cardinal): TDbgPtr;
|
||||
begin
|
||||
Result:=inherited GetLineAddress(AFileName, ALine);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
@ -34,7 +34,7 @@ File(s) with other licenses (see also header in file(s):
|
||||
|
||||
(Any modifications/translations of this file are from duby)
|
||||
"/>
|
||||
<Files Count="27">
|
||||
<Files Count="29">
|
||||
<Item1>
|
||||
<Filename Value="fpdbgclasses.pp"/>
|
||||
<UnitName Value="FpDbgClasses"/>
|
||||
@ -144,8 +144,16 @@ File(s) with other licenses (see also header in file(s):
|
||||
</Item26>
|
||||
<Item27>
|
||||
<Filename Value="fpdbgdwarffreepascal.pas"/>
|
||||
<UnitName Value="fpdbgdwarffreepascal"/>
|
||||
<UnitName Value="FpDbgDwarfFreePascal"/>
|
||||
</Item27>
|
||||
<Item28>
|
||||
<Filename Value="fpdbgsymtablecontext.pas"/>
|
||||
<UnitName Value="fpDbgSymTableContext"/>
|
||||
</Item28>
|
||||
<Item29>
|
||||
<Filename Value="fpdbgsymtable.pas"/>
|
||||
<UnitName Value="fpDbgSymTable"/>
|
||||
</Item29>
|
||||
</Files>
|
||||
<Type Value="RunAndDesignTime"/>
|
||||
<RequiredPkgs Count="3">
|
||||
|
@ -12,7 +12,8 @@ uses
|
||||
FpImgReaderElfTypes, FpImgReaderBase, FpPascalParser, macho,
|
||||
FpImgReaderMachoFile, FpImgReaderMacho, FpPascalBuilder, FpDbgInfo,
|
||||
FpdMemoryTools, FpErrorMessages, FPDbgController, FpDbgDwarfVerbosePrinter,
|
||||
FpDbgDwarfDataClasses, FpDbgDwarfFreePascal, LazarusPackageIntf;
|
||||
FpDbgDwarfDataClasses, FpDbgDwarfFreePascal, fpDbgSymTableContext,
|
||||
fpDbgSymTable, LazarusPackageIntf;
|
||||
|
||||
implementation
|
||||
|
||||
|
@ -8,6 +8,7 @@ uses
|
||||
{$ifdef windows}
|
||||
Windows, // After LCLType
|
||||
{$endif}
|
||||
fpDbgSymTable,
|
||||
Classes, SysUtils, LazUTF8Classes;
|
||||
|
||||
type
|
||||
@ -64,6 +65,7 @@ type
|
||||
public
|
||||
class function isValid(ASource: TDbgFileLoader): Boolean; virtual; abstract;
|
||||
class function UserName: AnsiString; virtual; abstract;
|
||||
procedure ParseSymbolTable(AFpSymbolInfo: TfpSymbolList); virtual;
|
||||
constructor Create({%H-}ASource: TDbgFileLoader; {%H-}OwnSource: Boolean); virtual;
|
||||
|
||||
property ImageBase: QWord read FImageBase;
|
||||
@ -234,6 +236,12 @@ begin
|
||||
FImage64Bit := AValue;
|
||||
end;
|
||||
|
||||
procedure TDbgImageReader.ParseSymbolTable(AFpSymbolInfo: TfpSymbolList);
|
||||
begin
|
||||
// The format of the symbol-table-section(s) can be different on each
|
||||
// platform. That's why parsing the data is done in TDbgImageReader.
|
||||
end;
|
||||
|
||||
constructor TDbgImageReader.Create(ASource: TDbgFileLoader; OwnSource: Boolean);
|
||||
begin
|
||||
inherited Create;
|
||||
|
@ -5,7 +5,8 @@ unit FpImgReaderMacho;
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, macho, FpImgReaderMachoFile, FpImgReaderBase, LazLoggerBase; //, stabs;
|
||||
Classes, SysUtils, macho, FpImgReaderMachoFile, FpImgReaderBase, LazLoggerBase,
|
||||
fpDbgSymTable;
|
||||
|
||||
type
|
||||
|
||||
@ -17,20 +18,21 @@ type
|
||||
FSections: TStringList;
|
||||
fOwnSource : Boolean;
|
||||
fFile : TMachoFile;
|
||||
isStabs : Boolean;
|
||||
hasSymTable : Boolean;
|
||||
StabsCmd : symtab_command;
|
||||
fileRead : Boolean;
|
||||
function GetSectionInfo(const SectionName: AnsiString; var Size: int64): Boolean;
|
||||
function GetSectionData(const SectionName: AnsiString; Offset, {%H-}Size: Int64; var Buf: array of byte): Int64;
|
||||
protected
|
||||
procedure ReadFile;
|
||||
function GetStabSectionInfo({%H-}StabStr: Boolean; var {%H-}SectionOffset, {%H-}SectionSize: Int64): Boolean;
|
||||
function GetSymTableSectionInfo({%H-}StabStr: Boolean; var {%H-}SectionOffset, {%H-}SectionSize: Int64): Boolean;
|
||||
function GetSectionIndex(const SectionName: AnsiString): Integer;
|
||||
|
||||
function GetSection(const AName: String): PDbgImageSection; override;
|
||||
public
|
||||
class function isValid(ASource: TDbgFileLoader): Boolean; override;
|
||||
class function UserName: AnsiString; override;
|
||||
procedure ParseSymbolTable(AfpSymbolInfo: TfpSymbolList); override;
|
||||
public
|
||||
constructor Create(ASource: TDbgFileLoader; OwnSource: Boolean); override;
|
||||
destructor Destroy; override;
|
||||
@ -38,10 +40,14 @@ type
|
||||
|
||||
implementation
|
||||
|
||||
type
|
||||
PnlistArray = ^TnlistArray;
|
||||
TnlistArray = array[0..maxSmallint] of nlist;
|
||||
|
||||
const
|
||||
//StabSectoinName
|
||||
_stab = '.stab';
|
||||
_stabstr = '.stabstr';
|
||||
// Symbol-map section name
|
||||
_symbol = '.symbols';
|
||||
_symbolstrings = '.symbolsstrings';
|
||||
|
||||
|
||||
function isValidMachoStream(ASource: TDbgFileLoader): Boolean;
|
||||
@ -82,6 +88,37 @@ begin
|
||||
Result:='mach-o file';
|
||||
end;
|
||||
|
||||
procedure TDbgMachoDataSource.ParseSymbolTable(AfpSymbolInfo: TfpSymbolList);
|
||||
var
|
||||
p: PDbgImageSection;
|
||||
ps: PDbgImageSection;
|
||||
SymbolArr: PnlistArray;
|
||||
SymbolStr: pointer;
|
||||
i: integer;
|
||||
SymbolCount: integer;
|
||||
begin
|
||||
p := Section[_symbol];
|
||||
ps := Section[_symbolstrings];
|
||||
if assigned(p) and assigned(ps) then
|
||||
begin
|
||||
SymbolArr:=PDbgImageSectionEx(p)^.Sect.RawData;
|
||||
SymbolStr:=PDbgImageSectionEx(ps)^.Sect.RawData;
|
||||
SymbolCount := PDbgImageSectionEx(p)^.Sect.Size div sizeof(nlist);
|
||||
for i := 0 to SymbolCount-1 do
|
||||
begin
|
||||
if (SymbolArr^[i].n_type and $e0)<>0 then
|
||||
// This is a stabs-entry. Ignore.
|
||||
Continue;
|
||||
if (SymbolArr^[i].n_type and $0e)=$e then
|
||||
begin
|
||||
// Section-index is ignored for now...
|
||||
AfpSymbolInfo.AddObject(pchar(SymbolStr+SymbolArr^[i].n_un.n_strx), TObject(SymbolArr^[i].n_value));
|
||||
end
|
||||
end;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
procedure TDbgMachoDataSource.ReadFile;
|
||||
var
|
||||
i : Integer;
|
||||
@ -90,8 +127,8 @@ begin
|
||||
fFile:=TMachOFile.Create;
|
||||
fFile.LoadFromFile(fSource);
|
||||
for i := 0 to fFile.header.ncmds - 1 do begin
|
||||
isStabs := fFile.commands[i]^.cmd = LC_SYMTAB;
|
||||
if isStabs then begin
|
||||
hasSymTable := fFile.commands[i]^.cmd = LC_SYMTAB;
|
||||
if hasSymTable then begin
|
||||
StabsCmd := psymtab_command(fFile.commands[i])^;
|
||||
Break;
|
||||
end;
|
||||
@ -99,20 +136,18 @@ begin
|
||||
fileRead := true;
|
||||
end;
|
||||
|
||||
function TDbgMachoDataSource.GetStabSectionInfo(StabStr: Boolean; var SectionOffset, SectionSize: Int64): Boolean;
|
||||
function TDbgMachoDataSource.GetSymTableSectionInfo(StabStr: Boolean;
|
||||
var SectionOffset, SectionSize: Int64): Boolean;
|
||||
begin
|
||||
exit(false);
|
||||
(*
|
||||
Result := isStabs;
|
||||
Result := hasSymTable;
|
||||
if not Result then Exit;
|
||||
if StabStr then begin
|
||||
SectionOffset := StabsCmd.stroff;
|
||||
SectionSize := StabsCmd.strsize;
|
||||
end else begin
|
||||
SectionOffset := StabsCmd.symoff;
|
||||
SectionSize := Int64(StabsCmd.nsyms * sizeof(TStabSym));
|
||||
SectionSize := Int64(StabsCmd.nsyms * sizeof(nlist));
|
||||
end;
|
||||
*)
|
||||
end;
|
||||
|
||||
function TDbgMachoDataSource.GetSectionIndex(const SectionName: AnsiString): Integer;
|
||||
@ -152,11 +187,15 @@ begin
|
||||
end;
|
||||
|
||||
constructor TDbgMachoDataSource.Create(ASource: TDbgFileLoader; OwnSource: Boolean);
|
||||
const
|
||||
SymbolsSectionName : array [Boolean] of AnsiString = (_symbol, _symbolstrings);
|
||||
var
|
||||
p: PDbgImageSectionEx;
|
||||
fs: TMachOsection;
|
||||
i: Integer;
|
||||
Name: String;
|
||||
soffset: int64;
|
||||
ssize: int64;
|
||||
begin
|
||||
fSource := ASource;
|
||||
fOwnSource := OwnSource;
|
||||
@ -189,6 +228,24 @@ DebugLn(Name);
|
||||
FSections.AddObject(Name, TObject(p));
|
||||
end;
|
||||
|
||||
if GetSymTableSectionInfo(false, soffset, ssize) then begin
|
||||
new(p);
|
||||
p^.Offs:=soffset;
|
||||
p^.Sect.Size:=ssize;
|
||||
p^.Sect.VirtualAddress:=0;
|
||||
p^.Loaded:=false;
|
||||
FSections.AddObject(SymbolsSectionName[false], TObject(p));
|
||||
end;
|
||||
|
||||
if GetSymTableSectionInfo(true, soffset, ssize) then begin
|
||||
new(p);
|
||||
p^.Offs:=soffset;
|
||||
p^.Sect.Size:=ssize;
|
||||
p^.Sect.VirtualAddress:=0;
|
||||
p^.Loaded:=false;
|
||||
FSections.AddObject(SymbolsSectionName[true], TObject(p));
|
||||
end;
|
||||
|
||||
inherited Create(ASource, OwnSource);
|
||||
end;
|
||||
|
||||
@ -272,14 +329,14 @@ end;}
|
||||
function TDbgMachoDataSource.GetSectionInfo(const SectionName: AnsiString; var Size: int64): Boolean;
|
||||
var
|
||||
idx : integer;
|
||||
stabstr : Boolean;
|
||||
symtablestr : Boolean;
|
||||
dummy : int64;
|
||||
begin
|
||||
if not fileRead then ReadFile;
|
||||
|
||||
stabstr := (SectionName = _stabstr);
|
||||
if stabstr or (SectionName = _stab) then
|
||||
Result := GetStabSectionInfo(stabstr, dummy, Size)
|
||||
symtablestr := (SectionName = _symbolstrings);
|
||||
if symtablestr or (SectionName = _symbol) then
|
||||
Result := GetSymTableSectionInfo(symtablestr, dummy, Size)
|
||||
else begin
|
||||
idx := GetSectionIndex(SectionName);
|
||||
Result := idx >= 0;
|
||||
@ -297,16 +354,16 @@ var
|
||||
idx : Integer;
|
||||
sofs : int64;
|
||||
ssize : int64;
|
||||
stabstr : Boolean;
|
||||
symstr : Boolean;
|
||||
sz : Int64;
|
||||
s : TMachOsection;
|
||||
begin
|
||||
if not fileRead then ReadFile;
|
||||
|
||||
Result := 0;
|
||||
stabstr := SectionName = _stabstr;
|
||||
if stabstr or (SectionName = _stab) then begin
|
||||
if not GetStabSectionInfo(stabstr, sofs, ssize) then
|
||||
symstr := SectionName = _symbolstrings;
|
||||
if symstr or (SectionName = _symbol) then begin
|
||||
if not GetSymTableSectionInfo(symstr, sofs, ssize) then
|
||||
Exit;
|
||||
end else begin
|
||||
idx := GetSectionIndex(SectionName);
|
||||
|
Loading…
Reference in New Issue
Block a user