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:
joost 2015-04-25 19:15:09 +00:00
parent 77b0466028
commit c53e775af5
7 changed files with 379 additions and 25 deletions

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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 );

View File

@ -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;