mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-16 11:29:31 +02:00
FpDebug: The developers at Apple were not able to build a linker
with the ability to deal with Dwarf-debug info. Added the ability to read the Dwarf-debug info from the object files and to map the corresponding addresses to their position in the final executable. git-svn-id: trunk@48864 -
This commit is contained in:
parent
77b0466028
commit
c53e775af5
@ -16,6 +16,7 @@ uses
|
||||
DbgIntfBaseTypes,
|
||||
FpDbgLinuxExtra,
|
||||
FpDbgDwarfDataClasses,
|
||||
FpImgReaderMacho,
|
||||
FpDbgInfo,
|
||||
MacOSAll,
|
||||
FpDbgUtil,
|
||||
@ -639,9 +640,12 @@ end;
|
||||
procedure TDbgDarwinProcess.InitializeLoaders;
|
||||
var
|
||||
dSYMFilename: string;
|
||||
PrimaryLoader: TDbgImageLoader;
|
||||
ALoader: TDbgImageLoader;
|
||||
begin
|
||||
LoaderList.Add(TDbgImageLoader.Create(FExecutableFilename));
|
||||
ALoader:=nil;
|
||||
PrimaryLoader := TDbgImageLoader.Create(FExecutableFilename);
|
||||
LoaderList.Add(PrimaryLoader);
|
||||
|
||||
// JvdS: Mach-O binaries do not contain DWARF-debug info. Instead this info
|
||||
// is stored inside the .o files, and the executable contains a map (in stabs-
|
||||
@ -657,13 +661,23 @@ begin
|
||||
if FileExists(dSYMFilename) then
|
||||
begin
|
||||
ALoader := TDbgImageLoader.Create(dSYMFilename);
|
||||
if GUIDToString(ALoader.UUID)<>GUIDToString(LoaderList[0].UUID) then
|
||||
log('The unique UUID''s of the executable and the dSYM bundle with debug-info ('+dSYMFilename+') do not match. This can lead to problems during debugging.', dllInfo);
|
||||
if GUIDToString(ALoader.UUID)<>GUIDToString(PrimaryLoader.UUID) then
|
||||
begin
|
||||
log('The unique UUID''s of the executable and the dSYM bundle with debug-info ('+dSYMFilename+') do not match.', dllDebug);
|
||||
FreeAndNil(ALoader);
|
||||
end
|
||||
else
|
||||
begin
|
||||
log('Load debug-info from dSYM bundle ('+dSYMFilename+').', dllDebug);
|
||||
LoaderList.Add(ALoader);
|
||||
end;
|
||||
end;
|
||||
|
||||
LoaderList.Add(ALoader);
|
||||
end
|
||||
else
|
||||
log('No dSYM bundle ('+dSYMFilename+') found.', dllInfo);
|
||||
if not assigned(ALoader) then
|
||||
begin
|
||||
log('Read debug-info from separate object files.', dllDebug);
|
||||
TDbgMachoDataSource.LoadSubFiles(PrimaryLoader.SubFiles, LoaderList);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TDbgDarwinProcess.CreateThread(AthreadIdentifier: THandle; out IsMainThread: boolean): TDbgThread;
|
||||
|
@ -2897,6 +2897,8 @@ begin
|
||||
|
||||
if LocationParser.ResultKind in [lseValue] then begin
|
||||
AnAddress := TargetLoc(LocationParser.ResultData);
|
||||
if ATag=DW_AT_location then
|
||||
AnAddress.Address :=CompilationUnit.MapAddressToNewValue(AnAddress.Address);
|
||||
Result := True;
|
||||
end
|
||||
else
|
||||
|
@ -465,6 +465,7 @@ type
|
||||
|
||||
TDwarfDebugFile = record
|
||||
Sections: array[TDwarfSection] of TDwarfSectionInfo;
|
||||
AddressMapList: TDbgAddressMapList;
|
||||
end;
|
||||
PDwarfDebugFile = ^TDwarfDebugFile;
|
||||
|
||||
@ -544,6 +545,8 @@ type
|
||||
function ReadValue(AAttribute: Pointer; AForm: Cardinal; out AValue: String): Boolean;
|
||||
function ReadValue(AAttribute: Pointer; AForm: Cardinal; out AValue: PChar): Boolean;
|
||||
function ReadValue(AAttribute: Pointer; AForm: Cardinal; out AValue: TByteDynArray): Boolean;
|
||||
// Read a value that contains an address. The address is evaluated using MapAddressToNewValue
|
||||
function ReadAddressValue(AAttribute: Pointer; AForm: Cardinal; out AValue: QWord): Boolean;
|
||||
|
||||
public
|
||||
constructor Create(AOwner: TFpDwarfInfo; ADebugFile: PDwarfDebugFile; ADataOffset: QWord; ALength: QWord; AVersion: Word; AAbbrevOffset: QWord; AAddressSize: Byte; AIsDwarf64: Boolean); virtual;
|
||||
@ -554,6 +557,9 @@ type
|
||||
function GetLineAddress(const AFileName: String; ALine: Cardinal): TDbgPtr;
|
||||
procedure BuildLineInfo(AAddressInfo: PDwarfAddressInfo; ADoAll: Boolean);
|
||||
function FullFileName(const AFileName:string): String;
|
||||
// On Darwin it could be that the debug-information is not included into the executable by the linker.
|
||||
// This function is to map object-file addresses into the corresponding addresses in the executable.
|
||||
function MapAddressToNewValue(AValue: QWord): QWord;
|
||||
|
||||
property Valid: Boolean read FValid;
|
||||
property FileName: String read FFileName;
|
||||
@ -2677,7 +2683,10 @@ begin
|
||||
end
|
||||
else
|
||||
if (Form = DW_FORM_ref_addr) then begin
|
||||
Result := FCompUnit.ReadValue(InfoData, Form, Offs);
|
||||
if FCompUnit.Version=2 then
|
||||
Result := FCompUnit.ReadAddressValue(InfoData, Form, Offs)
|
||||
else
|
||||
Result := FCompUnit.ReadValue(InfoData, Form, Offs);
|
||||
if not Result then
|
||||
exit;
|
||||
AValue := FCompUnit.DebugFile^.Sections[dsInfo].RawData + Offs;
|
||||
@ -2819,6 +2828,7 @@ begin
|
||||
SetLength(FFiles, ALoaderList.Count);
|
||||
for i := 0 to ALoaderList.Count-1 do
|
||||
begin
|
||||
FFiles[i].AddressMapList:=ALoaderList[i].AddressMapList;
|
||||
for Section := Low(Section) to High(Section) do
|
||||
begin
|
||||
p := ALoaderList[i].Section[DWARF_SECTION_NAME[Section]];
|
||||
@ -3191,6 +3201,7 @@ begin
|
||||
if FOwner.FLineInfo.Addr64
|
||||
then FAddress := PQWord(pbyte(FLineInfoPtr)+1)^
|
||||
else FAddress := PLongWord(pbyte(FLineInfoPtr)+1)^;
|
||||
FAddress:=FOwner.MapAddressToNewValue(FAddress);
|
||||
end;
|
||||
DW_LNE_define_file: begin
|
||||
// don't move pb, it's done at the end by instruction length
|
||||
@ -3437,10 +3448,10 @@ begin
|
||||
if (dafHasLowAddr in AttribList.Abbrev^.flags) and
|
||||
LocateAttribute(Scope.Entry, DW_AT_low_pc, AttribList, Attrib, Form)
|
||||
then begin
|
||||
ReadValue(Attrib, Form, Info.StartPC);
|
||||
ReadAddressValue(Attrib, Form, Info.StartPC);
|
||||
|
||||
if LocateAttribute(Scope.Entry, DW_AT_high_pc, AttribList, Attrib, Form)
|
||||
then ReadValue(Attrib, Form, Info.EndPC)
|
||||
then ReadAddressValue(Attrib, Form, Info.EndPC)
|
||||
else Info.EndPC := Info.StartPC;
|
||||
|
||||
// TODO (dafHasName in Abbrev.flags)
|
||||
@ -3652,10 +3663,10 @@ begin
|
||||
end;
|
||||
|
||||
if LocateAttribute(Scope.Entry, DW_AT_low_pc, AttribList, Attrib, Form)
|
||||
then ReadValue(Attrib, Form, FMinPC);
|
||||
then ReadAddressValue(Attrib, Form, FMinPC);
|
||||
|
||||
if LocateAttribute(Scope.Entry, DW_AT_high_pc, AttribList, Attrib, Form)
|
||||
then ReadValue(Attrib, Form, FMaxPC);
|
||||
then ReadAddressValue(Attrib, Form, FMaxPC);
|
||||
|
||||
if FMinPC = 0 then FMinPC := FMaxPC;
|
||||
if FMaxPC = 0 then FMAxPC := FMinPC;
|
||||
@ -3984,6 +3995,29 @@ begin
|
||||
if AIncPointer then inc(AData, FAddressSize);
|
||||
end;
|
||||
|
||||
function TDwarfCompilationUnit.MapAddressToNewValue(AValue: QWord): QWord;
|
||||
var
|
||||
i: Integer;
|
||||
AddrMap: TDbgAddressMap;
|
||||
begin
|
||||
result := avalue;
|
||||
if assigned(DebugFile^.AddressMapList) then
|
||||
for i := 0 to DebugFile^.AddressMapList.Count-1 do
|
||||
begin
|
||||
AddrMap:=DebugFile^.AddressMapList[i];
|
||||
if AddrMap.OrgAddr=AValue then
|
||||
begin
|
||||
result:=AddrMap.NewAddr;
|
||||
break;
|
||||
end
|
||||
else if (AddrMap.OrgAddr<AValue) and (AValue<=(AddrMap.OrgAddr+AddrMap.Length)) then
|
||||
begin
|
||||
result:=AddrMap.NewAddr + (AValue-AddrMap.OrgAddr) ;
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TDwarfCompilationUnit.ReadValue(AAttribute: Pointer; AForm: Cardinal; out AValue: Cardinal): Boolean;
|
||||
begin
|
||||
Result := True;
|
||||
@ -4192,6 +4226,13 @@ begin
|
||||
Move(AAttribute^, AValue[0], Size);
|
||||
end;
|
||||
|
||||
function TDwarfCompilationUnit.ReadAddressValue(AAttribute: Pointer; AForm: Cardinal; out AValue: QWord): Boolean;
|
||||
begin
|
||||
result := ReadValue(AAttribute, AForm, AValue);
|
||||
if result then
|
||||
AValue := MapAddressToNewValue(AValue);
|
||||
end;
|
||||
|
||||
initialization
|
||||
TheDwarfSymbolClassMapList := TFpDwarfSymbolClassMapList.Create;
|
||||
|
||||
|
@ -56,6 +56,8 @@ type
|
||||
private
|
||||
FFileLoader: TDbgFileLoader;
|
||||
FImgReader: TDbgImageReader;
|
||||
function GetAddressMapList: TDbgAddressMapList;
|
||||
function GetSubFiles: TStrings;
|
||||
function GetImage64Bit: Boolean;
|
||||
function GetUUID: TGuid;
|
||||
protected
|
||||
@ -65,7 +67,7 @@ type
|
||||
property ImgReader: TDbgImageReader read FImgReader write FImgReader;
|
||||
public
|
||||
constructor Create; virtual;
|
||||
constructor Create(AFileName: String);
|
||||
constructor Create(AFileName: String; ADebugMap: TObject = nil);
|
||||
procedure ParseSymbolTable(AFpSymbolInfo: TfpSymbolList);
|
||||
{$ifdef USE_WIN_FILE_MAPPING}
|
||||
constructor Create(AFileHandle: THandle);
|
||||
@ -76,6 +78,12 @@ type
|
||||
Property Image64Bit: Boolean read GetImage64Bit;
|
||||
property UUID: TGuid read GetUUID;
|
||||
property Section[const AName: String]: PDbgImageSection read GetSection;
|
||||
// On Darwin, the Dwarf-debuginfo is not linked into the main
|
||||
// executable, but has to be read from the object files.
|
||||
property SubFiles: TStrings read GetSubFiles;
|
||||
// This is to map the addresses inside the object file
|
||||
// to their corresponding addresses in the executable. (Darwin)
|
||||
property AddressMapList: TDbgAddressMapList read GetAddressMapList;
|
||||
end;
|
||||
|
||||
{ TDbgImageLoaderList }
|
||||
@ -140,6 +148,22 @@ begin
|
||||
result := ImgReader.Image64Bit;
|
||||
end;
|
||||
|
||||
function TDbgImageLoader.GetAddressMapList: TDbgAddressMapList;
|
||||
begin
|
||||
if IsValid then
|
||||
result := FImgReader.AddressMapList
|
||||
else
|
||||
result := nil
|
||||
end;
|
||||
|
||||
function TDbgImageLoader.GetSubFiles: TStrings;
|
||||
begin
|
||||
if IsValid then
|
||||
result := FImgReader.SubFiles
|
||||
else
|
||||
result := nil;
|
||||
end;
|
||||
|
||||
function TDbgImageLoader.GetUUID: TGuid;
|
||||
begin
|
||||
if assigned(FImgReader) then
|
||||
@ -161,10 +185,10 @@ begin
|
||||
inherited Create;
|
||||
end;
|
||||
|
||||
constructor TDbgImageLoader.Create(AFileName: String);
|
||||
constructor TDbgImageLoader.Create(AFileName: String; ADebugMap: TObject = nil);
|
||||
begin
|
||||
FFileLoader := TDbgFileLoader.Create(AFileName);
|
||||
FImgReader := GetImageReader(FFileLoader, True);
|
||||
FImgReader := GetImageReader(FFileLoader, ADebugMap, True);
|
||||
end;
|
||||
|
||||
procedure TDbgImageLoader.ParseSymbolTable(AFpSymbolInfo: TfpSymbolList);
|
||||
|
@ -75,7 +75,7 @@ type
|
||||
public
|
||||
class function isValid(ASource: TDbgFileLoader): Boolean; override;
|
||||
class function UserName: AnsiString; override;
|
||||
constructor Create(ASource: TDbgFileLoader; OwnSource: Boolean); override;
|
||||
constructor Create(ASource: TDbgFileLoader; ADebugMap: TObject; OwnSource: Boolean); override;
|
||||
destructor Destroy; override;
|
||||
procedure ParseSymbolTable(AFpSymbolInfo: TfpSymbolList); override;
|
||||
|
||||
@ -292,7 +292,7 @@ begin
|
||||
Result := 'ELF executable';
|
||||
end;
|
||||
|
||||
constructor TElfDbgSource.Create(ASource: TDbgFileLoader; OwnSource: Boolean);
|
||||
constructor TElfDbgSource.Create(ASource: TDbgFileLoader; ADebugMap: TObject; OwnSource: Boolean);
|
||||
var
|
||||
p: PDbgImageSectionEx;
|
||||
idx: integer;
|
||||
@ -320,7 +320,7 @@ begin
|
||||
FSections.Objects[idx] := TObject(p);
|
||||
end;
|
||||
SetImage64Bit(fElfFile.Is64Bit);
|
||||
inherited Create(ASource, OwnSource);
|
||||
inherited Create(ASource, ADebugMap, OwnSource);
|
||||
end;
|
||||
|
||||
destructor TElfDbgSource.Destroy;
|
||||
|
@ -5,7 +5,10 @@ unit FpImgReaderMacho;
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, macho, FpImgReaderMachoFile, FpImgReaderBase, LazLoggerBase,
|
||||
Classes, SysUtils, contnrs,
|
||||
macho, FpImgReaderMachoFile, FpImgReaderBase, LazLoggerBase,
|
||||
DbgIntfBaseTypes,
|
||||
lazfglhash,
|
||||
fpDbgSymTable;
|
||||
|
||||
type
|
||||
@ -16,6 +19,8 @@ type
|
||||
private
|
||||
fSource : TDbgFileLoader;
|
||||
FSections: TStringList;
|
||||
fSubFiles: TStringList;
|
||||
fAddressMapList: TDbgAddressMapList;
|
||||
fOwnSource : Boolean;
|
||||
fFile : TMachoFile;
|
||||
hasSymTable : Boolean;
|
||||
@ -23,8 +28,12 @@ type
|
||||
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;
|
||||
procedure ParseMainAppleDwarfDataMap;
|
||||
procedure ParseSubAppleDwarfDataMap(ADebugMap: TObject);
|
||||
protected
|
||||
procedure ReadFile;
|
||||
function GetSubFiles: TStrings; override;
|
||||
function GetAddressMapList: TDbgAddressMapList; override;
|
||||
function GetSymTableSectionInfo({%H-}StabStr: Boolean; var {%H-}SectionOffset, {%H-}SectionSize: Int64): Boolean;
|
||||
function GetSectionIndex(const SectionName: AnsiString): Integer;
|
||||
|
||||
@ -32,14 +41,18 @@ type
|
||||
public
|
||||
class function isValid(ASource: TDbgFileLoader): Boolean; override;
|
||||
class function UserName: AnsiString; override;
|
||||
class procedure LoadSubFiles(ASubFiles: TStrings; ALoaderList: TFPObjectList);
|
||||
procedure ParseSymbolTable(AfpSymbolInfo: TfpSymbolList); override;
|
||||
public
|
||||
constructor Create(ASource: TDbgFileLoader; OwnSource: Boolean); override;
|
||||
constructor Create(ASource: TDbgFileLoader; ADebugMap: TObject; OwnSource: Boolean); override;
|
||||
destructor Destroy; override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
FpDbgLoader;
|
||||
|
||||
type
|
||||
PnlistArray = ^TnlistArray;
|
||||
TnlistArray = array[0..maxSmallint] of nlist;
|
||||
@ -49,6 +62,46 @@ const
|
||||
_symbol = '.symbols';
|
||||
_symbolstrings = '.symbolsstrings';
|
||||
|
||||
type
|
||||
TDebugTableState = (dtsDir, dtsSource, dtsObjectFile, dtsProc, dtsProcLen, dtsProcEnd, dtsEnd);
|
||||
TDebugTableEntry = record
|
||||
Dir: string;
|
||||
SourceFile: string;
|
||||
ObjectFile: string;
|
||||
ObjFileAge: longint;
|
||||
Offset: TDBGPtr;
|
||||
end;
|
||||
|
||||
{ TAppleDwarfDebugMap }
|
||||
|
||||
TAppleDwarfDebugMap = class(TObject)
|
||||
private
|
||||
FAddressMap: TDbgAddressMapList;
|
||||
FDir: string;
|
||||
FGlobalList: TDbgAddressMapHashList;
|
||||
FObjectFile: string;
|
||||
FObjFileAge: longint;
|
||||
FOffset: TDBGPtr;
|
||||
FSourceFile: string;
|
||||
public
|
||||
constructor create;
|
||||
destructor destroy; override;
|
||||
property Offset: TDBGPtr read FOffset write FOffset;
|
||||
property Dir: string read FDir write FDir;
|
||||
property ObjectFile: string read FObjectFile write FObjectFile;
|
||||
property SourceFile: string read FSourceFile write FSourceFile;
|
||||
property ObjFileAge: longint read FObjFileAge write FObjFileAge;
|
||||
// This list contains the locations for all symbols in the executable,
|
||||
// parsed from the 'stabs'-debuginfo in the executable.
|
||||
// This property is only available in the debug-map for the main
|
||||
// executable.
|
||||
property GlobalList: TDbgAddressMapHashList read FGlobalList;
|
||||
// This list maps addresses in an object-file to the addresses
|
||||
// in the main executable.
|
||||
// This property is only available in the debug-map for a specific
|
||||
// object-file.
|
||||
property AddressMap: TDbgAddressMapList read FAddressMap;
|
||||
end;
|
||||
|
||||
function isValidMachoStream(ASource: TDbgFileLoader): Boolean;
|
||||
var
|
||||
@ -74,7 +127,18 @@ begin
|
||||
Result := macsectionname;
|
||||
end;
|
||||
|
||||
constructor TAppleDwarfDebugMap.create;
|
||||
begin
|
||||
FGlobalList := TDbgAddressMapHashList.Create;
|
||||
FAddressMap := TDbgAddressMapList.Create;
|
||||
end;
|
||||
|
||||
destructor TAppleDwarfDebugMap.destroy;
|
||||
begin
|
||||
FAddressMap.Free;
|
||||
FGlobalList.Free;
|
||||
inherited destroy;
|
||||
end;
|
||||
|
||||
{ TDbgMachoDataSource }
|
||||
|
||||
@ -88,6 +152,33 @@ begin
|
||||
Result:='mach-o file';
|
||||
end;
|
||||
|
||||
class procedure TDbgMachoDataSource.LoadSubFiles(ASubFiles: TStrings; ALoaderList: TFPObjectList);
|
||||
var
|
||||
DwarfDebugMap: TAppleDwarfDebugMap;
|
||||
Loader: TDbgImageLoader;
|
||||
i: Integer;
|
||||
begin
|
||||
if assigned(ASubFiles) then
|
||||
begin
|
||||
for i := 0 to ASubFiles.Count -1 do
|
||||
begin
|
||||
if (ASubFiles.Objects[i] is TAppleDwarfDebugMap) and FileExists(ASubFiles[i]) then
|
||||
begin
|
||||
DwarfDebugMap:=TAppleDwarfDebugMap(ASubFiles.Objects[i]);
|
||||
if FileAge(ASubFiles[i]) <> DwarfDebugMap.ObjFileAge then
|
||||
debugln(Format('The timestamp of the object-file "%s" does not correspond to the timestamp (%s) stored inside the executable. The debug-info in this file is not loaded.', [DwarfDebugMap.ObjectFile, DateTimeToStr(FileDatetoDateTime(DwarfDebugMap.ObjFileAge))]))
|
||||
else
|
||||
begin
|
||||
Loader := TDbgImageLoader.Create(DwarfDebugMap.ObjectFile, DwarfDebugMap);
|
||||
ALoaderList.Add(Loader);
|
||||
end;
|
||||
end
|
||||
else
|
||||
DebugLn('File with debug-info "'+DwarfDebugMap.ObjectFile+'" does not exist. This could lead to missing debug-information.');
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TDbgMachoDataSource.ParseSymbolTable(AfpSymbolInfo: TfpSymbolList);
|
||||
var
|
||||
p: PDbgImageSection;
|
||||
@ -138,6 +229,25 @@ begin
|
||||
fileRead := true;
|
||||
end;
|
||||
|
||||
function TDbgMachoDataSource.GetSubFiles: TStrings;
|
||||
begin
|
||||
if not assigned(fSubFiles) then
|
||||
begin
|
||||
fSubFiles:=TStringList.Create;
|
||||
fSubFiles.OwnsObjects:=true;
|
||||
end;
|
||||
Result:=fSubFiles;
|
||||
end;
|
||||
|
||||
function TDbgMachoDataSource.GetAddressMapList: TDbgAddressMapList;
|
||||
begin
|
||||
if not assigned(fAddressMapList) then
|
||||
begin
|
||||
fAddressMapList:=TDbgAddressMapList.Create;
|
||||
end;
|
||||
Result:=fAddressMapList;
|
||||
end;
|
||||
|
||||
function TDbgMachoDataSource.GetSymTableSectionInfo(StabStr: Boolean;
|
||||
var SectionOffset, SectionSize: Int64): Boolean;
|
||||
begin
|
||||
@ -188,7 +298,7 @@ begin
|
||||
fSource.LoadMemory(ex^.Offs, Result^.Size, Result^.RawData);
|
||||
end;
|
||||
|
||||
constructor TDbgMachoDataSource.Create(ASource: TDbgFileLoader; OwnSource: Boolean);
|
||||
constructor TDbgMachoDataSource.Create(ASource: TDbgFileLoader; ADebugMap: TObject; OwnSource: Boolean);
|
||||
const
|
||||
SymbolsSectionName : array [Boolean] of AnsiString = (_symbol, _symbolstrings);
|
||||
var
|
||||
@ -248,11 +358,20 @@ DebugLn(Name);
|
||||
FSections.AddObject(SymbolsSectionName[true], TObject(p));
|
||||
end;
|
||||
|
||||
inherited Create(ASource, OwnSource);
|
||||
if assigned(ADebugMap) then
|
||||
ParseSubAppleDwarfDataMap(ADebugMap)
|
||||
else
|
||||
ParseMainAppleDwarfDataMap;
|
||||
|
||||
inherited Create(ASource, ADebugMap, OwnSource);
|
||||
end;
|
||||
|
||||
destructor TDbgMachoDataSource.Destroy;
|
||||
begin
|
||||
if assigned(fSubFiles) then
|
||||
fSubFiles.Free;
|
||||
if assigned(fAddressMapList) then
|
||||
fAddressMapList.Free;
|
||||
if Assigned(fFile) then fFile.Free;
|
||||
if fOwnSource then fSource.Free;
|
||||
while FSections.Count > 0 do begin
|
||||
@ -387,6 +506,160 @@ begin
|
||||
Result := fSource.Read(sofs + Offset, sz, @Buf[0]);
|
||||
end;
|
||||
|
||||
procedure TDbgMachoDataSource.ParseMainAppleDwarfDataMap;
|
||||
var
|
||||
p: PDbgImageSection;
|
||||
ps: PDbgImageSection;
|
||||
SymbolArr: PnlistArray;
|
||||
SymbolStr: pointer;
|
||||
i: integer;
|
||||
SymbolCount: integer;
|
||||
State: TDebugTableState;
|
||||
AddressMap: TDbgAddressMap;
|
||||
ProcName: string;
|
||||
DwarfDebugMap: TAppleDwarfDebugMap;
|
||||
begin
|
||||
DwarfDebugMap:=nil;
|
||||
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);
|
||||
state := dtsEnd;
|
||||
for i := 0 to SymbolCount-1 do
|
||||
begin
|
||||
case state of
|
||||
dtsEnd:
|
||||
begin
|
||||
if SymbolArr^[i].n_type = N_SO then
|
||||
begin
|
||||
if assigned(DwarfDebugMap) then
|
||||
DwarfDebugMap.Free;
|
||||
DwarfDebugMap := TAppleDwarfDebugMap.Create;
|
||||
DwarfDebugMap.Dir := pchar(SymbolStr+SymbolArr^[i].n_un.n_strx);
|
||||
state := dtsDir;
|
||||
end;
|
||||
end;
|
||||
dtsDir:
|
||||
begin
|
||||
if SymbolArr^[i].n_type = N_SO then
|
||||
begin
|
||||
DwarfDebugMap.SourceFile:=pchar(SymbolStr+SymbolArr^[i].n_un.n_strx);
|
||||
inc(state);
|
||||
end
|
||||
else
|
||||
state := dtsEnd;
|
||||
end;
|
||||
dtsSource:
|
||||
begin
|
||||
if SymbolArr^[i].n_type = N_OSO then
|
||||
begin
|
||||
DwarfDebugMap.ObjectFile:=pchar(SymbolStr+SymbolArr^[i].n_un.n_strx);
|
||||
DwarfDebugMap.ObjFileAge:=SymbolArr^[i].n_value;
|
||||
inc(state);
|
||||
end;
|
||||
end;
|
||||
dtsObjectFile:
|
||||
begin
|
||||
if (SymbolArr^[i].n_type = N_BNSYM) then
|
||||
begin
|
||||
inc(state);
|
||||
end
|
||||
else if (SymbolArr^[i].n_type = N_STSYM) then
|
||||
begin
|
||||
AddressMap.NewAddr:=SymbolArr^[i].n_value;
|
||||
AddressMap.OrgAddr:=0;
|
||||
AddressMap.Length:=0;
|
||||
DwarfDebugMap.GlobalList.Add(pchar(SymbolStr+SymbolArr^[i].n_un.n_strx), AddressMap);
|
||||
end
|
||||
else if (SymbolArr^[i].n_type = N_SO) and (SymbolArr^[i].n_sect=1) then
|
||||
begin
|
||||
state := dtsEnd;
|
||||
SubFiles.AddObject(DwarfDebugMap.ObjectFile, DwarfDebugMap);
|
||||
DwarfDebugMap:=nil;
|
||||
end;
|
||||
end;
|
||||
dtsProc:
|
||||
begin
|
||||
if (SymbolArr^[i].n_type = N_FUN) and (SymbolArr^[i].n_sect=1) then
|
||||
begin
|
||||
AddressMap.NewAddr:=SymbolArr^[i].n_value;
|
||||
ProcName:=pchar(SymbolStr+SymbolArr^[i].n_un.n_strx);
|
||||
inc(state);
|
||||
end;
|
||||
end;
|
||||
dtsProcLen:
|
||||
begin
|
||||
if (SymbolArr^[i].n_type = N_FUN) and (SymbolArr^[i].n_sect=0) then
|
||||
begin
|
||||
AddressMap.Length:=SymbolArr^[i].n_value;
|
||||
inc(state);
|
||||
end;
|
||||
end;
|
||||
dtsProcEnd:
|
||||
begin
|
||||
if (SymbolArr^[i].n_type = N_ENSYM) and (SymbolArr^[i].n_sect=1) then
|
||||
begin
|
||||
DwarfDebugMap.GlobalList.Add(ProcName, AddressMap);
|
||||
state := dtsObjectFile;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TDbgMachoDataSource.ParseSubAppleDwarfDataMap(ADebugMap: TObject);
|
||||
var
|
||||
p: PDbgImageSection;
|
||||
ps: PDbgImageSection;
|
||||
SymbolArr: PnlistArray;
|
||||
SymbolStr: pointer;
|
||||
i: integer;
|
||||
SymbolCount: integer;
|
||||
MainDwarfDebugMap: TAppleDwarfDebugMap;
|
||||
ind: THTCustomNode;
|
||||
AddressMap: TDbgAddressMap;
|
||||
s: string;
|
||||
begin
|
||||
MainDwarfDebugMap:=TAppleDwarfDebugMap(ADebugMap);
|
||||
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 = N_SECT then
|
||||
begin
|
||||
s := pchar(SymbolStr+SymbolArr^[i].n_un.n_strx);
|
||||
ind := MainDwarfDebugMap.GlobalList.Find(s);
|
||||
if assigned(ind) then
|
||||
begin
|
||||
AddressMap:=MainDwarfDebugMap.GlobalList.Items[s];
|
||||
AddressMap.OrgAddr:=SymbolArr^[i].n_value;
|
||||
AddressMapList.Add(AddressMap);
|
||||
end;
|
||||
end;
|
||||
if SymbolArr^[i].n_type = N_SECT+N_EXT then
|
||||
begin
|
||||
s := pchar(SymbolStr+SymbolArr^[i].n_un.n_strx);
|
||||
ind := MainDwarfDebugMap.GlobalList.Find(s);
|
||||
if assigned(ind) then
|
||||
begin
|
||||
AddressMap:=MainDwarfDebugMap.GlobalList.Items[s];
|
||||
AddressMap.OrgAddr:=SymbolArr^[i].n_value;
|
||||
AddressMapList.Add(AddressMap);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
initialization
|
||||
RegisterImageReaderClass( TDbgMachoDataSource );
|
||||
|
||||
|
@ -60,7 +60,7 @@ type
|
||||
class function isValid(ASource: TDbgFileLoader): Boolean; override;
|
||||
class function UserName: AnsiString; override;
|
||||
public
|
||||
constructor Create(ASource: TDbgFileLoader; OwnSource: Boolean); override;
|
||||
constructor Create(ASource: TDbgFileLoader; ADebugMap: TObject; OwnSource: Boolean); override;
|
||||
destructor Destroy; override;
|
||||
procedure ParseSymbolTable(AfpSymbolInfo: TfpSymbolList); override;
|
||||
end;
|
||||
@ -92,7 +92,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
constructor TPEFileSource.Create(ASource: TDbgFileLoader; OwnSource: Boolean);
|
||||
constructor TPEFileSource.Create(ASource: TDbgFileLoader; ADebugMap: TObject; OwnSource: Boolean);
|
||||
begin
|
||||
FSections := TStringList.Create;
|
||||
FSections.Sorted := True;
|
||||
@ -102,7 +102,7 @@ begin
|
||||
FFileLoader:=ASource;
|
||||
FOwnLoader:=OwnSource;
|
||||
LoadSections;
|
||||
inherited Create(ASource, OwnSource);
|
||||
inherited Create(ASource, ADebugMap, OwnSource);
|
||||
end;
|
||||
|
||||
destructor TPEFileSource.Destroy;
|
||||
|
Loading…
Reference in New Issue
Block a user