FPDebug: refactored reading image-file, ported elf reader from duby

git-svn-id: trunk@42925 -
This commit is contained in:
martin 2013-09-24 23:56:45 +00:00
parent ff8b5f7a1b
commit b37ec153f8
11 changed files with 2038 additions and 210 deletions

5
.gitattributes vendored
View File

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

View 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

View File

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

View File

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

View File

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

View File

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

View File

@ -8,7 +8,8 @@ interface
uses
FpDbgClasses, FpDbgDisasX86, FpDbgDwarf, FpDbgDwarfConst, FpDbgLoader, FpDbgPETypes,
FpDbgSymbols, FpDbgUtil, FpDbgWinExtra, LazarusPackageIntf;
FpDbgSymbols, FpDbgUtil, FpDbgWinExtra, FpImgReaderWinPE, FpImgReaderElf,
FpImgReaderElfTypes, LazarusPackageIntf;
implementation

View 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.

View 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 processs 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 instructions 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 entrys relocation type or symbol
table index, it means the result of applyingELF32_R_TYPEorELF32_R_SYM, respectively,
to the entrysr_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.

View 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.

View 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.