FpDebug: On Windows the RelocationOffset can only be calculated after the file-header has been read. So the whole logic to obtain the RelocationOffset out of the LoadedTargetImageAddr and ImageBase is refactored

This commit is contained in:
Joost van der Sluis 2021-12-15 01:07:39 +01:00
parent e71c784ab0
commit 8205a04199
9 changed files with 102 additions and 58 deletions

View File

@ -466,7 +466,7 @@ type
procedure SetFileName(const AValue: String);
procedure SetMode(AMode: TFPDMode); experimental; // for testcase
public
constructor Create(const AProcess: TDbgProcess; ARelocationOffset: TDBGPtr = 0); virtual;
constructor Create(const AProcess: TDbgProcess); virtual;
destructor Destroy; override;
// Returns the addresses at the given source-filename and line-number.
@ -498,15 +498,10 @@ type
TDbgLibrary = class(TDbgInstance)
private
FModuleHandle: THandle;
FRelocationOffset: TDBGPtr;
public
constructor Create(const AProcess: TDbgProcess; const ADefaultName: String; const AModuleHandle: THandle; const ARelocationAddress: TDbgPtr);
constructor Create(const AProcess: TDbgProcess; const ADefaultName: String; const AModuleHandle: THandle);
property Name: String read FFileName;
property ModuleHandle: THandle read FModuleHandle;
// The relocationoffset is the offset at which the binary (most likely
// library) is loaded into memory. It is not part of the binary itself, unlike
// the BaseAddr.
property RelocationOffset: TDBGPtr read FRelocationOffset;
end;
TStartInstanceFlag = (siRediretOutput, siForceNewConsole);
@ -1637,11 +1632,11 @@ begin
Result := SymbolTableInfo.FindProcSymbol(AName);
end;
constructor TDbgInstance.Create(const AProcess: TDbgProcess; ARelocationOffset: TDBGPtr);
constructor TDbgInstance.Create(const AProcess: TDbgProcess);
begin
FProcess := AProcess;
FMemManager := AProcess.MemManager;
FLoaderList := TDbgImageLoaderList.Create(True, ARelocationOffset);
FLoaderList := TDbgImageLoaderList.Create(True);
inherited Create;
end;
@ -1725,12 +1720,11 @@ end;
{ TDbgLibrary }
constructor TDbgLibrary.Create(const AProcess: TDbgProcess; const ADefaultName: String; const AModuleHandle: THandle; const ARelocationAddress: TDbgPtr);
constructor TDbgLibrary.Create(const AProcess: TDbgProcess; const ADefaultName: String; const AModuleHandle: THandle);
begin
inherited Create(AProcess, ARelocationAddress);
inherited Create(AProcess);
FModuleHandle:=AModuleHandle;
FRelocationOffset:=ARelocationAddress;
end;
{ TDbgProcess }

View File

@ -14,6 +14,12 @@ type
TByteOrder = (boNone, boLSB, boMSB);
TOperatingSystem = (osNone, osBSD, osDarwin, osEmbedded, osLinux, osUnix, osMac, osWindows);
TDBGPtrSign = (sPositive, sNegative);
TDBGPtrOffset = record
Offset: Int64;
Sign: TDBGPtrSign;
end;
TTargetDescriptor = record
machineType: TMachineType;
bitness: TBitness;
@ -32,6 +38,8 @@ procedure SetCurrentFpDebugThreadIdForAssert(AnId: TThreadID);
property CurrentFpDebugThreadIdForAssert: TThreadID write SetCurrentFpDebugThreadIdForAssert;
{$ENDIF}
Operator + (Addr : QWord; Offset : TDBGPtrOffset) Res : QWord;
implementation
function hostDescriptor: TTargetDescriptor;
@ -58,6 +66,14 @@ begin
end;
end;
operator+(Addr: QWord; Offset: TDBGPtrOffset) Res: QWord;
begin
if Offset.Sign=sPositive then
Res := Addr + Offset.Offset
else
Res := Addr - Offset.Offset;
end;
{$IFDEF FPDEBUG_THREAD_CHECK}
var
FCurrentFpDebugThreadIdForAssert: TThreadID;

View File

@ -45,7 +45,7 @@ uses
Classes, Types, SysUtils, contnrs, Math, Maps, LazClasses, LazFileUtils,
{$ifdef FORCE_LAZLOGGER_DUMMY} LazLoggerDummy {$else} LazLoggerBase {$endif}, LazUTF8, lazCollections,
// FpDebug
FpDbgUtil, FpDbgInfo, FpDbgDwarfConst,
FpDbgUtil, FpDbgInfo, FpDbgDwarfConst, FpDbgCommon,
FpDbgLoader, FpImgReaderBase, FpdMemoryTools, FpErrorMessages, DbgIntfBaseTypes;
type
@ -757,7 +757,7 @@ type
FFiles: array of TDwarfDebugFile;
private
FImageBase: QWord;
FRelocationOffset: TDBGPtr;
FRelocationOffset: TDBGPtrOffset;
function GetCompilationUnit(AIndex: Integer): TDwarfCompilationUnit; inline;
protected
function GetCompilationUnitClass: TDwarfCompilationUnitClass; virtual;
@ -780,7 +780,7 @@ type
property CompilationUnits[AIndex: Integer]: TDwarfCompilationUnit read GetCompilationUnit;
property ImageBase: QWord read FImageBase;
property RelocationOffset: TDBGPtr read FRelocationOffset;
property RelocationOffset: TDBGPtrOffset read FRelocationOffset;
property WorkQueue: TFpGlobalThreadWorkerQueue read FWorkQueue;
end;

View File

@ -298,6 +298,8 @@ type
function GetStackPointerRegisterValue: TDbgPtr; override;
end;
tDbgLinuxLibrary = class;
{ TDbgLinuxProcess }
TDbgLinuxProcess = class(TDbgProcess)
@ -337,7 +339,7 @@ type
function SynchronizeProcMapsWithLibraryList: TFPDEvent;
// Scan /proc/[pid]/maps and return the results
function ObtainProcMaps: TDbgLinuxMemoryMappingList;
procedure AddLib(const ALibrary: TDbgLibrary);
procedure AddLib(const ALibrary: tDbgLinuxLibrary);
public
class function isSupported(ATargetInfo: TTargetDescriptor): boolean; override;
constructor Create(const AFileName: string; AnOsClasses: TOSDbgClasses; AMemManager: TFpDbgMemManager; AProcessConfig: TDbgProcessConfig = nil); override;
@ -372,9 +374,10 @@ type
tDbgLinuxLibrary = class(TDbgLibrary)
protected
FLoadedTargetImageAddr: TDbgPtr;
procedure InitializeLoaders; override;
public
constructor Create(const AProcess: TDbgProcess; const AFileName: string; const AModuleHandle: THandle; const ARelocationAddress: TDbgPtr);
constructor Create(const AProcess: TDbgProcess; const AFileName: string; const AModuleHandle: THandle; const ALoadedTargetImageAddr: TDbgPtr);
end;
@ -396,7 +399,7 @@ procedure tDbgLinuxLibrary.InitializeLoaders;
var
Loader: TDbgImageLoader;
begin
Loader := TDbgImageLoader.Create(Name, nil, LoaderList.RelocationOffset);
Loader := TDbgImageLoader.Create(Name, nil, FLoadedTargetImageAddr);
// The dynamic-loader (dl) on Linux also loads other stuff then ELF-
// formatted libraries.
// So it is reasonable likely that the loaded 'library' can not be handled
@ -407,9 +410,10 @@ begin
Loader.Free;
end;
constructor tDbgLinuxLibrary.Create(const AProcess: TDbgProcess; const AFileName: string; const AModuleHandle: THandle; const ARelocationAddress: TDbgPtr);
constructor tDbgLinuxLibrary.Create(const AProcess: TDbgProcess; const AFileName: string; const AModuleHandle: THandle; const ALoadedTargetImageAddr: TDbgPtr);
begin
Inherited Create(AProcess, AFileName, AModuleHandle, ARelocationAddress);
FLoadedTargetImageAddr := ALoadedTargetImageAddr;
Inherited Create(AProcess, AFileName, AModuleHandle);
SetFileName(AFileName);
LoadInfo;
@ -1071,11 +1075,11 @@ begin
end;
end;
procedure TDbgLinuxProcess.AddLib(const ALibrary: TDbgLibrary);
procedure TDbgLinuxProcess.AddLib(const ALibrary: tDbgLinuxLibrary);
var
ID: TDbgPtr;
begin
ID := ALibrary.RelocationOffset;
ID := ALibrary.FLoadedTargetImageAddr;
FLibMap.Add(ID, ALibrary);
if (ALibrary.DbgInfo.HasInfo) or (ALibrary.SymbolTableInfo.HasInfo) then
FSymInstances.Add(ALibrary);

View File

@ -62,6 +62,7 @@ type
FImgReader: TDbgImageReader;
function GetAddressMapList: TDbgAddressMapList;
function GetImageBase: QWord;
function GetRelocationOffset: TDBGPtrOffset;
function GetReaderErrors: String;
function GetSubFiles: TStrings;
function GetTargetInfo: TTargetDescriptor;
@ -73,10 +74,10 @@ type
public
constructor Create; virtual;
constructor Create(AFileName: String; ADebugMap: TObject = nil;
ARelocationOffset: TDBGPtr = 0);
ALoadedTargetImageAddr: TDBGPtr = 0);
{$ifdef USE_WIN_FILE_MAPPING}
constructor Create(AFileHandle: THandle; ADebugMap: TObject = nil;
ARelocationOffset: TDBGPtr = 0);
ALoadedTargetImageAddr: TDBGPtr = 0);
{$endif}
destructor Destroy; override;
procedure ParseSymbolTable(AFpSymbolInfo: TfpSymbolList); virtual;
@ -85,6 +86,7 @@ type
function IsValid: Boolean;
property FileName: String read FFileName; // Empty if using USE_WIN_FILE_MAPPING
property ImageBase: QWord read GetImageBase;
property RelocationOffset: TDBGPtrOffset read GetRelocationOffset;
property TargetInfo: TTargetDescriptor read GetTargetInfo;
property UUID: TGuid read GetUUID;
@ -110,16 +112,15 @@ type
TDbgImageLoaderList = class(TFPObjectList)
private
FRelocationOffset: TDBGPtr;
function GetRelocationOffset: TDBGPtrOffset;
function GetImageBase: QWord;
function GetTargetInfo: TTargetDescriptor;
function GetItem(Index: Integer): TDbgImageLoader;
procedure SetItem(Index: Integer; AValue: TDbgImageLoader);
public
constructor Create(FreeObjects : Boolean; ARelocationOffset: TDbgPtr);
property Items[Index: Integer]: TDbgImageLoader read GetItem write SetItem; default;
property ImageBase: QWord read GetImageBase;
property RelocationOffset: QWord read FRelocationOffset;
property RelocationOffset: TDBGPtrOffset read GetRelocationOffset;
property TargetInfo: TTargetDescriptor read GetTargetInfo;
end;
@ -127,6 +128,17 @@ implementation
{ TDbgImageLoaderList }
function TDbgImageLoaderList.GetRelocationOffset: TDBGPtrOffset;
begin
if Count>0 then
result := Items[0].RelocationOffset
else
begin
Result.Offset := 0;
Result.Sign := sPositive;
end;
end;
function TDbgImageLoaderList.GetImageBase: QWord;
begin
if Count>0 then
@ -153,12 +165,6 @@ begin
inherited SetItem(Index, AValue);
end;
constructor TDbgImageLoaderList.Create(FreeObjects: Boolean; ARelocationOffset: TDbgPtr);
begin
inherited Create(FreeObjects);
FRelocationOffset := ARelocationOffset;
end;
{ TDbgImageLoaderLibrary }
procedure TDbgImageLoaderLibrary.ParseSymbolTable(AFpSymbolInfo: TfpSymbolList);
@ -194,6 +200,17 @@ begin
Result := 0;
end;
function TDbgImageLoader.GetRelocationOffset: TDBGPtrOffset;
begin
if Assigned(FImgReader) then
Result := FImgReader.RelocationOffset
else
begin
Result.Offset := 0;
Result.Sign := sPositive;
end;
end;
function TDbgImageLoader.GetReaderErrors: String;
begin
if FImgReader <> nil then
@ -238,21 +255,21 @@ begin
end;
constructor TDbgImageLoader.Create(AFileName: String; ADebugMap: TObject;
ARelocationOffset: TDBGPtr);
ALoadedTargetImageAddr: TDBGPtr);
begin
FFileName := AFileName;
FFileLoader := TDbgFileLoader.Create(AFileName);
FImgReader := GetImageReader(FFileLoader, ADebugMap, ARelocationOffset, False);
FImgReader := GetImageReader(FFileLoader, ADebugMap, ALoadedTargetImageAddr, False);
if not Assigned(FImgReader) then
FreeAndNil(FFileLoader);
end;
{$ifdef USE_WIN_FILE_MAPPING}
constructor TDbgImageLoader.Create(AFileHandle: THandle; ADebugMap: TObject;
ARelocationOffset: TDBGPtr);
ALoadedTargetImageAddr: TDBGPtr);
begin
FFileLoader := TDbgFileLoader.Create(AFileHandle);
FImgReader := GetImageReader(FFileLoader, ADebugMap, ARelocationOffset, False);
FImgReader := GetImageReader(FFileLoader, ADebugMap, ALoadedTargetImageAddr, False);
if not Assigned(FImgReader) then
FreeAndNil(FFileLoader);
end;

View File

@ -229,7 +229,7 @@ type
procedure InitializeLoaders; override;
public
constructor Create(const AProcess: TDbgProcess; const ADefaultName: String;
const AModuleHandle: THandle; const ABaseAddr: TDbgPtr; AInfo: TLoadDLLDebugInfo);
const AModuleHandle: THandle; AInfo: TLoadDLLDebugInfo);
end;
@ -451,11 +451,11 @@ end;
constructor tDbgWinLibrary.Create(const AProcess: TDbgProcess;
const ADefaultName: String; const AModuleHandle: THandle;
const ABaseAddr: TDbgPtr; AInfo: TLoadDLLDebugInfo);
AInfo: TLoadDLLDebugInfo);
var
S: String;
begin
inherited Create(AProcess, ADefaultName, AModuleHandle, ABaseAddr);
inherited Create(AProcess, ADefaultName, AModuleHandle);
FInfo := AInfo;
s := TDbgWinProcess(AProcess).GetProcFilename(AProcess, AInfo.lpImageName, AInfo.fUnicode, AInfo.hFile);
@ -481,7 +481,7 @@ procedure TDbgWinProcess.InitializeLoaders;
var
Loader: TDbgImageLoader;
begin
Loader := TDbgImageLoader.Create(FInfo.hFile);
Loader := TDbgImageLoader.Create(FInfo.hFile, nil, TDbgPtr(FInfo.lpBaseOfImage));
if Loader.IsValid then
Loader.AddToLoaderList(LoaderList)
else
@ -1389,7 +1389,7 @@ function TDbgWinProcess.AddLib(const AInfo: TLoadDLLDebugInfo): TDbgLibrary;
var
ID: TDbgPtr;
begin
Result := TDbgWinLibrary.Create(Self, HexValue(AInfo.lpBaseOfDll, SizeOf(Pointer), [hvfIncludeHexchar]), AInfo.hFile, TDbgPtr(AInfo.lpBaseOfDll), AInfo);
Result := TDbgWinLibrary.Create(Self, HexValue(AInfo.lpBaseOfDll, SizeOf(Pointer), [hvfIncludeHexchar]), AInfo.hFile, AInfo);
ID := TDbgPtr(AInfo.lpBaseOfDll);
FLibMap.Add(ID, Result);
if (Result.DbgInfo.HasInfo) or (Result.SymbolTableInfo.HasInfo)

View File

@ -97,7 +97,8 @@ type
private
FImageBase: QWord;
FImageSize: QWord;
FRelocationOffset: TDBGPtr;
FRelocationOffset: TDBGPtrOffset;
FLoadedTargetImageAddr: TDBGPtr;
FReaderErrors: String;
FUUID: TGuid;
protected
@ -109,15 +110,17 @@ type
procedure SetUUID(AGuid: TGuid);
procedure SetImageBase(ABase: QWord);
procedure SetImageSize(ASize: QWord);
procedure SetRelocationOffset(AnOffset: TDBGPtr; Sign: TDBGPtrSign);
procedure AddReaderError(AnError: String);
function ReadGnuDebugLinkSection(out AFileName: String; out ACrc: Cardinal): Boolean;
function LoadGnuDebugLink(ASearchPath, AFileName: String; ACrc: Cardinal): TDbgFileLoader;
property LoadedTargetImageAddr: TDBGPtr read FLoadedTargetImageAddr;
public
class function isValid(ASource: TDbgFileLoader): Boolean; virtual; abstract;
class function UserName: AnsiString; virtual; abstract;
procedure ParseSymbolTable(AFpSymbolInfo: TfpSymbolList); virtual;
procedure ParseLibrarySymbolTable(AFpSymbolInfo: TfpSymbolList); virtual;
constructor Create({%H-}ASource: TDbgFileLoader; {%H-}ADebugMap: TObject; ARelocationOffset: TDbgPtr; OwnSource: Boolean); virtual;
constructor Create({%H-}ASource: TDbgFileLoader; {%H-}ADebugMap: TObject; ALoadedTargetImageAddr: TDbgPtr; OwnSource: Boolean); virtual;
procedure AddSubFilesToLoaderList(ALoaderList: TObject; PrimaryLoader: TObject); virtual;
// The ImageBase is the address at which the linker assumed the binary will be
// loaded. So it is stored inside the binary itself, in contrast to the
@ -125,6 +128,10 @@ type
// been loaded into another position.
property ImageBase: QWord read FImageBase;
property ImageSize: QWord read FImageSize;
// The relocationoffset is the offset at which the binary (most likely
// library) is loaded into memory. It is not part of the binary itself, unlike
// the BaseAddr.
property RelocationOffset: TDBGPtrOffset read FRelocationOffset;
property TargetInfo: TTargetDescriptor read FTargetInfo;
@ -134,15 +141,10 @@ type
property SubFiles: TStrings read GetSubFiles;
property AddressMapList: TDbgAddressMapList read GetAddressMapList;
property ReaderErrors: String read FReaderErrors;
// The relocationoffset is the offset at which the binary (most likely
// library) is loaded into memory. It is not part of the binary itself, unlike
// the BaseAddr.
property RelocationOffset: TDBGPtr read FRelocationOffset;
end;
TDbgImageReaderClass = class of TDbgImageReader;
function GetImageReader(ASource: TDbgFileLoader; ADebugMap: TObject; ARelocationOffset: TDbgPtr; OwnSource: Boolean): TDbgImageReader; overload;
function GetImageReader(ASource: TDbgFileLoader; ADebugMap: TObject; ALoadedTargetImageAddr: TDbgPtr; OwnSource: Boolean): TDbgImageReader; overload;
procedure RegisterImageReaderClass(DataSource: TDbgImageReaderClass);
implementation
@ -184,7 +186,7 @@ end;
result := (r1.OrgAddr=r2.OrgAddr) and (r1.Length=r2.Length) and (r1.NewAddr=r2.NewAddr);
end;
function GetImageReader(ASource: TDbgFileLoader; ADebugMap: TObject; ARelocationOffset: TDbgPtr; OwnSource: Boolean): TDbgImageReader;
function GetImageReader(ASource: TDbgFileLoader; ADebugMap: TObject; ALoadedTargetImageAddr: TDbgPtr; OwnSource: Boolean): TDbgImageReader;
var
i : Integer;
cls : TDbgImageReaderClass;
@ -196,7 +198,7 @@ begin
cls := TDbgImageReaderClass(RegisteredImageReaderClasses[i]);
try
if cls.isValid(ASource) then begin
Result := cls.Create(ASource, ADebugMap, ARelocationOffset, OwnSource);
Result := cls.Create(ASource, ADebugMap, ALoadedTargetImageAddr, OwnSource);
ASource.Close;
Exit;
end
@ -418,6 +420,12 @@ begin
FImageSize := ASize;
end;
procedure TDbgImageReader.SetRelocationOffset(AnOffset: TDBGPtr; Sign: TDBGPtrSign);
begin
FRelocationOffset.Offset := AnOffset;
FRelocationOffset.Sign := Sign;
end;
procedure TDbgImageReader.AddReaderError(AnError: String);
begin
if FReaderErrors <> '' then
@ -503,10 +511,10 @@ begin
//
end;
constructor TDbgImageReader.Create(ASource: TDbgFileLoader; ADebugMap: TObject; ARelocationOffset: TDbgPtr; OwnSource: Boolean);
constructor TDbgImageReader.Create(ASource: TDbgFileLoader; ADebugMap: TObject; ALoadedTargetImageAddr: TDbgPtr; OwnSource: Boolean);
begin
inherited Create;
FRelocationOffset := ARelocationOffset;
FLoadedTargetImageAddr := ALoadedTargetImageAddr;
end;
procedure TDbgImageReader.AddSubFilesToLoaderList(ALoaderList: TObject;

View File

@ -411,6 +411,8 @@ begin
//FSections.Duplicates := dupError;
FSections.CaseSensitive := False;
SetRelocationOffset(ALoadedTargetImageAddr, sPositive);
FFileLoader := ASource;
fOwnSource := OwnSource;
fElfFile := TElfFile.Create;

View File

@ -66,7 +66,7 @@ type
class function isValid(ASource: TDbgFileLoader): Boolean; override;
class function UserName: AnsiString; override;
public
constructor Create(ASource: TDbgFileLoader; ADebugMap: TObject; ARelocationOffset: TDbgPtr; OwnSource: Boolean); override;
constructor Create(ASource: TDbgFileLoader; ADebugMap: TObject; ALoadedTargetImageAddr: TDbgPtr; OwnSource: Boolean); override;
destructor Destroy; override;
procedure ParseSymbolTable(AfpSymbolInfo: TfpSymbolList); override;
procedure ParseLibrarySymbolTable(AFpSymbolInfo: TfpSymbolList); override;
@ -105,13 +105,13 @@ begin
end;
end;
constructor TPEFileSource.Create(ASource: TDbgFileLoader; ADebugMap: TObject; ARelocationOffset: TDbgPtr; OwnSource: Boolean);
constructor TPEFileSource.Create(ASource: TDbgFileLoader; ADebugMap: TObject; ALoadedTargetImageAddr: TDbgPtr; OwnSource: Boolean);
var
crc: cardinal;
DbgFileName, SourceFileName: String;
NewFileLoader: TDbgFileLoader;
begin
inherited Create(ASource, ADebugMap, ARelocationOffset, OwnSource);
inherited Create(ASource, ADebugMap, ALoadedTargetImageAddr, OwnSource);
FSections := TStringListUTF8Fast.Create;
FSections.Sorted := False; // need sections in original order / Symbols use "SectionNumber"
//FSections.Duplicates := dupError;
@ -231,7 +231,6 @@ begin
if ImageBase = 0 then
exit;
SetImageBase(ImageBase);
FFileLoader.LoadMemory(0, 1, hBase); // size does not matter, only obtain address
if (hBase = nil) or (hBase^.e_magic <> IMAGE_DOS_SIGNATURE) then
exit;
@ -457,6 +456,10 @@ begin
SetImageBase(NtHeaders.W32.OptionalHeader.ImageBase);
SetImageSize(NtHeaders.W32.OptionalHeader.SizeOfImage);
end;
if LoadedTargetImageAddr >= ImageBase then
SetRelocationOffset(LoadedTargetImageAddr-ImageBase, sPositive)
else
SetRelocationOffset(ImageBase-LoadedTargetImageAddr, sNegative);
FCodeBase := NtHeaders.W32.OptionalHeader.BaseOfCode;
SectionMax := FFileLoader.LoadMemory(
DosHeader.e_lfanew +