diff --git a/components/fpdebug/fpdbgclasses.pp b/components/fpdebug/fpdbgclasses.pp index 0cdf955475..d667da22f4 100644 --- a/components/fpdebug/fpdbgclasses.pp +++ b/components/fpdebug/fpdbgclasses.pp @@ -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; diff --git a/components/fpdebug/fpdbgloader.pp b/components/fpdebug/fpdbgloader.pp index d009b454b2..dd3e4340e3 100644 --- a/components/fpdebug/fpdbgloader.pp +++ b/components/fpdebug/fpdbgloader.pp @@ -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; diff --git a/components/fpdebug/fpimgreaderbase.pas b/components/fpdebug/fpimgreaderbase.pas index 8d4d48da56..d8c3de9d98 100644 --- a/components/fpdebug/fpimgreaderbase.pas +++ b/components/fpdebug/fpimgreaderbase.pas @@ -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; diff --git a/components/fpdebug/fpimgreaderelf.pas b/components/fpdebug/fpimgreaderelf.pas index 4a656a1ad0..4d8b4edea5 100644 --- a/components/fpdebug/fpimgreaderelf.pas +++ b/components/fpdebug/fpimgreaderelf.pas @@ -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; diff --git a/components/fpdebug/fpimgreadermacho.pas b/components/fpdebug/fpimgreadermacho.pas index b647faa1bf..6661cacbe7 100644 --- a/components/fpdebug/fpimgreadermacho.pas +++ b/components/fpdebug/fpimgreadermacho.pas @@ -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; diff --git a/components/fpdebug/fpimgreaderwinpe.pas b/components/fpdebug/fpimgreaderwinpe.pas index 4bf8aa54c6..bc01db92a5 100644 --- a/components/fpdebug/fpimgreaderwinpe.pas +++ b/components/fpdebug/fpimgreaderwinpe.pas @@ -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);