Added functionality to mark sections as loadable based on section information.

This commit is contained in:
ccrause 2021-11-01 12:11:48 +02:00
parent e524997317
commit 5d14d15403
6 changed files with 107 additions and 13 deletions

View File

@ -473,6 +473,7 @@ type
property Mode: TFPDMode read FMode;
property PointerSize: Integer read GetPointerSize;
property MemManager: TFpDbgMemManager read FMemManager;
property LoaderList: TDbgImageLoaderList read FLoaderList write FLoaderList;
end;
{ TDbgLibrary }
@ -656,6 +657,7 @@ public
procedure ThreadsBeforeContinue;
procedure ThreadsClearCallStack;
procedure LoadInfo; override;
procedure InitializeLoaders; override;
function WriteData(const AAdress: TDbgPtr; const ASize: Cardinal; const AData): Boolean; virtual;
// Modify the debugee's code.
@ -2224,6 +2226,11 @@ begin
FSymInstances.Add(Self);
end;
procedure TDbgProcess.InitializeLoaders;
begin
inherited InitializeLoaders;
end;
function TDbgProcess.GetLastEventProcessIdentifier: THandle;
begin
result := 0;

View File

@ -68,6 +68,7 @@ type
protected
FImageBase: QWord unimplemented;
function GetSection(const AName: String): PDbgImageSection; virtual;
function GetSection(const ID: integer): PDbgImageSection; virtual;
property ImgReader: TDbgImageReader read FImgReader write FImgReader;
public
constructor Create; virtual;
@ -88,6 +89,7 @@ type
property UUID: TGuid read GetUUID;
property Section[const AName: String]: PDbgImageSection read GetSection;
property SectionByID[const ID: integer]: 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;
@ -205,6 +207,14 @@ begin
Result := nil;
end;
function TDbgImageLoader.GetSection(const ID: integer): PDbgImageSection;
begin
if FImgReader <> nil then
Result := FImgReader.SectionByID[ID]
else
Result := nil;
end;
constructor TDbgImageLoader.Create;
begin
inherited Create;

View File

@ -21,6 +21,10 @@ type
RawData: Pointer;
Size: QWord;
VirtualAddress: QWord;
// Use this flag to identify sections that should be uploaded via RSP
// This is probably only relevant for uploads to low level targets (embedded, FreeRTOS...)
IsLoadable: Boolean;
Name: String;
end;
PDbgImageSection = ^TDbgImageSection;
@ -101,6 +105,7 @@ type
function GetSubFiles: TStrings; virtual;
function GetAddressMapList: TDbgAddressMapList; virtual;
function GetSection(const AName: String): PDbgImageSection; virtual; abstract;
function GetSection(const ID: integer): PDbgImageSection; virtual; abstract;
procedure SetUUID(AGuid: TGuid);
procedure SetImageBase(ABase: QWord);
procedure SetImageSize(ASize: QWord);
@ -122,6 +127,7 @@ type
property UUID: TGuid read FUUID;
property Section[const AName: String]: PDbgImageSection read GetSection;
property SectionByID[const ID: integer]: PDbgImageSection read GetSection;
property SubFiles: TStrings read GetSubFiles;
property AddressMapList: TDbgAddressMapList read GetAddressMapList;
property ReaderErrors: String read FReaderErrors;

View File

@ -39,10 +39,12 @@ uses
type
TElfSection = packed record
name : AnsiString;
FileOfs : QWord;
Address : QWord;
Size : QWord;
name : AnsiString;
FileOfs : QWord;
Address : QWord;
Size : QWord;
SectionType : QWord;
Flags : QWord;
end;
PElfSection = ^TElfSection;
@ -55,7 +57,7 @@ type
protected
function Load32BitFile(ALoader: TDbgFileLoader): Boolean;
function Load64BitFile(ALoader: TDbgFileLoader): Boolean;
procedure AddSection(const name: AnsiString; FileOffset, Address, Size: Qword);
procedure AddSection(const name: AnsiString; FileOffset, Address, Size, SectionType, Flags: Qword);
public
sections : array of TElfSection;
seccount : Integer;
@ -73,6 +75,7 @@ type
fElfFile : TElfFile;
protected
function GetSection(const AName: String): PDbgImageSection; override;
function GetSection(const ID: integer): PDbgImageSection; override;
procedure LoadSections;
procedure ClearSections;
public
@ -185,7 +188,7 @@ begin
for i := 0 to hdr.e_shnum - 1 do
with sect[i] do begin
nm := PChar( @strs[sh_name] );
AddSection(nm, sh_offset, sh_addr, sh_size );
AddSection(nm, sh_offset, sh_addr, sh_size, sh_type, sh_flags);
end;
end;
@ -224,12 +227,12 @@ begin
for i := 0 to hdr.e_shnum - 1 do
with sect[i] do begin
nm := PChar( @strs[sh_name] );
AddSection(nm, sh_offset, sh_address, sh_size );
AddSection(nm, sh_offset, sh_address, sh_size, sh_type, sh_flags);
end;
end;
procedure TElfFile.AddSection(const name: AnsiString; FileOffset, Address,
Size: Qword);
Size, SectionType, Flags: Qword);
begin
if seccount=Length(sections) then begin
if seccount = 0 then SetLength(sections, 4)
@ -239,6 +242,8 @@ begin
sections[seccount].name:=name;
sections[seccount].FileOfs:=FileOffset;
sections[seccount].Size:=Size;
sections[seccount].SectionType:=SectionType;
sections[seccount].Flags:=Flags;
inc(seccount);
end;
@ -319,6 +324,25 @@ begin
FFileLoader.LoadMemory(ex^.Offs, Result^.Size, Result^.RawData);
end;
function TElfDbgSource.GetSection(const ID: integer): PDbgImageSection;
var
ex: PDbgImageSectionEx;
begin
if (ID >= 0) and (ID < FSections.Count) then
begin
ex := PDbgImageSectionEx(FSections.Objects[ID]);
Result := @ex^.Sect;
Result^.Name := FSections[ID];
if not ex^.Loaded then
begin
FFileLoader.LoadMemory(ex^.Offs, Result^.Size, Result^.RawData);
ex^.Loaded := True;
end;
end
else
Result := nil;
end;
procedure TElfDbgSource.LoadSections;
var
p: PDbgImageSectionEx;
@ -333,6 +357,8 @@ begin
P^.Offs := fs.FileOfs;
p^.Sect.Size := fs.Size;
p^.Sect.VirtualAddress := fs.Address; //0; // Todo? fs.Address - ImageBase
p^.Sect.IsLoadable := ((fs.SectionType and SHT_PROGBITS) > 0) and ((fs.Flags and SHF_ALLOC) > 0) and
((fs.SectionType and SHT_NOBITS) = 0);
p^.Loaded := False;
FSections.Objects[idx] := TObject(p);
end;

View File

@ -38,6 +38,7 @@ type
function GetSectionIndex(const SectionName: AnsiString): Integer;
function GetSection(const AName: String): PDbgImageSection; override;
function GetSection(const ID: integer): PDbgImageSection; override;
public
class function isValid(ASource: TDbgFileLoader): Boolean; override;
class function UserName: AnsiString; override;
@ -341,6 +342,25 @@ begin
fSource.LoadMemory(ex^.Offs, Result^.Size, Result^.RawData);
end;
function TDbgMachoDataSource.GetSection(const ID: integer): PDbgImageSection;
var
ex: PDbgImageSectionEx;
begin
if (ID >= 0) and (ID < FSections.Count) then
begin
ex := PDbgImageSectionEx(FSections.Objects[ID]);
Result := @ex^.Sect;
Result^.Name := FSections[ID];
if not ex^.Loaded then
begin
ex^.Loaded := True;
fSource.LoadMemory(ex^.Offs, Result^.Size, Result^.RawData);
end;
end
else
Result := nil;
end;
procedure TDbgMachoDataSource.AddSubFilesToLoaderList(ALoaderList: TObject;
PrimaryLoader: TObject);
var
@ -428,6 +448,7 @@ begin
end;
p^.Sect.VirtualAddress := 0; // Todo?
p^.Sect.IsLoadable := False; // Todo - needed for remote uploads via RSP only
p^.Loaded := False;
FSections.AddObject(Name, TObject(p));
end;

View File

@ -56,6 +56,7 @@ type
FCodeBase : DWord;
protected
function GetSection(const AName: String): PDbgImageSection; override;
function GetSection(const ID: integer): PDbgImageSection; override;
function GetSection(const AVirtAddr: QWord): PDbgImageSection;
function MapVirtAddressToSection(AVirtAddr: Pointer): Pointer;
@ -310,6 +311,25 @@ begin
FFileLoader.LoadMemory(ex^.Offs, Result^.Size, Result^.RawData);
end;
function TPEFileSource.GetSection(const ID: integer): PDbgImageSection;
var
ex: PDbgImageSectionEx;
begin
if (ID >= 0) and (ID < FSections.Count) then
begin
ex := PDbgImageSectionEx(FSections.Objects[ID]);
Result := @ex^.Sect;
Result^.Name := FSections[ID];
if not ex^.Loaded then
begin
ex^.Loaded := True;
FFileLoader.LoadMemory(ex^.Offs, Result^.Size, Result^.RawData);
end;
end
else
Result := nil;
end;
function TPEFileSource.GetSection(const AVirtAddr: QWord): PDbgImageSection;
var
i: Integer;
@ -347,7 +367,8 @@ end;
procedure TPEFileSource.LoadSections;
procedure Add(const AName: String; ARawData: QWord; ASize: QWord; AVirtualAdress: QWord);
procedure Add(const AName: String; ARawData: QWord; ASize: QWord; AVirtualAdress: QWord;
AIsLoadable: boolean);
var
p: PDbgImageSectionEx;
idx: integer;
@ -357,6 +378,7 @@ procedure TPEFileSource.LoadSections;
P^.Offs := ARawData;
p^.Sect.Size := ASize;
p^.Sect.VirtualAddress := AVirtualAdress;
p^.Sect.IsLoadable := AIsLoadable; // Could also default to false since it isn't currently used
p^.Loaded := False;
FSections.Objects[idx] := TObject(p);
end;
@ -461,21 +483,23 @@ begin
NTHeaders.Sys.FileHeader.NumberOfSymbols * IMAGE_SIZEOF_SYMBOL +
StrToIntDef(PChar(@SectionName[1]), 0), 255, @s[1]);
s[Min(i, 255)] := #0;
Add(pchar(@s[1]), SectionHeader[n].PointerToRawData, SectionHeader[n].Misc.VirtualSize, SectionHeader[n].VirtualAddress);
Add(pchar(@s[1]), SectionHeader[n].PointerToRawData, SectionHeader[n].Misc.VirtualSize, SectionHeader[n].VirtualAddress,
not((SectionHeader[n].Characteristics and (IMAGE_SCN_CNT_CODE or IMAGE_SCN_CNT_INITIALIZED_DATA)) = 0));
end
else begin
// short name
Add(SectionName, SectionHeader[n].PointerToRawData, SectionHeader[n].Misc.VirtualSize, SectionHeader[n].VirtualAddress);
Add(SectionName, SectionHeader[n].PointerToRawData, SectionHeader[n].Misc.VirtualSize, SectionHeader[n].VirtualAddress,
not((SectionHeader[n].Characteristics and (IMAGE_SCN_CNT_CODE or IMAGE_SCN_CNT_INITIALIZED_DATA)) = 0));
end
end;
// Create a fake-sections for the symbol-table:
if NtHeaders.Sys.FileHeader.PointerToSymbolTable<>0 then
begin
Add(_symbol,NtHeaders.Sys.FileHeader.PointerToSymbolTable, NtHeaders.Sys.FileHeader.NumberOfSymbols*IMAGE_SIZEOF_SYMBOL,0);
Add(_symbol,NtHeaders.Sys.FileHeader.PointerToSymbolTable, NtHeaders.Sys.FileHeader.NumberOfSymbols*IMAGE_SIZEOF_SYMBOL,0,false);
StringTableStart:=NtHeaders.Sys.FileHeader.PointerToSymbolTable+NtHeaders.Sys.FileHeader.NumberOfSymbols*IMAGE_SIZEOF_SYMBOL;
FFileLoader.Read(StringTableStart, sizeof(DWord), @StringTableLen);
Add(_symbolstrings,StringTableStart, StringTableLen, 0);
Add(_symbolstrings,StringTableStart, StringTableLen, 0,false);
end;
FFileLoader.UnloadMemory(SectionHeader);