4835 lines
160 KiB
ObjectPascal
4835 lines
160 KiB
ObjectPascal
{**************************************************************************************************}
|
|
{ }
|
|
{ Project JEDI Code Library (JCL) }
|
|
{ }
|
|
{ The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); }
|
|
{ you may not use this file except in compliance with the License. You may obtain a copy of the }
|
|
{ License at http://www.mozilla.org/MPL/ }
|
|
{ }
|
|
{ Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF }
|
|
{ ANY KIND, either express or implied. See the License for the specific language governing rights }
|
|
{ and limitations under the License. }
|
|
{ }
|
|
{ The Original Code is JclMetadata.pas. }
|
|
{ }
|
|
{ The Initial Developer of the Original Code is Flier Lu (<flier_lu att yahoo dott com dott cn>). }
|
|
{ Portions created by Flier Lu are Copyright (C) Flier Lu. All Rights Reserved. }
|
|
{ }
|
|
{ Contributors: }
|
|
{ Flier Lu (flier) }
|
|
{ Robert Marquardt (marquardt) }
|
|
{ Olivier Sannier (obones) }
|
|
{ }
|
|
{**************************************************************************************************}
|
|
{ }
|
|
{ Microsoft .Net framework Clr information support routines and classes. }
|
|
{ }
|
|
{ Unit owner: Flier Lu }
|
|
{ }
|
|
{**************************************************************************************************}
|
|
|
|
// Last modified: $Date: 2006-08-11 17:24:18 +0200 (ven., 11 août 2006) $
|
|
|
|
unit JclMetadata;
|
|
|
|
{$I jcl.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
{$IFDEF UNITVERSIONING}
|
|
JclUnitVersioning,
|
|
{$ENDIF UNITVERSIONING}
|
|
{$IFDEF MSWINDOWS}
|
|
Windows,
|
|
{$ENDIF MSWINDOWS}
|
|
Classes, SysUtils,
|
|
{$IFDEF RTL130_UP}
|
|
Contnrs,
|
|
{$ENDIF RTL130_UP}
|
|
JclBase, JclClr, JclFileUtils, JclPeImage, JclSysUtils;
|
|
|
|
type
|
|
TJclClrElementType = (etEnd, etVoid, etBoolean, etChar,
|
|
etI1, etU1, etI2, etU2, etI4, etU4, etI8, etU8, etR4, etR8, etString,
|
|
etPtr, etByRef, etValueType, etClass, etArray, etTypedByRef,
|
|
etI, etU, etFnPtr, etObject, etSzArray, etCModReqd, etCModOpt,
|
|
etInternal, etMax, etModifier, etSentinel, etPinned);
|
|
|
|
TJclClrTableModuleRow = class(TJclClrTableRow)
|
|
private
|
|
FGeneration: Word;
|
|
FNameOffset: DWORD;
|
|
FMvidIdx: DWORD;
|
|
FEncIdIdx: DWORD;
|
|
FEncBaseIdIdx: DWORD;
|
|
function GetMvid: TGUID;
|
|
function GetName: WideString;
|
|
function GetEncBaseId: TGUID;
|
|
function GetEncId: TGUID;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
function DumpIL: string; override;
|
|
|
|
function HasEncId: Boolean;
|
|
function HasEncBaseId: Boolean;
|
|
|
|
property Generation: Word read FGeneration;
|
|
property NameOffset: DWORD read FNameOffset;
|
|
property MvidIdx: DWORD read FMvidIdx;
|
|
property EncIdIdx: DWORD read FEncIdIdx;
|
|
property EncBaseIdIdx: DWORD read FEncBaseIdIdx;
|
|
|
|
property Name: WideString read GetName;
|
|
property Mvid: TGUID read GetMvid;
|
|
property EncId: TGUID read GetEncId;
|
|
property EncBaseId: TGUID read GetEncBaseId;
|
|
end;
|
|
|
|
TJclClrTableModule = class(TJclClrTable, ITableCanDumpIL)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableModuleRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableModuleRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableModuleRefRow = class(TJclClrTableRow)
|
|
private
|
|
FNameOffset: DWORD;
|
|
function GetName: WideString;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
function DumpIL: string; override;
|
|
property NameOffset: DWORD read FNameOffset;
|
|
property Name: WideString read GetName;
|
|
end;
|
|
|
|
TJclClrTableModuleRef = class(TJclClrTable, ITableCanDumpIL)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableModuleRefRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableModuleRefRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrAssemblyFlag =
|
|
(cafPublicKey, cafCompatibilityMask, cafSideBySideCompatible,
|
|
cafNonSideBySideAppDomain, cafNonSideBySideProcess,
|
|
cafNonSideBySideMachine, cafEnableJITcompileTracking,
|
|
cafDisableJITcompileOptimizer);
|
|
TJclClrAssemblyFlags = set of TJclClrAssemblyFlag;
|
|
|
|
TJclClrTableAssemblyRow = class(TJclClrTableRow)
|
|
private
|
|
FCultureOffset: DWORD;
|
|
FPublicKeyOffset: DWORD;
|
|
FHashAlgId: DWORD;
|
|
FNameOffset: DWORD;
|
|
FMajorVersion: Word;
|
|
FBuildNumber: Word;
|
|
FRevisionNumber: Word;
|
|
FMinorVersion: Word;
|
|
FFlagMask: DWORD;
|
|
function GetCulture: WideString;
|
|
function GetName: WideString;
|
|
function GetPublicKey: TJclClrBlobRecord;
|
|
function GetVersion: string;
|
|
function GetFlags: TJclClrAssemblyFlags;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
function DumpIL: string; override;
|
|
|
|
class function AssemblyFlags(const Flags: TJclClrAssemblyFlags): DWORD; overload;
|
|
class function AssemblyFlags(const Flags: DWORD): TJclClrAssemblyFlags; overload;
|
|
|
|
property HashAlgId: DWORD read FHashAlgId;
|
|
property MajorVersion: Word read FMajorVersion;
|
|
property MinorVersion: Word read FMinorVersion;
|
|
property BuildNumber: Word read FBuildNumber;
|
|
property RevisionNumber: Word read FRevisionNumber;
|
|
property FlagMask: DWORD read FFlagMask;
|
|
property PublicKeyOffset: DWORD read FPublicKeyOffset;
|
|
property NameOffset: DWORD read FNameOffset;
|
|
property CultureOffset: DWORD read FCultureOffset;
|
|
|
|
property PublicKey: TJclClrBlobRecord read GetPublicKey;
|
|
property Name: WideString read GetName;
|
|
property Culture: WideString read GetCulture;
|
|
property Version: string read GetVersion;
|
|
property Flags: TJclClrAssemblyFlags read GetFlags;
|
|
end;
|
|
|
|
TJclClrTableAssembly = class(TJclClrTable, ITableCanDumpIL)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableAssemblyRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableAssemblyRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableAssemblyOSRow = class(TJclClrTableRow)
|
|
private
|
|
FPlatformID: DWORD;
|
|
FMajorVersion: DWORD;
|
|
FMinorVersion: DWORD;
|
|
function GetVersion: string;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
property PlatformID: DWORD read FPlatformID;
|
|
property MajorVersion: DWORD read FMajorVersion;
|
|
property MinorVersion: DWORD read FMinorVersion;
|
|
property Version: string read GetVersion;
|
|
end;
|
|
|
|
TJclClrTableAssemblyOS = class(TJclClrTable)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableAssemblyOSRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableAssemblyOSRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableAssemblyProcessorRow = class(TJclClrTableRow)
|
|
private
|
|
FProcessor: DWORD;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
property Processor: DWORD read FProcessor;
|
|
end;
|
|
|
|
TJclClrTableAssemblyProcessor = class(TJclClrTable)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableAssemblyProcessorRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableAssemblyProcessorRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableAssemblyRefRow = class(TJclClrTableRow)
|
|
private
|
|
FCultureOffset: DWORD;
|
|
FNameOffset: DWORD;
|
|
FPublicKeyOrTokenOffset: DWORD;
|
|
FHashValueOffset: DWORD;
|
|
FMajorVersion: Word;
|
|
FRevisionNumber: Word;
|
|
FBuildNumber: Word;
|
|
FMinorVersion: Word;
|
|
FFlagMask: DWORD;
|
|
function GetCulture: WideString;
|
|
function GetHashValue: TJclClrBlobRecord;
|
|
function GetName: WideString;
|
|
function GetPublicKeyOrToken: TJclClrBlobRecord;
|
|
function GetVersion: string;
|
|
function GetFlags: TJclClrAssemblyFlags;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
function DumpIL: string; override;
|
|
|
|
property MajorVersion: Word read FMajorVersion;
|
|
property MinorVersion: Word read FMinorVersion;
|
|
property BuildNumber: Word read FBuildNumber;
|
|
property RevisionNumber: Word read FRevisionNumber;
|
|
property FlagMask: DWORD read FFlagMask;
|
|
property PublicKeyOrTokenOffset: DWORD read FPublicKeyOrTokenOffset;
|
|
property NameOffset: DWORD read FNameOffset;
|
|
property CultureOffset: DWORD read FCultureOffset;
|
|
property HashValueOffset: DWORD read FHashValueOffset;
|
|
|
|
property PublicKeyOrToken: TJclClrBlobRecord read GetPublicKeyOrToken;
|
|
property Name: WideString read GetName;
|
|
property Culture: WideString read GetCulture;
|
|
property Version: string read GetVersion;
|
|
property HashValue: TJclClrBlobRecord read GetHashValue;
|
|
property Flags: TJclClrAssemblyFlags read GetFlags;
|
|
end;
|
|
|
|
TJclClrTableAssemblyRef = class(TJclClrTable, ITableCanDumpIL)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableAssemblyRefRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableAssemblyRefRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableAssemblyRefOSRow = class(TJclClrTableAssemblyOSRow)
|
|
private
|
|
FAssemblyRefIdx: DWORD;
|
|
function GetAssemblyRef: TJclClrTableAssemblyRefRow;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
property AssemblyRefIdx: DWORD read FAssemblyRefIdx;
|
|
property AssemblyRef: TJclClrTableAssemblyRefRow read GetAssemblyRef;
|
|
end;
|
|
|
|
TJclClrTableAssemblyRefOS = class(TJclClrTableAssemblyOS)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableAssemblyRefOSRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableAssemblyRefOSRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableAssemblyRefProcessorRow = class(TJclClrTableAssemblyProcessorRow)
|
|
private
|
|
FAssemblyRefIdx: DWORD;
|
|
function GetAssemblyRef: TJclClrTableAssemblyRefRow;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
property AssemblyRefIdx: DWORD read FAssemblyRefIdx;
|
|
property AssemblyRef: TJclClrTableAssemblyRefRow read GetAssemblyRef;
|
|
end;
|
|
|
|
TJclClrTableAssemblyRefProcessor = class(TJclClrTableAssemblyProcessor)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableAssemblyRefProcessorRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableAssemblyRefProcessorRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableClassLayoutRow = class(TJclClrTableRow)
|
|
private
|
|
FClassSize: DWORD;
|
|
FParentIdx: DWORD;
|
|
FPackingSize: Word;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
property PackingSize: Word read FPackingSize;
|
|
property ClassSize: DWORD read FClassSize;
|
|
property ParentIdx: DWORD read FParentIdx;
|
|
end;
|
|
|
|
TJclClrTableClassLayout = class(TJclClrTable)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableClassLayoutRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableClassLayoutRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableConstantRow = class(TJclClrTableRow)
|
|
private
|
|
FKind: Byte;
|
|
FParentIdx: DWORD;
|
|
FValueOffset: DWORD;
|
|
function GetElementType: TJclClrElementType;
|
|
function GetParent: TJclClrTableRow;
|
|
function GetValue: TJclClrBlobRecord;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
function DumpIL: string; override;
|
|
|
|
property Kind: Byte read FKind;
|
|
property ParentIdx: DWORD read FParentIdx;
|
|
property ValueOffset: DWORD read FValueOffset;
|
|
|
|
property ElementType: TJclClrElementType read GetElementType;
|
|
property Parent: TJclClrTableRow read GetParent;
|
|
property Value: TJclClrBlobRecord read GetValue;
|
|
end;
|
|
|
|
TJclClrTableConstant = class(TJclClrTable)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableConstantRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableConstantRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableCustomAttributeRow = class(TJclClrTableRow)
|
|
private
|
|
FParentIdx: DWORD;
|
|
FTypeIdx: DWORD;
|
|
FValueOffset: DWORD;
|
|
function GetValue: TJclClrBlobRecord;
|
|
function GetParent: TJclClrTableRow;
|
|
function GetMethod: TJclClrTableRow;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
function DumpIL: string; override;
|
|
|
|
property ParentIdx: DWORD read FParentIdx;
|
|
property TypeIdx: DWORD read FTypeIdx;
|
|
property ValueOffset: DWORD read FValueOffset;
|
|
|
|
property Parent: TJclClrTableRow read GetParent;
|
|
property Method: TJclClrTableRow read GetMethod;
|
|
property Value: TJclClrBlobRecord read GetValue;
|
|
end;
|
|
|
|
TJclClrTableCustomAttribute = class(TJclClrTable)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableCustomAttributeRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableCustomAttributeRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableDeclSecurityRow = class(TJclClrTableRow)
|
|
private
|
|
FPermissionSetOffset: DWORD;
|
|
FParentIdx: DWORD;
|
|
FAction: Word;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
property Action: Word read FAction;
|
|
property ParentIdx: DWORD read FParentIdx;
|
|
property PermissionSetOffset: DWORD read FPermissionSetOffset;
|
|
end;
|
|
|
|
TJclClrTableDeclSecurity = class(TJclClrTable)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableDeclSecurityRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableDeclSecurityRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableEventMapRow = class(TJclClrTableRow)
|
|
private
|
|
FEventListIdx: DWORD;
|
|
FParentIdx: DWORD;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
property ParentIdx: DWORD read FParentIdx;
|
|
property EventListIdx: DWORD read FEventListIdx;
|
|
end;
|
|
|
|
TJclClrTableEventMap = class(TJclClrTable)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableEventMapRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableEventMapRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableEventFlag = (efSpecialName, efRTSpecialName);
|
|
TJclClrTableEventFlags = set of TJclClrTableEventFlag;
|
|
|
|
TJclClrTableEventDefRow = class(TJclClrTableRow)
|
|
private
|
|
FNameOffset: DWORD;
|
|
FEventTypeIdx: DWORD;
|
|
FEventFlags: Word;
|
|
function GetName: WideString;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
property EventFlags: Word read FEventFlags;
|
|
property NameOffset: DWORD read FNameOffset;
|
|
property EventTypeIdx: DWORD read FEventTypeIdx;
|
|
property Name: WideString read GetName;
|
|
end;
|
|
|
|
TJclClrTableEventDef = class(TJclClrTable)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableEventDefRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableEventDefRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableExportedTypeRow = class(TJclClrTableRow)
|
|
private
|
|
FTypeDefIdx: DWORD;
|
|
FFlags: DWORD;
|
|
FImplementationIdx: DWORD;
|
|
FTypeNamespaceOffset: DWORD;
|
|
FTypeNameOffset: DWORD;
|
|
function GetTypeName: WideString;
|
|
function GetTypeNamespace: WideString;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
property Flags: DWORD read FFlags;
|
|
property TypeDefIdx: DWORD read FTypeDefIdx;
|
|
property TypeNameOffset: DWORD read FTypeNameOffset;
|
|
property TypeNamespaceOffset: DWORD read FTypeNamespaceOffset;
|
|
property ImplementationIdx: DWORD read FImplementationIdx;
|
|
property TypeName: WideString read GetTypeName;
|
|
property TypeNamespace: WideString read GetTypeNamespace;
|
|
end;
|
|
|
|
TJclClrTableEventPtrRow = class(TJclClrTableRow)
|
|
private
|
|
FEventIdx: DWORD;
|
|
function GetEvent: TJclClrTableEventDefRow;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
property EventIdx: DWORD read FEventIdx;
|
|
property Event: TJclClrTableEventDefRow read GetEvent;
|
|
end;
|
|
|
|
TJclClrTableEventPtr = class(TJclClrTable)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableEventPtrRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableEventPtrRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableExportedType = class(TJclClrTable)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableExportedTypeRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableExportedTypeRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableTypeDefRow = class;
|
|
|
|
TJclClrTableFieldDefVisibility =
|
|
(fvPrivateScope, fvPrivate, fvFamANDAssem,
|
|
fvAssembly, fvFamily, fvFamORAssem, fvPublic);
|
|
|
|
TJclClrTableFieldDefFlag =
|
|
(ffStatic, ffInitOnly, ffLiteral, ffNotSerialized,
|
|
ffSpecialName, ffPinvokeImpl, ffRTSpecialName,
|
|
ffHasFieldMarshal, ffHasDefault, ffHasFieldRVA);
|
|
TJclClrTableFieldDefFlags = set of TJclClrTableFieldDefFlag;
|
|
|
|
TJclClrTableFieldDefRow = class(TJclClrTableRow)
|
|
private
|
|
FFlags: Word;
|
|
FNameOffset: DWORD;
|
|
FSignatureOffset: DWORD;
|
|
FParentToken: TJclClrTableTypeDefRow;
|
|
function GetName: WideString;
|
|
function GetSignature: TJclClrBlobRecord;
|
|
function GetFlag: TJclClrTableFieldDefFlags;
|
|
function GetVisibility: TJclClrTableFieldDefVisibility;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
procedure SetParentToken(const ARow: TJclClrTableTypeDefRow);
|
|
public
|
|
function DumpIL: string; override;
|
|
|
|
property RawFlags: Word read FFlags;
|
|
property NameOffset: DWORD read FNameOffset;
|
|
property SignatureOffset: DWORD read FSignatureOffset;
|
|
|
|
property Name: WideString read GetName;
|
|
property Signature: TJclClrBlobRecord read GetSignature;
|
|
|
|
property ParentToken: TJclClrTableTypeDefRow read FParentToken;
|
|
property Visibility: TJclClrTableFieldDefVisibility read GetVisibility;
|
|
property Flags: TJclClrTableFieldDefFlags read GetFlag;
|
|
end;
|
|
|
|
TJclClrTableFieldDef = class(TJclClrTable)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableFieldDefRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableFieldDefRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableFieldPtrRow = class(TJclClrTableRow)
|
|
private
|
|
FFieldIdx: DWORD;
|
|
function GetField: TJclClrTableFieldDefRow;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
property FieldIdx: DWORD read FFieldIdx;
|
|
property Field: TJclClrTableFieldDefRow read GetField;
|
|
end;
|
|
|
|
TJclClrTableFieldPtr = class(TJclClrTable)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableFieldPtrRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableFieldPtrRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableFieldLayoutRow = class(TJclClrTableRow)
|
|
private
|
|
FOffset: DWORD;
|
|
FFieldIdx: DWORD;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
property Offset: DWORD read FOffset;
|
|
property FieldIdx: DWORD read FFieldIdx;
|
|
end;
|
|
|
|
TJclClrTableFieldLayout = class(TJclClrTable)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableFieldLayoutRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableFieldLayoutRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableFieldMarshalRow = class(TJclClrTableRow)
|
|
private
|
|
FParentIdx: DWORD;
|
|
FNativeTypeOffset: DWORD;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
property ParentIdx: DWORD read FParentIdx;
|
|
property NativeTypeOffset: DWORD read FNativeTypeOffset;
|
|
end;
|
|
|
|
TJclClrTableFieldMarshal = class(TJclClrTable)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableFieldMarshalRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableFieldMarshalRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableFieldRVARow = class(TJclClrTableRow)
|
|
private
|
|
FRVA: DWORD;
|
|
FFieldIdx: DWORD;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
property RVA: DWORD read FRVA;
|
|
property FieldIdx: DWORD read FFieldIdx;
|
|
end;
|
|
|
|
TJclClrTableFieldRVA = class(TJclClrTable)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableFieldRVARow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableFieldRVARow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableFileRow = class(TJclClrTableRow)
|
|
private
|
|
FHashValueOffset: DWORD;
|
|
FNameOffset: DWORD;
|
|
FFlags: DWORD;
|
|
function GetName: WideString;
|
|
function GetHashValue: TJclClrBlobRecord;
|
|
function GetContainsMetadata: Boolean;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
function DumpIL: string; override;
|
|
|
|
property Flags: DWORD read FFlags;
|
|
property NameOffset: DWORD read FNameOffset;
|
|
property HashValueOffset: DWORD read FHashValueOffset;
|
|
|
|
property Name: WideString read GetName;
|
|
property HashValue: TJclClrBlobRecord read GetHashValue;
|
|
property ContainsMetadata: Boolean read GetContainsMetadata;
|
|
end;
|
|
|
|
TJclClrTableFile = class(TJclClrTable, ITableCanDumpIL)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableFileRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableFileRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableImplMapRow = class(TJclClrTableRow)
|
|
private
|
|
FImportNameOffset: DWORD;
|
|
FMemberForwardedIdx: DWORD;
|
|
FImportScopeIdx: DWORD;
|
|
FMappingFlags: Word;
|
|
function GetImportName: WideString;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
property MappingFlags: Word read FMappingFlags;
|
|
property MemberForwardedIdx: DWORD read FMemberForwardedIdx;
|
|
property ImportNameOffset: DWORD read FImportNameOffset;
|
|
property ImportScopeIdx: DWORD read FImportScopeIdx;
|
|
property ImportName: WideString read GetImportName;
|
|
end;
|
|
|
|
TJclClrTableImplMap = class(TJclClrTable)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableImplMapRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableImplMapRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableInterfaceImplRow = class(TJclClrTableRow)
|
|
private
|
|
FInterfaceIdx: DWORD;
|
|
FClassIdx: DWORD;
|
|
function GetImplClass: TJclClrTableRow;
|
|
function GetImplInterface: TJclClrTableRow;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
function DumpIL: string; override;
|
|
|
|
property ClassIdx: DWORD read FClassIdx;
|
|
property InterfaceIdx: DWORD read FInterfaceIdx;
|
|
|
|
property ImplClass: TJclClrTableRow read GetImplClass;
|
|
property ImplInterface: TJclClrTableRow read GetImplInterface;
|
|
end;
|
|
|
|
TJclClrTableInterfaceImpl = class(TJclClrTable)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableInterfaceImplRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableInterfaceImplRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableManifestResourceVisibility = (rvPublic, rvPrivate);
|
|
|
|
TJclClrTableManifestResourceRow = class(TJclClrTableRow)
|
|
private
|
|
FOffset: DWORD;
|
|
FFlags: DWORD;
|
|
FImplementationIdx: DWORD;
|
|
FNameOffset: DWORD;
|
|
function GetName: WideString;
|
|
function GetVisibility: TJclClrTableManifestResourceVisibility;
|
|
function GetImplementationRow: TJclClrTableRow;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
function DumpIL: string; override;
|
|
|
|
property Offset: DWORD read FOffset;
|
|
property Flags: DWORD read FFlags;
|
|
property NameOffset: DWORD read FNameOffset;
|
|
property ImplementationIdx: DWORD read FImplementationIdx;
|
|
|
|
property Name: WideString read GetName;
|
|
property Visibility: TJclClrTableManifestResourceVisibility read GetVisibility;
|
|
property ImplementationRow: TJclClrTableRow read GetImplementationRow;
|
|
end;
|
|
|
|
TJclClrTableManifestResource = class(TJclClrTable, ITableCanDumpIL)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableManifestResourceRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableManifestResourceRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableMemberRefRow = class(TJclClrTableRow)
|
|
private
|
|
FClassIdx: DWORD;
|
|
FNameOffset: DWORD;
|
|
FSignatureOffset: DWORD;
|
|
function GetName: WideString;
|
|
function GetSignature: TJclClrBlobRecord;
|
|
function GetParentClass: TJclClrTableRow;
|
|
function GetFullName: WideString;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
property ClassIdx: DWORD read FClassIdx;
|
|
property NameOffset: DWORD read FNameOffset;
|
|
property SignatureOffset: DWORD read FSignatureOffset;
|
|
|
|
property Name: WideString read GetName;
|
|
property FullName: WideString read GetFullName;
|
|
property Signature: TJclClrBlobRecord read GetSignature;
|
|
property ParentClass: TJclClrTableRow read GetParentClass;
|
|
end;
|
|
|
|
TJclClrTableMemberRef = class(TJclClrTable)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableMemberRefRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableMemberRefRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableMethodDefRow = class;
|
|
|
|
TJclClrParamKind = (pkIn, pkOut, pkOptional, pkHasDefault, pkHasFieldMarshal);
|
|
TJclClrParamKinds = set of TJclClrParamKind;
|
|
|
|
TJclClrTableParamDefRow = class(TJclClrTableRow)
|
|
private
|
|
FFlagMask: Word;
|
|
FSequence: Word;
|
|
FNameOffset: DWORD;
|
|
FMethod: TJclClrTableMethodDefRow;
|
|
FFlags: TJclClrParamKinds;
|
|
function GetName: WideString;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
procedure SetMethod(const AMethod: TJclClrTableMethodDefRow);
|
|
public
|
|
function DumpIL: string; override;
|
|
|
|
class function ParamFlags(const AFlags: TJclClrParamKinds): Word; overload;
|
|
class function ParamFlags(const AFlags: Word): TJclClrParamKinds; overload;
|
|
|
|
property FlagMask: Word read FFlagMask;
|
|
property Sequence: Word read FSequence;
|
|
property NameOffset: DWORD read FNameOffset;
|
|
|
|
property Name: WideString read GetName;
|
|
property Method: TJclClrTableMethodDefRow read FMethod;
|
|
property Flags: TJclClrParamKinds read FFlags;
|
|
end;
|
|
|
|
TJclClrTableParamDef = class(TJclClrTable)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableParamDefRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableParamDefRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableParamPtrRow = class(TJclClrTableRow)
|
|
private
|
|
FParamIdx: DWORD;
|
|
function GetParam: TJclClrTableParamDefRow;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
property ParamIdx: DWORD read FParamIdx;
|
|
property Param: TJclClrTableParamDefRow read GetParam;
|
|
end;
|
|
|
|
TJclClrTableParamPtr = class(TJclClrTable)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableParamPtrRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableParamPtrRow read GetRow; default;
|
|
end;
|
|
|
|
IMAGE_COR_ILMETHOD_TINY = packed record
|
|
Flags_CodeSize: Byte;
|
|
end;
|
|
TImageCorILMethodTiny = IMAGE_COR_ILMETHOD_TINY;
|
|
PImageCorILMethodTiny = ^TImageCorILMethodTiny;
|
|
|
|
IMAGE_COR_ILMETHOD_FAT = packed record
|
|
Flags_Size,
|
|
MaxStack: Word;
|
|
CodeSize: DWORD;
|
|
LocalVarSigTok: TJclClrToken;
|
|
end;
|
|
TImageCorILMethodFat = IMAGE_COR_ILMETHOD_FAT;
|
|
PImageCorILMethodFat = ^TImageCorILMethodFat;
|
|
|
|
PImageCorILMethodHeader = ^TImageCorILMethodHeader;
|
|
TImageCorILMethodHeader = packed record
|
|
case Boolean of
|
|
True:
|
|
(Tiny: TImageCorILMethodTiny);
|
|
False:
|
|
(Fat: TImageCorILMethodFat);
|
|
end;
|
|
|
|
IMAGE_COR_ILMETHOD_SECT_SMALL = packed record
|
|
Kind: Byte;
|
|
Datasize: Byte;
|
|
Padding: Word;
|
|
end;
|
|
TImageCorILMethodSectSmall = IMAGE_COR_ILMETHOD_SECT_SMALL;
|
|
PImageCorILMethodSectSmall = ^TImageCorILMethodSectSmall;
|
|
|
|
IMAGE_COR_ILMETHOD_SECT_FAT = packed record
|
|
Kind_DataSize: DWORD;
|
|
end;
|
|
TImageCorILMethodSectFat = IMAGE_COR_ILMETHOD_SECT_FAT;
|
|
PImageCorILMethodSectFat = ^TImageCorILMethodSectFat;
|
|
|
|
PImageCorILMethodSectHeader = ^TImageCorILMethodSectHeader;
|
|
TImageCorILMethodSectHeader = packed record
|
|
case Boolean of
|
|
True:
|
|
(Small: TImageCorILMethodSectSmall);
|
|
False:
|
|
(Fat: TImageCorILMethodSectFat);
|
|
end;
|
|
|
|
IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT = packed record
|
|
Flags: DWORD;
|
|
TryOffset: DWORD;
|
|
TryLength: DWORD; // relative to start of try block
|
|
HandlerOffset: DWORD;
|
|
HandlerLength: DWORD; // relative to start of handler
|
|
case Boolean of
|
|
True:
|
|
(ClassToken: DWORD); // use for type-based exception handlers
|
|
False:
|
|
(FilterOffset: DWORD); // use for filter-based exception handlers (COR_ILEXCEPTION_FILTER is set)
|
|
end;
|
|
TImageCorILMethodSectEHClauseFat = IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT;
|
|
PImageCorILMethodSectEHClauseFat = ^TImageCorILMethodSectEHClauseFat;
|
|
|
|
IMAGE_COR_ILMETHOD_SECT_EH_FAT = packed record
|
|
SectFat: IMAGE_COR_ILMETHOD_SECT_FAT;
|
|
Clauses: array [0..MaxWord-1] of IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT; // actually variable size
|
|
end;
|
|
TImageCorILMethodSectEHFat = IMAGE_COR_ILMETHOD_SECT_EH_FAT;
|
|
PImageCorILMethodSectEHFat = ^TImageCorILMethodSectEHFat;
|
|
|
|
IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL = packed record
|
|
Flags,
|
|
TryOffset: Word;
|
|
TryLength: Byte; // relative to start of try block
|
|
HandlerOffset: Word;
|
|
HandlerLength: Byte; // relative to start of handler
|
|
case Boolean of
|
|
True:
|
|
(ClassToken: DWORD); // use for type-based exception handlers
|
|
False:
|
|
(FilterOffset: DWORD); // use for filter-based exception handlers (COR_ILEXCEPTION_FILTER is set)
|
|
end;
|
|
TImageCorILMethodSectEHClauseSmall = IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL;
|
|
PImageCorILMethodSectEHClauseSmall = ^TImageCorILMethodSectEHClauseSmall;
|
|
|
|
IMAGE_COR_ILMETHOD_SECT_EH_SMALL = packed record
|
|
SectSmall: IMAGE_COR_ILMETHOD_SECT_SMALL;
|
|
Clauses: array [0..MaxWord-1] of IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL; // actually variable size
|
|
end;
|
|
TImageCorILMethodSectEHSmall = IMAGE_COR_ILMETHOD_SECT_EH_SMALL;
|
|
PImageCorILMethodSectEHSmall = ^TImageCorILMethodSectEHSmall;
|
|
|
|
IMAGE_COR_ILMETHOD_SECT_EH = packed record
|
|
case Boolean of
|
|
True:
|
|
(Small: IMAGE_COR_ILMETHOD_SECT_EH_SMALL);
|
|
False:
|
|
(Fat: IMAGE_COR_ILMETHOD_SECT_EH_FAT);
|
|
end;
|
|
TImageCorILMethodSectEH = IMAGE_COR_ILMETHOD_SECT_EH;
|
|
PImageCorILMethodSectEH = ^TImageCorILMethodSectEH;
|
|
|
|
TJclClrCodeBlock = record
|
|
Offset: DWORD;
|
|
Length: DWORD;
|
|
end;
|
|
|
|
TJclClrExceptionClauseFlag = (cfException, cfFilter, cfFinally, cfFault);
|
|
TJclClrExceptionClauseFlags = set of TJclClrExceptionClauseFlag;
|
|
|
|
TJclClrExceptionHandler = class(TObject)
|
|
private
|
|
FFlags: DWORD;
|
|
FFilterOffset: DWORD;
|
|
FTryBlock: TJclClrCodeBlock;
|
|
FHandlerBlock: TJclClrCodeBlock;
|
|
FClassToken: TJclClrToken;
|
|
function GetFlags: TJclClrExceptionClauseFlags;
|
|
public
|
|
constructor Create(const EHClause: TImageCorILMethodSectEHClauseSmall); overload;
|
|
constructor Create(const EHClause: TImageCorILMethodSectEHClauseFat); overload;
|
|
|
|
property EHFlags: DWORD read FFlags;
|
|
property Flags: TJclClrExceptionClauseFlags read GetFlags;
|
|
|
|
property TryBlock: TJclClrCodeBlock read FTryBlock;
|
|
property HandlerBlock: TJclClrCodeBlock read FHandlerBlock;
|
|
|
|
property ClassToken: TJclClrToken read FClassToken;
|
|
property FilterOffset: DWORD read FFilterOffset;
|
|
end;
|
|
|
|
TJclClrSignature = class(TObject)
|
|
private
|
|
FBlob: TJclClrBlobRecord;
|
|
protected
|
|
function IsModifierType(const AElementType: TJclClrElementType): Boolean;
|
|
function IsPrimitiveType(const AElementType: TJclClrElementType): Boolean;
|
|
|
|
function Inc(var DataPtr: PJclByteArray; Step: Integer = 1): PByte;
|
|
|
|
function UncompressedDataSize(DataPtr: PJclByteArray): Integer;
|
|
function UncompressData(DataPtr: PJclByteArray; var Value: DWord): Integer;
|
|
function UncompressToken(DataPtr: PJclByteArray; var Token: TJclClrToken): Integer;
|
|
function UncompressCallingConv(DataPtr: PJclByteArray): Byte;
|
|
function UncompressSignedInt(DataPtr: PJclByteArray; var Value: Integer): Integer;
|
|
function UncompressElementType(DataPtr: PJclByteArray): TJclClrElementType;
|
|
function UncompressTypeSignature(DataPtr: PJclByteArray): string;
|
|
public
|
|
constructor Create(const ABlob: TJclClrBlobRecord);
|
|
|
|
function UncompressFieldSignature: string;
|
|
|
|
function ReadValue: DWORD;
|
|
function ReadByte: Byte;
|
|
function ReadInteger: Integer;
|
|
function ReadToken: TJclClrToken;
|
|
function ReadElementType: TJclClrElementType;
|
|
|
|
property Blob: TJclClrBlobRecord read FBlob;
|
|
end;
|
|
|
|
TJclClrArrayData = (adSize, adLowBound);
|
|
|
|
TJclClrArraySignBound = array [TJclClrArrayData] of Integer;
|
|
TJclClrArraySignBounds = array of TJclClrArraySignBound;
|
|
|
|
TJclClrArraySign = class(TJclClrSignature)
|
|
private
|
|
FBounds: TJclClrArraySignBounds;
|
|
public
|
|
constructor Create(const ABlob: TJclClrBlobRecord);
|
|
end;
|
|
|
|
TJclClrLocalVarFlag = (lvfPinned, lvfByRef);
|
|
TJclClrLocalVarFlags = set of TJclClrLocalVarFlag;
|
|
|
|
TJclClrLocalVar = class(TObject)
|
|
private
|
|
FElementType: TJclClrElementType;
|
|
FFlags: TJclClrLocalVarFlags;
|
|
FToken: TJclClrToken;
|
|
function GetName: WideString;
|
|
public
|
|
property ElementType: TJclClrElementType read FElementType write FElementType;
|
|
|
|
property Name: WideString read GetName;
|
|
property Flags: TJclClrLocalVarFlags read FFlags write FFlags;
|
|
property Token: TJclClrToken read FToken write FToken;
|
|
end;
|
|
|
|
TJclClrLocalVarSign = class(TJclClrSignature)
|
|
private
|
|
FLocalVars: TObjectList;
|
|
function GetLocalVar(const Idx: Integer): TJclClrLocalVar;
|
|
function GetLocalVarCount: Integer;
|
|
public
|
|
constructor Create(const ABlob: TJclClrBlobRecord);
|
|
destructor Destroy; override;
|
|
|
|
property LocalVars[const Idx: Integer]: TJclClrLocalVar read GetLocalVar;
|
|
property LocalVarCount: Integer read GetLocalVarCount;
|
|
end;
|
|
|
|
TJclClrMethodBody = class(TObject)
|
|
private
|
|
FMethod: TJclClrTableMethodDefRow;
|
|
FSize: DWORD;
|
|
FCode: Pointer;
|
|
FMaxStack: DWORD;
|
|
FLocalVarSignToken: TJclClrToken;
|
|
FLocalVarSign: TJclClrLocalVarSign;
|
|
FEHTable: TObjectList;
|
|
procedure AddEHTable(EHTable: PImageCorILMethodSectEH);
|
|
procedure AddOptILTable(OptILTable: Pointer; Size: Integer);
|
|
|
|
procedure ParseMoreSections(SectHeader: PImageCorILMethodSectHeader);
|
|
|
|
function GetExceptionHandler(const Idx: Integer): TJclClrExceptionHandler;
|
|
function GetExceptionHandlerCount: Integer;
|
|
function GetLocalVarSign: TJclClrLocalVarSign;
|
|
function GetLocalVarSignData: TJclClrBlobRecord;
|
|
public
|
|
constructor Create(const AMethod: TJclClrTableMethodDefRow);
|
|
destructor Destroy; override;
|
|
|
|
property Method: TJclClrTableMethodDefRow read FMethod;
|
|
|
|
property Size: DWORD read FSize;
|
|
property Code: Pointer read FCode;
|
|
|
|
property MaxStack: DWORD read FMaxStack;
|
|
property LocalVarSignToken: TJclClrToken read FLocalVarSignToken;
|
|
property LocalVarSignData: TJclClrBlobRecord read GetLocalVarSignData;
|
|
property LocalVarSign: TJclClrLocalVarSign read GetLocalVarSign;
|
|
property ExceptionHandlers[const Idx: Integer]: TJclClrExceptionHandler read GetExceptionHandler;
|
|
property ExceptionHandlerCount: Integer read GetExceptionHandlerCount;
|
|
end;
|
|
|
|
TJclClrCustomModifierSign = class(TJclClrSignature)
|
|
private
|
|
FRequired: Boolean;
|
|
FToken: TJclClrToken;
|
|
public
|
|
constructor Create(const ABlob: TJclClrBlobRecord);
|
|
property Required: Boolean read FRequired;
|
|
property Token: TJclClrToken read FToken;
|
|
end;
|
|
|
|
TJclClrMethodSign = class;
|
|
|
|
TJclClrMethodParam = class(TJclClrSignature)
|
|
private
|
|
FCustomMods: TObjectList;
|
|
FByRef: Boolean;
|
|
FElementType: TJclClrElementType;
|
|
FToken: TJclClrToken;
|
|
FMethodSign: TJclClrMethodSign;
|
|
FArraySign: TJclClrArraySign;
|
|
function GetCustomModifier(const Idx: Integer): TJclClrCustomModifierSign;
|
|
function GetCustomModifierCount: Integer;
|
|
public
|
|
constructor Create(const ABlob: TJclClrBlobRecord);
|
|
destructor Destroy; override;
|
|
|
|
property CustomModifiers[const Idx: Integer]: TJclClrCustomModifierSign read GetCustomModifier;
|
|
property CustomModifierCount: Integer read GetCustomModifierCount;
|
|
|
|
property ElementType: TJclClrElementType read FElementType;
|
|
property ByRef: Boolean read FByRef;
|
|
property Token: TJclClrToken read FToken;
|
|
property MethodSign: TJclClrMethodSign read FMethodSign;
|
|
property ArraySign: TJclClrArraySign read FArraySign;
|
|
end;
|
|
|
|
TJclClrMethodRetType = class(TJclClrMethodParam)
|
|
end;
|
|
|
|
TJclClrMethodSignFlag = (mfHasThis, mfExplicitThis, mfDefault, mfVarArg);
|
|
TJclClrMethodSignFlags = set of TJclClrMethodSignFlag;
|
|
|
|
TJclClrMethodSign = class(TJclClrSignature)
|
|
private
|
|
FFlags: TJclClrMethodSignFlags;
|
|
FParams: TObjectList;
|
|
FRetType: TJclClrMethodRetType;
|
|
function GetParam(const Idx: Integer): TJclClrMethodParam;
|
|
function GetParamCount: Integer;
|
|
public
|
|
constructor Create(const ABlob: TJclClrBlobRecord);
|
|
destructor Destroy; override;
|
|
|
|
property Flags: TJclClrMethodSignFlags read FFlags;
|
|
property Params[const Idx: Integer]: TJclClrMethodParam read GetParam;
|
|
property ParamCount: Integer read GetParamCount;
|
|
property RetType: TJclClrMethodRetType read FRetType;
|
|
end;
|
|
|
|
TJclClrMemberAccess =
|
|
(maCompilercontrolled, maPrivate, maFamilyAndAssembly,
|
|
maAssembly, maFamily, maFamilyOrAssembly, maPublic);
|
|
|
|
TJclClrMethodFlag =
|
|
(mfStatic, mfFinal, mfVirtual, mfHideBySig,
|
|
mfCheckAccessOnOverride, mfAbstract, mfSpecialName,
|
|
mfPInvokeImpl, mfUnmanagedExport,
|
|
mfRTSpcialName, mfHasSecurity, mfRequireSecObject);
|
|
TJclClrMethodFlags = set of TJclClrMethodFlag;
|
|
|
|
TJclClrMethodCodeType = (ctIL, ctNative, ctOptIL, ctRuntime);
|
|
|
|
TJclClrMethodImplFlag =
|
|
(mifForwardRef, mifPreserveSig, mifInternalCall,
|
|
mifSynchronized, mifNoInlining);
|
|
TJclClrMethodImplFlags = set of TJclClrMethodImplFlag;
|
|
|
|
TJclClrTableMethodDefRow = class(TJclClrTableRow)
|
|
private
|
|
FRVA: DWORD;
|
|
FImplFlags: Word;
|
|
FFlags: Word;
|
|
FNameOffset: DWORD;
|
|
FSignatureOffset: DWORD;
|
|
FParamListIdx: DWORD;
|
|
FParentToken: TJclClrTableTypeDefRow;
|
|
FParams: TList;
|
|
FMethodBody: TJclClrMethodBody;
|
|
FSignature: TJclClrMethodSign;
|
|
function GetName: WideString;
|
|
function GetSignatureData: TJclClrBlobRecord;
|
|
function GetParam(const Idx: Integer): TJclClrTableParamDefRow;
|
|
function GetParamCount: Integer;
|
|
function GetHasParam: Boolean;
|
|
procedure UpdateParams;
|
|
function GetFullName: WideString;
|
|
function GetSignature: TJclClrMethodSign;
|
|
function GetMemberAccess: TJclClrMemberAccess;
|
|
function GetMethodFlags: TJclClrMethodFlags;
|
|
function GetNewSlot: Boolean;
|
|
function GetCodeType: TJclClrMethodCodeType;
|
|
function GetManaged: Boolean;
|
|
function GetMethodImplFlags: TJclClrMethodImplFlags;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
procedure Update; override;
|
|
procedure SetParentToken(const ARow: TJclClrTableTypeDefRow);
|
|
public
|
|
function DumpIL: string; override;
|
|
|
|
destructor Destroy; override;
|
|
|
|
property RVA: DWORD read FRVA;
|
|
property ImplFlags: Word read FImplFlags;
|
|
property Flags: Word read FFlags;
|
|
property NameOffset: DWORD read FNameOffset;
|
|
property SignatureOffset: DWORD read FSignatureOffset;
|
|
property ParamListIdx: DWORD read FParamListIdx;
|
|
|
|
property Name: WideString read GetName;
|
|
property FullName: WideString read GetFullName;
|
|
|
|
property MethodFlags: TJclClrMethodFlags read GetMethodFlags;
|
|
property MethodImplFlags: TJclClrMethodImplFlags read GetMethodImplFlags;
|
|
|
|
property MemberAccess: TJclClrMemberAccess read GetMemberAccess;
|
|
property NewSlot: Boolean read GetNewSlot;
|
|
property CodeType: TJclClrMethodCodeType read GetCodeType;
|
|
property Managed: Boolean read GetManaged;
|
|
|
|
property Signature: TJclClrMethodSign read GetSignature;
|
|
property SignatureData: TJclClrBlobRecord read GetSignatureData;
|
|
property ParentToken: TJclClrTableTypeDefRow read FParentToken;
|
|
property HasParam: Boolean read GetHasParam;
|
|
property Params[const Idx: Integer]: TJclClrTableParamDefRow read GetParam;
|
|
property ParamCount: Integer read GetParamCount;
|
|
|
|
property MethodBody: TJclClrMethodBody read FMethodBody;
|
|
end;
|
|
|
|
TJclClrTableMethodDef = class(TJclClrTable)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableMethodDefRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableMethodDefRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableMethodPtrRow = class(TJclClrTableRow)
|
|
private
|
|
FMethodIdx: DWORD;
|
|
function GetMethod: TJclClrTableMethodDefRow;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
property MethodIdx: DWORD read FMethodIdx;
|
|
property Method: TJclClrTableMethodDefRow read GetMethod;
|
|
end;
|
|
|
|
TJclClrTableMethodPtr = class(TJclClrTable)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableMethodPtrRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableMethodPtrRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableMethodImplRow = class(TJclClrTableRow)
|
|
private
|
|
FClassIdx: DWORD;
|
|
FMethodBodyIdx: DWORD;
|
|
FMethodDeclarationIdx: DWORD;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
property ClassIdx: DWORD read FClassIdx;
|
|
property MethodBodyIdx: DWORD read FMethodBodyIdx;
|
|
property MethodDeclarationIdx: DWORD read FMethodDeclarationIdx;
|
|
end;
|
|
|
|
TJclClrTableMethodImpl = class(TJclClrTable)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableMethodImplRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableMethodImplRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableMethodSemanticsRow = class(TJclClrTableRow)
|
|
private
|
|
FSemantics: Word;
|
|
FMethodIdx: DWORD;
|
|
FAssociationIdx: DWORD;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
property Semantics: Word read FSemantics;
|
|
property MethodIdx: DWORD read FMethodIdx;
|
|
property AssociationIdx: DWORD read FAssociationIdx;
|
|
end;
|
|
|
|
TJclClrTableMethodSemantics = class(TJclClrTable)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableMethodSemanticsRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableMethodSemanticsRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableMethodSpecRow = class(TJclClrTableRow)
|
|
private
|
|
FMethodIdx: DWORD;
|
|
FInstantiationOffset: DWORD;
|
|
function GetInstantiation: TJclClrBlobRecord;
|
|
function GetMethod: TJclClrTableRow;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
property MethodIdx: DWORD read FMethodIdx;
|
|
property InstantiationOffset: DWORD read FInstantiationOffset;
|
|
property Method: TJclClrTableRow read GetMethod;
|
|
property Instantiation: TJclClrBlobRecord read GetInstantiation;
|
|
end;
|
|
|
|
TJclClrTableMethodSpec = class(TJclClrTable)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableMethodSpecRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableMethodSpecRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableNestedClassRow = class(TJclClrTableRow)
|
|
private
|
|
FEnclosingClassIdx: DWORD;
|
|
FNestedClassIdx: DWORD;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
property NestedClassIdx: DWORD read FNestedClassIdx;
|
|
property EnclosingClassIdx: DWORD read FEnclosingClassIdx;
|
|
end;
|
|
|
|
TJclClrTableNestedClass = class(TJclClrTable)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableNestedClassRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableNestedClassRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTablePropertyFlag = (pfSpecialName, pfRTSpecialName, pfHasDefault);
|
|
TJclClrTablePropertyFlags = set of TJclClrTablePropertyFlag;
|
|
|
|
TJclClrTablePropertyDefRow = class(TJclClrTableRow)
|
|
private
|
|
FKindIdx: DWORD;
|
|
FNameOffset: DWORD;
|
|
FFlags: Word;
|
|
function GetName: WideString;
|
|
function GetFlags: TJclClrTablePropertyFlags;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
function DumpIL: string; override;
|
|
|
|
property RawFlags: Word read FFlags;
|
|
property NameOffset: DWORD read FNameOffset;
|
|
property KindIdx: DWORD read FKindIdx;
|
|
|
|
property Name: WideString read GetName;
|
|
property Flags: TJclClrTablePropertyFlags read GetFlags;
|
|
end;
|
|
|
|
TJclClrTablePropertyDef = class(TJclClrTable)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTablePropertyDefRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTablePropertyDefRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTablePropertyPtrRow = class(TJclClrTableRow)
|
|
private
|
|
FPropertyIdx: DWORD;
|
|
function GetProperty: TJclClrTablePropertyDefRow;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
property PropertyIdx: DWORD read FPropertyIdx;
|
|
property _Property: TJclClrTablePropertyDefRow read GetProperty;
|
|
end;
|
|
|
|
TJclClrTablePropertyPtr = class(TJclClrTable)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTablePropertyPtrRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTablePropertyPtrRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTablePropertyMapRow = class(TJclClrTableRow)
|
|
private
|
|
FParentIdx: DWORD;
|
|
FPropertyListIdx: DWORD;
|
|
FProperties: TList;
|
|
function GetParent: TJclClrTableTypeDefRow;
|
|
function GetProperty(const Idx: Integer): TJclClrTablePropertyDefRow;
|
|
function GetPropertyCount: Integer;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
|
|
function Add(const ARow: TJclClrTablePropertyDefRow): Integer;
|
|
public
|
|
destructor Destroy; override;
|
|
|
|
property ParentIdx: DWORD read FParentIdx;
|
|
property PropertyListIdx: DWORD read FPropertyListIdx;
|
|
|
|
property Parent: TJclClrTableTypeDefRow read GetParent;
|
|
|
|
property Properties[const Idx: Integer]: TJclClrTablePropertyDefRow read GetProperty;
|
|
property PropertyCount: Integer read GetPropertyCount;
|
|
end;
|
|
|
|
TJclClrTablePropertyMap = class(TJclClrTable)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTablePropertyMapRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
procedure Update; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTablePropertyMapRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableStandAloneSigRow = class(TJclClrTableRow)
|
|
private
|
|
FSignatureOffset: DWORD;
|
|
function GetSignature: TJclClrBlobRecord;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
property SignatureOffset: DWORD read FSignatureOffset;
|
|
property Signature: TJclClrBlobRecord read GetSignature;
|
|
end;
|
|
|
|
TJclClrTableStandAloneSig = class(TJclClrTable)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableStandAloneSigRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableStandAloneSigRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTypeVisibility =
|
|
(tvNotPublic, tvPublic, tvNestedPublic,
|
|
tvNestedPrivate, tvNestedFamily, tvNestedAssembly,
|
|
tvNestedFamANDAssem, tvNestedFamORAssem);
|
|
TJclClrClassLayout = (clAuto, clSequential, clExplicit);
|
|
TJclClrClassSemantics = (csClass, csInterface);
|
|
TJclClrStringFormatting = (sfAnsi, sfUnicode, sfAutoChar);
|
|
|
|
TJclClrTypeAttribute =
|
|
(taAbstract, taSealed, taSpecialName, taImport,
|
|
taSerializable, taBeforeFieldInit, taRTSpecialName, taHasSecurity);
|
|
TJclClrTypeAttributes = set of TJclClrTypeAttribute;
|
|
|
|
TJclClrTableTypeDefRow = class(TJclClrTableRow)
|
|
private
|
|
FNamespaceOffset: DWORD;
|
|
FNameOffset: DWORD;
|
|
FFlags: DWORD;
|
|
FExtendsIdx: DWORD;
|
|
FFieldListIdx: DWORD;
|
|
FMethodListIdx: DWORD;
|
|
FFields: TList;
|
|
FMethods: TList;
|
|
function GetName: WideString;
|
|
function GetNamespace: WideString;
|
|
function GetField(const Idx: Integer): TJclClrTableFieldDefRow;
|
|
function GetFieldCount: Integer;
|
|
function GetMethod(const Idx: Integer): TJclClrTableMethodDefRow;
|
|
function GetMethodCount: Integer;
|
|
procedure UpdateFields;
|
|
procedure UpdateMethods;
|
|
function GetFullName: WideString;
|
|
function GetAttributes: TJclClrTypeAttributes;
|
|
function GetClassLayout: TJclClrClassLayout;
|
|
function GetClassSemantics: TJclClrClassSemantics;
|
|
function GetStringFormatting: TJclClrStringFormatting;
|
|
function GetVisibility: TJclClrTypeVisibility;
|
|
function GetExtends: TJclClrTableRow;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
procedure Update; override;
|
|
public
|
|
destructor Destroy; override;
|
|
|
|
function DumpIL: string; override;
|
|
|
|
function HasField: Boolean;
|
|
function HasMethod: Boolean;
|
|
|
|
property Flags: DWORD read FFlags;
|
|
property NameOffset: DWORD read FNameOffset;
|
|
property NamespaceOffset: DWORD read FNamespaceOffset;
|
|
property ExtendsIdx: DWORD read FExtendsIdx;
|
|
property FieldListIdx: DWORD read FFieldListIdx;
|
|
property MethodListIdx: DWORD read FMethodListIdx;
|
|
|
|
property Name: WideString read GetName;
|
|
property Namespace: WideString read GetNamespace;
|
|
property FullName: WideString read GetFullName;
|
|
property Extends: TJclClrTableRow read GetExtends;
|
|
|
|
property Attributes: TJclClrTypeAttributes read GetAttributes;
|
|
|
|
property Visibility: TJclClrTypeVisibility read GetVisibility;
|
|
property ClassLayout: TJclClrClassLayout read GetClassLayout;
|
|
property ClassSemantics: TJclClrClassSemantics read GetClassSemantics;
|
|
property StringFormatting: TJclClrStringFormatting read GetStringFormatting;
|
|
|
|
property Fields[const Idx: Integer]: TJclClrTableFieldDefRow read GetField;
|
|
property FieldCount: Integer read GetFieldCount;
|
|
property Methods[const Idx: Integer]: TJclClrTableMethodDefRow read GetMethod;
|
|
property MethodCount: Integer read GetMethodCount;
|
|
end;
|
|
|
|
TJclClrTableTypeDef = class(TJclClrTable, ITableCanDumpIL)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableTypeDefRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableTypeDefRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableTypeRefRow = class(TJclClrTableRow)
|
|
private
|
|
FResolutionScopeIdx: DWORD;
|
|
FNamespaceOffset: DWORD;
|
|
FNameOffset: DWORD;
|
|
function GetName: WideString;
|
|
function GetNamespace: WideString;
|
|
function GetResolutionScope: TJclClrTableRow;
|
|
function GetResolutionScopeName: string;
|
|
function GetFullName: WideString;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
function DumpIL: string; override;
|
|
|
|
property ResolutionScopeIdx: DWORD read FResolutionScopeIdx;
|
|
property NameOffset: DWORD read FNameOffset;
|
|
property NamespaceOffset: DWORD read FNamespaceOffset;
|
|
|
|
property ResolutionScope: TJclClrTableRow read GetResolutionScope;
|
|
property ResolutionScopeName: string read GetResolutionScopeName;
|
|
property Name: WideString read GetName;
|
|
property Namespace: WideString read GetNamespace;
|
|
property FullName: WideString read GetFullName;
|
|
end;
|
|
|
|
TJclClrTableTypeRef = class(TJclClrTable)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableTypeRefRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableTypeRefRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableTypeSpecRow = class(TJclClrTableRow)
|
|
private
|
|
FSignatureOffset: DWORD;
|
|
function GetSignature: TJclClrBlobRecord;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
public
|
|
property SignatureOffset: DWORD read FSignatureOffset;
|
|
property Signature: TJclClrBlobRecord read GetSignature;
|
|
end;
|
|
|
|
TJclClrTableTypeSpec = class(TJclClrTable)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableTypeSpecRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableTypeSpecRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableENCMapRow = class(TJclClrTableRow)
|
|
private
|
|
FToken: DWORD;
|
|
FFuncCode: DWORD;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
property FuncCode: DWORD read FFuncCode;
|
|
end;
|
|
|
|
TJclClrTableENCMap = class(TJclClrTable)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableENCMapRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableENCMapRow read GetRow; default;
|
|
end;
|
|
|
|
TJclClrTableENCLogRow = class(TJclClrTableENCMapRow)
|
|
private
|
|
FFuncCode: DWORD;
|
|
protected
|
|
constructor Create(const ATable: TJclClrTable); override;
|
|
property FuncCode: DWORD read FFuncCode;
|
|
end;
|
|
|
|
TJclClrTableENCLog = class(TJclClrTable)
|
|
private
|
|
function GetRow(const Idx: Integer): TJclClrTableENCLogRow;
|
|
protected
|
|
class function TableRowClass: TJclClrTableRowClass; override;
|
|
public
|
|
property Rows[const Idx: Integer]: TJclClrTableENCLogRow read GetRow; default;
|
|
end;
|
|
|
|
EJclMetadataError = class(EJclError);
|
|
|
|
{$IFDEF UNITVERSIONING}
|
|
const
|
|
UnitVersioning: TUnitVersionInfo = (
|
|
RCSfile: '$URL: https://jcl.svn.sourceforge.net:443/svnroot/jcl/tags/JCL-1.100-Build2646/jcl/source/windows/JclMetadata.pas $';
|
|
Revision: '$Revision: 1726 $';
|
|
Date: '$Date: 2006-08-11 17:24:18 +0200 (ven., 11 août 2006) $';
|
|
LogPath: 'JCL\source\common'
|
|
);
|
|
{$ENDIF UNITVERSIONING}
|
|
|
|
implementation
|
|
|
|
uses
|
|
Math,
|
|
JclCIL, JclResources, JclStrings;
|
|
|
|
const
|
|
MAX_CLASS_NAME = 1024;
|
|
MAX_PATH_NAME = 260;
|
|
|
|
// Assembly attr bits, used by DefineAssembly.
|
|
afPublicKey = $0001; // The assembly ref holds the full (unhashed) public key.
|
|
afCompatibilityMask = $0070;
|
|
afSideBySideCompatible = $0000; // The assembly is side by side compatible.
|
|
afNonSideBySideAppDomain = $0010; // The assembly cannot execute with other versions if
|
|
// they are executing in the same application domain.
|
|
afNonSideBySideProcess = $0020; // The assembly cannot execute with other versions if
|
|
// they are executing in the same process.
|
|
afNonSideBySideMachine = $0030; // The assembly cannot execute with other versions if
|
|
// they are executing on the same machine.
|
|
afEnableJITcompileTracking = $8000; // From "DebuggableAttribute".
|
|
afDisableJITcompileOptimizer = $4000; // From "DebuggableAttribute".
|
|
|
|
ClrAssemblyFlagMapping: array [TJclClrAssemblyFlag] of DWORD =
|
|
(afPublicKey, afCompatibilityMask, afSideBySideCompatible,
|
|
afNonSideBySideAppDomain, afNonSideBySideProcess,
|
|
afNonSideBySideMachine, afEnableJITcompileTracking,
|
|
afDisableJITcompileOptimizer);
|
|
|
|
mrVisibilityMask = $0007;
|
|
mrPublic = $0001; // The Resource is exported from the Assembly.
|
|
mrPrivate = $0002; // The Resource is private to the Assembly.
|
|
|
|
ManifestResourceVisibilityMapping: array [TJclClrTableManifestResourceVisibility] of DWORD =
|
|
(mrPublic, mrPrivate);
|
|
|
|
// MethodDef attr bits, Used by DefineMethod.
|
|
// member access mask - Use this mask to retrieve accessibility information.
|
|
mdMemberAccessMask = $0007;
|
|
mdPrivateScope = $0000; // Member not referenceable.
|
|
mdPrivate = $0001; // Accessible only by the parent type.
|
|
mdFamANDAssem = $0002; // Accessible by sub-types only in this Assembly.
|
|
mdAssem = $0003; // Accessibly by anyone in the Assembly.
|
|
mdFamily = $0004; // Accessible only by type and sub-types.
|
|
mdFamORAssem = $0005; // Accessibly by sub-types anywhere, plus anyone in assembly.
|
|
mdPublic = $0006; // Accessibly by anyone who has visibility to this scope.
|
|
// end member access mask
|
|
|
|
// method contract attributes.
|
|
mdStatic = $0010; // Defined on type, else per instance.
|
|
mdFinal = $0020; // Method may not be overridden.
|
|
mdVirtual = $0040; // Method virtual.
|
|
mdHideBySig = $0080; // Method hides by name+sig, else just by name.
|
|
|
|
// vtable layout mask - Use this mask to retrieve vtable attributes.
|
|
mdVtableLayoutMask = $0100;
|
|
mdReuseSlot = $0000; // The default.
|
|
mdNewSlot = $0100; // Method always gets a new slot in the vtable.
|
|
// end vtable layout mask
|
|
|
|
// method implementation attributes.
|
|
mdCheckAccessOnOverride = $0200; // Overridability is the same as the visibility.
|
|
mdAbstract = $0400; // Method does not provide an implementation.
|
|
mdSpecialName = $0800; // Method is special. Name describes how.
|
|
|
|
// interop attributes
|
|
mdPinvokeImpl = $2000; // Implementation is forwarded through pinvoke.
|
|
mdUnmanagedExport = $0008; // Managed method exported via thunk to unmanaged code.
|
|
|
|
// Reserved flags for runtime use only.
|
|
mdReservedMask = $d000;
|
|
mdRTSpecialName = $1000; // Runtime should check name encoding.
|
|
mdHasSecurity = $4000; // Method has security associate with it.
|
|
mdRequireSecObject = $8000; // Method calls another method containing security code.
|
|
|
|
// MethodImpl attr bits, used by DefineMethodImpl.
|
|
// code impl mask
|
|
miCodeTypeMask = $0003; // Flags about code type.
|
|
miIL = $0000; // Method impl is IL.
|
|
miNative = $0001; // Method impl is native.
|
|
miOPTIL = $0002; // Method impl is OPTIL
|
|
miRuntime = $0003; // Method impl is provided by the runtime.
|
|
// end code impl mask
|
|
|
|
// managed mask
|
|
miManagedMask = $0004; // Flags specifying whether the code is managed or unmanaged.
|
|
miUnmanaged = $0004; // Method impl is unmanaged, otherwise managed.
|
|
miManaged = $0000; // Method impl is managed.
|
|
// end managed mask
|
|
|
|
// implementation info and interop
|
|
miForwardRef = $0010; // Indicates method is defined; used primarily in merge scenarios.
|
|
miPreserveSig = $0080; // Indicates method sig is not to be mangled to do HRESULT conversion.
|
|
|
|
miInternalCall = $1000; // Reserved for internal use.
|
|
|
|
miSynchronized = $0020; // Method is single threaded through the body.
|
|
miNoInlining = $0008; // Method may not be inlined.
|
|
miMaxMethodImplVal = $ffff; // Range check value
|
|
|
|
// Calling convention flags.
|
|
IMAGE_CEE_CS_CALLCONV_DEFAULT = $0;
|
|
IMAGE_CEE_CS_CALLCONV_VARARG = $5;
|
|
IMAGE_CEE_CS_CALLCONV_FIELD = $6;
|
|
IMAGE_CEE_CS_CALLCONV_LOCAL_SIG = $7;
|
|
IMAGE_CEE_CS_CALLCONV_PROPERTY = $8;
|
|
IMAGE_CEE_CS_CALLCONV_UNMGD = $9;
|
|
IMAGE_CEE_CS_CALLCONV_MAX = $10; // first invalid calling convention
|
|
// The high bits of the calling convention convey additional info
|
|
IMAGE_CEE_CS_CALLCONV_MASK = $0f; // Calling convention is bottom 4 bits
|
|
IMAGE_CEE_CS_CALLCONV_HASTHIS = $20; // Top bit indicates a 'this' parameter
|
|
IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS = $40; // This parameter is explicitly in the signature
|
|
|
|
// TypeDef/ExportedType attr bits, used by DefineTypeDef.
|
|
// Use this mask to retrieve the type visibility information.
|
|
tdVisibilityMask = $00000007;
|
|
tdNotPublic = $00000000; // Class is not public scope.
|
|
tdPublic = $00000001; // Class is public scope.
|
|
tdNestedPublic = $00000002; // Class is nested with public visibility.
|
|
tdNestedPrivate = $00000003; // Class is nested with private visibility.
|
|
tdNestedFamily = $00000004; // Class is nested with family visibility.
|
|
tdNestedAssembly = $00000005; // Class is nested with assembly visibility.
|
|
tdNestedFamANDAssem = $00000006; // Class is nested with family and assembly visibility.
|
|
tdNestedFamORAssem = $00000007; // Class is nested with family or assembly visibility.
|
|
|
|
// Use this mask to retrieve class layout information
|
|
tdLayoutMask = $00000018;
|
|
tdAutoLayout = $00000000; // Class fields are auto-laid out
|
|
tdSequentialLayout = $00000008; // Class fields are laid out sequentially
|
|
tdExplicitLayout = $00000010; // Layout is supplied explicitly
|
|
// end layout mask
|
|
|
|
// Use this mask to retrieve class semantics information.
|
|
tdClassSemanticsMask = $00000020;
|
|
tdClass = $00000000; // Type is a class.
|
|
tdInterface = $00000020; // Type is an interface.
|
|
// end semantics mask
|
|
|
|
// Special semantics in addition to class semantics.
|
|
tdAbstract = $00000080; // Class is abstract
|
|
tdSealed = $00000100; // Class is concrete and may not be extended
|
|
tdSpecialName = $00000400; // Class name is special. Name describes how.
|
|
|
|
// Implementation attributes.
|
|
tdImport = $00001000; // Class / interface is imported
|
|
tdSerializable = $00002000; // The class is Serializable.
|
|
|
|
// Use tdStringFormatMask to retrieve string information for native interop
|
|
tdStringFormatMask = $00030000;
|
|
tdAnsiClass = $00000000; // LPTSTR is interpreted as ANSI in this class
|
|
tdUnicodeClass = $00010000; // LPTSTR is interpreted as UNICODE
|
|
tdAutoClass = $00020000; // LPTSTR is interpreted automatically
|
|
// end string format mask
|
|
|
|
tdBeforeFieldInit = $00100000; // Initialize the class any time before first static field access.
|
|
|
|
// Flags reserved for runtime use.
|
|
tdReservedMask = $00040800;
|
|
tdRTSpecialName = $00000800; // Runtime should check name encoding.
|
|
tdHasSecurity = $00040000; // Class has security associate with it.
|
|
|
|
// FieldDef attr bits, used by DefineField.
|
|
// member access mask - Use this mask to retrieve accessibility information.
|
|
fdFieldAccessMask = $0007;
|
|
fdPrivateScope = $0000; // Member not referenceable.
|
|
fdPrivate = $0001; // Accessible only by the parent type.
|
|
fdFamANDAssem = $0002; // Accessible by sub-types only in this Assembly.
|
|
fdAssembly = $0003; // Accessibly by anyone in the Assembly.
|
|
fdFamily = $0004; // Accessible only by type and sub-types.
|
|
fdFamORAssem = $0005; // Accessibly by sub-types anywhere, plus anyone in assembly.
|
|
fdPublic = $0006; // Accessibly by anyone who has visibility to this scope.
|
|
// end member access mask
|
|
|
|
// field contract attributes.
|
|
fdStatic = $0010; // Defined on type, else per instance.
|
|
fdInitOnly = $0020; // Field may only be initialized, not written to after init.
|
|
fdLiteral = $0040; // Value is compile time constant.
|
|
fdNotSerialized = $0080; // Field does not have to be serialized when type is remoted.
|
|
|
|
fdSpecialName = $0200; // field is special. Name describes how.
|
|
|
|
// interop attributes
|
|
fdPinvokeImpl = $2000; // Implementation is forwarded through pinvoke.
|
|
|
|
// Reserved flags for runtime use only.
|
|
fdReservedMask = $9500;
|
|
fdRTSpecialName = $0400; // Runtime(metadata internal APIs) should check name encoding.
|
|
fdHasFieldMarshal = $1000; // Field has marshalling information.
|
|
fdHasDefault = $8000; // Field has default.
|
|
fdHasFieldRVA = $0100; // Field has RVA.
|
|
|
|
// Flags for Params
|
|
pdIn = $0001; // Param is [In]
|
|
pdOut = $0002; // Param is [out]
|
|
pdOptional = $0010; // Param is optional
|
|
|
|
// Reserved flags for Runtime use only.
|
|
pdReservedMask = $f000;
|
|
pdHasDefault = $1000; // Param has default value.
|
|
pdHasFieldMarshal = $2000; // Param has FieldMarshal.
|
|
|
|
pdUnused = $cfe0;
|
|
|
|
ClrParamKindMapping: array [TJclClrParamKind] of DWORD =
|
|
(pdIn, pdOut, pdOptional, pdHasDefault, pdHasFieldMarshal);
|
|
|
|
// Element type for Cor signature
|
|
ELEMENT_TYPE_END = $0;
|
|
ELEMENT_TYPE_VOID = $1;
|
|
ELEMENT_TYPE_BOOLEAN = $2;
|
|
ELEMENT_TYPE_CHAR = $3;
|
|
ELEMENT_TYPE_I1 = $4;
|
|
ELEMENT_TYPE_U1 = $5;
|
|
ELEMENT_TYPE_I2 = $6;
|
|
ELEMENT_TYPE_U2 = $7;
|
|
ELEMENT_TYPE_I4 = $8;
|
|
ELEMENT_TYPE_U4 = $9;
|
|
ELEMENT_TYPE_I8 = $a;
|
|
ELEMENT_TYPE_U8 = $b;
|
|
ELEMENT_TYPE_R4 = $c;
|
|
ELEMENT_TYPE_R8 = $d;
|
|
ELEMENT_TYPE_STRING = $e;
|
|
|
|
// every type above PTR will be simple type
|
|
ELEMENT_TYPE_PTR = $f; // PTR <type>
|
|
ELEMENT_TYPE_BYREF = $10; // BYREF <type>
|
|
|
|
// Please use ELEMENT_TYPE_VALUETYPE. ELEMENT_TYPE_VALUECLASS is deprecated.
|
|
ELEMENT_TYPE_VALUETYPE = $11; // VALUETYPE <class Token>
|
|
ELEMENT_TYPE_CLASS = $12; // CLASS <class Token>
|
|
|
|
ELEMENT_TYPE_ARRAY = $14; // MDARRAY <type> <rank> <bcount> <bound1> ... <lbcount> <lb1> ...
|
|
|
|
ELEMENT_TYPE_TYPEDBYREF = $16; // This is a simple type.
|
|
|
|
ELEMENT_TYPE_I = $18; // native integer size
|
|
ELEMENT_TYPE_U = $19; // native unsigned integer size
|
|
ELEMENT_TYPE_FNPTR = $1B; // FNPTR <complete sig for the function including calling convention>
|
|
ELEMENT_TYPE_OBJECT = $1C; // Shortcut for System.Object
|
|
ELEMENT_TYPE_SZARRAY = $1D; // Shortcut for single dimension zero lower bound array
|
|
// SZARRAY <type>
|
|
|
|
// This is only for binding
|
|
ELEMENT_TYPE_CMOD_REQD = $1F; // required C modifier : E_T_CMOD_REQD <mdTypeRef/mdTypeDef>
|
|
ELEMENT_TYPE_CMOD_OPT = $20; // optional C modifier : E_T_CMOD_OPT <mdTypeRef/mdTypeDef>
|
|
|
|
// This is for signatures generated internally (which will not be persisted in any way).
|
|
ELEMENT_TYPE_INTERNAL = $21; // INTERNAL <typehandle>
|
|
|
|
// Note that this is the max of base type excluding modifiers
|
|
ELEMENT_TYPE_MAX = $22; // first invalid element type
|
|
|
|
|
|
ELEMENT_TYPE_MODIFIER = $40;
|
|
ELEMENT_TYPE_SENTINEL = $01 or ELEMENT_TYPE_MODIFIER; // sentinel for varargs
|
|
ELEMENT_TYPE_PINNED = $05 or ELEMENT_TYPE_MODIFIER;
|
|
|
|
ClrElementTypeMapping: array [TJclClrElementType] of Byte =
|
|
(ELEMENT_TYPE_END, ELEMENT_TYPE_VOID, ELEMENT_TYPE_BOOLEAN,
|
|
ELEMENT_TYPE_CHAR, ELEMENT_TYPE_I1, ELEMENT_TYPE_U1,
|
|
ELEMENT_TYPE_I2, ELEMENT_TYPE_U2, ELEMENT_TYPE_I4, ELEMENT_TYPE_U4,
|
|
ELEMENT_TYPE_I8, ELEMENT_TYPE_U8, ELEMENT_TYPE_R4, ELEMENT_TYPE_R8,
|
|
ELEMENT_TYPE_STRING, ELEMENT_TYPE_PTR, ELEMENT_TYPE_BYREF,
|
|
ELEMENT_TYPE_VALUETYPE, ELEMENT_TYPE_CLASS, ELEMENT_TYPE_ARRAY,
|
|
ELEMENT_TYPE_TYPEDBYREF, ELEMENT_TYPE_I, ELEMENT_TYPE_U,
|
|
ELEMENT_TYPE_FNPTR, ELEMENT_TYPE_OBJECT, ELEMENT_TYPE_SZARRAY,
|
|
ELEMENT_TYPE_CMOD_REQD, ELEMENT_TYPE_CMOD_OPT, ELEMENT_TYPE_INTERNAL,
|
|
ELEMENT_TYPE_MAX, ELEMENT_TYPE_MODIFIER, ELEMENT_TYPE_SENTINEL,
|
|
ELEMENT_TYPE_PINNED);
|
|
|
|
ClrMethodFlagMapping: array [TJclClrMethodFlag] of Word =
|
|
(mdStatic, mdFinal, mdVirtual, mdHideBySig, mdCheckAccessOnOverride,
|
|
mdAbstract, mdSpecialName, mdPinvokeImpl, mdUnmanagedExport,
|
|
mdRTSpecialName, mdHasSecurity, mdRequireSecObject);
|
|
|
|
ClrMethodImplFlagMapping: array [TJclClrMethodImplFlag] of Word =
|
|
(miForwardRef, miPreserveSig, miInternalCall, miSynchronized, miNoInlining);
|
|
|
|
// Property attr bits, used by DefineProperty.
|
|
prSpecialName = $0200; // property is special. Name describes how.
|
|
|
|
// Reserved flags for Runtime use only.
|
|
prReservedMask = $f400;
|
|
prRTSpecialName = $0400; // Runtime(metadata internal APIs) should check name encoding.
|
|
prHasDefault = $1000; // Property has default
|
|
|
|
prUnused = $e9ff;
|
|
|
|
ClrTablePropertyFlagMapping: array [TJclClrTablePropertyFlag] of Word =
|
|
(prSpecialName, prRTSpecialName, prHasDefault);
|
|
|
|
// Event attr bits, used by DefineEvent.
|
|
evSpecialName = $0200; // event is special. Name describes how.
|
|
|
|
// Reserved flags for Runtime use only.
|
|
evReservedMask = $0400;
|
|
evRTSpecialName = $0400; // Runtime(metadata internal APIs) should check name encoding.
|
|
|
|
ClrTableEventFlagMapping: array [TJclClrTableEventFlag] of Word =
|
|
(evSpecialName, evRTSpecialName);
|
|
|
|
// DeclSecurity attr bits, used by DefinePermissionSet
|
|
dclActionMask = $000f; // Mask allows growth of enum.
|
|
dclActionNil = $0000;
|
|
dclRequest = $0001;
|
|
dclDemand = $0002;
|
|
dclAssert = $0003;
|
|
dclDeny = $0004;
|
|
dclPermitOnly = $0005;
|
|
dclLinktimeCheck = $0006;
|
|
dclInheritanceCheck = $0007;
|
|
dclRequestMinimum = $0008;
|
|
dclRequestOptional = $0009;
|
|
dclRequestRefuse = $000a;
|
|
dclPrejitGrant = $000b; // Persisted grant set at prejit time
|
|
dclPrejitDenied = $000c; // Persisted denied set at prejit time
|
|
dclNonCasDemand = $000d; //
|
|
dclNonCasLinkDemand = $000e;
|
|
dclNonCasInheritance = $000f;
|
|
dclMaximumValue = $000f; // Maximum legal value
|
|
|
|
// PinvokeMap attr bits, used by DefinePinvokeMap
|
|
pmNoMangle = $0001; // Pinvoke is to use the member name as specified.
|
|
|
|
// Use this mask to retrieve the CharSet information.
|
|
pmCharSetMask = $0006;
|
|
pmCharSetNotSpec = $0000;
|
|
pmCharSetAnsi = $0002;
|
|
pmCharSetUnicode = $0004;
|
|
pmCharSetAuto = $0006;
|
|
|
|
|
|
pmBestFitUseAssem = $0000;
|
|
pmBestFitEnabled = $0010;
|
|
pmBestFitDisabled = $0020;
|
|
pmBestFitMask = $0030;
|
|
|
|
pmThrowOnUnmappableCharUseAssem = $0000;
|
|
pmThrowOnUnmappableCharEnabled = $1000;
|
|
pmThrowOnUnmappableCharDisabled = $2000;
|
|
pmThrowOnUnmappableCharMask = $3000;
|
|
|
|
pmSupportsLastError = $0040; // Information about target function. Not relevant for fields.
|
|
|
|
// None of the calling convention flags is relevant for fields.
|
|
pmCallConvMask = $0700;
|
|
pmCallConvWinapi = $0100; // Pinvoke will use native callconv appropriate to target windows platform.
|
|
pmCallConvCdecl = $0200;
|
|
pmCallConvStdcall = $0300;
|
|
pmCallConvThiscall = $0400; // In M9, pinvoke will raise exception.
|
|
pmCallConvFastcall = $0500;
|
|
|
|
function IsBitSet(const Value, Flag: DWORD): Boolean;
|
|
begin
|
|
Result := (Value and Flag) = Flag;
|
|
end;
|
|
|
|
//=== { TJclClrSignature } ===================================================
|
|
|
|
constructor TJclClrSignature.Create(const ABlob: TJclClrBlobRecord);
|
|
begin
|
|
inherited Create;
|
|
FBlob := ABlob;
|
|
end;
|
|
|
|
function TJclClrSignature.IsModifierType(const AElementType: TJclClrElementType): Boolean;
|
|
begin
|
|
Result := AElementType in [etPtr, etByRef, etModifier, etSentinel, etPinned];
|
|
end;
|
|
|
|
function TJclClrSignature.IsPrimitiveType(const AElementType: TJclClrElementType): Boolean;
|
|
begin
|
|
Result := AElementType < etPtr;
|
|
end;
|
|
|
|
function TJclClrSignature.UncompressedDataSize(DataPtr: PJclByteArray): Integer;
|
|
begin
|
|
if (DataPtr[0] and $80) = 0 then
|
|
Result := 1
|
|
else
|
|
if (DataPtr[0] and $C0) = $80 then
|
|
Result := 2
|
|
else
|
|
Result := 4;
|
|
end;
|
|
|
|
function TJclClrSignature.UncompressData(DataPtr: PJclByteArray; var Value: DWord): Integer;
|
|
begin
|
|
if (DataPtr[0] and $80) = 0 then // 0??? ????
|
|
begin
|
|
Value := DataPtr[0];
|
|
Result := 1;
|
|
end
|
|
else
|
|
if (DataPtr[0] and $C0) = $80 then // 10?? ????
|
|
begin
|
|
Value := (DataPtr[0] and $3F) shl 8 + DataPtr[1];
|
|
Result := 2;
|
|
end
|
|
else
|
|
if (DataPtr[0] and $E0) = $C0 then // 110? ????
|
|
begin
|
|
Value := (DataPtr[0] and $1F) shl 24 + DataPtr[1] shl 16 + DataPtr[2] shl 8 + DataPtr[3];
|
|
Result := 4;
|
|
end
|
|
else
|
|
raise EJclMetadataError.CreateResFmt(@RsInvalidSignatureData,
|
|
[DataPtr[0], DataPtr[1], DataPtr[2], DataPtr[3]]);
|
|
end;
|
|
|
|
function TJclClrSignature.UncompressToken(DataPtr: PJclByteArray; var Token: TJclClrToken): Integer;
|
|
const
|
|
TableMapping: array [0..3] of TJclClrTableKind = (ttTypeDef, ttTypeRef, ttTypeSpec, TJclClrTableKind(0));
|
|
begin
|
|
Result := UncompressData(DataPtr, Token);
|
|
Token := Byte(TableMapping[Token and 3]) shl 24 + Token shr 2;
|
|
end;
|
|
|
|
function TJclClrSignature.UncompressCallingConv(DataPtr: PJclByteArray): Byte;
|
|
begin
|
|
Result := DataPtr[0];
|
|
end;
|
|
|
|
function TJclClrSignature.UncompressSignedInt(DataPtr: PJclByteArray; var Value: Integer): Integer;
|
|
var
|
|
Data: DWord;
|
|
begin
|
|
Result := UncompressData(DataPtr, Data);
|
|
|
|
if (Data and 1) <> 0 then
|
|
begin
|
|
case Result of
|
|
1:
|
|
Value := Integer(DWord(Data shr 1) or $ffffffc0);
|
|
2:
|
|
Value := Integer(DWord(Data shr 1) or $ffffe000);
|
|
else
|
|
Value := Integer(DWord(Data shr 1) or $f0000000);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TJclClrSignature.UncompressElementType(DataPtr: PJclByteArray): TJclClrElementType;
|
|
begin
|
|
for Result := Low(TJclClrElementType) to High(TJclClrElementType) do
|
|
if ClrElementTypeMapping[Result] = (DataPtr[0] and $7F) then
|
|
Break;
|
|
end;
|
|
|
|
function TJclClrSignature.UncompressFieldSignature: string;
|
|
var
|
|
DataPtr: PJclByteArray;
|
|
begin
|
|
DataPtr := Blob.Memory;
|
|
|
|
Assert(DataPtr[0] = IMAGE_CEE_CS_CALLCONV_FIELD);
|
|
Inc(DataPtr);
|
|
Result := UncompressTypeSignature(DataPtr);
|
|
end;
|
|
|
|
function TJclClrSignature.UncompressTypeSignature(DataPtr: PJclByteArray): string;
|
|
const
|
|
SimpleTypeName: array [etVoid..etString] of PChar =
|
|
('void', 'bool', 'char',
|
|
'int8', 'unsigned int8', 'int16', 'unsigned int16',
|
|
'int32', 'unsigned int32', 'int64', 'unsigned int64',
|
|
'float32', 'float64', 'string');
|
|
TypedTypeName: array [etPtr..etClass] of PChar =
|
|
('ptr', 'byref', 'valuetype', 'class');
|
|
var
|
|
ElementType: TJclClrElementType;
|
|
Token: TJclClrToken;
|
|
begin
|
|
ElementType := UncompressElementType(DataPtr);
|
|
|
|
case ElementType of
|
|
etVoid, etBoolean, etChar, etI1, etU1, etI2, etU2, etI4, etU4, etI8, etU8, etR4, etR8, etString:
|
|
Result := SimpleTypeName[ElementType];
|
|
etI:
|
|
Result := 'System.IntPtr';
|
|
etU:
|
|
Result := 'System.UIntPtr';
|
|
etObject:
|
|
Result := 'System.object';
|
|
etTypedByRef:
|
|
Result := 'Typed By Ref';
|
|
etPtr, etByRef, etValueType, etClass:
|
|
begin
|
|
UncompressToken(DataPtr, Token);
|
|
Result := Format('%s /*%.8x*/', [TypedTypeName[ElementType], Token]);
|
|
end;
|
|
etSzArray:
|
|
begin
|
|
end;
|
|
etFnPtr:
|
|
begin
|
|
end;
|
|
etArray:
|
|
begin
|
|
end;
|
|
else
|
|
Result := 'Unknown Type';
|
|
end;
|
|
end;
|
|
|
|
function TJclClrSignature.Inc(var DataPtr: PJclByteArray; Step: Integer): PByte;
|
|
begin
|
|
Result := PByte(Integer(DataPtr) + Step);
|
|
DataPtr := PJclByteArray(Result);
|
|
end;
|
|
|
|
function TJclClrSignature.ReadValue: DWORD;
|
|
begin
|
|
FBlob.Seek(UncompressData(Blob.Data, Result), soFromCurrent);
|
|
end;
|
|
|
|
function TJclClrSignature.ReadInteger: Integer;
|
|
begin
|
|
FBlob.Seek(UncompressSignedInt(Blob.Data, Result), soFromCurrent);
|
|
end;
|
|
|
|
function TJclClrSignature.ReadToken: TJclClrToken;
|
|
begin
|
|
FBlob.Seek(UncompressToken(Blob.Data, Result), soFromCurrent);
|
|
end;
|
|
|
|
function TJclClrSignature.ReadElementType: TJclClrElementType;
|
|
begin
|
|
Result := UncompressElementType(Blob.Data);
|
|
FBlob.Seek(1, soFromCurrent);
|
|
end;
|
|
|
|
function TJclClrSignature.ReadByte: Byte;
|
|
begin
|
|
Result := Blob.Data[0];
|
|
FBlob.Seek(1, soFromCurrent);
|
|
end;
|
|
|
|
//=== { TJclClrArraySign } ===================================================
|
|
|
|
constructor TJclClrArraySign.Create(const ABlob: TJclClrBlobRecord);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
inherited Create(ABlob);
|
|
|
|
SetLength(FBounds, ReadInteger);
|
|
|
|
for I := 0 to Length(FBounds)-1 do
|
|
begin
|
|
FBounds[I][adSize] := 0;
|
|
FBounds[I][adLowBound] := 0;
|
|
end;
|
|
for I := 0 to ReadInteger-1 do
|
|
FBounds[I][adSize] := ReadInteger;
|
|
for I := 0 to ReadInteger-1 do
|
|
FBounds[I][adLowBound] := ReadInteger;
|
|
end;
|
|
|
|
//=== { TJclClrTableModuleRow } ==============================================
|
|
|
|
constructor TJclClrTableModuleRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FGeneration := Table.ReadWord; // Generation (reserved, shall be zero)
|
|
FNameOffset := Table.ReadIndex(hkString); // Name (index into String heap)
|
|
FMvidIdx := Table.ReadIndex(hkGuid); // Mvid (index into Guid heap)
|
|
FEncIdIdx := Table.ReadIndex(hkGuid); // Mvid (index into Guid heap)
|
|
FEncBaseIdIdx := Table.ReadIndex(hkGuid); // Mvid (index into Guid heap)
|
|
end;
|
|
|
|
function TJclClrTableModuleRow.HasEncId: Boolean;
|
|
begin
|
|
Result := FEncIdIdx > 0;
|
|
end;
|
|
|
|
function TJclClrTableModuleRow.HasEncBaseId: Boolean;
|
|
begin
|
|
Result := FEncBaseIdIdx > 0;
|
|
end;
|
|
|
|
function TJclClrTableModuleRow.GetName: WideString;
|
|
begin
|
|
Result := Table.Stream.Metadata.StringAt(FNameOffset);
|
|
Assert(Result <> ''); // Name shall index a non-null string.
|
|
Assert(Length(Result) < MAX_PATH_NAME);
|
|
end;
|
|
|
|
function TJclClrTableModuleRow.GetMvid: TGUID;
|
|
begin
|
|
// Mvid shall index a non-null GUID in the Guid heap
|
|
Assert(FMvidIdx <= DWORD(Table.Stream.Metadata.GuidCount));
|
|
Result := Table.Stream.Metadata.Guids[FMvidIdx-1];
|
|
end;
|
|
|
|
function TJclClrTableModuleRow.GetEncId: TGUID;
|
|
begin
|
|
Result := Table.Stream.Metadata.Guids[FEncIdIdx-1];
|
|
end;
|
|
|
|
function TJclClrTableModuleRow.GetEncBaseId: TGUID;
|
|
begin
|
|
Result := Table.Stream.Metadata.Guids[FEncBaseIdIdx-1];
|
|
end;
|
|
|
|
function TJclClrTableModuleRow.DumpIL: string;
|
|
begin
|
|
Result := '.module ' + Name + ' // MVID:' + JclGUIDToString(Mvid) + AnsiLineBreak;
|
|
end;
|
|
|
|
function TJclClrTableModule.GetRow(const Idx: Integer): TJclClrTableModuleRow;
|
|
begin
|
|
Result := TJclClrTableModuleRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableModule.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableModuleRow;
|
|
end;
|
|
|
|
//=== { TJclClrTableModuleRefRow } ===========================================
|
|
|
|
constructor TJclClrTableModuleRefRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FNameOffset := Table.ReadIndex(hkString);
|
|
end;
|
|
|
|
function TJclClrTableModuleRefRow.DumpIL: string;
|
|
begin
|
|
Result := '.module extern ' + Name + AnsiLineBreak;
|
|
end;
|
|
|
|
function TJclClrTableModuleRefRow.GetName: WideString;
|
|
begin
|
|
Result := Table.Stream.Metadata.StringAt(FNameOffset);
|
|
end;
|
|
|
|
function TJclClrTableModuleRef.GetRow(const Idx: Integer): TJclClrTableModuleRefRow;
|
|
begin
|
|
Result := TJclClrTableModuleRefRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableModuleRef.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableModuleRefRow;
|
|
end;
|
|
|
|
//=== { TJclClrTableAssemblyRow } ============================================
|
|
|
|
constructor TJclClrTableAssemblyRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
|
|
FHashAlgId := Table.ReadDWord;
|
|
|
|
FMajorVersion := Table.ReadWord;
|
|
FMinorVersion := Table.ReadWord;
|
|
FBuildNumber := Table.ReadWord;
|
|
FRevisionNumber := Table.ReadWord;
|
|
|
|
FFlagMask := Table.ReadDWord;
|
|
|
|
FPublicKeyOffset := Table.ReadIndex(hkBlob);
|
|
FNameOffset := Table.ReadIndex(hkString);
|
|
FCultureOffset := Table.ReadIndex(hkString);
|
|
end;
|
|
|
|
function TJclClrTableAssemblyRow.GetCulture: WideString;
|
|
begin
|
|
Result := Table.Stream.Metadata.StringAt(FCultureOffset);
|
|
end;
|
|
|
|
function TJclClrTableAssemblyRow.GetName: WideString;
|
|
begin
|
|
Result := Table.Stream.Metadata.StringAt(FNameOffset);
|
|
end;
|
|
|
|
function TJclClrTableAssemblyRow.GetPublicKey: TJclClrBlobRecord;
|
|
begin
|
|
Result := Table.Stream.Metadata.BlobAt(FPublicKeyOffset);
|
|
end;
|
|
|
|
function TJclClrTableAssemblyRow.GetVersion: string;
|
|
begin
|
|
Result := FormatVersionString(FMajorVersion, FMinorVersion, FBuildNumber, FRevisionNumber);
|
|
end;
|
|
|
|
function TJclClrTableAssemblyRow.GetFlags: TJclClrAssemblyFlags;
|
|
begin
|
|
Result := AssemblyFlags(FFlagMask);
|
|
end;
|
|
|
|
class function TJclClrTableAssemblyRow.AssemblyFlags(const Flags: DWORD): TJclClrAssemblyFlags;
|
|
var
|
|
AFlag: TJclClrAssemblyFlag;
|
|
begin
|
|
Result := [];
|
|
for AFlag := Low(TJclClrAssemblyFlag) to High(TJclClrAssemblyFlag) do
|
|
if (Flags and ClrAssemblyFlagMapping[AFlag]) = ClrAssemblyFlagMapping[AFlag] then
|
|
Include(Result, AFlag);
|
|
end;
|
|
|
|
class function TJclClrTableAssemblyRow.AssemblyFlags(const Flags: TJclClrAssemblyFlags): DWORD;
|
|
var
|
|
AFlag: TJclClrAssemblyFlag;
|
|
begin
|
|
Result := 0;
|
|
for AFlag := Low(TJclClrAssemblyFlag) to High(TJclClrAssemblyFlag) do
|
|
if AFlag in Flags then
|
|
Result := Result or ClrAssemblyFlagMapping[AFlag];
|
|
end;
|
|
|
|
function TJclClrTableAssemblyRow.DumpIL: string;
|
|
var
|
|
I: Integer;
|
|
TblCustomAttribute: TJclClrTableCustomAttribute;
|
|
begin
|
|
with TStringList.Create do
|
|
try
|
|
Add(Format('.assembly /*%.8x*/ %s', [Token, Name]));
|
|
Add('{');
|
|
|
|
if Table.Stream.FindTable(ttCustomAttribute, TJclClrTable(TblCustomAttribute)) then
|
|
for I := 0 to TblCustomAttribute.RowCount-1 do
|
|
if TblCustomAttribute.Rows[I].Parent = Self then
|
|
Add(' ' + TblCustomAttribute.Rows[I].DumpIL);
|
|
|
|
if FPublicKeyOffset <> 0 then
|
|
Add(PublicKey.Dump(' .publickey = '));
|
|
|
|
Add(' .hash algorithm 0x' + IntToHex(HashAlgId, 8));
|
|
|
|
if FCultureOffset <> 0 then
|
|
Add(' .culture "' + Culture + '"');
|
|
|
|
Add(' .ver ' + Version);
|
|
Add('}');
|
|
Result := Text;
|
|
finally
|
|
Free;
|
|
end;
|
|
end;
|
|
|
|
function TJclClrTableAssembly.GetRow(const Idx: Integer): TJclClrTableAssemblyRow;
|
|
begin
|
|
Result := TJclClrTableAssemblyRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableAssembly.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableAssemblyRow;
|
|
end;
|
|
|
|
//=== { TJclClrTableAssemblyOSRow } ==========================================
|
|
|
|
constructor TJclClrTableAssemblyOSRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
|
|
FPlatformID := Table.ReadDWord;
|
|
FMajorVersion := Table.ReadDWord;
|
|
FMinorVersion := Table.ReadDWord;
|
|
end;
|
|
|
|
function TJclClrTableAssemblyOSRow.GetVersion: string;
|
|
begin
|
|
Result := FormatVersionString(FMajorVersion, FMinorVersion);
|
|
end;
|
|
|
|
function TJclClrTableAssemblyOS.GetRow(const Idx: Integer): TJclClrTableAssemblyOSRow;
|
|
begin
|
|
Result := TJclClrTableAssemblyOSRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableAssemblyOS.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableAssemblyOSRow;
|
|
end;
|
|
|
|
//=== { TJclClrTableAssemblyProcessorRow } ===================================
|
|
|
|
constructor TJclClrTableAssemblyProcessorRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FProcessor := Table.ReadDWord;
|
|
end;
|
|
|
|
function TJclClrTableAssemblyProcessor.GetRow(const Idx: Integer): TJclClrTableAssemblyProcessorRow;
|
|
begin
|
|
Result := TJclClrTableAssemblyProcessorRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableAssemblyProcessor.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableAssemblyProcessorRow;
|
|
end;
|
|
|
|
//=== { TJclClrTableAssemblyRefRow } =========================================
|
|
|
|
constructor TJclClrTableAssemblyRefRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
|
|
FMajorVersion := Table.ReadWord;
|
|
FMinorVersion := Table.ReadWord;
|
|
FBuildNumber := Table.ReadWord;
|
|
FRevisionNumber := Table.ReadWord;
|
|
|
|
FFlagMask := Table.ReadDWord;
|
|
|
|
FPublicKeyOrTokenOffset := Table.ReadIndex(hkBlob);
|
|
FNameOffset := Table.ReadIndex(hkString);
|
|
FCultureOffset := Table.ReadIndex(hkString);
|
|
FHashValueOffset := Table.ReadIndex(hkBlob);
|
|
end;
|
|
|
|
function TJclClrTableAssemblyRefRow.DumpIL: string;
|
|
var
|
|
I: Integer;
|
|
TblCustomAttribute: TJclClrTableCustomAttribute;
|
|
|
|
function DumpPublicKey: string;
|
|
var
|
|
I: Integer;
|
|
Pch: PChar;
|
|
HexStr, AsciiStr: string;
|
|
begin
|
|
Pch := PChar(PublicKeyOrToken.Memory);
|
|
for I := 0 to PublicKeyOrToken.Size do
|
|
begin
|
|
HexStr := HexStr + IntToHex(Integer(Pch[I]), 2) + ' ';
|
|
if CharIsAlphaNum(Pch[I]) then
|
|
AsciiStr := AsciiStr + Pch[I]
|
|
else
|
|
AsciiStr := AsciiStr + '.';
|
|
end;
|
|
Result := '(' + HexStr + ') // ' + AsciiStr;
|
|
end;
|
|
|
|
begin
|
|
with TStringList.Create do
|
|
try
|
|
Add(Format('.assembly extern /*%.8x*/ %s', [Token, Name]));
|
|
Add('{');
|
|
|
|
if Table.Stream.FindTable(ttCustomAttribute, TJclClrTable(TblCustomAttribute)) then
|
|
for I := 0 to TblCustomAttribute.RowCount-1 do
|
|
if TblCustomAttribute.Rows[I].Parent = Self then
|
|
Add(' ' + TblCustomAttribute.Rows[I].DumpIL);
|
|
|
|
if Assigned(HashValue) then
|
|
Add(PublicKeyOrToken.Dump(' .hash = '));
|
|
|
|
if Assigned(PublicKeyOrToken) then
|
|
Add(PublicKeyOrToken.Dump(' .publickeytoken = '));
|
|
|
|
if FCultureOffset <> 0 then
|
|
Add(' .culture "' + Culture + '"');
|
|
|
|
Add(' .ver ' + Version);
|
|
Add('}');
|
|
Result := Text;
|
|
finally
|
|
Free;
|
|
end;
|
|
end;
|
|
|
|
function TJclClrTableAssemblyRefRow.GetCulture: WideString;
|
|
begin
|
|
Result := Table.Stream.Metadata.StringAt(FCultureOffset);
|
|
end;
|
|
|
|
function TJclClrTableAssemblyRefRow.GetFlags: TJclClrAssemblyFlags;
|
|
begin
|
|
Result := TJclClrTableAssemblyRow.AssemblyFlags(FFlagMask);
|
|
end;
|
|
|
|
function TJclClrTableAssemblyRefRow.GetHashValue: TJclClrBlobRecord;
|
|
begin
|
|
Result := Table.Stream.Metadata.BlobAt(FHashValueOffset);
|
|
end;
|
|
|
|
function TJclClrTableAssemblyRefRow.GetName: WideString;
|
|
begin
|
|
Result := Table.Stream.Metadata.StringAt(FNameOffset);
|
|
end;
|
|
|
|
function TJclClrTableAssemblyRefRow.GetPublicKeyOrToken: TJclClrBlobRecord;
|
|
begin
|
|
Result := Table.Stream.Metadata.BlobAt(FPublicKeyOrTokenOffset);
|
|
end;
|
|
|
|
function TJclClrTableAssemblyRefRow.GetVersion: string;
|
|
begin
|
|
Result := FormatVersionString(FMajorVersion, FMinorVersion, FBuildNumber, FRevisionNumber);
|
|
end;
|
|
|
|
function TJclClrTableAssemblyRef.GetRow(const Idx: Integer): TJclClrTableAssemblyRefRow;
|
|
begin
|
|
Result := TJclClrTableAssemblyRefRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableAssemblyRef.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableAssemblyRefRow;
|
|
end;
|
|
|
|
//=== { TJclClrTableAssemblyRefOSRow } =======================================
|
|
|
|
constructor TJclClrTableAssemblyRefOSRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FAssemblyRefIdx := Table.ReadIndex([ttAssemblyRef]);
|
|
end;
|
|
|
|
function TJclClrTableAssemblyRefOSRow.GetAssemblyRef: TJclClrTableAssemblyRefRow;
|
|
var
|
|
AssemblyRefTable: TJclClrTableAssemblyRef;
|
|
begin
|
|
if Table.Stream.FindTable(ttAssemblyRef, TJclClrTable(AssemblyRefTable)) then
|
|
Result := AssemblyRefTable[FAssemblyRefIdx-1]
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
function TJclClrTableAssemblyRefOS.GetRow(const Idx: Integer): TJclClrTableAssemblyRefOSRow;
|
|
begin
|
|
Result := TJclClrTableAssemblyRefOSRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableAssemblyRefOS.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableAssemblyRefOSRow;
|
|
end;
|
|
|
|
//=== { TJclClrTableAssemblyRefProcessorRow } ================================
|
|
|
|
constructor TJclClrTableAssemblyRefProcessorRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FAssemblyRefIdx := Table.ReadIndex([ttAssemblyRef]);
|
|
end;
|
|
|
|
function TJclClrTableAssemblyRefProcessorRow.GetAssemblyRef: TJclClrTableAssemblyRefRow;
|
|
var
|
|
AssemblyRefTable: TJclClrTableAssemblyRef;
|
|
begin
|
|
if Table.Stream.FindTable(ttAssemblyRef, TJclClrTable(AssemblyRefTable)) then
|
|
Result := AssemblyRefTable[FAssemblyRefIdx-1]
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
function TJclClrTableAssemblyRefProcessor.GetRow(
|
|
const Idx: Integer): TJclClrTableAssemblyRefProcessorRow;
|
|
begin
|
|
Result := TJclClrTableAssemblyRefProcessorRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableAssemblyRefProcessor.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableAssemblyRefProcessorRow;
|
|
end;
|
|
|
|
//=== { TJclClrTableClassLayoutRow } =========================================
|
|
|
|
constructor TJclClrTableClassLayoutRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FPackingSize := Table.ReadWord;
|
|
FClassSize := Table.ReadDWord;
|
|
FParentIdx := Table.ReadIndex([ttTypeDef]);
|
|
end;
|
|
|
|
function TJclClrTableClassLayout.GetRow(const Idx: Integer): TJclClrTableClassLayoutRow;
|
|
begin
|
|
Result := TJclClrTableClassLayoutRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableClassLayout.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableClassLayoutRow;
|
|
end;
|
|
|
|
//=== { TJclClrTableConstantRow } ============================================
|
|
|
|
constructor TJclClrTableConstantRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FKind := Table.ReadByte;
|
|
Table.ReadByte; // padding zero
|
|
FParentIdx := Table.ReadIndex([ttParamDef, ttFieldDef, ttPropertyDef]);
|
|
FValueOffset := Table.ReadIndex(hkBlob);
|
|
end;
|
|
|
|
function TJclClrTableConstantRow.DumpIL: string;
|
|
begin
|
|
case ElementType of
|
|
etBoolean:
|
|
Result := BooleanToStr(PBoolean(Value.Memory)^);
|
|
etChar:
|
|
Result := PWideChar(Value.Memory)^;
|
|
etI1:
|
|
Result := IntToStr(PShortInt(Value.Memory)^);
|
|
etU1:
|
|
Result := IntToStr(PByte(Value.Memory)^);
|
|
etI2:
|
|
Result := IntToStr(PSmallint(Value.Memory)^);
|
|
etU2:
|
|
Result := IntToStr(PWord(Value.Memory)^);
|
|
etI4:
|
|
Result := IntToStr(PInteger(Value.Memory)^);
|
|
etU4:
|
|
Result := IntToStr(PDWord(Value.Memory)^);
|
|
etI8:
|
|
Result := IntToStr(PInt64(Value.Memory)^);
|
|
etU8:
|
|
Result := IntToStr(PInt64(Value.Memory)^);
|
|
etR4:
|
|
Result := FloatToStr(PSingle(Value.Memory)^);
|
|
etR8:
|
|
Result := FloatToStr(PDouble(Value.Memory)^);
|
|
etString:
|
|
Result := '"' + WideCharLenToString(PWideChar(Value.Memory), Value.Size div 2) + '"';
|
|
etClass:
|
|
begin
|
|
if FValueOffset = 0 then
|
|
begin
|
|
Result := ' nullref';
|
|
Exit;
|
|
end;
|
|
|
|
Result := Table.Stream.Metadata.Tokens[PJclClrToken(Value.Memory)^].DumpIL;
|
|
end;
|
|
end;
|
|
Result := ' = ' + Result;
|
|
end;
|
|
|
|
function TJclClrTableConstantRow.GetElementType: TJclClrElementType;
|
|
begin
|
|
for Result := Low(TJclClrElementType) to High(TJclClrElementType) do
|
|
if ClrElementTypeMapping[Result] = FKind then
|
|
Exit;
|
|
Result := etEnd;
|
|
end;
|
|
|
|
function TJclClrTableConstantRow.GetParent: TJclClrTableRow;
|
|
const
|
|
HasConstantMapping: array [0..2] of TJclClrTableKind =
|
|
(ttFieldDef, ttParamDef, ttPropertyDef);
|
|
begin
|
|
Assert(FParentIdx and 3 <> 3);
|
|
Result := Table.Stream.Tables[HasConstantMapping[FParentIdx and 3]].Rows[FParentIdx shr 2 - 1];
|
|
end;
|
|
|
|
function TJclClrTableConstantRow.GetValue: TJclClrBlobRecord;
|
|
begin
|
|
Result := Table.Stream.Metadata.BlobAt(FValueOffset);
|
|
end;
|
|
|
|
function TJclClrTableConstant.GetRow(const Idx: Integer): TJclClrTableConstantRow;
|
|
begin
|
|
Result := TJclClrTableConstantRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableConstant.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableConstantRow;
|
|
end;
|
|
|
|
//=== { TJclClrTableCustomAttributeRow } =====================================
|
|
|
|
constructor TJclClrTableCustomAttributeRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FParentIdx := Table.ReadIndex([ttModule, ttTypeRef, ttTypeDef, ttFieldDef,
|
|
ttMethodDef, ttParamDef, ttInterfaceImpl, ttMemberRef, ttConstant,
|
|
ttFieldMarshal, ttDeclSecurity, ttClassLayout, ttFieldLayout, ttSignature,
|
|
ttEventMap, ttEventDef, ttPropertyMap, ttPropertyDef, ttMethodSemantics,
|
|
ttMethodImpl, ttModuleRef, ttTypeSpec, ttImplMap, ttFieldRVA, ttAssembly,
|
|
ttAssemblyProcessor, ttAssemblyOS, ttAssemblyRef, ttAssemblyRefProcessor,
|
|
ttAssemblyRefOS, ttFile, ttExportedType, ttManifestResource, ttNestedClass]);
|
|
FTypeIdx := Table.ReadIndex([ttMethodDef, ttMemberRef]);
|
|
FValueOffset := Table.ReadIndex(hkBlob);
|
|
end;
|
|
|
|
function TJclClrTableCustomAttributeRow.GetParent: TJclClrTableRow;
|
|
const
|
|
MapTagToTable: array [0..18] of TJclClrTableKind =
|
|
(ttMethodDef, ttFieldDef, ttTypeRef, ttTypeDef, ttParamDef, ttInterfaceImpl,
|
|
ttMemberRef, ttModule, ttDeclSecurity, ttPropertyDef, ttEventDef, ttSignature,
|
|
ttModuleRef, ttTypeSpec, ttAssembly, ttAssemblyRef, ttFile, ttExportedType,
|
|
ttManifestResource);
|
|
var
|
|
WideIndex: Boolean;
|
|
begin
|
|
WideIndex := Table.IsWideIndex([ttModule, ttTypeRef, ttTypeDef, ttFieldDef,
|
|
ttMethodDef, ttParamDef, ttInterfaceImpl, ttMemberRef, ttConstant,
|
|
ttFieldMarshal, ttDeclSecurity, ttClassLayout, ttFieldLayout, ttSignature,
|
|
ttEventMap, ttEventDef, ttPropertyMap, ttPropertyDef, ttMethodSemantics,
|
|
ttMethodImpl, ttModuleRef, ttTypeSpec, ttImplMap, ttFieldRVA, ttAssembly,
|
|
ttAssemblyProcessor, ttAssemblyOS, ttAssemblyRef, ttAssemblyRefProcessor,
|
|
ttAssemblyRefOS, ttFile, ttExportedType, ttManifestResource, ttNestedClass]);
|
|
|
|
Assert(Table.GetCodedIndexTag(FParentIdx, 5, WideIndex) <= 18);
|
|
Result := Table.Stream.Tables[
|
|
MapTagToTable[Table.GetCodedIndexTag(FParentIdx, 5, WideIndex)]].
|
|
Rows[Table.GetCodedIndexValue(FParentIdx, 5, WideIndex)-1];
|
|
end;
|
|
|
|
function TJclClrTableCustomAttributeRow.GetMethod: TJclClrTableRow;
|
|
const
|
|
MapTagToTable: array [2..3] of TJclClrTableKind = (ttMethodDef, ttMemberRef);
|
|
var
|
|
WideIndex: Boolean;
|
|
begin
|
|
WideIndex := Table.IsWideIndex([ttMethodDef, ttMemberRef]);
|
|
Assert(Table.GetCodedIndexTag(FTypeIdx, 3, WideIndex) in [2, 3]);
|
|
Result := Table.Stream.Tables[
|
|
MapTagToTable[Table.GetCodedIndexTag(FTypeIdx, 3, WideIndex)]].
|
|
Rows[Table.GetCodedIndexValue(FTypeIdx, 3, WideIndex)-1];
|
|
end;
|
|
|
|
function TJclClrTableCustomAttributeRow.GetValue: TJclClrBlobRecord;
|
|
begin
|
|
Result := Table.Stream.Metadata.BlobAt(FValueOffset);
|
|
end;
|
|
|
|
function TJclClrTableCustomAttributeRow.DumpIL: string;
|
|
begin
|
|
// .custom /*0C000001:0A00000C*/ intance void [mscorlib/* 23000001 */]System.Reflection.AssemblyInformationalVersionAttribute/* 0100001C */::.ctor(string) /* 0A00000C */ = ( 01 00 0A 31 2E 30 2E 33 37 30 35 2E 30 00 00 ) // ...1.0.3705.0..
|
|
Result := Value.Dump(Format('.custom /*%.8x:%.8x*/ %s = ', [Token, Method.Token, Method.DumpIL]));
|
|
end;
|
|
|
|
function TJclClrTableCustomAttribute.GetRow(const Idx: Integer): TJclClrTableCustomAttributeRow;
|
|
begin
|
|
Result := TJclClrTableCustomAttributeRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableCustomAttribute.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableCustomAttributeRow;
|
|
end;
|
|
|
|
//=== { TJclClrTableDeclSecurityRow } ========================================
|
|
|
|
constructor TJclClrTableDeclSecurityRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FAction := Table.ReadWord;
|
|
FParentIdx := Table.ReadIndex([ttTypeDef, ttMethodDef, ttAssembly]);
|
|
FPermissionSetOffset := Table.ReadIndex(hkBlob);
|
|
end;
|
|
|
|
function TJclClrTableDeclSecurity.GetRow(const Idx: Integer): TJclClrTableDeclSecurityRow;
|
|
begin
|
|
Result := TJclClrTableDeclSecurityRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableDeclSecurity.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableDeclSecurityRow;
|
|
end;
|
|
|
|
//=== { TJclClrTableEventMapRow } ============================================
|
|
|
|
constructor TJclClrTableEventMapRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FParentIdx := Table.ReadIndex([ttTypeDef]);
|
|
FEventListIdx := Table.ReadIndex([ttEventDef]);
|
|
end;
|
|
|
|
function TJclClrTableEventMap.GetRow(const Idx: Integer): TJclClrTableEventMapRow;
|
|
begin
|
|
Result := TJclClrTableEventMapRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableEventMap.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableEventMapRow;
|
|
end;
|
|
|
|
//=== { TJclClrTableEventDefRow } ============================================
|
|
|
|
constructor TJclClrTableEventDefRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FEventFlags := Table.ReadWord;
|
|
FNameOffset := Table.ReadIndex(hkString);
|
|
FEventTypeIdx := Table.ReadIndex([ttTypeDef, ttTypeRef, ttTypeSpec]);
|
|
end;
|
|
|
|
function TJclClrTableEventDefRow.GetName: WideString;
|
|
begin
|
|
Result := Table.Stream.Metadata.StringAt(FNameOffset);
|
|
end;
|
|
|
|
function TJclClrTableEventDef.GetRow(const Idx: Integer): TJclClrTableEventDefRow;
|
|
begin
|
|
Result := TJclClrTableEventDefRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableEventDef.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableEventDefRow;
|
|
end;
|
|
|
|
//=== { TJclClrTableEventPtrRow } ============================================
|
|
|
|
constructor TJclClrTableEventPtrRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FEventIdx := Table.ReadIndex([ttEventDef]);
|
|
end;
|
|
|
|
function TJclClrTableEventPtrRow.GetEvent: TJclClrTableEventDefRow;
|
|
begin
|
|
Result := TJclClrTableEventDef(Table.Stream.Tables[ttEventDef]).Rows[FEventIdx-1];
|
|
end;
|
|
|
|
function TJclClrTableEventPtr.GetRow(const Idx: Integer): TJclClrTableEventPtrRow;
|
|
begin
|
|
Result := TJclClrTableEventPtrRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableEventPtr.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableEventPtrRow;
|
|
end;
|
|
|
|
//=== { TJclClrTableExportedTypeRow } ========================================
|
|
|
|
constructor TJclClrTableExportedTypeRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FFlags := Table.ReadDWord;
|
|
FTypeDefIdx := Table.ReadDWord;
|
|
FTypeNameOffset := Table.ReadIndex(hkString);
|
|
FTypeNamespaceOffset := Table.ReadIndex(hkString);
|
|
FImplementationIdx := Table.ReadIndex([ttFile, ttExportedType]);
|
|
end;
|
|
|
|
function TJclClrTableExportedTypeRow.GetTypeName: WideString;
|
|
begin
|
|
Result := Table.Stream.Metadata.StringAt(FTypeNameOffset);
|
|
end;
|
|
|
|
function TJclClrTableExportedTypeRow.GetTypeNamespace: WideString;
|
|
begin
|
|
Result := Table.Stream.Metadata.StringAt(FTypeNamespaceOffset);
|
|
end;
|
|
|
|
function TJclClrTableExportedType.GetRow(const Idx: Integer): TJclClrTableExportedTypeRow;
|
|
begin
|
|
Result := TJclClrTableExportedTypeRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableExportedType.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableExportedTypeRow;
|
|
end;
|
|
|
|
//=== { TJclClrTableFieldDefRow } ============================================
|
|
|
|
constructor TJclClrTableFieldDefRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FFlags := Table.ReadWord;
|
|
FNameOffset := Table.ReadIndex(hkString);
|
|
FSignatureOffset := Table.ReadIndex(hkBlob);
|
|
FParentToken := nil;
|
|
end;
|
|
|
|
function TJclClrTableFieldDefRow.DumpIL: string;
|
|
const
|
|
StaticName: array [Boolean] of PChar =
|
|
('', 'static ');
|
|
VisibilityName: array [TJclClrTableFieldDefVisibility] of PChar =
|
|
('', 'private', 'famandassem', 'assembly', 'family', 'famandassem', 'public');
|
|
var
|
|
I: Integer;
|
|
|
|
function DumpFlags: string;
|
|
const
|
|
FlagName: array [ffInitOnly..ffRTSpecialName] of PChar =
|
|
('initonly', 'literal', 'notserialized', 'specialname', '', 'rtspecialname');
|
|
var
|
|
AFlag: TJclClrTableFieldDefFlag;
|
|
begin
|
|
for AFlag := Low(FlagName) to High(FlagName) do
|
|
if AFlag in Flags then
|
|
Result := Result + FlagName[AFlag] + ' ';
|
|
end;
|
|
|
|
function DumpSignature: string;
|
|
begin
|
|
with TJclClrSignature.Create(Signature) do
|
|
try
|
|
Result := UncompressFieldSignature;
|
|
finally
|
|
Free;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
Result := Format('.field /*%.8x*/ %s%s %s%s %s', [Token,
|
|
StaticName[ffStatic in Flags], VisibilityName[Visibility],
|
|
DumpFlags, DumpSignature, Name]);
|
|
|
|
if ffHasDefault in Flags then
|
|
begin
|
|
with TJclClrTableConstant(Table.Stream.Tables[ttConstant]) do
|
|
for I := 0 to RowCount-1 do
|
|
if Rows[I].Parent = Self then
|
|
begin
|
|
Result := Result + Rows[I].DumpIL;
|
|
Break;
|
|
end;
|
|
end
|
|
else
|
|
if ffHasFieldRVA in Flags then
|
|
begin
|
|
{ TODO : What to do? }
|
|
end;
|
|
end;
|
|
|
|
function TJclClrTableFieldDefRow.GetName: WideString;
|
|
begin
|
|
Result := Table.Stream.Metadata.StringAt(FNameOffset);
|
|
end;
|
|
|
|
function TJclClrTableFieldDefRow.GetSignature: TJclClrBlobRecord;
|
|
begin
|
|
Result := Table.Stream.Metadata.BlobAt(FSignatureOffset);
|
|
end;
|
|
|
|
function TJclClrTableFieldDefRow.GetVisibility: TJclClrTableFieldDefVisibility;
|
|
const
|
|
FieldVisibilityMapping: array [fdPrivateScope..fdPublic] of TJclClrTableFieldDefVisibility =
|
|
(fvPrivateScope, fvPrivate, fvFamANDAssem, fvAssembly, fvFamily, fvFamORAssem, fvPublic);
|
|
begin
|
|
Result := FieldVisibilityMapping[FFlags and fdFieldAccessMask];
|
|
end;
|
|
|
|
function TJclClrTableFieldDefRow.GetFlag: TJclClrTableFieldDefFlags;
|
|
const
|
|
FieldFlagMapping: array [TJclClrTableFieldDefFlag] of Word =
|
|
(fdStatic, fdInitOnly, fdLiteral, fdNotSerialized, fdSpecialName,
|
|
fdPinvokeImpl, fdRTSpecialName, fdHasFieldMarshal, fdHasDefault, fdHasFieldRVA);
|
|
var
|
|
AFlag: TJclClrTableFieldDefFlag;
|
|
begin
|
|
for AFlag := Low(TJclClrTableFieldDefFlag) to High(TJclClrTableFieldDefFlag) do
|
|
if FFlags and FieldFlagMapping[AFlag] <> 0 then
|
|
Include(Result, AFlag);
|
|
end;
|
|
|
|
procedure TJclClrTableFieldDefRow.SetParentToken(const ARow: TJclClrTableTypeDefRow);
|
|
begin
|
|
FParentToken := ARow;
|
|
end;
|
|
|
|
function TJclClrTableFieldDef.GetRow(const Idx: Integer): TJclClrTableFieldDefRow;
|
|
begin
|
|
Result := TJclClrTableFieldDefRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableFieldDef.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableFieldDefRow;
|
|
end;
|
|
|
|
//=== { TJclClrTableFieldPtrRow } ============================================
|
|
|
|
constructor TJclClrTableFieldPtrRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FFieldIdx := Table.ReadIndex([ttFieldDef]);
|
|
end;
|
|
|
|
function TJclClrTableFieldPtrRow.GetField: TJclClrTableFieldDefRow;
|
|
begin
|
|
Result := TJclClrTableFieldDef(Table.Stream.Tables[ttFieldDef]).Rows[FFieldIdx-1];
|
|
end;
|
|
|
|
function TJclClrTableFieldPtr.GetRow(const Idx: Integer): TJclClrTableFieldPtrRow;
|
|
begin
|
|
Result := TJclClrTableFieldPtrRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableFieldPtr.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableFieldPtrRow;
|
|
end;
|
|
|
|
//=== { TJclClrTableFieldLayoutRow } =========================================
|
|
|
|
constructor TJclClrTableFieldLayoutRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FOffset := Table.ReadDWord;
|
|
FFieldIdx := Table.ReadIndex([ttFieldDef]);
|
|
end;
|
|
|
|
function TJclClrTableFieldLayout.GetRow(
|
|
const Idx: Integer): TJclClrTableFieldLayoutRow;
|
|
begin
|
|
Result := TJclClrTableFieldLayoutRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableFieldLayout.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableFieldLayoutRow;
|
|
end;
|
|
|
|
//=== { TJclClrTableFieldMarshalRow } ========================================
|
|
|
|
constructor TJclClrTableFieldMarshalRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FParentIdx := Table.ReadIndex([ttFieldDef, ttParamDef]);
|
|
FNativeTypeOffset := Table.ReadIndex(hkBlob);
|
|
end;
|
|
|
|
function TJclClrTableFieldMarshal.GetRow(
|
|
const Idx: Integer): TJclClrTableFieldMarshalRow;
|
|
begin
|
|
Result := TJclClrTableFieldMarshalRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableFieldMarshal.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableFieldMarshalRow;
|
|
end;
|
|
|
|
//=== { TJclClrTableFieldRVARow } ============================================
|
|
|
|
constructor TJclClrTableFieldRVARow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FRVA := Table.ReadDWord;
|
|
FFieldIdx := Table.ReadIndex([ttFieldDef]);
|
|
end;
|
|
|
|
function TJclClrTableFieldRVA.GetRow(const Idx: Integer): TJclClrTableFieldRVARow;
|
|
begin
|
|
Result := TJclClrTableFieldRVARow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableFieldRVA.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableFieldRVARow;
|
|
end;
|
|
|
|
//=== { TJclClrTableFileRow } ================================================
|
|
|
|
constructor TJclClrTableFileRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FFlags := Table.ReadDWord;
|
|
FNameOffset := Table.ReadIndex(hkString);
|
|
FHashValueOffset := Table.ReadIndex(hkBlob);
|
|
end;
|
|
|
|
function TJclClrTableFileRow.GetName: WideString;
|
|
begin
|
|
Result := Table.Stream.Metadata.StringAt(FNameOffset);
|
|
end;
|
|
|
|
function TJclClrTableFileRow.GetHashValue: TJclClrBlobRecord;
|
|
begin
|
|
Result := Table.Stream.Metadata.BlobAt(FHashValueOffset);
|
|
end;
|
|
|
|
function TJclClrTableFileRow.GetContainsMetadata: Boolean;
|
|
const
|
|
ffContainsNoMetaData = $0001;
|
|
begin
|
|
Result := (FFlags and ffContainsNoMetaData) = ffContainsNoMetaData;
|
|
end;
|
|
|
|
function TJclClrTableFileRow.DumpIL: string;
|
|
|
|
function GetMetadataName: string;
|
|
begin
|
|
if not ContainsMetadata then
|
|
Result := 'nometadata '
|
|
end;
|
|
|
|
begin
|
|
Result := HashValue.Dump('.file ' + GetMetadataName + Name + ' .hash = ');
|
|
end;
|
|
|
|
function TJclClrTableFile.GetRow(const Idx: Integer): TJclClrTableFileRow;
|
|
begin
|
|
Result := TJclClrTableFileRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableFile.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableFileRow;
|
|
end;
|
|
|
|
//=== { TJclClrTableImplMapRow } =============================================
|
|
|
|
constructor TJclClrTableImplMapRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FMappingFlags := Table.ReadWord;
|
|
FMemberForwardedIdx := Table.ReadIndex([ttFieldDef, ttMethodDef]);
|
|
FImportNameOffset := Table.ReadIndex(hkString);
|
|
FImportScopeIdx := Table.ReadIndex([ttModuleRef]);
|
|
end;
|
|
|
|
function TJclClrTableImplMapRow.GetImportName: WideString;
|
|
begin
|
|
Result := Table.Stream.Metadata.StringAt(FImportNameOffset);
|
|
end;
|
|
|
|
function TJclClrTableImplMap.GetRow(const Idx: Integer): TJclClrTableImplMapRow;
|
|
begin
|
|
Result := TJclClrTableImplMapRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableImplMap.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableImplMapRow;
|
|
end;
|
|
|
|
//=== { TJclClrTableInterfaceImplRow } =======================================
|
|
|
|
constructor TJclClrTableInterfaceImplRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FClassIdx := Table.ReadIndex([ttTypeDef]);
|
|
FInterfaceIdx := Table.ReadIndex([ttTypeDef, ttTypeRef, ttTypeSpec]);
|
|
end;
|
|
|
|
function TJclClrTableInterfaceImplRow.DumpIL: string;
|
|
begin
|
|
if ImplInterface is TJclClrTableTypeRefRow then
|
|
Result := TJclClrTableTypeRefRow(ImplInterface).DumpIL
|
|
else
|
|
if ImplInterface is TJclClrTableTypeDefRow then
|
|
with TJclClrTableTypeDefRow(ImplInterface) do
|
|
Result := Format('%s.%s/*%.8x*/', [Namespace, Name, Token])
|
|
else
|
|
Result := 'Unknown';
|
|
end;
|
|
|
|
function TJclClrTableInterfaceImplRow.GetImplClass: TJclClrTableRow;
|
|
begin
|
|
Result := Table.Stream.Metadata.Tokens[FClassIdx];
|
|
end;
|
|
|
|
function TJclClrTableInterfaceImplRow.GetImplInterface: TJclClrTableRow;
|
|
begin
|
|
Result := DecodeTypeDefOrRef(FInterfaceIdx);
|
|
end;
|
|
|
|
function TJclClrTableInterfaceImpl.GetRow(
|
|
const Idx: Integer): TJclClrTableInterfaceImplRow;
|
|
begin
|
|
Result := TJclClrTableInterfaceImplRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableInterfaceImpl.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableInterfaceImplRow;
|
|
end;
|
|
|
|
//=== { TJclClrTableManifestResourceRow } ====================================
|
|
|
|
constructor TJclClrTableManifestResourceRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FOffset := Table.ReadDWord;
|
|
FFlags := Table.ReadDWord;
|
|
FNameOffset := Table.ReadIndex(hkString);
|
|
FImplementationIdx := Table.ReadIndex([ttFile, ttAssemblyRef]);
|
|
end;
|
|
|
|
function TJclClrTableManifestResourceRow.DumpIL: string;
|
|
const
|
|
VisibilityName: array [TJclClrTableManifestResourceVisibility] of PChar =
|
|
('public', 'private');
|
|
var
|
|
I: Integer;
|
|
TblCustomAttribute: TJclClrTableCustomAttribute;
|
|
begin
|
|
with TStringList.Create do
|
|
try
|
|
Add(Format('.mresource /*%.8x*/ %s %s', [Token, VisibilityName[Visibility], Name]));
|
|
Add('(');
|
|
|
|
if Table.Stream.FindTable(ttCustomAttribute, TJclClrTable(TblCustomAttribute)) then
|
|
for I := 0 to TblCustomAttribute.RowCount-1 do
|
|
if TblCustomAttribute.Rows[I].Parent = Self then
|
|
Add(' ' + TblCustomAttribute.Rows[I].DumpIL);
|
|
|
|
if FImplementationIdx <> 0 then
|
|
if ImplementationRow is TJclClrTableAssemblyRefRow then
|
|
Add(' .assembly extern ' +
|
|
TJclClrTableAssemblyRefRow(ImplementationRow).Name)
|
|
else
|
|
Add(Format(' .file %s at %d',
|
|
[TJclClrTableFileRow(ImplementationRow).Name, Offset]));
|
|
Add(')');
|
|
Result := Text;
|
|
finally
|
|
Free;
|
|
end;
|
|
end;
|
|
|
|
function TJclClrTableManifestResourceRow.GetImplementationRow: TJclClrTableRow;
|
|
begin
|
|
Result := Table.Stream.Metadata.Tokens[FImplementationIdx];
|
|
end;
|
|
|
|
function TJclClrTableManifestResourceRow.GetName: WideString;
|
|
begin
|
|
Result := Table.Stream.Metadata.StringAt(FNameOffset);
|
|
end;
|
|
|
|
function TJclClrTableManifestResourceRow.GetVisibility: TJclClrTableManifestResourceVisibility;
|
|
begin
|
|
for Result := Low(TJclClrTableManifestResourceVisibility) to High(TJclClrTableManifestResourceVisibility) do
|
|
if (FFlags and mrVisibilityMask) = ManifestResourceVisibilityMapping[Result] then
|
|
Exit;
|
|
raise EJclMetadataError.CreateResFmt(@RsUnknownManifestResource, [FFlags and mrVisibilityMask]);
|
|
end;
|
|
|
|
function TJclClrTableManifestResource.GetRow(
|
|
const Idx: Integer): TJclClrTableManifestResourceRow;
|
|
begin
|
|
Result := TJclClrTableManifestResourceRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableManifestResource.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableManifestResourceRow;
|
|
end;
|
|
|
|
//=== { TJclClrTableMemberRefRow } ===========================================
|
|
|
|
constructor TJclClrTableMemberRefRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FClassIdx := Table.ReadIndex([ttTypeRef, ttModuleRef, ttMethodDef, ttTypeSpec, ttTypeDef]);
|
|
FNameOffset := Table.ReadIndex(hkString);
|
|
FSignatureOffset := Table.ReadIndex(hkBlob);
|
|
end;
|
|
|
|
function TJclClrTableMemberRefRow.GetName: WideString;
|
|
begin
|
|
Result := Table.Stream.Metadata.StringAt(FNameOffset);
|
|
end;
|
|
|
|
function TJclClrTableMemberRefRow.GetSignature: TJclClrBlobRecord;
|
|
begin
|
|
Result := Table.Stream.Metadata.BlobAt(FSignatureOffset);
|
|
end;
|
|
|
|
function TJclClrTableMemberRefRow.GetParentClass: TJclClrTableRow;
|
|
const
|
|
MapTagToTable: array [1..5] of TJclClrTableKind =
|
|
(ttTypeRef, ttModuleRef, ttMethodDef, ttTypeSpec, ttTypeDef);
|
|
var
|
|
WideIndex: Boolean;
|
|
begin
|
|
WideIndex := Table.IsWideIndex([ttTypeRef, ttModuleRef, ttMethodDef, ttTypeSpec, ttTypeDef]);
|
|
Assert(Table.GetCodedIndexTag(FClassIdx, 3, WideIndex) in [1..5]);
|
|
Result := Table.Stream.Tables[
|
|
MapTagToTable[Table.GetCodedIndexTag(FClassIdx, 3, WideIndex)]].
|
|
Rows[Table.GetCodedIndexValue(FClassIdx, 3, WideIndex)-1];
|
|
end;
|
|
|
|
function TJclClrTableMemberRefRow.GetFullName: WideString;
|
|
var
|
|
Row: TJclClrTableRow;
|
|
begin
|
|
Row := GetParentClass;
|
|
|
|
if Row is TJclClrTableTypeRefRow then
|
|
Result := TJclClrTableTypeRefRow(Row).FullName
|
|
else
|
|
if Row is TJclClrTableModuleRow then
|
|
Result := TJclClrTableModuleRow(Row).Name
|
|
else
|
|
if Row is TJclClrTableMethodDefRow then
|
|
Result := TJclClrTableMethodDefRow(Row).FullName
|
|
else
|
|
if Row is TJclClrTableTypeSpecRow then
|
|
Result := ''
|
|
else
|
|
if Row is TJclClrTableTypeDefRow then
|
|
Result := TJclClrTableTypeDefRow(Row).FullName;
|
|
|
|
Result := Result + '.' + Name;
|
|
end;
|
|
|
|
function TJclClrTableMemberRef.GetRow(const Idx: Integer): TJclClrTableMemberRefRow;
|
|
begin
|
|
Result := TJclClrTableMemberRefRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableMemberRef.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableMemberRefRow;
|
|
end;
|
|
|
|
//=== { TJclClrTableParamDefRow } ============================================
|
|
|
|
constructor TJclClrTableParamDefRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FFlagMask := Table.ReadWord;
|
|
FSequence := Table.ReadWord;
|
|
FNameOffset := Table.ReadIndex(hkString);
|
|
|
|
FMethod := nil;
|
|
FFlags := ParamFlags(FFlagMask);
|
|
end;
|
|
|
|
function TJclClrTableParamDefRow.GetName: WideString;
|
|
begin
|
|
Result := Table.Stream.Metadata.StringAt(FNameOffset);
|
|
end;
|
|
|
|
procedure TJclClrTableParamDefRow.SetMethod(const AMethod: TJclClrTableMethodDefRow);
|
|
begin
|
|
FMethod := AMethod;
|
|
end;
|
|
|
|
class function TJclClrTableParamDefRow.ParamFlags(const AFlags: TJclClrParamKinds): Word;
|
|
var
|
|
AFlag: TJclClrParamKind;
|
|
begin
|
|
Result := 0;
|
|
for AFlag := Low(TJclClrParamKind) to High(TJclClrParamKind) do
|
|
if AFlag in AFlags then
|
|
Result := Result or ClrParamKindMapping[AFlag];
|
|
end;
|
|
|
|
class function TJclClrTableParamDefRow.ParamFlags(const AFlags: Word): TJclClrParamKinds;
|
|
var
|
|
AFlag: TJclClrParamKind;
|
|
begin
|
|
Result := [];
|
|
for AFlag := Low(TJclClrParamKind) to High(TJclClrParamKind) do
|
|
if (AFlags and ClrParamKindMapping[AFlag]) = ClrParamKindMapping[AFlag] then
|
|
Include(Result, AFlag);
|
|
end;
|
|
|
|
function TJclClrTableParamDefRow.DumpIL: string;
|
|
begin
|
|
{ TODO : What to do? }
|
|
end;
|
|
|
|
function TJclClrTableParamDef.GetRow(const Idx: Integer): TJclClrTableParamDefRow;
|
|
begin
|
|
Result := TJclClrTableParamDefRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableParamDef.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableParamDefRow;
|
|
end;
|
|
|
|
//=== { TJclClrTableParamPtrRow } ============================================
|
|
|
|
constructor TJclClrTableParamPtrRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FParamIdx := Table.ReadIndex([ttParamDef]);
|
|
end;
|
|
|
|
function TJclClrTableParamPtrRow.GetParam: TJclClrTableParamDefRow;
|
|
begin
|
|
Result := TJclClrTableParamDef(Table.Stream.Tables[ttParamDef]).Rows[FParamIdx-1];
|
|
end;
|
|
|
|
function TJclClrTableParamPtr.GetRow(const Idx: Integer): TJclClrTableParamPtrRow;
|
|
begin
|
|
Result := TJclClrTableParamPtrRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableParamPtr.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableParamPtrRow;
|
|
end;
|
|
|
|
//=== { TJclClrExceptionHandler } ============================================
|
|
|
|
const
|
|
// Indicates the format for the COR_ILMETHOD header
|
|
CorILMethod_FormatShift = 2;
|
|
CorILMethod_FormatMask = ((1 shl CorILMethod_FormatShift) - 1);
|
|
|
|
CorILMethod_TinyFormat = $0002;
|
|
CorILMethod_FatFormat = $0003;
|
|
|
|
CorILMethod_TinyFormatEven = $0002;
|
|
CorILMethod_TinyFormatOdd = $0006;
|
|
|
|
CorILMethod_InitLocals = $0010;
|
|
CorILMethod_MoreSects = $0008;
|
|
|
|
CorILMethod_Sect_Reserved = 0;
|
|
CorILMethod_Sect_EHTable = 1;
|
|
CorILMethod_Sect_OptILTable = 2;
|
|
|
|
CorILMethod_Sect_KindMask = $3F; // The mask for decoding the type code
|
|
CorILMethod_Sect_FatFormat = $40; // fat format
|
|
CorILMethod_Sect_MoreSects = $80; // there is another attribute after this one
|
|
|
|
COR_ILEXCEPTION_CLAUSE_NONE = $0000; // This is a typed handler
|
|
COR_ILEXCEPTION_CLAUSE_OFFSETLEN = $0000; // Deprecated
|
|
COR_ILEXCEPTION_CLAUSE_DEPRECATED = $0000; // Deprecated
|
|
COR_ILEXCEPTION_CLAUSE_FILTER = $0001; // If this bit is on, then this EH entry is for a filter
|
|
COR_ILEXCEPTION_CLAUSE_FINALLY = $0002; // This clause is a finally clause
|
|
COR_ILEXCEPTION_CLAUSE_FAULT = $0004; // Fault clause (finally that is called on exception only)
|
|
|
|
ExceptionClauseFlags: array [TJclClrExceptionClauseFlag] of DWORD =
|
|
(COR_ILEXCEPTION_CLAUSE_NONE, COR_ILEXCEPTION_CLAUSE_FILTER,
|
|
COR_ILEXCEPTION_CLAUSE_FINALLY, COR_ILEXCEPTION_CLAUSE_FAULT);
|
|
|
|
constructor TJclClrExceptionHandler.Create(const EHClause: TImageCorILMethodSectEHClauseSmall);
|
|
begin
|
|
FFlags := EHClause.Flags;
|
|
FTryBlock.Offset := EHClause.TryOffset;
|
|
FTryBlock.Length := EHClause.TryLength;
|
|
FHandlerBlock.Offset := EHClause.HandlerOffset;
|
|
FHandlerBlock.Length := EHClause.HandlerLength;
|
|
if (FFlags and COR_ILEXCEPTION_CLAUSE_FILTER) = COR_ILEXCEPTION_CLAUSE_FILTER then
|
|
begin
|
|
FClassToken := 0;
|
|
FFilterOffset := EHClause.FilterOffset;
|
|
end
|
|
else
|
|
begin
|
|
FClassToken := EHClause.ClassToken;
|
|
FFilterOffset := 0;
|
|
end;
|
|
end;
|
|
|
|
constructor TJclClrExceptionHandler.Create(const EHClause: TImageCorILMethodSectEHClauseFat);
|
|
begin
|
|
FFlags := EHClause.Flags;
|
|
FTryBlock.Offset := EHClause.TryOffset;
|
|
FTryBlock.Length := EHClause.TryLength;
|
|
FHandlerBlock.Offset := EHClause.HandlerOffset;
|
|
FHandlerBlock.Length := EHClause.HandlerLength;
|
|
if (FFlags and COR_ILEXCEPTION_CLAUSE_FILTER) = COR_ILEXCEPTION_CLAUSE_FILTER then
|
|
begin
|
|
FClassToken := 0;
|
|
FFilterOffset := EHClause.FilterOffset;
|
|
end
|
|
else
|
|
begin
|
|
FClassToken := EHClause.ClassToken;
|
|
FFilterOffset := 0;
|
|
end;
|
|
end;
|
|
|
|
function TJclClrExceptionHandler.GetFlags: TJclClrExceptionClauseFlags;
|
|
var
|
|
AFlag: TJclClrExceptionClauseFlag;
|
|
begin
|
|
Result := [];
|
|
for AFlag := Low(TJclClrExceptionClauseFlag) to High(TJclClrExceptionClauseFlag) do
|
|
if (FFlags and ExceptionClauseFlags[AFlag]) = ExceptionClauseFlags[AFlag] then
|
|
Include(Result, AFlag);
|
|
end;
|
|
|
|
//=== { TJclClrMethodBody } ==================================================
|
|
|
|
constructor TJclClrMethodBody.Create(const AMethod: TJclClrTableMethodDefRow);
|
|
var
|
|
ILMethod: PImageCorILMethodHeader;
|
|
begin
|
|
FMethod := AMethod;
|
|
FEHTable := TObjectList.Create;
|
|
|
|
FLocalVarSign := nil;
|
|
|
|
ILMethod := FMethod.Table.Stream.Metadata.Image.RvaToVa(FMethod.RVA);
|
|
if (ILMethod.Tiny.Flags_CodeSize and CorILMethod_FormatMask) = CorILMethod_TinyFormat then
|
|
begin
|
|
FSize := (ILMethod.Tiny.Flags_CodeSize shr CorILMethod_FormatShift) and ((1 shl 6) - 1);
|
|
FCode := Pointer(DWORD(ILMethod) + 1);
|
|
FMaxStack := 0;
|
|
FLocalVarSignToken := 0;
|
|
end
|
|
else
|
|
begin
|
|
FSize := ILMethod.Fat.CodeSize;
|
|
FCode := Pointer(DWORD(ILMethod) + (ILMethod.Fat.Flags_Size shr 12) * SizeOf(DWORD));
|
|
FMaxStack := ILMethod.Fat.MaxStack;
|
|
FLocalVarSignToken := ILMethod.Fat.LocalVarSigTok;
|
|
|
|
if IsBitSet(ILMethod.Fat.Flags_Size, CorILMethod_MoreSects) then
|
|
ParseMoreSections(Pointer((DWORD(FCode) + FSize + 1) and not 1));
|
|
end;
|
|
end;
|
|
|
|
destructor TJclClrMethodBody.Destroy;
|
|
begin
|
|
FreeAndNil(FLocalVarSign);
|
|
FreeAndNil(FEHTable);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TJclClrMethodBody.AddEHTable(EHTable: PImageCorILMethodSectEH);
|
|
var
|
|
I, Count: Integer;
|
|
FatFormat: Boolean;
|
|
begin
|
|
FatFormat := IsBitSet( EHTable.Small.SectSmall.Kind, CorILMethod_Sect_FatFormat);
|
|
if FatFormat then
|
|
Count := ((EHTable.Fat.SectFat.Kind_DataSize shr 8) - SizeOf(DWORD)) div SizeOf(TImageCorILMethodSectEHClauseFat)
|
|
else
|
|
Count := (EHTable.Small.SectSmall.Datasize - SizeOf(DWORD)) div SizeOf(TImageCorILMethodSectEHClauseSmall);
|
|
|
|
for I := 0 to Count-1 do
|
|
begin
|
|
if FatFormat then
|
|
FEHTable.Add(TJclClrExceptionHandler.Create(EHTable.Fat.Clauses[I]))
|
|
else
|
|
FEHTable.Add(TJclClrExceptionHandler.Create(EHTable.Small.Clauses[I]));
|
|
end;
|
|
end;
|
|
|
|
procedure TJclClrMethodBody.AddOptILTable(OptILTable: Pointer; Size: Integer);
|
|
begin
|
|
{ TODO : What to do? }
|
|
end;
|
|
|
|
procedure TJclClrMethodBody.ParseMoreSections(SectHeader: PImageCorILMethodSectHeader);
|
|
var
|
|
SectSize: DWORD;
|
|
begin
|
|
if IsBitSet(SectHeader.Small.Kind, CorILMethod_Sect_FatFormat) then
|
|
SectSize := SectHeader.Fat.Kind_DataSize shr 8
|
|
else
|
|
SectSize := SectHeader.Small.Datasize;
|
|
|
|
if IsBitSet(SectHeader.Small.Kind, CorILMethod_Sect_EHTable) then
|
|
AddEHTable(PImageCorILMethodSectEH(SectHeader))
|
|
else
|
|
if IsBitSet(SectHeader.Small.Kind, CorILMethod_Sect_OptILTable) then
|
|
AddOptILTable(Pointer(DWORD(FCode) + FSize), SectSize);
|
|
|
|
if IsBitSet(SectHeader.Small.Kind, CorILMethod_Sect_MoreSects) then
|
|
ParseMoreSections(Pointer(DWORD(SectHeader) + SectSize));
|
|
end;
|
|
|
|
function TJclClrMethodBody.GetExceptionHandler(const Idx: Integer): TJclClrExceptionHandler;
|
|
begin
|
|
Result := TJclClrExceptionHandler(FEHTable.Items[Idx]);
|
|
end;
|
|
|
|
function TJclClrMethodBody.GetExceptionHandlerCount: Integer;
|
|
begin
|
|
Result := FEHTable.Count;
|
|
end;
|
|
|
|
function TJclClrMethodBody.GetLocalVarSign: TJclClrLocalVarSign;
|
|
begin
|
|
if not Assigned(FLocalVarSign) and (FLocalVarSignToken <> 0) then
|
|
FLocalVarSign := TJclClrLocalVarSign.Create(LocalVarSignData);
|
|
|
|
Result := FLocalVarSign;
|
|
end;
|
|
|
|
function TJclClrMethodBody.GetLocalVarSignData: TJclClrBlobRecord;
|
|
begin
|
|
Result := TJclClrTableStandAloneSigRow(FMethod.Table.Stream.Metadata.Tokens[FLocalVarSignToken]).Signature;
|
|
end;
|
|
|
|
//=== { TJclClrTableMethodDefRow } ===========================================
|
|
|
|
constructor TJclClrTableMethodDefRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
|
|
FRVA := Table.ReadDWord;
|
|
FImplFlags := Table.ReadWord;
|
|
FFlags := Table.ReadWord;
|
|
FNameOffset := Table.ReadIndex(hkString);
|
|
FSignatureOffset := Table.ReadIndex(hkBlob);
|
|
FParamListIdx := Table.ReadIndex([ttParamDef]);
|
|
|
|
FParentToken := nil;
|
|
FParams := nil;
|
|
FSignature := nil;
|
|
|
|
if FRVA <> 0 then
|
|
FMethodBody := TJclClrMethodBody.Create(Self)
|
|
else
|
|
FMethodBody := nil;
|
|
end;
|
|
|
|
destructor TJclClrTableMethodDefRow.Destroy;
|
|
begin
|
|
FreeAndNil(FParams);
|
|
FreeAndNil(FSignature);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TJclClrTableMethodDefRow.GetName: WideString;
|
|
begin
|
|
Result := Table.Stream.Metadata.StringAt(FNameOffset);
|
|
end;
|
|
|
|
function TJclClrTableMethodDefRow.GetSignatureData: TJclClrBlobRecord;
|
|
begin
|
|
Result := Table.Stream.Metadata.BlobAt(FSignatureOffset);
|
|
end;
|
|
|
|
procedure TJclClrTableMethodDefRow.SetParentToken(const ARow: TJclClrTableTypeDefRow);
|
|
begin
|
|
FParentToken := ARow;
|
|
end;
|
|
|
|
procedure TJclClrTableMethodDefRow.UpdateParams;
|
|
var
|
|
ParamTable: TJclClrTableParamDef;
|
|
Idx, MaxParamListIdx: DWORD;
|
|
begin
|
|
with Table as TJclClrTableMethodDef do
|
|
if not Assigned(FParams) and (ParamListIdx <> 0) and
|
|
Stream.FindTable(ttParamDef, TJclClrTable(ParamTable)) then
|
|
begin
|
|
if RowCount > (Index+1) then
|
|
MaxParamListIdx := Rows[Index+1].ParamListIdx-1
|
|
else
|
|
MaxParamListIdx := ParamTable.RowCount;
|
|
if (ParamListIdx-1) < MaxParamListIdx then
|
|
begin
|
|
FParams := TList.Create;
|
|
for Idx := ParamListIdx-1 to MaxParamListIdx-1 do
|
|
begin
|
|
FParams.Add(ParamTable.Rows[Idx]);
|
|
ParamTable.Rows[Idx].SetMethod(Self);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJclClrTableMethodDefRow.Update;
|
|
begin
|
|
UpdateParams;
|
|
end;
|
|
|
|
function TJclClrTableMethodDefRow.GetHasParam: Boolean;
|
|
begin
|
|
Result := Assigned(FParams);
|
|
end;
|
|
|
|
function TJclClrTableMethodDefRow.GetParam(const Idx: Integer): TJclClrTableParamDefRow;
|
|
begin
|
|
Result := TJclClrTableParamDefRow(FParams.Items[Idx]);
|
|
end;
|
|
|
|
function TJclClrTableMethodDefRow.GetParamCount: Integer;
|
|
begin
|
|
Result := FParams.Count;
|
|
end;
|
|
|
|
function TJclClrTableMethodDefRow.DumpIL: string;
|
|
const
|
|
MemberAccessNames: array [TJclClrMemberAccess] of PChar =
|
|
('compilercontrolled', 'private', 'famandassem',
|
|
'assembly', 'family', 'famorassem', 'public');
|
|
CodeTypeNames: array [TJclClrMethodCodeType] of PChar =
|
|
('cil', 'native', 'optil', 'runtime');
|
|
ManagedNames: array [Boolean] of PChar =
|
|
('unmanaged', 'managed');
|
|
var
|
|
I: Integer;
|
|
|
|
function LocalVarToString(LocalVar: TJclClrLocalVar): string;
|
|
var
|
|
Row: TJclClrTableRow;
|
|
begin
|
|
case LocalVar.ElementType of
|
|
etClass:
|
|
if LocalVar.Token <> 0 then
|
|
begin
|
|
Row := Table.Stream.Metadata.Tokens[LocalVar.Token];
|
|
if Row is TJclClrTableTypeDefRow then
|
|
Result := TJclClrTableTypeDefRow(Row).FullName
|
|
else
|
|
if Row is TJclClrTableTypeRefRow then
|
|
Result := TJclClrTableTypeRefRow(Row).FullName
|
|
else
|
|
if Row is TJclClrTableTypeSpecRow then
|
|
Result := TJclClrTableTypeSpecRow(Row).Signature.Dump('')
|
|
else
|
|
Result := '/*' + IntToHex(Row.Token, 8) + '*/';
|
|
end;
|
|
else
|
|
Result := LocalVar.Name;
|
|
end;
|
|
end;
|
|
|
|
function GetMethodFlagDescription: string;
|
|
const
|
|
MethodFlagName: array [TJclClrMethodFlag] of PChar =
|
|
('static', 'final', 'virtual', 'hidebysig', '', 'abstract',
|
|
'specialname', 'pinvokeimpl', 'unmanagedexp', 'rtspecialname', '', '');
|
|
var
|
|
AFlag: TJclClrMethodFlag;
|
|
begin
|
|
for AFlag := Low(TJclClrMethodFlag) to High(TJclClrMethodFlag) do
|
|
if AFlag in MethodFlags then
|
|
Result := Result + MethodFlagName[AFlag] + ' ';
|
|
end;
|
|
|
|
function GetMethodImplFlagDescription: string;
|
|
const
|
|
MethodImplFlagName: array [TJclClrMethodImplFlag] of PChar =
|
|
('forwardref', '', 'internalcall', 'synchronized', 'noinlining');
|
|
var
|
|
AFlag: TJclClrMethodImplFlag;
|
|
begin
|
|
for AFlag := Low(TJclClrMethodImplFlag) to High(TJclClrMethodImplFlag) do
|
|
if AFlag in MethodImplFlags then
|
|
Result := Result + ' ' + MethodImplFlagName[AFlag];
|
|
end;
|
|
|
|
function GetParamTypeName(Param: TJclClrMethodParam): string;
|
|
const
|
|
BuildInTypeNames: array [etVoid..etString] of PChar =
|
|
('void', 'bool', 'char', 'sbyte', 'byte', 'short', 'ushort',
|
|
'int', 'uint', 'long', 'ulong', 'float', 'double', 'string');
|
|
var
|
|
Row: TJclClrTableRow;
|
|
begin
|
|
case Param.ElementType of
|
|
etVoid, etBoolean, etChar,
|
|
etI1, etU1, etI2, etU2, etI4, etU4,
|
|
etI8, etU8, etR4, etR8, etString:
|
|
Result := BuildInTypeNames[Param.ElementType];
|
|
etI:
|
|
Result := 'System.IntPtr';
|
|
etU:
|
|
Result := 'System.UIntPtr';
|
|
etObject:
|
|
Result := 'object';
|
|
etClass:
|
|
begin
|
|
Row := Table.Stream.Metadata.Tokens[Param.Token];
|
|
if Row is TJclClrTableTypeDefRow then
|
|
Result := TJclClrTableTypeDefRow(Row).FullName
|
|
else
|
|
if Row is TJclClrTableTypeRefRow then
|
|
Result := TJclClrTableTypeRefRow(Row).FullName;
|
|
|
|
Result := Result + ' /* ' + IntToHex(Param.Token, 8) + ' */';
|
|
end;
|
|
etSzArray:
|
|
Result := 'char *';
|
|
end;
|
|
if Param.ByRef then
|
|
Result := 'ref ' + Result;
|
|
end;
|
|
|
|
begin
|
|
Result := Format('.method /*%.8x*/ %s %s%s %s(', [Token,
|
|
MemberAccessNames[MemberAccess], GetMethodFlagDescription,
|
|
GetParamTypeName(Signature.RetType), Name]);
|
|
if HasParam then
|
|
for I := 0 to Min(ParamCount, Signature.ParamCount)-1 do
|
|
begin
|
|
Result := Result + GetParamTypeName(Signature.Params[I]) + ' ' + Params[I].Name;
|
|
if I <> ParamCount-1 then
|
|
Result := Result + ', ';
|
|
end;
|
|
Result := Result + ') ' + CodeTypeNames[CodeType] + ' ' + ManagedNames[Managed] + GetMethodImplFlagDescription;
|
|
|
|
if Assigned(MethodBody) then
|
|
begin
|
|
Result := Result + AnsiLineBreak + '{' + AnsiLineBreak +
|
|
'.maxstack ' + IntToStr(MethodBody.MaxStack) + AnsiLineBreak;
|
|
|
|
if MethodBody.LocalVarSignToken <> 0 then
|
|
begin
|
|
Result := Result + '.locals /* ' + IntToHex(MethodBody.LocalVarSignToken, 8) + ' */ init(' + AnsiLineBreak;
|
|
for I := 0 to MethodBody.LocalVarSign.LocalVarCount-1 do
|
|
begin
|
|
Result := Format(Result+' %s V_%d', [LocalVarToString(MethodBody.LocalVarSign.LocalVars[I]), I]);
|
|
if I = MethodBody.LocalVarSign.LocalVarCount-1 then
|
|
Result := Result + ')' + AnsiLineBreak
|
|
else
|
|
Result := Result + ',' + AnsiLineBreak;
|
|
end;
|
|
end;
|
|
|
|
with TJclClrILGenerator.Create(MethodBody) do
|
|
try
|
|
Result := Result + AnsiLineBreak + DumpIL(InstructionDumpILAllOption);
|
|
finally
|
|
Free;
|
|
end;
|
|
Result := Result + '}';
|
|
end;
|
|
end;
|
|
|
|
function TJclClrTableMethodDefRow.GetFullName: WideString;
|
|
begin
|
|
Result := ParentToken.FullName + '.' + Name;
|
|
end;
|
|
|
|
function TJclClrTableMethodDefRow.GetSignature: TJclClrMethodSign;
|
|
begin
|
|
if not Assigned(FSignature) then
|
|
FSignature := TJclClrMethodSign.Create(SignatureData);
|
|
Result := FSignature;
|
|
end;
|
|
|
|
function TJclClrTableMethodDefRow.GetMemberAccess: TJclClrMemberAccess;
|
|
begin
|
|
Result := TJclClrMemberAccess(FFlags and mdMemberAccessMask)
|
|
end;
|
|
|
|
function TJclClrTableMethodDefRow.GetMethodFlags: TJclClrMethodFlags;
|
|
var
|
|
AFlag: TJclClrMethodFlag;
|
|
begin
|
|
for AFlag := Low(TJclClrMethodFlag) to High(TJclClrMethodFlag) do
|
|
if (FFlags and ClrMethodFlagMapping[AFlag]) = ClrMethodFlagMapping[AFlag] then
|
|
Include(Result, AFlag);
|
|
end;
|
|
|
|
function TJclClrTableMethodDefRow.GetNewSlot: Boolean;
|
|
begin
|
|
Result := (FFlags and mdVtableLayoutMask) = mdNewSlot;
|
|
end;
|
|
|
|
function TJclClrTableMethodDefRow.GetCodeType: TJclClrMethodCodeType;
|
|
begin
|
|
Result := TJclClrMethodCodeType(FImplFlags and miCodeTypeMask);
|
|
end;
|
|
|
|
function TJclClrTableMethodDefRow.GetManaged: Boolean;
|
|
begin
|
|
Result := (FImplFlags and miManagedMask) = miManaged;
|
|
end;
|
|
|
|
function TJclClrTableMethodDefRow.GetMethodImplFlags: TJclClrMethodImplFlags;
|
|
var
|
|
AFlag: TJclClrMethodImplFlag;
|
|
begin
|
|
for AFlag := Low(TJclClrMethodImplFlag) to High(TJclClrMethodImplFlag) do
|
|
if (FFlags and ClrMethodImplFlagMapping[AFlag]) = ClrMethodImplFlagMapping[AFlag] then
|
|
Include(Result, AFlag);
|
|
end;
|
|
|
|
function TJclClrTableMethodDef.GetRow(const Idx: Integer): TJclClrTableMethodDefRow;
|
|
begin
|
|
Result := TJclClrTableMethodDefRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableMethodDef.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableMethodDefRow;
|
|
end;
|
|
|
|
//=== { TJclClrTableMethodPtrRow } ===========================================
|
|
|
|
constructor TJclClrTableMethodPtrRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FMethodIdx := Table.ReadIndex([ttMethodDef]);
|
|
end;
|
|
|
|
function TJclClrTableMethodPtrRow.GetMethod: TJclClrTableMethodDefRow;
|
|
begin
|
|
Result := TJclClrTableMethodDef(Table.Stream.Tables[ttMethodDef]).Rows[FMethodIdx-1];
|
|
end;
|
|
|
|
function TJclClrTableMethodPtr.GetRow(const Idx: Integer): TJclClrTableMethodPtrRow;
|
|
begin
|
|
Result := TJclClrTableMethodPtrRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableMethodPtr.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableMethodPtrRow;
|
|
end;
|
|
|
|
//=== { TJclClrTableMethodImplRow } ==========================================
|
|
|
|
constructor TJclClrTableMethodImplRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FClassIdx := Table.ReadIndex([ttTypeDef]);
|
|
FMethodBodyIdx := Table.ReadIndex([ttMethodDef, ttMemberRef]);
|
|
FMethodDeclarationIdx := Table.ReadIndex([ttMethodDef, ttMemberRef]);
|
|
end;
|
|
|
|
function TJclClrTableMethodImpl.GetRow(
|
|
const Idx: Integer): TJclClrTableMethodImplRow;
|
|
begin
|
|
Result := TJclClrTableMethodImplRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableMethodImpl.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableMethodImplRow;
|
|
end;
|
|
|
|
//=== { TJclClrTableMethodSemanticsRow } =====================================
|
|
|
|
constructor TJclClrTableMethodSemanticsRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FSemantics := Table.ReadWord;
|
|
FMethodIdx := Table.ReadIndex([ttMethodDef]);
|
|
FAssociationIdx := Table.ReadIndex([ttEventDef, ttPropertyDef]);
|
|
end;
|
|
|
|
function TJclClrTableMethodSemantics.GetRow(const Idx: Integer): TJclClrTableMethodSemanticsRow;
|
|
begin
|
|
Result := TJclClrTableMethodSemanticsRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableMethodSemantics.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableMethodSemanticsRow;
|
|
end;
|
|
|
|
//=== { TJclClrTableMethodSpecRow } ==========================================
|
|
|
|
constructor TJclClrTableMethodSpecRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FMethodIdx := Table.ReadIndex([ttMethodDef, ttMemberRef]);
|
|
FInstantiationOffset := Table.ReadIndex(hkBlob);
|
|
end;
|
|
|
|
function TJclClrTableMethodSpecRow.GetMethod: TJclClrTableRow;
|
|
const
|
|
MethodDefOrRefEncodedTag: array [0..1] of TJclClrTableKind =
|
|
(ttMethodDef, ttMemberRef);
|
|
begin
|
|
Result := Table.Stream.Metadata.Tables[MethodDefOrRefEncodedTag[FMethodIdx and 1]].Rows[FMethodIdx shr 1];
|
|
end;
|
|
|
|
function TJclClrTableMethodSpecRow.GetInstantiation: TJclClrBlobRecord;
|
|
begin
|
|
Result := Table.Stream.Metadata.BlobAt(FInstantiationOffset);
|
|
end;
|
|
|
|
function TJclClrTableMethodSpec.GetRow(const Idx: Integer): TJclClrTableMethodSpecRow;
|
|
begin
|
|
Result := TJclClrTableMethodSpecRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableMethodSpec.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableMethodSpecRow;
|
|
end;
|
|
|
|
//=== { TJclClrTableNestedClassRow } =========================================
|
|
|
|
constructor TJclClrTableNestedClassRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FNestedClassIdx := Table.ReadIndex([ttTypeDef]);
|
|
FEnclosingClassIdx := Table.ReadIndex([ttTypeDef]);
|
|
end;
|
|
|
|
function TJclClrTableNestedClass.GetRow(const Idx: Integer): TJclClrTableNestedClassRow;
|
|
begin
|
|
Result := TJclClrTableNestedClassRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableNestedClass.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableNestedClassRow;
|
|
end;
|
|
|
|
//=== { TJclClrTablePropertyDefRow } =========================================
|
|
|
|
constructor TJclClrTablePropertyDefRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FFlags := Table.ReadWord;
|
|
FNameOffset := Table.ReadIndex(hkString);
|
|
FKindIdx := Table.ReadIndex(hkBlob);
|
|
end;
|
|
|
|
function TJclClrTablePropertyDefRow.DumpIL: string;
|
|
|
|
function DumpFlags: string;
|
|
const
|
|
SpecialName: array [Boolean] of string = ('', 'specialname ');
|
|
RTSpecialName: array [Boolean] of string = ('', 'rtspecialname ');
|
|
begin
|
|
Result := SpecialName[pfSpecialName in Flags] +
|
|
RTSpecialName[pfRTSpecialName in Flags];
|
|
end;
|
|
|
|
begin
|
|
Result := Format('.property /*%.8x*/ %s%s ()', [Token, DumpFlags, Name]);
|
|
end;
|
|
|
|
function TJclClrTablePropertyDefRow.GetFlags: TJclClrTablePropertyFlags;
|
|
var
|
|
AFlag: TJclClrTablePropertyFlag;
|
|
begin
|
|
for AFlag := Low(TJclClrTablePropertyFlag) to High(TJclClrTablePropertyFlag) do
|
|
if ClrTablePropertyFlagMapping[AFlag] and FFlags <> 0 then
|
|
Include(Result, AFlag);
|
|
end;
|
|
|
|
function TJclClrTablePropertyDefRow.GetName: WideString;
|
|
begin
|
|
Result := Table.Stream.Metadata.StringAt(FNameOffset);
|
|
end;
|
|
|
|
function TJclClrTablePropertyDef.GetRow(const Idx: Integer): TJclClrTablePropertyDefRow;
|
|
begin
|
|
Result := TJclClrTablePropertyDefRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTablePropertyDef.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTablePropertyDefRow;
|
|
end;
|
|
|
|
//=== { TJclClrTablePropertyPtrRow } =========================================
|
|
|
|
constructor TJclClrTablePropertyPtrRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FPropertyIdx := Table.ReadIndex([ttPropertyDef]);
|
|
end;
|
|
|
|
function TJclClrTablePropertyPtrRow.GetProperty: TJclClrTablePropertyDefRow;
|
|
begin
|
|
Result := TJclClrTablePropertyDef(Table.Stream.Tables[ttPropertyDef]).Rows[FPropertyIdx-1];
|
|
end;
|
|
|
|
function TJclClrTablePropertyPtr.GetRow(const Idx: Integer): TJclClrTablePropertyPtrRow;
|
|
begin
|
|
Result := TJclClrTablePropertyPtrRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTablePropertyPtr.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTablePropertyPtrRow;
|
|
end;
|
|
|
|
//=== { TJclClrTablePropertyMapRow } =========================================
|
|
|
|
constructor TJclClrTablePropertyMapRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FParentIdx := Table.ReadIndex([ttTypeDef]);
|
|
FPropertyListIdx := Table.ReadIndex([ttPropertyDef]);
|
|
FProperties := TList.Create;
|
|
end;
|
|
|
|
destructor TJclClrTablePropertyMapRow.Destroy;
|
|
begin
|
|
FreeAndNil(FProperties);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TJclClrTablePropertyMapRow.GetParent: TJclClrTableTypeDefRow;
|
|
begin
|
|
Result := TJclClrTableTypeDef(Table.Stream.Tables[ttTypeDef]).Rows[FParentIdx-1];
|
|
end;
|
|
|
|
function TJclClrTablePropertyMapRow.Add(const ARow: TJclClrTablePropertyDefRow): Integer;
|
|
begin
|
|
Result := FProperties.Add(ARow);
|
|
end;
|
|
|
|
function TJclClrTablePropertyMapRow.GetProperty(const Idx: Integer): TJclClrTablePropertyDefRow;
|
|
begin
|
|
Result := TJclClrTablePropertyDefRow(FProperties.Items[Idx]);
|
|
end;
|
|
|
|
function TJclClrTablePropertyMapRow.GetPropertyCount: Integer;
|
|
begin
|
|
Result := FProperties.Count;
|
|
end;
|
|
|
|
function TJclClrTablePropertyMap.GetRow(const Idx: Integer): TJclClrTablePropertyMapRow;
|
|
begin
|
|
Result := TJclClrTablePropertyMapRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTablePropertyMap.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTablePropertyMapRow;
|
|
end;
|
|
|
|
procedure TJclClrTablePropertyMap.Update;
|
|
var
|
|
I, J: Integer;
|
|
begin
|
|
J := 0;
|
|
with TJclClrTablePropertyDef(Stream.Tables[ttPropertyDef]) do
|
|
for I := 0 to RowCount-1 do
|
|
begin
|
|
if I >= Integer(Self.Rows[J].PropertyListIdx) then
|
|
Inc(J);
|
|
if J >= Self.RowCount then
|
|
Break;
|
|
Self.Rows[J].Add(Rows[I]);
|
|
end;
|
|
end;
|
|
|
|
//=== { TJclClrTableStandAloneSigRow } =======================================
|
|
|
|
constructor TJclClrTableStandAloneSigRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FSignatureOffset := Table.ReadIndex(hkBlob);
|
|
end;
|
|
|
|
function TJclClrTableStandAloneSigRow.GetSignature: TJclClrBlobRecord;
|
|
begin
|
|
Result := Table.Stream.Metadata.BlobAt(FSignatureOffset);
|
|
end;
|
|
|
|
function TJclClrTableStandAloneSig.GetRow(
|
|
const Idx: Integer): TJclClrTableStandAloneSigRow;
|
|
begin
|
|
Result := TJclClrTableStandAloneSigRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableStandAloneSig.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableStandAloneSigRow;
|
|
end;
|
|
|
|
//=== { TJclClrTableTypeDefRow } =============================================
|
|
|
|
constructor TJclClrTableTypeDefRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FFlags := Table.ReadDWord;
|
|
FNameOffset := Table.ReadIndex(hkString);
|
|
FNamespaceOffset := Table.ReadIndex(hkString);
|
|
FExtendsIdx := Table.ReadIndex([ttTypeDef, ttTypeRef, ttTypeSpec]);
|
|
FFieldListIdx := Table.ReadIndex([ttFieldDef]);
|
|
FMethodListIdx := Table.ReadIndex([ttMethodDef]);
|
|
|
|
FFields := nil;
|
|
FMethods := nil;
|
|
end;
|
|
|
|
destructor TJclClrTableTypeDefRow.Destroy;
|
|
begin
|
|
FreeAndNil(FFields);
|
|
FreeAndNil(FMethods);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TJclClrTableTypeDefRow.GetName: WideString;
|
|
begin
|
|
Result := Table.Stream.Metadata.StringAt(FNameOffset);
|
|
end;
|
|
|
|
function TJclClrTableTypeDefRow.GetNamespace: WideString;
|
|
begin
|
|
Result := Table.Stream.Metadata.StringAt(FNamespaceOffset);
|
|
end;
|
|
|
|
function TJclClrTableTypeDefRow.GetField(const Idx: Integer): TJclClrTableFieldDefRow;
|
|
begin
|
|
Result := TJclClrTableFieldDefRow(FFields.Items[Idx])
|
|
end;
|
|
|
|
function TJclClrTableTypeDefRow.GetFieldCount: Integer;
|
|
begin
|
|
Result := FFields.Count
|
|
end;
|
|
|
|
function TJclClrTableTypeDefRow.HasField: Boolean;
|
|
begin
|
|
Result := Assigned(FFields);
|
|
end;
|
|
|
|
function TJclClrTableTypeDefRow.GetMethod(const Idx: Integer): TJclClrTableMethodDefRow;
|
|
begin
|
|
Result := TJclClrTableMethodDefRow(FMethods.Items[Idx])
|
|
end;
|
|
|
|
function TJclClrTableTypeDefRow.GetMethodCount: Integer;
|
|
begin
|
|
Result := FMethods.Count
|
|
end;
|
|
|
|
function TJclClrTableTypeDefRow.HasMethod: Boolean;
|
|
begin
|
|
Result := Assigned(FMethods);
|
|
end;
|
|
|
|
procedure TJclClrTableTypeDefRow.UpdateFields;
|
|
var
|
|
FieldTable: TJclClrTableFieldDef;
|
|
Idx, MaxFieldListIdx: DWORD;
|
|
begin
|
|
with Table as TJclClrTableTypeDef do
|
|
if not Assigned(FFields) and (FieldListIdx <> 0) and
|
|
Stream.FindTable(ttFieldDef, TJclClrTable(FieldTable)) then
|
|
begin
|
|
if RowCount > (Index+1) then
|
|
MaxFieldListIdx := Rows[Index+1].FieldListIdx-1
|
|
else
|
|
MaxFieldListIdx := FieldTable.RowCount;
|
|
if (FieldListIdx-1) < MaxFieldListIdx then
|
|
begin
|
|
FFields := TList.Create;
|
|
for Idx := FieldListIdx-1 to MaxFieldListIdx-1 do
|
|
begin
|
|
FFields.Add(FieldTable.Rows[Idx]);
|
|
FieldTable.Rows[Idx].SetParentToken(Self);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJclClrTableTypeDefRow.UpdateMethods;
|
|
var
|
|
MethodTable: TJclClrTableMethodDef;
|
|
Idx, MaxMethodListIdx: DWORD;
|
|
begin
|
|
with Table as TJclClrTableTypeDef do
|
|
if not Assigned(FMethods) and (MethodListIdx <> 0) and
|
|
Stream.FindTable(ttMethodDef, TJclClrTable(MethodTable)) then
|
|
begin
|
|
if RowCount > (Index+1) then
|
|
MaxMethodListIdx := Rows[Index+1].MethodListIdx-1
|
|
else
|
|
MaxMethodListIdx := MethodTable.RowCount;
|
|
if (MethodListIdx-1) < MaxMethodListIdx then
|
|
begin
|
|
FMethods := TList.Create;
|
|
for Idx := MethodListIdx-1 to MaxMethodListIdx-1 do
|
|
begin
|
|
FMethods.Add(MethodTable.Rows[Idx]);
|
|
MethodTable.Rows[Idx].SetParentToken(Self);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJclClrTableTypeDefRow.Update;
|
|
begin
|
|
inherited Update;
|
|
UpdateFields;
|
|
UpdateMethods;
|
|
end;
|
|
|
|
function TJclClrTableTypeDefRow.GetFullName: WideString;
|
|
begin
|
|
if FNamespaceOffset <> 0 then
|
|
Result := Namespace + '.' + Name
|
|
else
|
|
Result := Name;
|
|
end;
|
|
|
|
function TJclClrTableTypeDefRow.GetAttributes: TJclClrTypeAttributes;
|
|
const
|
|
TypeAttributesMapping: array [TJclClrTypeAttribute] of DWORD =
|
|
(tdAbstract, tdSealed, tdSpecialName, tdImport,
|
|
tdSerializable, tdBeforeFieldInit, tdRTSpecialName, tdHasSecurity);
|
|
var
|
|
Attr: TJclClrTypeAttribute;
|
|
begin
|
|
Result := [];
|
|
for Attr := Low(TJclClrTypeAttribute) to High(TJclClrTypeAttribute) do
|
|
if (FFlags and TypeAttributesMapping[Attr]) = TypeAttributesMapping[Attr] then
|
|
Include(Result, Attr);
|
|
end;
|
|
|
|
function TJclClrTableTypeDefRow.GetClassLayout: TJclClrClassLayout;
|
|
begin
|
|
case FFlags and tdLayoutMask of
|
|
tdAutoLayout:
|
|
Result := clAuto;
|
|
tdSequentialLayout:
|
|
Result := clSequential;
|
|
tdExplicitLayout:
|
|
Result := clExplicit;
|
|
else
|
|
raise EJclMetadataError.CreateResFmt(@RsUnknownClassLayout, [FFlags and tdLayoutMask]);
|
|
end;
|
|
end;
|
|
|
|
function TJclClrTableTypeDefRow.GetClassSemantics: TJclClrClassSemantics;
|
|
const
|
|
ClassSemanticsMapping: array [Boolean] of TJclClrClassSemantics =
|
|
(csClass, csInterface);
|
|
begin
|
|
Result := ClassSemanticsMapping[(FFlags and tdClassSemanticsMask) = tdInterface];
|
|
end;
|
|
|
|
function TJclClrTableTypeDefRow.GetStringFormatting: TJclClrStringFormatting;
|
|
begin
|
|
case FFlags and tdStringFormatMask of
|
|
tdAnsiClass:
|
|
Result := sfAnsi;
|
|
tdUnicodeClass:
|
|
Result := sfUnicode;
|
|
tdAutoClass:
|
|
Result := sfAutoChar;
|
|
else
|
|
raise EJclMetadataError.CreateResFmt(@RsUnknownStringFormatting, [FFlags and tdStringFormatMask]);
|
|
end;
|
|
end;
|
|
|
|
function TJclClrTableTypeDefRow.GetVisibility: TJclClrTypeVisibility;
|
|
begin
|
|
Result := TJclClrTypeVisibility(FFlags and tdVisibilityMask);
|
|
end;
|
|
|
|
function TJclClrTableTypeDefRow.GetExtends: TJclClrTableRow;
|
|
begin
|
|
Result := DecodeTypeDefOrRef(FExtendsIdx);
|
|
end;
|
|
|
|
function TJclClrTableTypeDefRow.DumpIL: string;
|
|
const
|
|
ClassSemanticName: array [TJclClrClassSemantics] of PChar =
|
|
('class', 'interface');
|
|
VisibilityName: array [TJclClrTypeVisibility] of PChar =
|
|
('private', 'public', 'nested public', 'nested private',
|
|
'nested family', 'nested assembly', 'nested famandassem', 'nested famorassem');
|
|
ClassLayoutName: array [TJclClrClassLayout] of PChar =
|
|
('auto', 'explicit', 'sequential');
|
|
StringFormattingName: array [TJclClrStringFormatting] of PChar =
|
|
('ansi', 'unicode', 'autoChar');
|
|
TypeAttributeName: array [TJclClrTypeAttribute] of PChar =
|
|
('abstract', 'sealed', 'specialname', '' {'import'},
|
|
'serializable', 'beforefieldinit', 'rtspecialname', '' {'hassecurity'});
|
|
Indent = ' ';
|
|
IntfPrefix: array [Boolean] of PChar = (' ', 'implements ');
|
|
var
|
|
I, J: Integer;
|
|
ListIntfs: TList;
|
|
|
|
function GetTypeAttributesName: string;
|
|
var
|
|
Attr: TJclClrTypeAttribute;
|
|
begin
|
|
for Attr := Low(TJclClrTypeAttribute) to High(TJclClrTypeAttribute) do
|
|
if Attr in Attributes then
|
|
Result := Result + TypeAttributeName[Attr] + ' ';
|
|
end;
|
|
|
|
function GetExtends(const Row: TJclClrTableTypeDefRow): string; overload;
|
|
begin
|
|
Result := Format('%s.%s/* %.8x */', [Row.Namespace, Row.Name, Row.Token]);
|
|
end;
|
|
|
|
function GetExtends(const Row: TJclClrTableRow): string; overload;
|
|
begin
|
|
if Row is TJclClrTableTypeDefRow then
|
|
Result := GetExtends(TJclClrTableTypeDefRow(Row))
|
|
else
|
|
if Row is TJclClrTableTypeRefRow then
|
|
Result := TJclClrTableTypeRefRow(Row).DumpIL
|
|
else
|
|
if Row is TJclClrTableTypeSpecRow then
|
|
Result := TJclClrTableTypeSpecRow(Row).DumpIL
|
|
else
|
|
Result := 'Unknown Extends ' + Row.ClassName;
|
|
end;
|
|
|
|
begin
|
|
with TStringList.Create do
|
|
try
|
|
Add(Format('.%s /*%.8x*/ %s %s %s %s%s.%s',
|
|
[ClassSemanticName[ClassSemantics], Token,
|
|
VisibilityName[Visibility], ClassLayoutName[ClassLayout],
|
|
StringFormattingName[StringFormatting], GetTypeAttributesName,
|
|
Namespace, Name]));
|
|
|
|
if ExtendsIdx <> 0 then
|
|
Add(Indent + 'extends ' + GetExtends(Extends));
|
|
|
|
ListIntfs := TList.Create;
|
|
try
|
|
if Assigned(Table.Stream.Tables[ttInterfaceImpl]) then
|
|
with TJclClrTableInterfaceImpl(Table.Stream.Tables[ttInterfaceImpl]) do
|
|
for I := 0 to RowCount-1 do
|
|
if Rows[I].ClassIdx = DWORD(Index + 1) then
|
|
ListIntfs.Add(Rows[I]);
|
|
|
|
if ListIntfs.Count > 0 then
|
|
for I := 0 to ListIntfs.Count-1 do
|
|
Add(Indent + IntfPrefix[I = 0] + TJclClrTableInterfaceImplRow(ListIntfs[I]).DumpIL);
|
|
finally
|
|
ListIntfs.Free;
|
|
end;
|
|
|
|
Add('(');
|
|
|
|
if HasField then
|
|
for I := 0 to FieldCount-1 do
|
|
Add(Indent + Fields[I].DumpIL);
|
|
|
|
if HasMethod then
|
|
for I := 0 to MethodCount-1 do
|
|
Add(Indent + Methods[I].DumpIL);
|
|
|
|
if Assigned(Table.Stream.Tables[ttPropertyMap]) then
|
|
with TJclClrTablePropertyMap(Table.Stream.Tables[ttPropertyMap]) do
|
|
for I := 0 to RowCount-1 do
|
|
if Rows[I].Parent = Self then
|
|
for J := 0 to Rows[I].PropertyCount-1 do
|
|
Add(Indent + Rows[I].Properties[J].DumpIL);
|
|
|
|
Add(') // end of class ' + Name);
|
|
Result := Text;
|
|
finally
|
|
Free;
|
|
end;
|
|
end;
|
|
|
|
class function TJclClrTableTypeDef.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableTypeDefRow;
|
|
end;
|
|
|
|
function TJclClrTableTypeDef.GetRow(const Idx: Integer): TJclClrTableTypeDefRow;
|
|
begin
|
|
Result := TJclClrTableTypeDefRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
//=== { TJclClrTableTypeRefRow } =============================================
|
|
|
|
constructor TJclClrTableTypeRefRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FResolutionScopeIdx := Table.ReadIndex([ttModule, ttModuleRef, ttAssemblyRef, ttTypeRef]);
|
|
FNameOffset := Table.ReadIndex(hkString);
|
|
FNamespaceOffset := Table.ReadIndex(hkString);
|
|
end;
|
|
|
|
function TJclClrTableTypeRefRow.DumpIL: string;
|
|
begin
|
|
Result := Format('[%s/* %.8x */]%s.%s/* %.8x */',
|
|
[ResolutionScopeName, ResolutionScope.Token, Namespace, Name, Token]);
|
|
end;
|
|
|
|
function TJclClrTableTypeRefRow.GetFullName: WideString;
|
|
begin
|
|
Result := Namespace + '.' + Name;
|
|
end;
|
|
|
|
function TJclClrTableTypeRefRow.GetName: WideString;
|
|
begin
|
|
Result := Table.Stream.Metadata.StringAt(FNameOffset);
|
|
end;
|
|
|
|
function TJclClrTableTypeRefRow.GetNamespace: WideString;
|
|
begin
|
|
Result := Table.Stream.Metadata.StringAt(FNamespaceOffset);
|
|
end;
|
|
|
|
function TJclClrTableTypeRefRow.GetResolutionScope: TJclClrTableRow;
|
|
begin
|
|
Result := DecodeResolutionScope(FResolutionScopeIdx);
|
|
end;
|
|
|
|
function TJclClrTableTypeRefRow.GetResolutionScopeName: string;
|
|
begin
|
|
if ResolutionScope is TJclClrTableModuleRow then
|
|
Result := TJclClrTableModuleRow(ResolutionScope).Name
|
|
else
|
|
if ResolutionScope is TJclClrTableModuleRefRow then
|
|
Result := TJclClrTableModuleRefRow(ResolutionScope).Name
|
|
else
|
|
if ResolutionScope is TJclClrTableAssemblyRefRow then
|
|
Result := TJclClrTableAssemblyRefRow(ResolutionScope).Name
|
|
else
|
|
if ResolutionScope is TJclClrTableTypeRefRow then
|
|
Result := TJclClrTableTypeRefRow(ResolutionScope).Namespace + '.' +
|
|
TJclClrTableTypeRefRow(ResolutionScope).Name
|
|
else
|
|
Result := 'Unknown';
|
|
end;
|
|
|
|
class function TJclClrTableTypeRef.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableTypeRefRow;
|
|
end;
|
|
|
|
function TJclClrTableTypeRef.GetRow(const Idx: Integer): TJclClrTableTypeRefRow;
|
|
begin
|
|
Result := TJclClrTableTypeRefRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
//=== { TJclClrTableTypeSpecRow } ============================================
|
|
|
|
constructor TJclClrTableTypeSpecRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FSignatureOffset := Table.ReadIndex(hkBlob);
|
|
end;
|
|
|
|
function TJclClrTableTypeSpecRow.GetSignature: TJclClrBlobRecord;
|
|
begin
|
|
Result := Table.Stream.Metadata.BlobAt(FSignatureOffset);
|
|
end;
|
|
|
|
function TJclClrTableTypeSpec.GetRow(const Idx: Integer): TJclClrTableTypeSpecRow;
|
|
begin
|
|
Result := TJclClrTableTypeSpecRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableTypeSpec.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableTypeSpecRow;
|
|
end;
|
|
|
|
//=== { TJclClrTableENCMapRow } ==============================================
|
|
|
|
constructor TJclClrTableENCMapRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FToken := Table.ReadDWord;
|
|
end;
|
|
|
|
function TJclClrTableENCMap.GetRow(const Idx: Integer): TJclClrTableENCMapRow;
|
|
begin
|
|
Result := TJclClrTableENCMapRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableENCMap.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableENCMapRow;
|
|
end;
|
|
|
|
//=== { TJclClrTableENCLogRow } ==============================================
|
|
|
|
constructor TJclClrTableENCLogRow.Create(const ATable: TJclClrTable);
|
|
begin
|
|
inherited Create(ATable);
|
|
FFuncCode := Table.ReadDWord;
|
|
end;
|
|
|
|
function TJclClrTableENCLog.GetRow(const Idx: Integer): TJclClrTableENCLogRow;
|
|
begin
|
|
Result := TJclClrTableENCLogRow(inherited GetRow(Idx));
|
|
end;
|
|
|
|
class function TJclClrTableENCLog.TableRowClass: TJclClrTableRowClass;
|
|
begin
|
|
Result := TJclClrTableENCLogRow;
|
|
end;
|
|
|
|
function TJclClrLocalVar.GetName: WideString;
|
|
const
|
|
ClrElementTypeNameMapping: array [etVoid..etString] of PChar =
|
|
('void', 'bool',
|
|
'char', 'sbyte', 'byte',
|
|
'short', 'ushort', 'int', 'unit',
|
|
'long', 'ulong', 'float', 'Double',
|
|
'string');
|
|
begin
|
|
case ElementType of
|
|
etVoid, etBoolean, etChar,
|
|
etI1, etU1, etI2, etU2, etI4, etU4,
|
|
etI8, etU8, etR4, etR8, etString:
|
|
Result := ClrElementTypeNameMapping[ElementType];
|
|
etPtr, etByRef, etValueType, etClass:
|
|
Result := IntToHex(Token, 8);
|
|
etArray:
|
|
Result := 'Array';
|
|
etTypedByRef:
|
|
Result := 'TypedByRef';
|
|
etI:
|
|
Result := 'IntPtr';
|
|
etU:
|
|
Result := 'UIntPtr';
|
|
etFnPtr:
|
|
Result := 'Function';
|
|
etObject:
|
|
Result := 'System.Object';
|
|
etSzArray:
|
|
// (rom) possible BUG! Result not assigned
|
|
else
|
|
Result := 'Unknown';
|
|
end;
|
|
end;
|
|
|
|
//=== { TJclClrLocalVarSign } ================================================
|
|
|
|
constructor TJclClrLocalVarSign.Create(const ABlob: TJclClrBlobRecord);
|
|
var
|
|
Sign, ElemType: Byte;
|
|
T: TJclClrElementType;
|
|
I, VarCount: DWORD;
|
|
LocalVar: TJclClrLocalVar;
|
|
begin
|
|
inherited Create(ABlob);
|
|
|
|
Blob.Seek(0, soFromBeginning);
|
|
|
|
Sign := ReadByte;
|
|
|
|
if (Sign and IMAGE_CEE_CS_CALLCONV_MASK) <> IMAGE_CEE_CS_CALLCONV_LOCAL_SIG then
|
|
raise EJclMetadataError.CreateResFmt(@RsNoLocalVarSig, [IntToHex(Sign, 2)]);
|
|
|
|
VarCount := ReadValue;
|
|
if (VarCount < 1) or ($FFFE < VarCount) then
|
|
raise EJclMetadataError.CreateResFmt(@RsLocalVarSigOutOfRange, [VarCount]);
|
|
|
|
FLocalVars := TObjectList.Create;
|
|
|
|
LocalVar := TJclClrLocalVar.Create;
|
|
|
|
for I := 0 to VarCount-1 do
|
|
begin
|
|
ElemType := ReadByte;
|
|
|
|
case ElemType of
|
|
ELEMENT_TYPE_PINNED:
|
|
LocalVar.Flags := LocalVar.Flags + [lvfPinned];
|
|
ELEMENT_TYPE_BYREF:
|
|
LocalVar.Flags := LocalVar.Flags + [lvfByRef];
|
|
ELEMENT_TYPE_END:
|
|
Break;
|
|
else
|
|
for T := Low(TJclClrElementType) to High(TJclClrElementType) do
|
|
if ClrElementTypeMapping[T] = ElemType then
|
|
begin
|
|
LocalVar.ElementType := T;
|
|
Break;
|
|
end;
|
|
if LocalVar.ElementType in [etPtr, etByRef, etValueType, etClass] then
|
|
LocalVar.Token := ReadToken
|
|
else
|
|
LocalVar.Token := 0;
|
|
|
|
FLocalVars.Add(LocalVar);
|
|
LocalVar := TJclClrLocalVar.Create;
|
|
end;
|
|
end;
|
|
FreeAndNil(LocalVar);
|
|
end;
|
|
|
|
destructor TJclClrLocalVarSign.Destroy;
|
|
begin
|
|
FreeAndNil(FLocalVars);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TJclClrLocalVarSign.GetLocalVar(const Idx: Integer): TJclClrLocalVar;
|
|
begin
|
|
Result := TJclClrLocalVar(FLocalVars[Idx]);
|
|
end;
|
|
|
|
function TJclClrLocalVarSign.GetLocalVarCount: Integer;
|
|
begin
|
|
Result := FLocalVars.Count;
|
|
end;
|
|
|
|
//=== { TJclClrMethodSign } ==================================================
|
|
|
|
constructor TJclClrMethodSign.Create(const ABlob: TJclClrBlobRecord);
|
|
var
|
|
Sign: Byte;
|
|
I, ParamCount: Integer;
|
|
begin
|
|
inherited Create(ABlob);
|
|
|
|
FParams := TObjectList.Create;
|
|
|
|
Sign := ReadByte;
|
|
|
|
if IsBitSet(Sign, IMAGE_CEE_CS_CALLCONV_HASTHIS) then
|
|
Include(FFlags, mfHasThis);
|
|
|
|
if IsBitSet(Sign, IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS) then
|
|
Include(FFlags, mfExplicitThis);
|
|
|
|
case Sign and IMAGE_CEE_CS_CALLCONV_MASK of
|
|
IMAGE_CEE_CS_CALLCONV_DEFAULT:
|
|
Include(FFlags, mfDefault);
|
|
IMAGE_CEE_CS_CALLCONV_VARARG:
|
|
Include(FFlags, mfVarArg);
|
|
end;
|
|
|
|
ParamCount := ReadValue;
|
|
|
|
FRetType := TJclClrMethodRetType.Create(Blob);
|
|
|
|
for I := 0 to ParamCount-1 do
|
|
FParams.Add(TJclClrMethodParam.Create(Blob));
|
|
end;
|
|
|
|
destructor TJclClrMethodSign.Destroy;
|
|
begin
|
|
FreeAndNil(FParams);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TJclClrMethodSign.GetParam(const Idx: Integer): TJclClrMethodParam;
|
|
begin
|
|
Result := TJclClrMethodParam(FParams.Items[Idx]);
|
|
end;
|
|
|
|
function TJclClrMethodSign.GetParamCount: Integer;
|
|
begin
|
|
Result := FParams.Count;
|
|
end;
|
|
|
|
//=== { TJclClrCustomModifierSign } ==========================================
|
|
|
|
constructor TJclClrCustomModifierSign.Create(const ABlob: TJclClrBlobRecord);
|
|
begin
|
|
inherited Create(ABlob);
|
|
FRequired := ReadByte = ELEMENT_TYPE_CMOD_REQD;
|
|
FToken := ReadToken;
|
|
end;
|
|
|
|
//=== { TJclClrMethodParam } =================================================
|
|
|
|
constructor TJclClrMethodParam.Create(const ABlob: TJclClrBlobRecord);
|
|
var
|
|
By: Byte;
|
|
Finished: Boolean;
|
|
begin
|
|
inherited Create(ABlob);
|
|
|
|
FCustomMods := TObjectList.Create;
|
|
FByRef := False;
|
|
FElementType := etEnd;
|
|
FToken := 0;
|
|
FMethodSign := nil;
|
|
|
|
Finished := False;
|
|
while not Finished and (Blob.Position < Blob.Size) do
|
|
begin
|
|
By := ReadByte;
|
|
case By of
|
|
ELEMENT_TYPE_CMOD_REQD, ELEMENT_TYPE_CMOD_OPT:
|
|
begin
|
|
Blob.Seek(-SizeOf(Byte), soFromCurrent);
|
|
FCustomMods.Add(TJclClrCustomModifierSign.Create(Blob));
|
|
end;
|
|
ELEMENT_TYPE_BYREF:
|
|
FByRef := True;
|
|
else
|
|
FElementType := TJclClrElementType(By);
|
|
case FElementType of
|
|
etPtr, etTypedByRef, etValueType, etClass:
|
|
FToken := ReadToken;
|
|
etFnPtr:
|
|
FMethodSign := TJclClrMethodSign.Create(Blob);
|
|
etArray:
|
|
FArraySign := TJclClrArraySign.Create(Blob);
|
|
end;
|
|
Finished := True;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
destructor TJclClrMethodParam.Destroy;
|
|
begin
|
|
FreeAndNil(FCustomMods);
|
|
FreeAndNil(FMethodSign);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TJclClrMethodParam.GetCustomModifier(const Idx: Integer): TJclClrCustomModifierSign;
|
|
begin
|
|
Result := TJclClrCustomModifierSign(FCustomMods.Items[Idx]);
|
|
end;
|
|
|
|
function TJclClrMethodParam.GetCustomModifierCount: Integer;
|
|
begin
|
|
Result := FCustomMods.Count;
|
|
end;
|
|
|
|
{$IFDEF UNITVERSIONING}
|
|
initialization
|
|
RegisterUnitVersion(HInstance, UnitVersioning);
|
|
|
|
finalization
|
|
UnregisterUnitVersion(HInstance);
|
|
{$ENDIF UNITVERSIONING}
|
|
|
|
end.
|