mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-16 19:29:34 +02:00
FPDebug: refactored reading image-file, ported elf reader from duby
git-svn-id: trunk@42925 -
This commit is contained in:
parent
ff8b5f7a1b
commit
b37ec153f8
5
.gitattributes
vendored
5
.gitattributes
vendored
@ -1192,6 +1192,7 @@ components/fpcunit/languages/guitestrunner.pt_BR.po svneol=native#text/plain
|
||||
components/fpcunit/languages/guitestrunner.ru.po svneol=native#text/plain
|
||||
components/fpcunit/languages/guitestrunner.uk.po svneol=native#text/plain
|
||||
components/fpcunit/lib/README.txt svneol=native#text/plain
|
||||
components/fpdebug/README_DUBY.txt svneol=native#text/pascal
|
||||
components/fpdebug/app/fpd/README.txt svneol=native#text/plain
|
||||
components/fpdebug/app/fpd/fpd.lpi svneol=native#text/pascal
|
||||
components/fpdebug/app/fpd/fpd.lpr svneol=native#text/pascal
|
||||
@ -1213,6 +1214,10 @@ components/fpdebug/fpdbgutil.pp svneol=native#text/pascal
|
||||
components/fpdebug/fpdbgwinextra.pp svneol=native#text/pascal
|
||||
components/fpdebug/fpdebug.lpk svneol=native#text/pascal
|
||||
components/fpdebug/fpdebug.pas svneol=native#text/pascal
|
||||
components/fpdebug/fpimgreaderelf.pas svneol=native#text/pascal
|
||||
components/fpdebug/fpimgreaderelftypes.pas svneol=native#text/pascal
|
||||
components/fpdebug/fpimgreaderwinpe.pas svneol=native#text/pascal
|
||||
components/fpdebug/fpimgreaderwinpetypes.pas svneol=native#text/pascal
|
||||
components/fpdebug/test/asmtest.lpi svneol=native#text/plain
|
||||
components/fpdebug/test/asmtest.lpr svneol=native#text/pascal
|
||||
components/fpdebug/test/asmtestunit.lfm svneol=native#text/plain
|
||||
|
7
components/fpdebug/README_DUBY.txt
Normal file
7
components/fpdebug/README_DUBY.txt
Normal file
@ -0,0 +1,7 @@
|
||||
Some parts of this package were ported from (or based on) DUBY:
|
||||
|
||||
http://sourceforge.net/projects/duby/
|
||||
|
||||
For details the svn log
|
||||
|
||||
Many thanks to Dmitry Boyarintsev for his work on Duby
|
@ -37,7 +37,7 @@ interface
|
||||
|
||||
uses
|
||||
{$ifdef windows}
|
||||
Windows,
|
||||
Windows, FpImgReaderWinPE,
|
||||
{$endif}
|
||||
Classes, Maps, FpDbgUtil, FpDbgWinExtra, FpDbgLoader, LazLoggerBase;
|
||||
|
||||
@ -384,7 +384,7 @@ end;
|
||||
|
||||
procedure TDbgInstance.LoadInfo;
|
||||
begin
|
||||
FLoader := TDbgWinPEImageLoader.Create(FModuleHandle);
|
||||
FLoader := TDbgImageLoader.Create(FModuleHandle);
|
||||
FDbgInfo := TDbgDwarf.Create(FLoader);
|
||||
TDbgDwarf(FDbgInfo).LoadCompilationUnits;
|
||||
end;
|
||||
|
@ -1705,15 +1705,18 @@ end;
|
||||
|
||||
function TDbgDwarf.LoadCompilationUnits: Integer;
|
||||
var
|
||||
p: Pointer;
|
||||
p, pe: Pointer;
|
||||
CU32: PDwarfCUHeader32 absolute p;
|
||||
CU64: PDwarfCUHeader64 absolute p;
|
||||
CU: TDwarfCompilationUnit;
|
||||
CUClass: TDwarfCompilationUnitClass;
|
||||
inf: TDwarfSectionInfo;
|
||||
begin
|
||||
CUClass := GetCompilationUnitClass;
|
||||
inf := FSections[dsInfo];
|
||||
p := FSections[dsInfo].RawData;
|
||||
while p <> nil do
|
||||
pe := inf.RawData + inf.Size;
|
||||
while (p <> nil) and (p < pe) do
|
||||
begin
|
||||
if CU64^.Signature = DWARF_HEADER64_SIGNATURE
|
||||
then begin
|
||||
|
@ -6,6 +6,8 @@
|
||||
|
||||
This unit contains helper classes for loading secions form images.
|
||||
|
||||
This file contains some functionality ported from DUBY. See svn log for details
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
@created(Mon Aug 1st WET 2006)
|
||||
@ -42,7 +44,7 @@ uses
|
||||
{$ifdef windows}
|
||||
Windows, // After LCLType
|
||||
{$endif}
|
||||
Classes, SysUtils, FpDbgPETypes;
|
||||
Classes, SysUtils, FpDbgPETypes, LazUTF8Classes;
|
||||
|
||||
type
|
||||
TDbgImageSection = record
|
||||
@ -52,256 +54,298 @@ type
|
||||
end;
|
||||
PDbgImageSection = ^TDbgImageSection;
|
||||
|
||||
TDbgImageSectionEx = record
|
||||
Sect: TDbgImageSection;
|
||||
Offs: QWord;
|
||||
Loaded: Boolean;
|
||||
end;
|
||||
PDbgImageSectionEx = ^TDbgImageSectionEx;
|
||||
|
||||
{ TDbgFileLoader }
|
||||
{$ifdef windows}
|
||||
{$define USE_WIN_FILE_MAPPING}
|
||||
{$endif}
|
||||
|
||||
TDbgFileLoader = class(TObject)
|
||||
private
|
||||
{$ifdef USE_WIN_FILE_MAPPING}
|
||||
FFileHandle: THandle;
|
||||
FMapHandle: THandle;
|
||||
FModulePtr: Pointer;
|
||||
{$else}
|
||||
FStream: TStream;
|
||||
FList: TList;
|
||||
{$endif}
|
||||
public
|
||||
constructor Create(AFileName: String);
|
||||
{$ifdef USE_WIN_FILE_MAPPING}
|
||||
constructor Create(AFileHandle: THandle);
|
||||
{$endif}
|
||||
destructor Destroy; override;
|
||||
function Read(AOffset, ASize: QWord; AMem: Pointer): QWord;
|
||||
function LoadMemory(AOffset, ASize: QWord; out AMem: Pointer): QWord;
|
||||
procedure UnloadMemory(AMem: Pointer);
|
||||
end;
|
||||
|
||||
{ TDbgImageReader }
|
||||
|
||||
TDbgImageReader = class(TObject) // executable parser
|
||||
private
|
||||
FImage64Bit: Boolean;
|
||||
FImageBase: QWord;
|
||||
protected
|
||||
function GetSection(const AName: String): PDbgImageSection; virtual; abstract;
|
||||
procedure SetImageBase(ABase: QWord);
|
||||
procedure SetImage64Bit(AValue: Boolean);
|
||||
public
|
||||
class function isValid(ASource: TDbgFileLoader): Boolean; virtual; abstract;
|
||||
class function UserName: AnsiString; virtual; abstract;
|
||||
constructor Create(ASource: TDbgFileLoader; OwnSource: Boolean); virtual;
|
||||
|
||||
property ImageBase: QWord read FImageBase;
|
||||
Property Image64Bit: Boolean read FImage64Bit;
|
||||
property Section[const AName: String]: PDbgImageSection read GetSection;
|
||||
end;
|
||||
TDbgImageReaderClass = class of TDbgImageReader;
|
||||
|
||||
{ TDbgImageLoader }
|
||||
|
||||
TDbgImageLoader = class(TObject)
|
||||
private
|
||||
FImage64Bit: Boolean;
|
||||
FImageBase: QWord;
|
||||
FSections: TStringList;
|
||||
function GetSection(const AName: String): PDbgImageSection;
|
||||
FFileLoader: TDbgFileLoader;
|
||||
FImgReader: TDbgImageReader;
|
||||
function GetSection(const AName: String): PDbgImageSection; virtual;
|
||||
protected
|
||||
procedure Add(const AName: String; ARawData: Pointer; ASize: QWord; AVirtualAdress: QWord);
|
||||
procedure SetImageBase(ABase: QWord);
|
||||
procedure SetImage64Bit(AValue: Boolean);
|
||||
procedure LoadSections; virtual; abstract;
|
||||
procedure UnloadSections; virtual; abstract;
|
||||
FImage64Bit: Boolean unimplemented;
|
||||
FImageBase: QWord unimplemented;
|
||||
//procedure SetImageBase(ABase: QWord);
|
||||
//procedure SetImage64Bit(AValue: Boolean);
|
||||
public
|
||||
constructor Create;
|
||||
constructor Create; virtual;
|
||||
constructor Create(AFileName: String);
|
||||
{$ifdef USE_WIN_FILE_MAPPING}
|
||||
constructor Create(AFileHandle: THandle);
|
||||
{$endif}
|
||||
destructor Destroy; override;
|
||||
property ImageBase: QWord read FImageBase;
|
||||
Property Image64Bit: Boolean read FImage64Bit;
|
||||
property ImageBase: QWord read FImageBase; unimplemented;
|
||||
Property Image64Bit: Boolean read FImage64Bit; unimplemented;
|
||||
property Section[const AName: String]: PDbgImageSection read GetSection;
|
||||
end;
|
||||
|
||||
{ TDbgPEImageLoader }
|
||||
|
||||
TDbgPEImageLoader = class(TDbgImageLoader)
|
||||
private
|
||||
protected
|
||||
function LoadData(out AModuleBase: Pointer; out AHeaders: PImageNtHeaders): Boolean; virtual; abstract;
|
||||
procedure LoadSections; override;
|
||||
procedure UnloadData; virtual; abstract;
|
||||
procedure UnloadSections; override;
|
||||
public
|
||||
end;
|
||||
|
||||
{ TDbgWinPEImageLoader }
|
||||
|
||||
TDbgWinPEImageLoader = class(TDbgPEImageLoader)
|
||||
private
|
||||
FFileHandle: THandle;
|
||||
FMapHandle: THandle;
|
||||
FModulePtr: Pointer;
|
||||
procedure DoCleanup;
|
||||
protected
|
||||
function LoadData(out AModuleBase: Pointer; out AHeaders: PImageNtHeaders): Boolean; override;
|
||||
procedure UnloadData; override;
|
||||
public
|
||||
constructor Create(const AFileName: String);
|
||||
constructor Create(AFileHandle: THandle);
|
||||
end;
|
||||
function GetImageReader(const FileName: string): TDbgImageReader; overload;
|
||||
function GetImageReader(ASource: TDbgFileLoader; OwnSource: Boolean): TDbgImageReader; overload;
|
||||
procedure RegisterImageReaderClass(DataSource: TDbgImageReaderClass);
|
||||
|
||||
implementation
|
||||
|
||||
var
|
||||
RegisteredImageReaderClasses : TFPList;
|
||||
|
||||
function GetImageReader(const FileName: string): TDbgImageReader;
|
||||
begin
|
||||
try
|
||||
Result := GetImageReader(TDbgFileLoader.Create(FileName), true);
|
||||
except
|
||||
Result := nil;
|
||||
end;
|
||||
end;
|
||||
|
||||
function GetImageReader(ASource: TDbgFileLoader; OwnSource: Boolean): TDbgImageReader;
|
||||
var
|
||||
i : Integer;
|
||||
cls : TDbgImageReaderClass;
|
||||
begin
|
||||
Result := nil;
|
||||
if not Assigned(ASource) then Exit;
|
||||
|
||||
for i := 0 to RegisteredImageReaderClasses.Count - 1 do begin
|
||||
cls := TDbgImageReaderClass(RegisteredImageReaderClasses[i]);
|
||||
try
|
||||
if cls.isValid(ASource) then begin
|
||||
Result := cls.Create(ASource, OwnSource);
|
||||
Exit;
|
||||
end
|
||||
else
|
||||
;
|
||||
except
|
||||
on e: exception do begin
|
||||
//writeln('exception! WHY? ', e.Message);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
Result := nil;
|
||||
end;
|
||||
|
||||
procedure RegisterImageReaderClass( DataSource: TDbgImageReaderClass);
|
||||
begin
|
||||
if Assigned(DataSource) and (RegisteredImageReaderClasses.IndexOf(DataSource) < 0) then
|
||||
RegisteredImageReaderClasses.Add(DataSource)
|
||||
end;
|
||||
|
||||
{ TDbgImageLoader }
|
||||
|
||||
procedure TDbgImageLoader.Add(const AName: String; ARawData: Pointer; ASize: QWord; AVirtualAdress: QWord);
|
||||
var
|
||||
p: PDbgImageSection;
|
||||
idx: integer;
|
||||
function TDbgImageLoader.GetSection(const AName: String): PDbgImageSection;
|
||||
begin
|
||||
idx := FSections.AddObject(AName, nil);
|
||||
New(p);
|
||||
P^.RawData := ARawData;
|
||||
p^.Size := ASize;
|
||||
p^.VirtualAdress := AVirtualAdress;
|
||||
FSections.Objects[idx] := TObject(p);
|
||||
Result := FImgReader.Section[AName];
|
||||
end;
|
||||
|
||||
constructor TDbgImageLoader.Create;
|
||||
begin
|
||||
inherited Create;
|
||||
FSections := TStringList.Create;
|
||||
FSections.Sorted := True;
|
||||
FSections.Duplicates := dupError;
|
||||
FSections.CaseSensitive := False;
|
||||
LoadSections;
|
||||
end;
|
||||
|
||||
constructor TDbgImageLoader.Create(AFileName: String);
|
||||
begin
|
||||
FFileLoader := TDbgFileLoader.Create(AFileName);
|
||||
FImgReader := GetImageReader(FFileLoader, True);
|
||||
end;
|
||||
|
||||
{$ifdef USE_WIN_FILE_MAPPING}
|
||||
constructor TDbgImageLoader.Create(AFileHandle: THandle);
|
||||
begin
|
||||
FFileLoader := TDbgFileLoader.Create(AFileHandle);
|
||||
FImgReader := GetImageReader(FFileLoader, True);
|
||||
end;
|
||||
{$endif}
|
||||
|
||||
destructor TDbgImageLoader.Destroy;
|
||||
var
|
||||
n: integer;
|
||||
begin
|
||||
UnloadSections;
|
||||
for n := 0 to FSections.Count - 1 do
|
||||
Dispose(PDbgImageSection(FSections.Objects[n]));
|
||||
FSections.Clear;
|
||||
FreeAndNil(FImgReader);
|
||||
inherited Destroy;
|
||||
FreeAndNil(FSections);
|
||||
end;
|
||||
|
||||
function TDbgImageLoader.GetSection(const AName: String): PDbgImageSection;
|
||||
var
|
||||
idx: integer;
|
||||
{ TDbgFileLoader }
|
||||
|
||||
constructor TDbgFileLoader.Create(AFileName: String);
|
||||
begin
|
||||
idx := FSections.IndexOf(AName);
|
||||
if idx = -1
|
||||
then Result := nil
|
||||
else Result := PDbgImageSection(FSections.Objects[idx]);
|
||||
end;
|
||||
|
||||
procedure TDbgImageLoader.SetImage64Bit(AValue: Boolean);
|
||||
begin
|
||||
FImage64Bit := AValue;
|
||||
end;
|
||||
|
||||
procedure TDbgImageLoader.SetImageBase(ABase: QWord);
|
||||
begin
|
||||
FImageBase := ABase;
|
||||
end;
|
||||
|
||||
{ TDbgPEImageLoader }
|
||||
|
||||
procedure TDbgPEImageLoader.LoadSections;
|
||||
var
|
||||
ModulePtr: Pointer;
|
||||
NtHeaders: PImageNtHeaders;
|
||||
NtHeaders32: PImageNtHeaders32 absolute NtHeaders;
|
||||
NtHeaders64: PImageNtHeaders64 absolute NtHeaders;
|
||||
SectionHeader: PImageSectionHeader;
|
||||
n, idx: Integer;
|
||||
p: Pointer;
|
||||
SectionName: array[0..IMAGE_SIZEOF_SHORT_NAME] of Char;
|
||||
begin
|
||||
if not LoadData(ModulePtr, NtHeaders) then Exit;
|
||||
|
||||
if NtHeaders^.Signature <> IMAGE_NT_SIGNATURE
|
||||
then begin
|
||||
WriteLn('Invalid NT header: ', IntToHex(NtHeaders^.Signature, 8));
|
||||
Exit;
|
||||
end;
|
||||
|
||||
SetImage64Bit(NtHeaders^.OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR64_MAGIC);
|
||||
|
||||
if Image64Bit
|
||||
then SetImageBase(NtHeaders64^.OptionalHeader.ImageBase)
|
||||
else SetImageBase(NtHeaders32^.OptionalHeader.ImageBase);
|
||||
|
||||
for n := 0 to NtHeaders^.FileHeader.NumberOfSections - 1 do
|
||||
begin
|
||||
SectionHeader := Pointer(@NtHeaders^.OptionalHeader) + NtHeaders^.FileHeader.SizeOfOptionalHeader + SizeOf(SectionHeader^) * n;
|
||||
// make a null terminated name
|
||||
Move(SectionHeader^.Name, SectionName, IMAGE_SIZEOF_SHORT_NAME);
|
||||
SectionName[IMAGE_SIZEOF_SHORT_NAME] := #0;
|
||||
if (SectionName[0] = '/') and (SectionName[1] in ['0'..'9'])
|
||||
then begin
|
||||
// long name
|
||||
p := ModulePtr + NTHeaders^.FileHeader.PointerToSymbolTable + NTHeaders^.FileHeader.NumberOfSymbols * IMAGE_SIZEOF_SYMBOL + StrToIntDef(PChar(@SectionName[1]), 0);
|
||||
Add(PChar(p), ModulePtr + SectionHeader^.PointerToRawData, SectionHeader^.Misc.VirtualSize, SectionHeader^.VirtualAddress);
|
||||
end
|
||||
else begin
|
||||
// short name
|
||||
Add(SectionName, ModulePtr + SectionHeader^.PointerToRawData, SectionHeader^.Misc.VirtualSize, SectionHeader^.VirtualAddress);
|
||||
end
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TDbgPEImageLoader.UnloadSections;
|
||||
begin
|
||||
UnloadData;
|
||||
end;
|
||||
|
||||
{ TDbgWinPEImageLoader }
|
||||
|
||||
constructor TDbgWinPEImageLoader.Create(const AFileName: String);
|
||||
begin
|
||||
{$ifdef windows}
|
||||
{$ifdef USE_WIN_FILE_MAPPING}
|
||||
FFileHandle := CreateFile(PChar(AFileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
if FFileHandle = INVALID_HANDLE_VALUE
|
||||
then begin
|
||||
WriteLN('Cannot open file: ', AFileName);
|
||||
end;
|
||||
{$endif}
|
||||
Create(FFileHandle);
|
||||
{$else}
|
||||
FList := TList.Create;
|
||||
FStream := TFileStreamUTF8.Create(AFileName, fmOpenRead or fmShareDenyNone);
|
||||
inherited Create;
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
constructor TDbgWinPEImageLoader.Create(AFileHandle: THandle);
|
||||
{$ifdef USE_WIN_FILE_MAPPING}
|
||||
constructor TDbgFileLoader.Create(AFileHandle: THandle);
|
||||
begin
|
||||
FFileHandle := AFileHandle;
|
||||
if FFileHandle = INVALID_HANDLE_VALUE
|
||||
then begin
|
||||
WriteLN('Invalid file handle');
|
||||
end;
|
||||
|
||||
FMapHandle := CreateFileMapping(FFileHandle, nil, PAGE_READONLY{ or SEC_IMAGE}, 0, 0, nil);
|
||||
if FMapHandle = 0
|
||||
then begin
|
||||
WriteLn('Could not create module mapping');
|
||||
Exit;
|
||||
end;
|
||||
|
||||
FModulePtr := MapViewOfFile(FMapHandle, FILE_MAP_READ, 0, 0, 0);
|
||||
if FModulePtr = nil
|
||||
then begin
|
||||
WriteLn('Could not map view');
|
||||
Exit;
|
||||
end;
|
||||
|
||||
inherited Create;
|
||||
end;
|
||||
{$endif}
|
||||
|
||||
procedure TDbgWinPEImageLoader.DoCleanup;
|
||||
destructor TDbgFileLoader.Destroy;
|
||||
begin
|
||||
{$ifdef windows}
|
||||
{$ifdef USE_WIN_FILE_MAPPING}
|
||||
if FModulePtr <> nil
|
||||
then UnmapViewOfFile(FModulePtr);
|
||||
if FMapHandle <> 0
|
||||
then CloseHandle(FMapHandle);
|
||||
if FFileHandle <> INVALID_HANDLE_VALUE
|
||||
then CloseHandle(FFileHandle);
|
||||
{$endif}
|
||||
|
||||
FFileHandle := INVALID_HANDLE_VALUE;
|
||||
FMapHandle := 0;
|
||||
FModulePtr := nil;
|
||||
end;
|
||||
|
||||
function TDbgWinPEImageLoader.LoadData(out AModuleBase: Pointer; out AHeaders: PImageNtHeaders): Boolean;
|
||||
{$ifdef windows}
|
||||
var
|
||||
DosHeader: PImageDosHeader;
|
||||
{$endif}
|
||||
begin
|
||||
Result := False;
|
||||
|
||||
{$ifdef windows}
|
||||
try
|
||||
FMapHandle := CreateFileMapping(FFileHandle, nil, PAGE_READONLY{ or SEC_IMAGE}, 0, 0, nil);
|
||||
if FMapHandle = 0
|
||||
then begin
|
||||
WriteLn('Could not create module mapping');
|
||||
Exit;
|
||||
end;
|
||||
|
||||
FModulePtr := MapViewOfFile(FMapHandle, FILE_MAP_READ, 0, 0, 0);
|
||||
if FModulePtr = nil
|
||||
then begin
|
||||
WriteLn('Could not map view');
|
||||
Exit;
|
||||
end;
|
||||
|
||||
DosHeader := FModulePtr;
|
||||
if (DosHeader^.e_magic <> IMAGE_DOS_SIGNATURE)
|
||||
or (DosHeader^.e_lfanew = 0)
|
||||
then begin
|
||||
WriteLn('Invalid DOS header');
|
||||
Exit;
|
||||
end;
|
||||
|
||||
AModuleBase := FModulePtr;
|
||||
AHeaders := FModulePtr + DosHeader^.e_lfanew;
|
||||
Result := True;
|
||||
finally
|
||||
if not Result
|
||||
then begin
|
||||
// something failed, do some cleanup
|
||||
DoCleanup;
|
||||
end;
|
||||
end;
|
||||
{$else}
|
||||
while FList.Count > 0 do
|
||||
UnloadMemory(FList[0]);
|
||||
FreeAndNil(FList);
|
||||
FreeAndNil(FStream);
|
||||
inherited Destroy;
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
procedure TDbgWinPEImageLoader.UnloadData;
|
||||
function TDbgFileLoader.Read(AOffset, ASize: QWord; AMem: Pointer): QWord;
|
||||
begin
|
||||
DoCleanup;
|
||||
{$ifdef USE_WIN_FILE_MAPPING}
|
||||
move((FModulePtr + AOffset)^, AMem^, ASize);
|
||||
Result := ASize;
|
||||
{$else}
|
||||
Result := 0;
|
||||
if AMem = nil then
|
||||
exit;
|
||||
FStream.Position := AOffset;
|
||||
Result := FStream.Read(AMem^, ASize);
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
function TDbgFileLoader.LoadMemory(AOffset, ASize: QWord; out AMem: Pointer): QWord;
|
||||
begin
|
||||
{$ifdef USE_WIN_FILE_MAPPING}
|
||||
AMem := FModulePtr + AOffset;
|
||||
Result := ASize;
|
||||
{$else}
|
||||
Result := 0;
|
||||
AMem := AllocMem(ASize);
|
||||
if AMem = nil then
|
||||
exit;
|
||||
FList.Add(AMem);
|
||||
FStream.Position := AOffset;
|
||||
Result := FStream.Read(AMem^, ASize);
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
procedure TDbgFileLoader.UnloadMemory(AMem: Pointer);
|
||||
begin
|
||||
{$ifdef USE_WIN_FILE_MAPPING}
|
||||
{$else}
|
||||
FList.Remove(AMem);
|
||||
Freemem(AMem);
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
{ TDbgImageReader }
|
||||
|
||||
procedure TDbgImageReader.SetImageBase(ABase: QWord);
|
||||
begin
|
||||
FImageBase := ABase;
|
||||
end;
|
||||
|
||||
procedure TDbgImageReader.SetImage64Bit(AValue: Boolean);
|
||||
begin
|
||||
FImage64Bit := AValue;
|
||||
end;
|
||||
|
||||
constructor TDbgImageReader.Create(ASource: TDbgFileLoader; OwnSource: Boolean);
|
||||
begin
|
||||
inherited Create;
|
||||
end;
|
||||
|
||||
|
||||
procedure InitDebugInfoLists;
|
||||
begin
|
||||
RegisteredImageReaderClasses := TFPList.Create;
|
||||
end;
|
||||
|
||||
procedure ReleaseDebugInfoLists;
|
||||
begin
|
||||
FreeAndNil(RegisteredImageReaderClasses);
|
||||
end;
|
||||
|
||||
initialization
|
||||
InitDebugInfoLists;
|
||||
|
||||
finalization
|
||||
ReleaseDebugInfoLists;
|
||||
|
||||
end.
|
||||
|
||||
|
@ -16,43 +16,61 @@
|
||||
<CompilerPath Value="$(CompPath)"/>
|
||||
</Other>
|
||||
</CompilerOptions>
|
||||
<Files Count="9">
|
||||
<Description Value="A set of helperclasses for implementing a debugger.
|
||||
|
||||
Based on:
|
||||
1) FPDebug by Marc Weustink
|
||||
2) Duby by Dmitry Boyarintsev"/>
|
||||
<License Value="GPL"/>
|
||||
<Files Count="12">
|
||||
<Item1>
|
||||
<Filename Value="fpdbgclasses.pp"/>
|
||||
<UnitName Value="fpdbgclasses"/>
|
||||
<UnitName Value="FpDbgClasses"/>
|
||||
</Item1>
|
||||
<Item2>
|
||||
<Filename Value="fpdbgdisasx86.pp"/>
|
||||
<UnitName Value="fpdbgdisasx86"/>
|
||||
<UnitName Value="FpDbgDisasX86"/>
|
||||
</Item2>
|
||||
<Item3>
|
||||
<Filename Value="fpdbgdwarf.pas"/>
|
||||
<UnitName Value="fpdbgdwarf"/>
|
||||
<UnitName Value="FpDbgDwarf"/>
|
||||
</Item3>
|
||||
<Item4>
|
||||
<Filename Value="fpdbgdwarfconst.pas"/>
|
||||
<UnitName Value="fpdbgdwarfconst"/>
|
||||
<UnitName Value="FpDbgDwarfConst"/>
|
||||
</Item4>
|
||||
<Item5>
|
||||
<Filename Value="fpdbgloader.pp"/>
|
||||
<UnitName Value="fpdbgloader"/>
|
||||
<UnitName Value="FpDbgLoader"/>
|
||||
</Item5>
|
||||
<Item6>
|
||||
<Filename Value="fpdbgpetypes.pp"/>
|
||||
<UnitName Value="fpdbgpetypes"/>
|
||||
<UnitName Value="FpDbgPETypes"/>
|
||||
</Item6>
|
||||
<Item7>
|
||||
<Filename Value="fpdbgsymbols.pas"/>
|
||||
<UnitName Value="fpdbgsymbols"/>
|
||||
<UnitName Value="FpDbgSymbols"/>
|
||||
</Item7>
|
||||
<Item8>
|
||||
<Filename Value="fpdbgutil.pp"/>
|
||||
<UnitName Value="fpdbgutil"/>
|
||||
<UnitName Value="FpDbgUtil"/>
|
||||
</Item8>
|
||||
<Item9>
|
||||
<Filename Value="fpdbgwinextra.pp"/>
|
||||
<UnitName Value="fpdbgwinextra"/>
|
||||
<UnitName Value="FpDbgWinExtra"/>
|
||||
</Item9>
|
||||
<Item10>
|
||||
<Filename Value="fpimgreaderwinpe.pas"/>
|
||||
<UnitName Value="FpImgReaderWinPE"/>
|
||||
</Item10>
|
||||
<Item11>
|
||||
<Filename Value="fpimgreaderelf.pas"/>
|
||||
<UnitName Value="FpImgReaderElf"/>
|
||||
</Item11>
|
||||
<Item12>
|
||||
<Filename Value="fpimgreaderelftypes.pas"/>
|
||||
<UnitName Value="FpImgReaderElfTypes"/>
|
||||
</Item12>
|
||||
</Files>
|
||||
<Type Value="RunAndDesignTime"/>
|
||||
<RequiredPkgs Count="2">
|
||||
@ -69,5 +87,8 @@
|
||||
<PublishOptions>
|
||||
<Version Value="2"/>
|
||||
</PublishOptions>
|
||||
<CustomOptions Items="ExternHelp" Version="2">
|
||||
<_ExternHelp Items="Count"/>
|
||||
</CustomOptions>
|
||||
</Package>
|
||||
</CONFIG>
|
||||
|
@ -8,7 +8,8 @@ interface
|
||||
|
||||
uses
|
||||
FpDbgClasses, FpDbgDisasX86, FpDbgDwarf, FpDbgDwarfConst, FpDbgLoader, FpDbgPETypes,
|
||||
FpDbgSymbols, FpDbgUtil, FpDbgWinExtra, LazarusPackageIntf;
|
||||
FpDbgSymbols, FpDbgUtil, FpDbgWinExtra, FpImgReaderWinPE, FpImgReaderElf,
|
||||
FpImgReaderElfTypes, LazarusPackageIntf;
|
||||
|
||||
implementation
|
||||
|
||||
|
258
components/fpdebug/fpimgreaderelf.pas
Normal file
258
components/fpdebug/fpimgreaderelf.pas
Normal file
@ -0,0 +1,258 @@
|
||||
{
|
||||
This unit contains the types needed for reading Elf images.
|
||||
|
||||
This file was ported from DUBY. See svn log for details
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* This source is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This code is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* General Public License for more details. *
|
||||
* *
|
||||
* A copy of the GNU General Public License is available on the World *
|
||||
* Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
|
||||
* obtain it by writing to the Free Software Foundation, *
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
* *
|
||||
***************************************************************************
|
||||
}
|
||||
unit FpImgReaderElf;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils,
|
||||
FpDbgLoader,
|
||||
FpImgReaderElfTypes; // these files are part of
|
||||
|
||||
|
||||
type
|
||||
TElfSection = packed record
|
||||
name : AnsiString;
|
||||
FileOfs : QWord;
|
||||
Address : QWord;
|
||||
Size : QWord;
|
||||
end;
|
||||
|
||||
{ TElfFile }
|
||||
|
||||
TElfFile = class(TObject)
|
||||
protected
|
||||
function Load32BitFile(ALoader: TDbgFileLoader): Boolean;
|
||||
procedure AddSection(const name: AnsiString; FileOffset, Address, Size: Qword);
|
||||
public
|
||||
sections : array of TElfSection;
|
||||
seccount : Integer;
|
||||
function LoadFromFile(ALoader: TDbgFileLoader): Boolean;
|
||||
function FindSection(const Name: String): Integer;
|
||||
end;
|
||||
|
||||
{ TElfDbgSource }
|
||||
|
||||
TElfDbgSource = class(TDbgImageReader) // executable parser
|
||||
private
|
||||
FSections: TStringList;
|
||||
FFileLoader : TDbgFileLoader;
|
||||
fOwnSource : Boolean;
|
||||
fElfFile : TElfFile;
|
||||
protected
|
||||
function GetSection(const AName: String): PDbgImageSection; override;
|
||||
public
|
||||
class function isValid(ASource: TDbgFileLoader): Boolean; override;
|
||||
class function UserName: AnsiString; override;
|
||||
constructor Create(ASource: TDbgFileLoader; OwnSource: Boolean); override;
|
||||
destructor Destroy; override;
|
||||
|
||||
//function GetSectionInfo(const SectionName: AnsiString; var Size: int64): Boolean; override;
|
||||
//function GetSectionData(const SectionName: AnsiString; Offset, Size: Int64; var Buf: array of byte): Int64; override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
{ TElfFile }
|
||||
|
||||
function TElfFile.Load32BitFile(ALoader: TDbgFileLoader): Boolean;
|
||||
var
|
||||
hdr : Elf32_Ehdr;
|
||||
sect : array of Elf32_shdr;
|
||||
i, j : integer;
|
||||
nm : string;
|
||||
sz : LongWord;
|
||||
strs : array of byte;
|
||||
begin
|
||||
Result := ALoader.Read(0, sizeof(hdr), @hdr) = sizeof(hdr);
|
||||
if not Result then Exit;
|
||||
|
||||
SetLength(sect, hdr.e_shnum);
|
||||
//ALoader.Position := hdr.e_shoff;
|
||||
|
||||
sz := hdr.e_shetsize * hdr.e_shnum;
|
||||
if sz > LongWord(length(sect)*sizeof(Elf32_shdr)) then
|
||||
sz := LongWord(length(sect)*sizeof(Elf32_shdr));
|
||||
//ALoader.Read(sect[0], sz);
|
||||
ALoader.Read(hdr.e_shoff, sz, @sect[0]);
|
||||
|
||||
i := sect[hdr.e_shstrndx].sh_offset;
|
||||
j := sect[hdr.e_shstrndx].sh_size;
|
||||
SetLength(strs, j);
|
||||
//ALoader.Position:=i;
|
||||
//ALoader.Read(strs[0], j);
|
||||
ALoader.Read(i, j, @strs[0]);
|
||||
|
||||
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 );
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
procedure TElfFile.AddSection(const name: AnsiString; FileOffset, Address,
|
||||
Size: Qword);
|
||||
begin
|
||||
if seccount=Length(sections) then begin
|
||||
if seccount = 0 then SetLength(sections, 4)
|
||||
else SetLength(sections, seccount*2);
|
||||
end;
|
||||
sections[seccount].Address:= Address;
|
||||
sections[seccount].name:=name;
|
||||
sections[seccount].FileOfs:=FileOffset;
|
||||
sections[seccount].Size:=Size;
|
||||
inc(seccount);
|
||||
end;
|
||||
|
||||
function TElfFile.LoadFromFile(ALoader: TDbgFileLoader): Boolean;
|
||||
var
|
||||
ident : array [0..EINDENT-1] of byte;
|
||||
begin
|
||||
try
|
||||
Result := ALoader.Read(0, sizeof(ident), @ident[0]) = sizeof(ident);
|
||||
if not Result then Exit;
|
||||
|
||||
Result := (ident[EI_MAG0] = $7f) and
|
||||
(ident[EI_MAG1] = byte('E')) and
|
||||
(ident[EI_MAG2] = byte('L')) and
|
||||
(ident[EI_MAG3] = byte('F'));
|
||||
if not Result then Exit;
|
||||
|
||||
Result := ident[EI_CLASS] = ELFCLASS32;
|
||||
if not Result then Exit; //todo: 64-bit
|
||||
|
||||
Result := Load32BitFile(ALoader);
|
||||
|
||||
except
|
||||
Result := false;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TElfFile.FindSection(const Name: String): Integer;
|
||||
var
|
||||
i : Integer;
|
||||
begin
|
||||
Result := -1;
|
||||
for i := 0 to seccount - 1 do
|
||||
if sections[i].name = Name then begin
|
||||
Result := i;
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TElfDbgSource }
|
||||
|
||||
function TElfDbgSource.GetSection(const AName: String): PDbgImageSection;
|
||||
var
|
||||
i: Integer;
|
||||
ex: PDbgImageSectionEx;
|
||||
begin
|
||||
Result := nil;
|
||||
i := FSections.IndexOf(AName);
|
||||
if i < 0 then
|
||||
exit;
|
||||
ex := PDbgImageSectionEx(FSections.Objects[i]);
|
||||
Result := @ex^.Sect;
|
||||
if ex^.Loaded then
|
||||
exit;
|
||||
ex^.Loaded := True;
|
||||
FFileLoader.LoadMemory(ex^.Offs, Result^.Size, Result^.RawData);
|
||||
end;
|
||||
|
||||
class function TElfDbgSource.isValid(ASource: TDbgFileLoader): Boolean;
|
||||
var
|
||||
buf : array [0..3+sizeof(Elf32_EHdr)] of byte;
|
||||
begin
|
||||
try
|
||||
Result := Assigned(ASource) and
|
||||
(ASource.Read(0, sizeof(Elf32_EHdr), @buf[0]) = sizeof(Elf32_EHdr));
|
||||
|
||||
if not Result then Exit;
|
||||
|
||||
Result := (buf[EI_MAG0] = $7f) and (buf[EI_MAG1] = byte('E')) and
|
||||
(buf[EI_MAG2] = byte('L')) and (buf[EI_MAG3] = byte('F'));
|
||||
except
|
||||
Result := false;
|
||||
end;
|
||||
end;
|
||||
|
||||
class function TElfDbgSource.UserName: AnsiString;
|
||||
begin
|
||||
Result := 'ELF executable';
|
||||
end;
|
||||
|
||||
constructor TElfDbgSource.Create(ASource: TDbgFileLoader; OwnSource: Boolean);
|
||||
var
|
||||
p: PDbgImageSectionEx;
|
||||
idx: integer;
|
||||
i: Integer;
|
||||
fs: TElfSection;
|
||||
begin
|
||||
FSections := TStringList.Create;
|
||||
FSections.Sorted := True;
|
||||
//FSections.Duplicates := dupError;
|
||||
FSections.CaseSensitive := False;
|
||||
|
||||
FFileLoader := ASource;
|
||||
fOwnSource := OwnSource;
|
||||
fElfFile := TElfFile.Create;
|
||||
fElfFile.LoadFromFile(ASource);
|
||||
|
||||
for i := 0 to fElfFile.seccount - 1 do begin
|
||||
fs := fElfFile.sections[i];
|
||||
idx := FSections.AddObject(fs.name, nil);
|
||||
New(p);
|
||||
P^.Offs := fs.FileOfs;
|
||||
p^.Sect.Size := fs.Size;
|
||||
p^.Sect.VirtualAdress := 0; // Todo?
|
||||
p^.Loaded := False;
|
||||
FSections.Objects[idx] := TObject(p);
|
||||
end;
|
||||
|
||||
inherited Create(ASource, OwnSource);
|
||||
end;
|
||||
|
||||
destructor TElfDbgSource.Destroy;
|
||||
begin
|
||||
if fOwnSource then FFileLoader.Free;
|
||||
fElfFile.Free;
|
||||
while FSections.Count > 0 do begin
|
||||
Freemem(FSections.Objects[0]);
|
||||
FSections.Delete(0);
|
||||
end;
|
||||
FreeAndNil(FSections);
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
initialization
|
||||
RegisterImageReaderClass( TElfDbgSource );
|
||||
|
||||
end.
|
||||
|
380
components/fpdebug/fpimgreaderelftypes.pas
Normal file
380
components/fpdebug/fpimgreaderelftypes.pas
Normal file
@ -0,0 +1,380 @@
|
||||
{
|
||||
This unit contains the types needed for reading Elf images.
|
||||
|
||||
This file was ported from DUBY. See svn log for details
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* This source is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This code is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* General Public License for more details. *
|
||||
* *
|
||||
* A copy of the GNU General Public License is available on the World *
|
||||
* Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
|
||||
* obtain it by writing to the Free Software Foundation, *
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
* *
|
||||
***************************************************************************
|
||||
}
|
||||
unit FpImgReaderElfTypes;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
type
|
||||
Elf32_Addr = LongWord; // Unsigned program address
|
||||
Elf32_Half = Word; // Unsigned medium integer
|
||||
Elf32_Off = LongWord; // Usigned file offset
|
||||
Elf32_Sword = Integer; // Signed large integer
|
||||
Elf32_Word = LongWord; // Usigned large integer
|
||||
|
||||
Elf64_Addr = Qword; // Unsigned program address
|
||||
Elf64_Off = QWord; // Unsigned file offset
|
||||
Elf64_Half = Word; // Unsigned medium integer
|
||||
Elf64_Word = LongWord; // Unsigned integer
|
||||
Elf64_Sword = Integer; // Signed integer
|
||||
Elf64_Xword = QWord; // Unsigned long integer
|
||||
Elf64_Sxword = Int64; // Signed long integer
|
||||
|
||||
const
|
||||
EINDENT = 16;
|
||||
|
||||
type
|
||||
elf_ident = packed record
|
||||
case byte of
|
||||
0: (e_ident: array [0..EINDENT-1] of byte);
|
||||
1: (id_mag : array[0..3] of Char;
|
||||
id_class : Byte;
|
||||
id_data : Byte;
|
||||
id_version : Byte;
|
||||
id_OSABI : Byte;
|
||||
id_AbiVersion : Byte;
|
||||
);
|
||||
end;
|
||||
|
||||
const
|
||||
EI_MAG0 = 0; // $7F
|
||||
EI_MAG1 = 1; // E
|
||||
EI_MAG2 = 2; // L
|
||||
EI_MAG3 = 3; // F
|
||||
EI_CLASS = 4;
|
||||
EI_DATA = 1;
|
||||
EI_VERSION = 1;
|
||||
EI_OSABI = 1;
|
||||
EI_ABIVERSION = 1;
|
||||
|
||||
ELFMAGIC = chr($7f)+'ELF';
|
||||
|
||||
//elf class
|
||||
ELFCLASSNONE = 0;
|
||||
ELFCLASS32 = 1;
|
||||
ELFCLASS64 = 2;
|
||||
|
||||
//byte order
|
||||
ELFDATANONE = 0;
|
||||
ELFDATA2LSB = 1;
|
||||
ELFDATA2MSB = 2;
|
||||
|
||||
// Operating System and ABI Identifiers, e_ident[EI_OSABI]
|
||||
ELFOSABI_SYSV = 0; // System V ABI
|
||||
ELFOSABI_HPUX = 1; // HP-UX operating system
|
||||
ELFOSABI_STANDALONE = 255; // Standalone (embedded) application
|
||||
|
||||
|
||||
type
|
||||
//note: it doesn't include Ident block
|
||||
Elf32_EHdr = packed record
|
||||
e_ident : elf_ident; { ELF identification }
|
||||
e_type : Elf32_Half; { Object file type }
|
||||
e_machine : Elf32_Half; { Machine type }
|
||||
e_version : Elf32_Word; { Object file version }
|
||||
e_entry : Elf32_addr; { Entry point address }
|
||||
e_phoff : Elf32_Off; { Program header offset }
|
||||
e_shoff : Elf32_Off; { Section header offset }
|
||||
e_flags : Elf32_Word; { Processor-specific flags }
|
||||
e_ehsize : Elf32_Half; { ELF header size }
|
||||
e_phentsize : Elf32_Half; { Size of program header entry }
|
||||
e_phnum : Elf32_Half; { Number of program header entries }
|
||||
e_shetsize : Elf32_Half; { Size of section header entry }
|
||||
e_shnum : Elf32_Half; { Number of section header entries }
|
||||
e_shstrndx : Elf32_Half; { Section name string table index }
|
||||
end;
|
||||
PElf32_EHdr = ^Elf32_EHdr;
|
||||
|
||||
Elf64_EHdr = packed record
|
||||
e_ident : elf_ident; { ELF identification }
|
||||
e_type : Elf64_Half; { Object file type }
|
||||
e_machine : Elf64_Half; { Machine type }
|
||||
e_version : Elf64_Word; { Object file version }
|
||||
e_entry : Elf64_Addr; { Entry point address }
|
||||
e_phoff : Elf64_Off; { Program header offset }
|
||||
p_shoff : Elf64_Off; { Section header offset }
|
||||
e_flags : Elf64_Word; { Processor-specific flags }
|
||||
e_ehsize : Elf64_Half; { ELF header size }
|
||||
e_phentsize : Elf64_Half; { Size of program header entry }
|
||||
e_phun : Elf64_Half; { Number of program header entries }
|
||||
e_shentsize : Elf64_Half; { Size of section header entry }
|
||||
e_shnum : Elf64_Half; { Number of section header entries }
|
||||
e_shstrnds : Elf64_Half; { Section name string table index }
|
||||
end;
|
||||
PElf64_EHdr = ^Elf64_EHdr;
|
||||
|
||||
const
|
||||
// object file type {Elf32_Hdr.e_type}
|
||||
ET_NONE = 0; // No file type
|
||||
ET_REL = 1; // Relocatable object file .o
|
||||
ET_EXEC = 2; // Executable file
|
||||
ET_DYN = 3; // Shared object file .so
|
||||
ET_CORE = 4; // Core file
|
||||
ET_LOOS = $fe00; // os-specific
|
||||
ET_HIOS = $feff;
|
||||
ET_LOPROC = $ff00; // processor-specific
|
||||
ET_HIPROC = $ffff;
|
||||
|
||||
// machine type {Elf32_Hdr.e_machine}
|
||||
EM_NONE = 0;
|
||||
EM_SPARC = 2;
|
||||
EM_386 = 3;
|
||||
EM_68K = 4;
|
||||
EM_PPC = 20;
|
||||
EM_PPC64 = 21;
|
||||
EM_ARM = 40;
|
||||
EM_OLD_ALPHA = 41;
|
||||
EM_IA_64 = 50;
|
||||
EM_X86_64 = 62;
|
||||
EM_ALPHA = $9026; //unofficial, but used by gnu toolchain
|
||||
|
||||
//elf version {Elf32_Hdr.e_version}
|
||||
EV_NONE = 0;
|
||||
EV_CURRENT = 1;
|
||||
|
||||
SHN_UNDEF = $0; // Used to mark an undefined or meaningless section reference
|
||||
SHN_LORESERVE = $ff00; {This value specifies the lower bound of the range of reserved indexes.}
|
||||
SHN_LOPROC = $ff00;
|
||||
SHN_HIPROC = $ff1f;
|
||||
SHN_ABS = $fff1; // Indicates that the corresponding reference is an absolute value
|
||||
SHN_COMMON = $fff2; // Indicates a symbol that has been declared as a common block (Fortran COMMON or C tentative declaration)
|
||||
SHN_HIRESERVE = $ffff;
|
||||
|
||||
type
|
||||
Elf32_shdr = packed record
|
||||
sh_name : Elf32_Word;
|
||||
sh_type : Elf32_Word;
|
||||
sh_flags : Elf32_Word;
|
||||
sh_addr : Elf32_Addr;
|
||||
sh_offset : Elf32_Off;
|
||||
sh_size : Elf32_Word;
|
||||
sh_link : Elf32_Word;
|
||||
sh_info : Elf32_Word;
|
||||
sh_addralign : Elf32_Word;
|
||||
sh_entsize : Elf32_Word;
|
||||
end;
|
||||
PElf32_shdr = ^Elf32_shdr;
|
||||
|
||||
Elf64_Shdr = packed record
|
||||
sh_name : Elf64_Word; // Section name
|
||||
sh_type : Elf64_Word; // Section type
|
||||
sh_flags : Elf64_Xword; // Section attributes
|
||||
sh_address : Elf64_Addr; // Virtual address in memory
|
||||
sh_offset : Elf64_Off; // Offset in file
|
||||
sh_size : Elf64_Xword; // Size of section
|
||||
sh_link : Elf64_Word; // Link to other section
|
||||
sh_info : Elf64_Word; // Miscellaneous information
|
||||
sh_addralign : Elf64_Xword; // Address alignment boundary
|
||||
sh_entsize : Elf64_Xword; // Size of entries, if section has table
|
||||
end;
|
||||
PElf64_Shdr = ^Elf64_Shdr;
|
||||
|
||||
|
||||
const
|
||||
//section type
|
||||
SHT_NULL = 0; // Marks an unused section header
|
||||
SHT_PROGBITS = 1; // Contains information defined by the program
|
||||
SHT_SYMTAB = 2; // Contains a linker symbol table
|
||||
SHT_STRTAB = 3; // Contains a string table
|
||||
SHT_RELA = 4; // Contains “Rela” type relocation entries
|
||||
SHT_HASH = 5; // Contains a symbol hash table
|
||||
SHT_DYNAMIC = 6; // Contains dynamic linking tables
|
||||
SHT_NOTE = 7; // Contains note information
|
||||
SHT_NOBITS = 8; // Contains uninitialized space; does not occupy any space in the file
|
||||
SHT_REL = 9; // Contains “Rel” type relocation entries
|
||||
SHT_SHLIB = 10; // Reserved
|
||||
SHT_DYNSYM = 11; // Contains a dynamic loader symbol table
|
||||
|
||||
SHT_LOOS = $60000000; // Environment-specific use
|
||||
SHT_HIOS = $6fffffff;
|
||||
SHT_LOPROC = $70000000; // Processor-specific use
|
||||
SHT_HIPROC = $7fffffff;
|
||||
|
||||
//section attribute flags
|
||||
SHF_WRITE = 1; // Section contains writable data
|
||||
SHF_ALLOC = 2; // Section is allocated in memory image of program
|
||||
SHF_EXECINSTR = 4; // Section contains executable instructions
|
||||
SHF_MASKOS = $0f000000; // Environment-specific use
|
||||
SHF_MASKPROC = $f0000000; // Processor-specific use
|
||||
|
||||
|
||||
type
|
||||
Elf32_Sym = packed record
|
||||
st_name : Elf32_Word;
|
||||
st_value : Elf32_Addr;
|
||||
st_size : Elf32_Word;
|
||||
st_info : byte;
|
||||
st_other : byte;
|
||||
st_shndx : Elf32_Half;
|
||||
end;
|
||||
PElf32_Sym = ^Elf32_Sym;
|
||||
|
||||
Elf64_Sym = packed record
|
||||
st_name : Elf64_Word; // Symbol name
|
||||
st_info : Byte; // Type and Binding attributes
|
||||
st_other : Byte; // Reserved
|
||||
st_shndx : Elf64_Half; // Section table index
|
||||
st_value : Elf64_Addr; // Symbol value
|
||||
st_Size : Elf64_Xword // Size of object (e.g., common)
|
||||
end;
|
||||
PElf64_Sym = ^Elf64_Sym;
|
||||
|
||||
|
||||
const
|
||||
//symbol bindings
|
||||
STB_LOCAL = 0; // Not visible outside the object file
|
||||
STB_GLOBAL = 1; // Global symbol, visible to all object files
|
||||
STB_WEAK = 2; // Global scope, but with lower precedence than global symbols
|
||||
STB_LOOS = 10; // Environment-specific use
|
||||
STB_HIOS = 12;
|
||||
STB_LOPROC = 13; // Processor-specific use
|
||||
STB_HIPROC = 15;
|
||||
|
||||
//symbol types
|
||||
STT_NOTYPE = 0; // No type specified (e.g., an absolute symbol)
|
||||
STT_OBJECT = 1; // Data object
|
||||
STT_FUNC = 2; // Function entry point
|
||||
STT_SECTION = 3; // Symbol is associated with a section
|
||||
STT_FILE = 4; // Source file associated with the object file
|
||||
STT_COMMON = 5;
|
||||
STT_TLS = 6;
|
||||
STT_LOOS = 10; // Environment-specific use
|
||||
STT_HIOS = 12;
|
||||
STT_LOPROC = 13; // Processor-specific use
|
||||
STT_SPARC_REGISTER = 13;
|
||||
STT_HIPROC = 15;
|
||||
|
||||
|
||||
|
||||
{
|
||||
Relocation
|
||||
|
||||
Relocation is the process of connecting symbolic references with symbolic
|
||||
definitions. For example, when a program calls a function, the associated call
|
||||
instruction must transfer control to the proper destination address at execution.
|
||||
In other words, relocatable files must have information that describes how
|
||||
to modify their section contents, thus allowing executable and shared object
|
||||
files to hold the right information for a process’s program image.
|
||||
Relocation entriesare these data.
|
||||
}
|
||||
|
||||
type
|
||||
Elf32_Rel = packed record
|
||||
r_offset : Elf32_Addr;
|
||||
r_info : Elf32_Word;
|
||||
end;
|
||||
|
||||
Elf32_rela = packed record
|
||||
r_offset : Elf32_Addr;
|
||||
r_info : Elf32_Word;
|
||||
r_addend : Elf32_Sword;
|
||||
end;
|
||||
|
||||
{ r_offset This member gives the location at which to apply the relocation action. For a relocatable
|
||||
file, the value is the byte offset from the beginning of the section to the storage unit affected
|
||||
by the relocation. For an executable file or a shared object, the value is the virtual address of
|
||||
the storage unit affected by the relocation.
|
||||
r_info This member gives both the symbol table index with respect to which the relocation must be
|
||||
made, and the type of relocation to apply. For example, a call instruction’s relocation entry
|
||||
would hold the symbol table index of the function being called. If the index isSTN_UNDEF,
|
||||
the undefined symbol index, the relocation uses 0 as the ‘‘symbol value.’’ Relocation types
|
||||
are processor-specific. When the text refers to a relocation entry’s relocation type or symbol
|
||||
table index, it means the result of applyingELF32_R_TYPEorELF32_R_SYM, respectively,
|
||||
to the entry’sr_infomember }
|
||||
|
||||
|
||||
Elf64_Rel = packed record
|
||||
r_offset : Elf64_Addr; // Address of reference
|
||||
r_info : Elf64_Xword; // Symbol index and type of relocation
|
||||
end;
|
||||
PElf64_Rel = ^Elf64_Rel;
|
||||
|
||||
Elf64_Rela = packed record
|
||||
r_offset : Elf64_Addr; // Address of reference
|
||||
r_info : Elf64_Xword; // Symbol index and type of relocation
|
||||
r_addend : Elf64_Sxword; // Constant part of expression
|
||||
end;
|
||||
PElf64_Rela = ^Elf64_Rela;
|
||||
|
||||
|
||||
const
|
||||
R_386_NONE = 0;
|
||||
R_386_32 = 1;
|
||||
R_386_PC32 = 2;
|
||||
R_386_GOT32 = 3;
|
||||
R_386_PLT32 = 4;
|
||||
R_386_COPY = 5;
|
||||
R_386_GLOB_DAT = 6;
|
||||
R_386_JMP_SLOT = 7;
|
||||
R_386_RELATIVE = 8;
|
||||
R_386_GOTOFF = 9;
|
||||
R_386_GOTPC = 10;
|
||||
|
||||
|
||||
function Elf32_R_Sym(i: LongWord): LongWord; inline;
|
||||
function Elf32_R_Type(i: LongWord): LongWord; inline;
|
||||
function Elf32_R_Info(s, t: LongWord): LongWord; inline;
|
||||
|
||||
function Elf64_R_Sym(i: QWord): QWord; inline;
|
||||
function Elf64_R_Type(i: QWord): QWord; inline;
|
||||
function Elf64_R_Info(s, t: QWord): QWord; inline;
|
||||
|
||||
implementation
|
||||
|
||||
function Elf32_R_Sym(i: LongWord): LongWord; inline;
|
||||
begin
|
||||
Result := i shr 8;
|
||||
end;
|
||||
|
||||
function Elf32_R_Type(i: LongWord): LongWord; inline;
|
||||
begin
|
||||
Result := i and $FF;
|
||||
end;
|
||||
|
||||
function Elf32_R_Info(s, t: LongWord): LongWord; inline;
|
||||
begin
|
||||
Result := (s shl 8) + (t and $FF);
|
||||
end;
|
||||
|
||||
function Elf64_R_Info(s, t: QWord): QWord; inline;
|
||||
begin
|
||||
Result := (s shl 32) + (t and $FFFFFFFF);
|
||||
end;
|
||||
|
||||
function Elf64_R_Type(i: QWord): QWord; inline;
|
||||
begin
|
||||
Result := i and $ffffffff;
|
||||
end;
|
||||
|
||||
function Elf64_R_Sym(i: QWord): QWord; inline;
|
||||
begin
|
||||
Result := i shr 32;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
231
components/fpdebug/fpimgreaderwinpe.pas
Normal file
231
components/fpdebug/fpimgreaderwinpe.pas
Normal file
@ -0,0 +1,231 @@
|
||||
{
|
||||
This unit contains the types needed for reading PE images.
|
||||
|
||||
This file was ported from DUBY. See svn log for details
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
@created(Thu May 4th WET 2006)
|
||||
@lastmod($Date: 2009-01-16 03:26:10 +0300 (Пт, 16 янв 2009) $)
|
||||
@author(Marc Weustink <marc@@dommelstein.nl>)
|
||||
|
||||
@modified by dmitry boyarintsev (july 2009:
|
||||
+ removed Windows unit dependancy. added SectionCount and
|
||||
+ added Sections access by Index
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* This source is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This code is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* General Public License for more details. *
|
||||
* *
|
||||
* A copy of the GNU General Public License is available on the World *
|
||||
* Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
|
||||
* obtain it by writing to the Free Software Foundation, *
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
* *
|
||||
***************************************************************************
|
||||
}
|
||||
unit FpImgReaderWinPE;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, math, FpDbgLoader, FpImgReaderWinPETypes, LazLoggerBase;
|
||||
|
||||
type
|
||||
|
||||
{ TPEFileSource }
|
||||
|
||||
TPEFileSource = class(TDbgImageReader)
|
||||
private
|
||||
FSections: TStringList;
|
||||
FFileLoader : TDbgFileLoader;
|
||||
FOwnLoader : Boolean;
|
||||
protected
|
||||
function GetSection(const AName: String): PDbgImageSection; override;
|
||||
|
||||
procedure LoadSections;
|
||||
public
|
||||
class function isValid(ASource: TDbgFileLoader): Boolean; override;
|
||||
class function UserName: AnsiString; override;
|
||||
public
|
||||
constructor Create(ASource: TDbgFileLoader; OwnSource: Boolean); override;
|
||||
destructor Destroy; override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
function isValidPEStream(ASource: TDbgFileLoader): Boolean;
|
||||
var
|
||||
DosHeader: TImageDosHeader;
|
||||
begin
|
||||
try
|
||||
Result := false;
|
||||
if ASource.Read(0, sizeof(DosHeader), @DosHeader) <> sizeof(DosHeader) then
|
||||
Exit;
|
||||
if (DosHeader.e_magic <> IMAGE_DOS_SIGNATURE) or (DosHeader.e_lfanew = 0) then
|
||||
Exit;
|
||||
Result := true;
|
||||
except
|
||||
Result := false;
|
||||
end;
|
||||
end;
|
||||
|
||||
constructor TPEFileSource.Create(ASource: TDbgFileLoader; OwnSource: Boolean);
|
||||
begin
|
||||
FSections := TStringList.Create;
|
||||
FSections.Sorted := True;
|
||||
//FSections.Duplicates := dupError;
|
||||
FSections.CaseSensitive := False;
|
||||
|
||||
FFileLoader:=ASource;
|
||||
FOwnLoader:=OwnSource;
|
||||
LoadSections;
|
||||
inherited Create(ASource, OwnSource);
|
||||
end;
|
||||
|
||||
destructor TPEFileSource.Destroy;
|
||||
begin
|
||||
if FOwnLoader then FFileLoader.Free;
|
||||
while FSections.Count > 0 do begin
|
||||
Freemem(FSections.Objects[0]);
|
||||
FSections.Delete(0);
|
||||
end;
|
||||
FSections.Free;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function TPEFileSource.GetSection(const AName: String): PDbgImageSection;
|
||||
var
|
||||
i: Integer;
|
||||
ex: PDbgImageSectionEx;
|
||||
begin
|
||||
Result := nil;
|
||||
i := FSections.IndexOf(AName);
|
||||
if i < 0 then
|
||||
exit;
|
||||
ex := PDbgImageSectionEx(FSections.Objects[i]);
|
||||
Result := @ex^.Sect;
|
||||
if ex^.Loaded then
|
||||
exit;
|
||||
ex^.Loaded := True;
|
||||
FFileLoader.LoadMemory(ex^.Offs, Result^.Size, Result^.RawData);
|
||||
end;
|
||||
|
||||
procedure TPEFileSource.LoadSections;
|
||||
|
||||
procedure Add(const AName: String; ARawData: QWord; ASize: QWord; AVirtualAdress: QWord);
|
||||
var
|
||||
p: PDbgImageSectionEx;
|
||||
idx: integer;
|
||||
begin
|
||||
idx := FSections.AddObject(AName, nil);
|
||||
New(p);
|
||||
P^.Offs := ARawData;
|
||||
p^.Sect.Size := ASize;
|
||||
p^.Sect.VirtualAdress := AVirtualAdress;
|
||||
p^.Loaded := False;
|
||||
FSections.Objects[idx] := TObject(p);
|
||||
end;
|
||||
|
||||
var
|
||||
DosHeader: TImageDosHeader;
|
||||
ModulePtr: Pointer;
|
||||
NtHeaders: record
|
||||
case integer of
|
||||
1: (Sys: TImageNtHeaders;);
|
||||
2: (W32: TImageNtHeaders32;);
|
||||
3: (W64: TImageNtHeaders64;);
|
||||
end;
|
||||
SectionHeader: PImageSectionHeader;
|
||||
n, i: Integer;
|
||||
p: Pointer;
|
||||
SectionName: array[0..IMAGE_SIZEOF_SHORT_NAME] of Char;
|
||||
SectionMax: QWord;
|
||||
s: string[255];
|
||||
begin
|
||||
FFileLoader.Read(0, sizeof(DosHeader), @DosHeader);
|
||||
if (DosHeader.e_magic <> IMAGE_DOS_SIGNATURE)
|
||||
or (DosHeader.e_lfanew = 0)
|
||||
then begin
|
||||
//WriteLn('Invalid DOS header');
|
||||
Exit;
|
||||
end;
|
||||
|
||||
FFileLoader.Read(DosHeader.e_lfanew, sizeof(NtHeaders), @NtHeaders);
|
||||
if NtHeaders.Sys.Signature <> IMAGE_NT_SIGNATURE
|
||||
then begin
|
||||
//WriteLn('Invalid NT header: ', IntToHex(NtHeaders^.Signature, 8));
|
||||
Exit;
|
||||
end;
|
||||
|
||||
SetImage64Bit(NtHeaders.Sys.OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR64_MAGIC);
|
||||
|
||||
if Image64Bit
|
||||
then SetImageBase(NtHeaders.W64.OptionalHeader.ImageBase)
|
||||
else SetImageBase(NtHeaders.W32.OptionalHeader.ImageBase);
|
||||
|
||||
SectionMax := FFileLoader.LoadMemory(
|
||||
DosHeader.e_lfanew +
|
||||
(@NtHeaders.Sys.OptionalHeader - @NtHeaders.Sys) +
|
||||
NtHeaders.Sys.FileHeader.SizeOfOptionalHeader,
|
||||
SizeOf(TImageSectionHeader) * NtHeaders.Sys.FileHeader.NumberOfSections,
|
||||
SectionHeader
|
||||
)
|
||||
div SizeOf(TImageSectionHeader);
|
||||
if SectionMax <> NtHeaders.Sys.FileHeader.NumberOfSections then begin
|
||||
DebugLn(['Could not load all headers', NtHeaders.Sys.FileHeader.NumberOfSections, ' ', SectionMax]);
|
||||
end;
|
||||
|
||||
for n := 0 to SectionMax - 1 do
|
||||
begin
|
||||
//SectionHeader := Pointer(@NtHeaders.Sys.OptionalHeader) +
|
||||
// NtHeaders.Sys.FileHeader.SizeOfOptionalHeader +
|
||||
// SizeOf(TImageSectionHeader) * n;
|
||||
// make a null terminated name
|
||||
Move(SectionHeader[n].Name, SectionName, IMAGE_SIZEOF_SHORT_NAME);
|
||||
SectionName[IMAGE_SIZEOF_SHORT_NAME] := #0;
|
||||
if (SectionName[0] = '/') and (SectionName[1] in ['0'..'9'])
|
||||
then begin
|
||||
// long name
|
||||
i := FFileLoader.Read(
|
||||
NTHeaders.Sys.FileHeader.PointerToSymbolTable +
|
||||
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);
|
||||
end
|
||||
else begin
|
||||
// short name
|
||||
Add(SectionName, SectionHeader[n].PointerToRawData, SectionHeader[n].Misc.VirtualSize, SectionHeader[n].VirtualAddress);
|
||||
end
|
||||
end;
|
||||
|
||||
FFileLoader.UnloadMemory(SectionHeader);
|
||||
end;
|
||||
|
||||
class function TPEFileSource.isValid(ASource: TDbgFileLoader): Boolean;
|
||||
begin
|
||||
Result := isValidPEStream(ASource);
|
||||
end;
|
||||
|
||||
class function TPEFileSource.UserName: AnsiString;
|
||||
begin
|
||||
Result:='PE file';
|
||||
end;
|
||||
|
||||
|
||||
initialization
|
||||
RegisterImageReaderClass(TPEFileSource);
|
||||
|
||||
end.
|
||||
|
878
components/fpdebug/fpimgreaderwinpetypes.pas
Normal file
878
components/fpdebug/fpimgreaderwinpetypes.pas
Normal file
@ -0,0 +1,878 @@
|
||||
{
|
||||
---------------------------------------------------------------------------
|
||||
dbgpetypes.pp
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
This unit contains the types needed for reading PE images.
|
||||
At some time this may go to be part of the rtl ?
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
@created(Thu May 4th WET 2006)
|
||||
@author(Marc Weustink <marc@@dommelstein.nl>)
|
||||
|
||||
@update (2th july 2009). Removed "Uses Windows" by dmitry boyarintsev.
|
||||
|
||||
*****************************************************************************
|
||||
* *
|
||||
* This file is part of the Lazarus Project *
|
||||
* *
|
||||
* See the file COPYING.modifiedLGPL.txt, included in this distribution, *
|
||||
* for details about the copyright. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||
* *
|
||||
*****************************************************************************
|
||||
}
|
||||
unit FpImgReaderWinPETypes;
|
||||
|
||||
{$ifdef fpc}{$mode delphi}{$H+}{$inline on}{$endif}
|
||||
|
||||
interface
|
||||
|
||||
{$ifndef fpc}
|
||||
type
|
||||
QWord = Int64;
|
||||
DWORD = LongWord;
|
||||
{$endif}
|
||||
|
||||
type
|
||||
ULONGLONG = QWord;
|
||||
CLSID = TGUID;
|
||||
SHORT = Word;
|
||||
|
||||
const
|
||||
{$ifdef ENDIAN_LITTLE}
|
||||
|
||||
IMAGE_DOS_SIGNATURE = $5A4D; // MZ
|
||||
IMAGE_OS2_SIGNATURE = $454E; // NE
|
||||
IMAGE_OS2_SIGNATURE_LE = $454C; // LE
|
||||
IMAGE_VXD_SIGNATURE = $454C; // LE
|
||||
IMAGE_NT_SIGNATURE = $00004550; // PE00
|
||||
|
||||
{$else}
|
||||
|
||||
IMAGE_DOS_SIGNATURE = $4D5A; // MZ
|
||||
IMAGE_OS2_SIGNATURE = $4E45; // NE
|
||||
IMAGE_OS2_SIGNATURE_LE = $4C45; // LE
|
||||
IMAGE_NT_SIGNATURE = $50450000; // PE00
|
||||
|
||||
{$endif}
|
||||
|
||||
{$ifdef fpc}
|
||||
{$packrecords 2}
|
||||
{$endif}
|
||||
|
||||
type
|
||||
_IMAGE_DOS_HEADER = {$ifndef fpc} packed {$endif} record // DOS .EXE header
|
||||
e_magic: WORD; // Magic number
|
||||
e_cblp: WORD; // Bytes on last page of file
|
||||
e_cp: WORD; // Pages in file
|
||||
e_crlc: WORD; // Relocations
|
||||
e_cparhdr: WORD; // Size of header in paragraphs
|
||||
e_minalloc: WORD; // Minimum extra paragraphs needed
|
||||
e_maxalloc: WORD; // Maximum extra paragraphs needed
|
||||
e_ss: WORD; // Initial (relative) SS value
|
||||
e_sp: WORD; // Initial SP value
|
||||
e_csum: WORD; // Checksum
|
||||
e_ip: WORD; // Initial IP value
|
||||
e_cs: WORD; // Initial (relative) CS value
|
||||
e_lfarlc: WORD; // File address of relocation table
|
||||
e_ovno: WORD; // Overlay number
|
||||
e_res: array[0..3] of WORD; // Reserved words
|
||||
e_oemid: WORD; // OEM identifier (for e_oeminfo)
|
||||
e_oeminfo: WORD; // OEM information: e_oemid specific
|
||||
e_res2: array[0..9] of WORD; // Reserved words
|
||||
e_lfanew: LongWord; // File address of new exe header
|
||||
end;
|
||||
IMAGE_DOS_HEADER = _IMAGE_DOS_HEADER;
|
||||
TImageDosHeader = _IMAGE_DOS_HEADER;
|
||||
PImageDosHeader = ^TImageDosHeader;
|
||||
|
||||
type
|
||||
_IMAGE_OS2_HEADER = {$ifndef fpc} packed {$endif} record // OS/2 .EXE header
|
||||
ne_magic: WORD; // Magic number
|
||||
ne_ver: CHAR; // Version number
|
||||
ne_rev: CHAR; // Revision number
|
||||
ne_enttab: WORD; // Offset of Entry Table
|
||||
ne_cbenttab: WORD; // Number of bytes in Entry Table
|
||||
ne_crc: LongWord; // Checksum of whole file
|
||||
ne_flags: WORD; // Flag word
|
||||
ne_autodata: WORD; // Automatic data segment number
|
||||
ne_heap: WORD; // Initial heap allocation
|
||||
ne_stack: WORD; // Initial stack allocation
|
||||
ne_csip: LongWord; // Initial CS:IP setting
|
||||
ne_sssp: LongWord; // Initial SS:SP setting
|
||||
ne_cseg: WORD; // Count of file segments
|
||||
ne_cmod: WORD; // Entries in Module Reference Table
|
||||
ne_cbnrestab: WORD; // Size of non-resident name table
|
||||
ne_segtab: WORD; // Offset of Segment Table
|
||||
ne_rsrctab: WORD; // Offset of Resource Table
|
||||
ne_restab: WORD; // Offset of resident name table
|
||||
ne_modtab: WORD; // Offset of Module Reference Table
|
||||
ne_imptab: WORD; // Offset of Imported Names Table
|
||||
ne_nrestab: LongWord; // Offset of Non-resident Names Table
|
||||
ne_cmovent: WORD; // Count of movable entries
|
||||
ne_align: WORD; // Segment alignment shift count
|
||||
ne_cres: WORD; // Count of resource segments
|
||||
ne_exetyp: BYTE; // Target Operating system
|
||||
ne_flagsothers: BYTE; // Other .EXE flags
|
||||
ne_pretthunks: WORD; // offset to return thunks
|
||||
ne_psegrefbytes: WORD; // offset to segment ref. bytes
|
||||
ne_swaparea: WORD; // Minimum code swap area size
|
||||
ne_expver: WORD; // Expected Windows version number
|
||||
end;
|
||||
IMAGE_OS2_HEADER = _IMAGE_OS2_HEADER;
|
||||
TImageOS2Header = _IMAGE_OS2_HEADER;
|
||||
PImageOS2Header = ^TImageOS2Header;
|
||||
|
||||
type
|
||||
_IMAGE_VXD_HEADER = {$ifndef fpc} packed {$endif} record // Windows VXD header
|
||||
e32_magic: WORD; // Magic number
|
||||
e32_border: BYTE; // The byte ordering for the VXD
|
||||
e32_worder: BYTE; // The word ordering for the VXD
|
||||
e32_level: DWORD; // The EXE format level for now = 0
|
||||
e32_cpu: WORD; // The CPU type
|
||||
e32_os: WORD; // The OS type
|
||||
e32_ver: DWORD; // Module version
|
||||
e32_mflags: DWORD; // Module flags
|
||||
e32_mpages: DWORD; // Module # pages
|
||||
e32_startobj: DWORD; // Object # for instruction pointer
|
||||
e32_eip: DWORD; // Extended instruction pointer
|
||||
e32_stackobj: DWORD; // Object # for stack pointer
|
||||
e32_esp: DWORD; // Extended stack pointer
|
||||
e32_pagesize: DWORD; // VXD page size
|
||||
e32_lastpagesize: DWORD; // Last page size in VXD
|
||||
e32_fixupsize: DWORD; // Fixup section size
|
||||
e32_fixupsum: DWORD; // Fixup section checksum
|
||||
e32_ldrsize: DWORD; // Loader section size
|
||||
e32_ldrsum: DWORD; // Loader section checksum
|
||||
e32_objtab: DWORD; // Object table offset
|
||||
e32_objcnt: DWORD; // Number of objects in module
|
||||
e32_objmap: DWORD; // Object page map offset
|
||||
e32_itermap: DWORD; // Object iterated data map offset
|
||||
e32_rsrctab: DWORD; // Offset of Resource Table
|
||||
e32_rsrccnt: DWORD; // Number of resource entries
|
||||
e32_restab: DWORD; // Offset of resident name table
|
||||
e32_enttab: DWORD; // Offset of Entry Table
|
||||
e32_dirtab: DWORD; // Offset of Module Directive Table
|
||||
e32_dircnt: DWORD; // Number of module directives
|
||||
e32_fpagetab: DWORD; // Offset of Fixup Page Table
|
||||
e32_frectab: DWORD; // Offset of Fixup Record Table
|
||||
e32_impmod: DWORD; // Offset of Import Module Name Table
|
||||
e32_impmodcnt: DWORD; // Number of entries in Import Module Name Table
|
||||
e32_impproc: DWORD; // Offset of Import Procedure Name Table
|
||||
e32_pagesum: DWORD; // Offset of Per-Page Checksum Table
|
||||
e32_datapage: DWORD; // Offset of Enumerated Data Pages
|
||||
e32_preload: DWORD; // Number of preload pages
|
||||
e32_nrestab: DWORD; // Offset of Non-resident Names Table
|
||||
e32_cbnrestab: DWORD; // Size of Non-resident Name Table
|
||||
e32_nressum: DWORD; // Non-resident Name Table Checksum
|
||||
e32_autodata: DWORD; // Object # for automatic data object
|
||||
e32_debuginfo: DWORD; // Offset of the debugging information
|
||||
e32_debuglen: DWORD; // The length of the debugging info. in bytes
|
||||
e32_instpreload: DWORD; // Number of instance pages in preload section of VXD file
|
||||
e32_instdemand: DWORD; // Number of instance pages in demand load section of VXD file
|
||||
e32_heapsize: DWORD; // Size of heap - for 16-bit apps
|
||||
e32_res3: array[0..11] of BYTE; // Reserved words
|
||||
e32_winresoff: DWORD;
|
||||
e32_winreslen: DWORD;
|
||||
e32_devid: WORD; // Device ID for VxD
|
||||
e32_ddkver: WORD; // DDK version for VxD
|
||||
end;
|
||||
IMAGE_VXD_HEADER = _IMAGE_VXD_HEADER;
|
||||
TImageVXDHeader = _IMAGE_VXD_HEADER;
|
||||
PImageVXDHeader = ^TImageVXDHeader;
|
||||
|
||||
{$ifdef fpc}
|
||||
{$packrecords 4}
|
||||
{$endif}
|
||||
|
||||
//
|
||||
// File header format.
|
||||
//
|
||||
|
||||
type
|
||||
_IMAGE_FILE_HEADER = record
|
||||
Machine: WORD;
|
||||
NumberOfSections: WORD;
|
||||
TimeDateStamp: DWORD;
|
||||
PointerToSymbolTable: DWORD;
|
||||
NumberOfSymbols: DWORD;
|
||||
SizeOfOptionalHeader: WORD;
|
||||
Characteristics: WORD;
|
||||
end;
|
||||
IMAGE_FILE_HEADER = _IMAGE_FILE_HEADER;
|
||||
TImageFileHeader = _IMAGE_FILE_HEADER;
|
||||
PImageFileHeader = ^TImageFileHeader;
|
||||
|
||||
const
|
||||
IMAGE_SIZEOF_FILE_HEADER = 20;
|
||||
|
||||
|
||||
IMAGE_FILE_RELOCS_STRIPPED = $0001; // Relocation info stripped from file.
|
||||
IMAGE_FILE_EXECUTABLE_IMAGE = $0002; // File is executable (i.e. no unresolved externel references).
|
||||
IMAGE_FILE_LINE_NUMS_STRIPPED = $0004; // Line nunbers stripped from file.
|
||||
IMAGE_FILE_LOCAL_SYMS_STRIPPED = $0008; // Local symbols stripped from file.
|
||||
IMAGE_FILE_AGGRESIVE_WS_TRIM = $0010; // Agressively trim working set
|
||||
IMAGE_FILE_LARGE_ADDRESS_AWARE = $0020; // App can handle >2gb addresses
|
||||
IMAGE_FILE_BYTES_REVERSED_LO = $0080; // Bytes of machine word are reversed.
|
||||
IMAGE_FILE_32BIT_MACHINE = $0100; // 32 bit word machine.
|
||||
IMAGE_FILE_DEBUG_STRIPPED = $0200; // Debugging info stripped from file in .DBG file
|
||||
IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = $0400; // If Image is on removable media, copy and run from the swap file.
|
||||
IMAGE_FILE_NET_RUN_FROM_SWAP = $0800; // If Image is on Net, copy and run from the swap file.
|
||||
IMAGE_FILE_SYSTEM = $1000; // System File.
|
||||
IMAGE_FILE_DLL = $2000; // File is a DLL.
|
||||
IMAGE_FILE_UP_SYSTEM_ONLY = $4000; // File should only be run on a UP machine
|
||||
IMAGE_FILE_BYTES_REVERSED_HI = $8000; // Bytes of machine word are reversed.
|
||||
|
||||
IMAGE_FILE_MACHINE_UNKNOWN = 0;
|
||||
IMAGE_FILE_MACHINE_I386 = $014c; // Intel 386.
|
||||
IMAGE_FILE_MACHINE_R3000 = $0162; // MIPS little-endian, $160 big-endian
|
||||
IMAGE_FILE_MACHINE_R4000 = $0166; // MIPS little-endian
|
||||
IMAGE_FILE_MACHINE_R10000 = $0168; // MIPS little-endian
|
||||
IMAGE_FILE_MACHINE_WCEMIPSV2 = $0169; // MIPS little-endian WCE v2
|
||||
IMAGE_FILE_MACHINE_ALPHA = $0184; // Alpha_AXP
|
||||
IMAGE_FILE_MACHINE_SH3 = $01a2; // SH3 little-endian
|
||||
IMAGE_FILE_MACHINE_SH3DSP = $01a3;
|
||||
IMAGE_FILE_MACHINE_SH3E = $01a4; // SH3E little-endian
|
||||
IMAGE_FILE_MACHINE_SH4 = $01a6; // SH4 little-endian
|
||||
IMAGE_FILE_MACHINE_SH5 = $01a8; // SH5
|
||||
IMAGE_FILE_MACHINE_ARM = $01c0; // ARM Little-Endian
|
||||
IMAGE_FILE_MACHINE_THUMB = $01c2;
|
||||
IMAGE_FILE_MACHINE_AM33 = $01d3;
|
||||
IMAGE_FILE_MACHINE_POWERPC = $01F0; // IBM PowerPC Little-Endian
|
||||
IMAGE_FILE_MACHINE_POWERPCFP = $01f1;
|
||||
IMAGE_FILE_MACHINE_IA64 = $0200; // Intel 64
|
||||
IMAGE_FILE_MACHINE_MIPS16 = $0266; // MIPS
|
||||
IMAGE_FILE_MACHINE_ALPHA64 = $0284; // ALPHA64
|
||||
IMAGE_FILE_MACHINE_MIPSFPU = $0366; // MIPS
|
||||
IMAGE_FILE_MACHINE_MIPSFPU16 = $0466; // MIPS
|
||||
IMAGE_FILE_MACHINE_AXP64 = IMAGE_FILE_MACHINE_ALPHA64;
|
||||
IMAGE_FILE_MACHINE_TRICORE = $0520; // Infineon
|
||||
IMAGE_FILE_MACHINE_CEF = $0CEF;
|
||||
IMAGE_FILE_MACHINE_EBC = $0EBC; // EFI Byte Code
|
||||
IMAGE_FILE_MACHINE_AMD64 = $8664; // AMD64 (K8)
|
||||
IMAGE_FILE_MACHINE_M32R = $9041; // M32R little-endian
|
||||
IMAGE_FILE_MACHINE_CEE = $C0EE;
|
||||
|
||||
//
|
||||
// Directory format.
|
||||
//
|
||||
|
||||
type
|
||||
_IMAGE_DATA_DIRECTORY = record
|
||||
VirtualAddress: DWORD;
|
||||
Size: DWORD;
|
||||
end;
|
||||
IMAGE_DATA_DIRECTORY = _IMAGE_DATA_DIRECTORY;
|
||||
TImageDataDirectory = _IMAGE_DATA_DIRECTORY;
|
||||
PImageDataDirectory = ^TImageDataDirectory;
|
||||
|
||||
|
||||
const
|
||||
IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16;
|
||||
|
||||
//
|
||||
// Optional header format.
|
||||
//
|
||||
|
||||
type
|
||||
_IMAGE_OPTIONAL_HEADER = record
|
||||
//
|
||||
// Standard fields.
|
||||
//
|
||||
|
||||
Magic: WORD;
|
||||
MajorLinkerVersion: BYTE;
|
||||
MinorLinkerVersion: BYTE;
|
||||
SizeOfCode: DWORD;
|
||||
SizeOfInitializedData: DWORD;
|
||||
SizeOfUninitializedData: DWORD;
|
||||
AddressOfEntryPoint: DWORD;
|
||||
BaseOfCode: DWORD;
|
||||
BaseOfData: DWORD;
|
||||
|
||||
//
|
||||
// NT additional fields.
|
||||
//
|
||||
|
||||
ImageBase: DWORD;
|
||||
SectionAlignment: DWORD;
|
||||
FileAlignment: DWORD;
|
||||
MajorOperatingSystemVersion: WORD;
|
||||
MinorOperatingSystemVersion: WORD;
|
||||
MajorImageVersion: WORD;
|
||||
MinorImageVersion: WORD;
|
||||
MajorSubsystemVersion: WORD;
|
||||
MinorSubsystemVersion: WORD;
|
||||
Win32VersionValue: DWORD;
|
||||
SizeOfImage: DWORD;
|
||||
SizeOfHeaders: DWORD;
|
||||
CheckSum: DWORD;
|
||||
Subsystem: WORD;
|
||||
DllCharacteristics: WORD;
|
||||
SizeOfStackReserve: DWORD;
|
||||
SizeOfStackCommit: DWORD;
|
||||
SizeOfHeapReserve: DWORD;
|
||||
SizeOfHeapCommit: DWORD;
|
||||
LoaderFlags: DWORD;
|
||||
NumberOfRvaAndSizes: DWORD;
|
||||
DataDirectory: packed array[0..IMAGE_NUMBEROF_DIRECTORY_ENTRIES-1] of TImageDataDirectory;
|
||||
end;
|
||||
IMAGE_OPTIONAL_HEADER32 = _IMAGE_OPTIONAL_HEADER;
|
||||
TImageOptionalHeader32 = _IMAGE_OPTIONAL_HEADER;
|
||||
PImageOptionalHeader32 = ^TImageOptionalHeader32;
|
||||
|
||||
type
|
||||
_IMAGE_ROM_OPTIONAL_HEADER = record
|
||||
Magic: WORD;
|
||||
MajorLinkerVersion: BYTE;
|
||||
MinorLinkerVersion: BYTE;
|
||||
SizeOfCode: DWORD;
|
||||
SizeOfInitializedData: DWORD;
|
||||
SizeOfUninitializedData: DWORD;
|
||||
AddressOfEntryPoint: DWORD;
|
||||
BaseOfCode: DWORD;
|
||||
BaseOfData: DWORD;
|
||||
BaseOfBss: DWORD;
|
||||
GprMask: DWORD;
|
||||
CprMask: array[0..3] of DWORD;
|
||||
GpValue: DWORD;
|
||||
end;
|
||||
IMAGE_ROM_OPTIONAL_HEADER = _IMAGE_ROM_OPTIONAL_HEADER;
|
||||
TImageRomOptionalHeader = _IMAGE_ROM_OPTIONAL_HEADER;
|
||||
PImageRomOptionalHeader = ^TImageRomOptionalHeader;
|
||||
|
||||
type
|
||||
_IMAGE_OPTIONAL_HEADER64 = record
|
||||
Magic: WORD;
|
||||
MajorLinkerVersion: BYTE;
|
||||
MinorLinkerVersion: BYTE;
|
||||
SizeOfCode: DWORD;
|
||||
SizeOfInitializedData: DWORD;
|
||||
SizeOfUninitializedData: DWORD;
|
||||
AddressOfEntryPoint: DWORD;
|
||||
BaseOfCode: DWORD;
|
||||
ImageBase: ULONGLONG;
|
||||
SectionAlignment: DWORD;
|
||||
FileAlignment: DWORD;
|
||||
MajorOperatingSystemVersion: WORD;
|
||||
MinorOperatingSystemVersion: WORD;
|
||||
MajorImageVersion: WORD;
|
||||
MinorImageVersion: WORD;
|
||||
MajorSubsystemVersion: WORD;
|
||||
MinorSubsystemVersion: WORD;
|
||||
Win32VersionValue: DWORD;
|
||||
SizeOfImage: DWORD;
|
||||
SizeOfHeaders: DWORD;
|
||||
CheckSum: DWORD;
|
||||
Subsystem: WORD;
|
||||
DllCharacteristics: WORD;
|
||||
SizeOfStackReserve: ULONGLONG;
|
||||
SizeOfStackCommit: ULONGLONG;
|
||||
SizeOfHeapReserve: ULONGLONG;
|
||||
SizeOfHeapCommit: ULONGLONG;
|
||||
LoaderFlags: DWORD;
|
||||
NumberOfRvaAndSizes: DWORD;
|
||||
DataDirectory: packed array[0..IMAGE_NUMBEROF_DIRECTORY_ENTRIES-1] of TImageDataDirectory;
|
||||
end;
|
||||
IMAGE_OPTIONAL_HEADER64 = _IMAGE_OPTIONAL_HEADER64;
|
||||
TImageOptionalHeader64 = _IMAGE_OPTIONAL_HEADER64;
|
||||
PImageOptionalHeader64 = ^TImageOptionalHeader64;
|
||||
|
||||
const
|
||||
IMAGE_SIZEOF_ROM_OPTIONAL_HEADER = 56;
|
||||
IMAGE_SIZEOF_STD_OPTIONAL_HEADER = 28;
|
||||
IMAGE_SIZEOF_NT_OPTIONAL32_HEADER = 224;
|
||||
IMAGE_SIZEOF_NT_OPTIONAL64_HEADER = 240;
|
||||
|
||||
IMAGE_NT_OPTIONAL_HDR32_MAGIC = $10b;
|
||||
IMAGE_NT_OPTIONAL_HDR64_MAGIC = $20b;
|
||||
IMAGE_ROM_OPTIONAL_HDR_MAGIC = $107;
|
||||
|
||||
{$ifdef WIN64}
|
||||
type
|
||||
IMAGE_OPTIONAL_HEADER = IMAGE_OPTIONAL_HEADER64;
|
||||
TImageOptionalHeader = TImageOptionalHeader64;
|
||||
PImagePptionalHeader = PImageOptionalHeader64;
|
||||
const
|
||||
IMAGE_SIZEOF_NT_OPTIONAL_HEADER = IMAGE_SIZEOF_NT_OPTIONAL64_HEADER;
|
||||
IMAGE_NT_OPTIONAL_HDR_MAGIC = IMAGE_NT_OPTIONAL_HDR64_MAGIC;
|
||||
{$else}
|
||||
type
|
||||
IMAGE_OPTIONAL_HEADER = IMAGE_OPTIONAL_HEADER32;
|
||||
TImageOptionalHeader = TImageOptionalHeader32;
|
||||
PImagePptionalHeader = PImageOptionalHeader32;
|
||||
const
|
||||
IMAGE_SIZEOF_NT_OPTIONAL_HEADER = IMAGE_SIZEOF_NT_OPTIONAL32_HEADER;
|
||||
IMAGE_NT_OPTIONAL_HDR_MAGIC = IMAGE_NT_OPTIONAL_HDR32_MAGIC;
|
||||
{$endif}
|
||||
|
||||
type
|
||||
_IMAGE_NT_HEADERS64 = record
|
||||
Signature: DWORD;
|
||||
FileHeader: TImageFileHeader;
|
||||
OptionalHeader: TImageOptionalHeader64;
|
||||
end;
|
||||
IMAGE_NT_HEADERS64 = _IMAGE_NT_HEADERS64;
|
||||
TImageNtHeaders64 = _IMAGE_NT_HEADERS64;
|
||||
PImageNtHeaders64 = ^TImageNtHeaders64;
|
||||
|
||||
_IMAGE_NT_HEADERS32 = record
|
||||
Signature: DWORD;
|
||||
FileHeader: TImageFileHeader;
|
||||
OptionalHeader: TImageOptionalHeader32;
|
||||
end;
|
||||
IMAGE_NT_HEADERS32 = _IMAGE_NT_HEADERS32;
|
||||
TImageNtHeaders32 = _IMAGE_NT_HEADERS32;
|
||||
PImageNtHeaders32 = ^TImageNtHeaders32;
|
||||
|
||||
_IMAGE_ROM_HEADERS = record
|
||||
FileHeader: TImageFileHeader;
|
||||
OptionalHeader: TImageRomOptionalHeader;
|
||||
end;
|
||||
IMAGE_ROM_HEADERS = _IMAGE_ROM_HEADERS;
|
||||
TImageRomHeaders = _IMAGE_ROM_HEADERS;
|
||||
PImageRomHeaders = ^TImageRomHeaders;
|
||||
|
||||
{$ifdef WIN64}
|
||||
IMAGE_NT_HEADERS = IMAGE_NT_HEADERS64;
|
||||
TImageNtHeaders = TImageNtHeaders64;
|
||||
PImageNtHeaders = PImageNtHeaders64;
|
||||
{$else}
|
||||
IMAGE_NT_HEADERS = IMAGE_NT_HEADERS32;
|
||||
TImageNtHeaders = TImageNtHeaders32;
|
||||
PImageNtHeaders = PImageNtHeaders32;
|
||||
{$endif}
|
||||
|
||||
const
|
||||
// Subsystem Values
|
||||
IMAGE_SUBSYSTEM_UNKNOWN = 0; // Unknown subsystem.
|
||||
IMAGE_SUBSYSTEM_NATIVE = 1; // Image doesn't require a subsystem.
|
||||
IMAGE_SUBSYSTEM_WINDOWS_GUI = 2; // Image runs in the Windows GUI subsystem.
|
||||
IMAGE_SUBSYSTEM_WINDOWS_CUI = 3; // Image runs in the Windows character subsystem.
|
||||
IMAGE_SUBSYSTEM_OS2_CUI = 5; // image runs in the OS/2 character subsystem.
|
||||
IMAGE_SUBSYSTEM_POSIX_CUI = 7; // image runs in the Posix character subsystem.
|
||||
IMAGE_SUBSYSTEM_NATIVE_WINDOWS = 8; // image is a native Win9x driver.
|
||||
IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9; // Image runs in the Windows CE subsystem.
|
||||
IMAGE_SUBSYSTEM_EFI_APPLICATION = 10; //
|
||||
IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11; //
|
||||
IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER = 12; //
|
||||
IMAGE_SUBSYSTEM_EFI_ROM = 13;
|
||||
IMAGE_SUBSYSTEM_XBOX = 14;
|
||||
|
||||
// DllCharacteristics Entries
|
||||
|
||||
IMAGE_LIBRARY_PROCESS_INIT = $0001; // Reserved.
|
||||
IMAGE_LIBRARY_PROCESS_TERM = $0002; // Reserved.
|
||||
IMAGE_LIBRARY_THREAD_INIT = $0004; // Reserved.
|
||||
IMAGE_LIBRARY_THREAD_TERM = $0008; // Reserved.
|
||||
IMAGE_DLLCHARACTERISTICS_NO_ISOLATION = $0200; // Image understands isolation and doesn't want it
|
||||
IMAGE_DLLCHARACTERISTICS_NO_SEH = $0400; // Image does not use SEH. No SE handler may reside in this image
|
||||
IMAGE_DLLCHARACTERISTICS_NO_BIND = $0800; // Do not bind this image.
|
||||
// = $1000; // Reserved.
|
||||
IMAGE_DLLCHARACTERISTICS_WDM_DRIVER = $2000; // Driver uses WDM model
|
||||
// = $4000; // Reserved.
|
||||
IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = $8000;
|
||||
|
||||
// Directory Entries
|
||||
|
||||
IMAGE_DIRECTORY_ENTRY_EXPORT = 0; // Export Directory
|
||||
IMAGE_DIRECTORY_ENTRY_IMPORT = 1; // Import Directory
|
||||
IMAGE_DIRECTORY_ENTRY_RESOURCE = 2; // Resource Directory
|
||||
IMAGE_DIRECTORY_ENTRY_EXCEPTION = 3; // Exception Directory
|
||||
IMAGE_DIRECTORY_ENTRY_SECURITY = 4; // Security Directory
|
||||
IMAGE_DIRECTORY_ENTRY_BASERELOC = 5; // Base Relocation Table
|
||||
IMAGE_DIRECTORY_ENTRY_DEBUG = 6; // Debug Directory
|
||||
IMAGE_DIRECTORY_ENTRY_COPYRIGHT = 7; // (X86 usage)
|
||||
IMAGE_DIRECTORY_ENTRY_ARCHITECTURE = 7; // Architecture Specific Data
|
||||
IMAGE_DIRECTORY_ENTRY_GLOBALPTR = 8; // RVA of GP
|
||||
IMAGE_DIRECTORY_ENTRY_TLS = 9; // TLS Directory
|
||||
IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG = 10; // Load Configuration Directory
|
||||
IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT = 11; // Bound Import Directory in headers
|
||||
IMAGE_DIRECTORY_ENTRY_IAT = 12; // Import Address Table
|
||||
IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT = 13; // Delay Load Import Descriptors
|
||||
IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR = 14; // COM Runtime descriptor
|
||||
|
||||
//
|
||||
// Non-COFF Object file header
|
||||
//
|
||||
|
||||
type
|
||||
ANON_OBJECT_HEADER = record
|
||||
Sig1: WORD; // Must be IMAGE_FILE_MACHINE_UNKNOWN
|
||||
Sig2: WORD; // Must be $ffff;
|
||||
Version: WORD; // >= 1 (implies the CLSID field is present)
|
||||
Machine: WORD;
|
||||
TimeDateStamp: DWORD;
|
||||
ClassID: CLSID; // Used to invoke CoCreateInstance
|
||||
SizeOfData: DWORD; // Size of data that follows the header
|
||||
end;
|
||||
TAnonObjectHeader = ANON_OBJECT_HEADER;
|
||||
PAnonObjectHeader = ^TAnonObjectHeader;
|
||||
|
||||
//
|
||||
// Section header format.
|
||||
//
|
||||
|
||||
const
|
||||
IMAGE_SIZEOF_SHORT_NAME = 8;
|
||||
|
||||
type
|
||||
TISHMisc = record
|
||||
case Boolean of
|
||||
False: (PhysicalAddress: DWORD);
|
||||
True: (VirtualSize: DWORD);
|
||||
end;
|
||||
|
||||
_IMAGE_SECTION_HEADER = record
|
||||
Name: array[0..IMAGE_SIZEOF_SHORT_NAME-1] of BYTE;
|
||||
Misc: TISHMisc;
|
||||
VirtualAddress: DWORD;
|
||||
SizeOfRawData: DWORD;
|
||||
PointerToRawData: DWORD;
|
||||
PointerToRelocations: DWORD;
|
||||
PointerToLinenumbers: DWORD;
|
||||
NumberOfRelocations: WORD;
|
||||
NumberOfLinenumbers: WORD;
|
||||
Characteristics: DWORD;
|
||||
end;
|
||||
IMAGE_SECTION_HEADER = _IMAGE_SECTION_HEADER;
|
||||
TImageSectionHeader = _IMAGE_SECTION_HEADER;
|
||||
PImageSectionHeader = ^TImageSectionHeader;
|
||||
|
||||
const
|
||||
IMAGE_SIZEOF_SECTION_HEADER = 40;
|
||||
|
||||
//
|
||||
// Section characteristics.
|
||||
//
|
||||
IMAGE_SCN_TYPE_REG = $00000000; // Reserved.
|
||||
IMAGE_SCN_TYPE_DSECT = $00000001; // Reserved.
|
||||
IMAGE_SCN_TYPE_NOLOAD = $00000002; // Reserved.
|
||||
IMAGE_SCN_TYPE_GROUP = $00000004; // Reserved.
|
||||
IMAGE_SCN_TYPE_NO_PAD = $00000008; // Reserved.
|
||||
IMAGE_SCN_TYPE_COPY = $00000010; // Reserved.
|
||||
|
||||
IMAGE_SCN_CNT_CODE = $00000020; // Section contains code.
|
||||
IMAGE_SCN_CNT_INITIALIZED_DATA = $00000040; // Section contains initialized data.
|
||||
IMAGE_SCN_CNT_UNINITIALIZED_DATA = $00000080; // Section contains uninitialized data.
|
||||
|
||||
IMAGE_SCN_LNK_OTHER = $00000100; // Reserved.
|
||||
IMAGE_SCN_LNK_INFO = $00000200; // Section contains comments or some other type of information.
|
||||
IMAGE_SCN_TYPE_OVER = $00000400; // Reserved.
|
||||
IMAGE_SCN_LNK_REMOVE = $00000800; // Section contents will not become part of image.
|
||||
IMAGE_SCN_LNK_COMDAT = $00001000; // Section contents comdat.
|
||||
// = $00002000; // Reserved.
|
||||
IMAGE_SCN_MEM_PROTECTED = $00004000; // Obsolete
|
||||
IMAGE_SCN_NO_DEFER_SPEC_EXC = $00004000; // Reset speculative exceptions handling bits in the TLB entries for this section.
|
||||
IMAGE_SCN_GPREL = $00008000; // Section content can be accessed relative to GP
|
||||
IMAGE_SCN_MEM_FARDATA = $00008000;
|
||||
IMAGE_SCN_MEM_SYSHEAP = $00010000; // Obsolete
|
||||
IMAGE_SCN_MEM_PURGEABLE = $00020000;
|
||||
IMAGE_SCN_MEM_16BIT = $00020000;
|
||||
IMAGE_SCN_MEM_LOCKED = $00040000;
|
||||
IMAGE_SCN_MEM_PRELOAD = $00080000;
|
||||
|
||||
IMAGE_SCN_ALIGN_1BYTES = $00100000; //
|
||||
IMAGE_SCN_ALIGN_2BYTES = $00200000; //
|
||||
IMAGE_SCN_ALIGN_4BYTES = $00300000; //
|
||||
IMAGE_SCN_ALIGN_8BYTES = $00400000; //
|
||||
IMAGE_SCN_ALIGN_16BYTES = $00500000; // Default alignment if no others are specified.
|
||||
IMAGE_SCN_ALIGN_32BYTES = $00600000; //
|
||||
IMAGE_SCN_ALIGN_64BYTES = $00700000; //
|
||||
IMAGE_SCN_ALIGN_128BYTES = $00800000; //
|
||||
IMAGE_SCN_ALIGN_256BYTES = $00900000; //
|
||||
IMAGE_SCN_ALIGN_512BYTES = $00A00000; //
|
||||
IMAGE_SCN_ALIGN_1024BYTES = $00B00000; //
|
||||
IMAGE_SCN_ALIGN_2048BYTES = $00C00000; //
|
||||
IMAGE_SCN_ALIGN_4096BYTES = $00D00000; //
|
||||
IMAGE_SCN_ALIGN_8192BYTES = $00E00000; //
|
||||
// Unused = $00F00000;
|
||||
IMAGE_SCN_ALIGN_MASK = $00F00000;
|
||||
|
||||
IMAGE_SCN_LNK_NRELOC_OVFL = $01000000; // Section contains extended relocations.
|
||||
IMAGE_SCN_MEM_DISCARDABLE = $02000000; // Section can be discarded.
|
||||
IMAGE_SCN_MEM_NOT_CACHED = $04000000; // Section is not cachable.
|
||||
IMAGE_SCN_MEM_NOT_PAGED = $08000000; // Section is not pageable.
|
||||
IMAGE_SCN_MEM_SHARED = $10000000; // Section is shareable.
|
||||
IMAGE_SCN_MEM_EXECUTE = $20000000; // Section is executable.
|
||||
IMAGE_SCN_MEM_READ = $40000000; // Section is readable.
|
||||
IMAGE_SCN_MEM_WRITE = $80000000; // Section is writeable.
|
||||
|
||||
//
|
||||
// TLS Chaacteristic Flags
|
||||
//
|
||||
IMAGE_SCN_SCALE_INDEX = $00000001; // Tls index is scaled
|
||||
|
||||
{$ifdef fpc}
|
||||
{$packrecords 2}
|
||||
{$endif}
|
||||
|
||||
//
|
||||
// Symbol format.
|
||||
//
|
||||
type
|
||||
TISName = {$ifndef fpc}packed{$endif} record
|
||||
case Byte of
|
||||
0: (ShortName: array[0..7] of Char);
|
||||
1: (Name: record
|
||||
Short: DWORD;
|
||||
Long: DWORD;
|
||||
end);
|
||||
2: (LongName: array[0..1] of DWORD) ;
|
||||
end;
|
||||
|
||||
_IMAGE_SYMBOL = {$ifndef fpc}packed{$endif} record
|
||||
N: TISName;
|
||||
Value: DWORD;
|
||||
SectionNumber: SHORT;
|
||||
_Type: WORD;
|
||||
StorageClass: BYTE;
|
||||
NumberOfAuxSymbols: BYTE;
|
||||
end;
|
||||
IMAGE_SYMBOL = _IMAGE_SYMBOL;
|
||||
TImageSymbol = _IMAGE_SYMBOL;
|
||||
PImageSymbol = ^TImageSymbol;
|
||||
|
||||
const
|
||||
IMAGE_SIZEOF_SYMBOL = 18;
|
||||
|
||||
//
|
||||
// Section values.
|
||||
//
|
||||
// Symbols have a section number of the section in which they are
|
||||
// defined. Otherwise, section numbers have the following meanings:
|
||||
//
|
||||
|
||||
IMAGE_SYM_UNDEFINED = SHORT(0); // Symbol is undefined or is common.
|
||||
IMAGE_SYM_ABSOLUTE = SHORT(-1); // Symbol is an absolute value.
|
||||
IMAGE_SYM_DEBUG = SHORT(-2); // Symbol is a special debug item.
|
||||
IMAGE_SYM_SECTION_MAX = $FEFF; // Values = $FF00-= $FFFF are special
|
||||
|
||||
//
|
||||
// Type (fundamental) values.
|
||||
//
|
||||
|
||||
IMAGE_SYM_TYPE_NULL = $0000; // no type.
|
||||
IMAGE_SYM_TYPE_VOID = $0001; //
|
||||
IMAGE_SYM_TYPE_CHAR = $0002; // type character.
|
||||
IMAGE_SYM_TYPE_SHORT = $0003; // type short integer.
|
||||
IMAGE_SYM_TYPE_INT = $0004; //
|
||||
IMAGE_SYM_TYPE_LONG = $0005; //
|
||||
IMAGE_SYM_TYPE_FLOAT = $0006; //
|
||||
IMAGE_SYM_TYPE_DOUBLE = $0007; //
|
||||
IMAGE_SYM_TYPE_STRUCT = $0008; //
|
||||
IMAGE_SYM_TYPE_UNION = $0009; //
|
||||
IMAGE_SYM_TYPE_ENUM = $000A; // enumeration.
|
||||
IMAGE_SYM_TYPE_MOE = $000B; // member of enumeration.
|
||||
IMAGE_SYM_TYPE_BYTE = $000C; //
|
||||
IMAGE_SYM_TYPE_WORD = $000D; //
|
||||
IMAGE_SYM_TYPE_UINT = $000E; //
|
||||
IMAGE_SYM_TYPE_DWORD = $000F; //
|
||||
IMAGE_SYM_TYPE_PCODE = $8000; //
|
||||
//
|
||||
// Type (derived) values.
|
||||
//
|
||||
|
||||
IMAGE_SYM_DTYPE_NULL = 0; // no derived type.
|
||||
IMAGE_SYM_DTYPE_POINTER = 1; // pointer.
|
||||
IMAGE_SYM_DTYPE_FUNCTION = 2; // function.
|
||||
IMAGE_SYM_DTYPE_ARRAY = 3; // array.
|
||||
|
||||
//
|
||||
// Storage classes.
|
||||
//
|
||||
IMAGE_SYM_CLASS_END_OF_FUNCTION = High(BYTE);
|
||||
IMAGE_SYM_CLASS_NULL = $0000;
|
||||
IMAGE_SYM_CLASS_AUTOMATIC = $0001;
|
||||
IMAGE_SYM_CLASS_EXTERNAL = $0002;
|
||||
IMAGE_SYM_CLASS_STATIC = $0003;
|
||||
IMAGE_SYM_CLASS_REGISTER = $0004;
|
||||
IMAGE_SYM_CLASS_EXTERNAL_DEF = $0005;
|
||||
IMAGE_SYM_CLASS_LABEL = $0006;
|
||||
IMAGE_SYM_CLASS_UNDEFINED_LABEL = $0007;
|
||||
IMAGE_SYM_CLASS_MEMBER_OF_STRUCT = $0008;
|
||||
IMAGE_SYM_CLASS_ARGUMENT = $0009;
|
||||
IMAGE_SYM_CLASS_STRUCT_TAG = $000A;
|
||||
IMAGE_SYM_CLASS_MEMBER_OF_UNION = $000B;
|
||||
IMAGE_SYM_CLASS_UNION_TAG = $000C;
|
||||
IMAGE_SYM_CLASS_TYPE_DEFINITION = $000D;
|
||||
IMAGE_SYM_CLASS_UNDEFINED_STATIC = $000E;
|
||||
IMAGE_SYM_CLASS_ENUM_TAG = $000F;
|
||||
IMAGE_SYM_CLASS_MEMBER_OF_ENUM = $0010;
|
||||
IMAGE_SYM_CLASS_REGISTER_PARAM = $0011;
|
||||
IMAGE_SYM_CLASS_BIT_FIELD = $0012;
|
||||
|
||||
IMAGE_SYM_CLASS_FAR_EXTERNAL = $0044; //
|
||||
|
||||
IMAGE_SYM_CLASS_BLOCK = $0064;
|
||||
IMAGE_SYM_CLASS_FUNCTION = $0065;
|
||||
IMAGE_SYM_CLASS_END_OF_STRUCT = $0066;
|
||||
IMAGE_SYM_CLASS_FILE = $0067;
|
||||
// new
|
||||
IMAGE_SYM_CLASS_SECTION = $0068;
|
||||
IMAGE_SYM_CLASS_WEAK_EXTERNAL = $0069;
|
||||
|
||||
IMAGE_SYM_CLASS_CLR_TOKEN = $006B;
|
||||
|
||||
// type packing constants
|
||||
|
||||
N_BTMASK = $000F;
|
||||
N_TMASK = $0030;
|
||||
N_TMASK1 = $00C0;
|
||||
N_TMASK2 = $00F0;
|
||||
N_BTSHFT = 4;
|
||||
N_TSHIFT = 2;
|
||||
|
||||
// MACROS
|
||||
|
||||
// Basic Type of x
|
||||
function BTYPE(x: Byte): Byte; {$ifdef fpc}inline;{$endif}
|
||||
|
||||
// Is x a pointer?
|
||||
function ISPTR(x: Byte): Boolean; {$ifdef fpc}inline;{$endif}
|
||||
|
||||
// Is x a function?
|
||||
function ISFCN(x: Byte): Boolean; {$ifdef fpc}inline;{$endif}
|
||||
|
||||
// Is x an array?
|
||||
function ISARY(x: Byte): Boolean; {$ifdef fpc}inline;{$endif}
|
||||
|
||||
// Is x a structure, union, or enumeration TAG?
|
||||
function ISTAG(x: Byte): Boolean; {$ifdef fpc}inline;{$endif}
|
||||
|
||||
function INCREF(x: Byte): Byte; {$ifdef fpc}inline;{$endif}
|
||||
|
||||
function DECREF(x: Byte): Byte; {$ifdef fpc}inline;{$endif}
|
||||
|
||||
//
|
||||
// Auxiliary entry format.
|
||||
//
|
||||
type
|
||||
TIASMisc = record
|
||||
case Byte of
|
||||
0: (
|
||||
Linenumber: WORD; // declaration line number
|
||||
Size: WORD; // size of struct, union, or enum
|
||||
);
|
||||
1: (
|
||||
LnSz: record
|
||||
Linenumber: WORD; // declaration line number
|
||||
Size: WORD; // size of struct, union, or enum
|
||||
end;
|
||||
);
|
||||
2: (TotalSize: DWORD);
|
||||
end;
|
||||
|
||||
TIASFcnAry = packed record
|
||||
case Byte of
|
||||
0: (
|
||||
_Function: record // if ISFCN, tag, or .bb
|
||||
PointerToLinenumber: DWORD;
|
||||
PointerToNextFunction: DWORD;
|
||||
end;
|
||||
);
|
||||
1: (
|
||||
_Array: packed record // if ISARY, up to 4 dimen.
|
||||
Dimension: array[0..3] of WORD;
|
||||
end;
|
||||
);
|
||||
end;
|
||||
|
||||
_IMAGE_AUX_SYMBOL = record
|
||||
case Byte of
|
||||
0: (
|
||||
Sym: record
|
||||
TagIndex: DWORD; // struct, union, or enum tag index
|
||||
Misc: TIASMisc;
|
||||
FcnAry: TIASFcnAry;
|
||||
TvIndex: WORD; // tv index
|
||||
end;
|
||||
);
|
||||
1: (
|
||||
_File: record
|
||||
Name: array[0..IMAGE_SIZEOF_SYMBOL-1] of BYTE;
|
||||
end;
|
||||
);
|
||||
2: (
|
||||
Section: record
|
||||
Length: DWORD; // section length
|
||||
NumberOfRelocations: WORD; // number of relocation entries
|
||||
NumberOfLinenumbers: WORD; // number of line numbers
|
||||
CheckSum: DWORD; // checksum for communal
|
||||
Number: SHORT; // section number to associate with
|
||||
Selection: BYTE; // communal selection type
|
||||
end;
|
||||
);
|
||||
end;
|
||||
IMAGE_AUX_SYMBOL = _IMAGE_AUX_SYMBOL;
|
||||
TImageAuxSymbol = _IMAGE_AUX_SYMBOL;
|
||||
PImageAuxSymbol = ^TImageAuxSymbol;
|
||||
|
||||
|
||||
const
|
||||
IMAGE_SIZEOF_AUX_SYMBOL = 18;
|
||||
|
||||
type
|
||||
IMAGE_AUX_SYMBOL_TYPE = (
|
||||
IMAGE_AUX_SYMBOL_TYPE_TOKEN_DEF = 1
|
||||
);
|
||||
TImageAuxSymbolType = IMAGE_AUX_SYMBOL_TYPE;
|
||||
|
||||
{$ifdef fpc}{$packRecords 2}{$endif}
|
||||
|
||||
type
|
||||
IMAGE_AUX_SYMBOL_TOKEN_DEF = packed record
|
||||
bAuxType: BYTE; // IMAGE_AUX_SYMBOL_TYPE
|
||||
bReserved: BYTE; // Must be 0
|
||||
SymbolTableIndex: DWORD;
|
||||
rgbReserved: array [0..11] of BYTE; // Must be 0
|
||||
end;
|
||||
TImageAuxSymbolTokenDef = IMAGE_AUX_SYMBOL_TOKEN_DEF;
|
||||
PImageAuxSymbolTokenDef = ^TImageAuxSymbolTokenDef;
|
||||
|
||||
{$ifdef fpc}{$packRecords 2}{$endif}
|
||||
|
||||
implementation
|
||||
|
||||
function BTYPE(x: Byte): Byte; {$ifdef fpc}inline;{$endif}
|
||||
begin
|
||||
Result := x and N_BTMASK;
|
||||
end;
|
||||
|
||||
function ISPTR(x: Byte): Boolean; {$ifdef fpc}inline;{$endif}
|
||||
begin
|
||||
Result := (x and N_TMASK) = (IMAGE_SYM_DTYPE_POINTER shl N_BTSHFT);
|
||||
end;
|
||||
|
||||
function ISFCN(x: Byte): Boolean; {$ifdef fpc}inline;{$endif}
|
||||
begin
|
||||
Result := (x and N_TMASK) = (IMAGE_SYM_DTYPE_FUNCTION shl N_BTSHFT);
|
||||
end;
|
||||
|
||||
function ISARY(x: Byte): Boolean; {$ifdef fpc}inline;{$endif}
|
||||
begin
|
||||
Result := (x and N_TMASK) = (IMAGE_SYM_DTYPE_ARRAY shl N_BTSHFT);
|
||||
end;
|
||||
|
||||
function ISTAG(x: Byte): Boolean; {$ifdef fpc}inline;{$endif}
|
||||
begin
|
||||
Result := (x = IMAGE_SYM_CLASS_STRUCT_TAG) or (x = IMAGE_SYM_CLASS_UNION_TAG) or (x = IMAGE_SYM_CLASS_ENUM_TAG);
|
||||
end;
|
||||
|
||||
function INCREF(x: Byte): Byte; {$ifdef fpc}inline;{$endif}
|
||||
begin
|
||||
Result := ((x and not N_BTMASK) shl N_TSHIFT) or (IMAGE_SYM_DTYPE_POINTER shl N_BTSHFT) or (x and N_BTMASK);
|
||||
end;
|
||||
|
||||
function DECREF(x: Byte): Byte; {$ifdef fpc}inline;{$endif}
|
||||
begin
|
||||
Result := ((x shr N_TSHIFT) and not N_BTMASK) or (x and N_BTMASK);
|
||||
end;
|
||||
|
||||
|
||||
end.
|
Loading…
Reference in New Issue
Block a user