/src/sys/dotnet/perwapi/PERWAPI.cs
C# | 13234 lines | 8246 code | 1818 blank | 3170 comment | 1527 complexity | 6cf790997bbe38881aabbe059f2403ff MD5 | raw file
Possible License(s): CC-BY-SA-3.0
Large files files are truncated, but you can click here to view the full file
- /*
- * PERWAPI - An API for Reading and Writing PE Files
- *
- * Copyright (c) Diane Corney, Queensland University of Technology, 2004.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the PERWAPI Copyright as included with this
- * distribution in the file PERWAPIcopyright.rtf.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY as is explained in the copyright notice.
- *
- * The author may be contacted at d.corney@qut.edu.au
- *
- * Version Date: 26/01/07
- *
- * Contributions Made By:
- *
- * Douglas Stockwell - Developed support for PDB files.
- * Andrew Bacon - Integrated PDB file support and developed automatic
- * stack depth calculations.
- *
- * Placed in Subversion repository by John Gough on 2-Mar-2007
- *
- */
- using System;
- using System.IO;
- using System.Collections;
- using SCG = System.Collections.Generic;
- using System.Text;
- using System.Security.Permissions;
- using System.Diagnostics;
- using System.Diagnostics.SymbolStore;
- using System.Runtime.InteropServices;
- using QUT;
- namespace PERWAPI {
- /// <summary>
- /// Diagnostic
- /// </summary>
- public class Diag {
- /// <summary>
- /// Flag for diagnostic output.
- /// </summary>
- public static bool DiagOn = false;
- }
- /// <summary>
- /// Facilities for outputting hexadecimal strings
- /// </summary>
- public class Hex {
- readonly static char[] hexDigit = {'0','1','2','3','4','5','6','7',
- '8','9','A','B','C','D','E','F'};
- readonly static uint[] iByteMask = {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000};
- readonly static ulong[] lByteMask = {0x00000000000000FF, 0x000000000000FF00,
- 0x0000000000FF0000, 0x00000000FF000000,
- 0x000000FF00000000, 0x0000FF0000000000,
- 0x00FF000000000000, 0xFF00000000000000 };
- readonly static uint nibble0Mask = 0x0000000F;
- readonly static uint nibble1Mask = 0x000000F0;
- /// <summary>
- /// Derives a hexademical string for a byte value
- /// </summary>
- /// <param name="b">the byte value</param>
- /// <returns>hex string for the byte value</returns>
- public static String Byte(int b) {
- char[] str = new char[2];
- uint num = (uint)b;
- uint b1 = num & nibble0Mask;
- uint b2 = (num & nibble1Mask) >> 4;
- str[0] = hexDigit[b2];
- str[1] = hexDigit[b1];
- return new String(str);
- }
- /// <summary>
- /// Derives a hexademical string for a short value
- /// </summary>
- /// <param name="b">the short value</param>
- /// <returns>hex string for the short value</returns>
- public static String Short(int b) {
- char[] str = new char[4];
- uint num1 = (uint)b & iByteMask[0];
- uint num2 = ((uint)b & iByteMask[1]) >> 8;
- uint b1 = num1 & nibble0Mask;
- uint b2 = (num1 & nibble1Mask) >> 4;
- uint b3 = num2 & nibble0Mask;
- uint b4 = (num2 & nibble1Mask) >> 4;
- str[0] = hexDigit[b4];
- str[1] = hexDigit[b3];
- str[2] = hexDigit[b2];
- str[3] = hexDigit[b1];
- return new String(str);
- }
- /// <summary>
- /// Derives a hexademical string for an int value
- /// </summary>
- /// <param name="val">the int value</param>
- /// <returns>hex string for the int value</returns>
- public static String Int(int val) {
- char[] str = new char[8];
- uint num = (uint)val;
- int strIx = 7;
- for (int i=0; i < iByteMask.Length; i++) {
- uint b = num & iByteMask[i];
- b >>= (i*8);
- uint b1 = b & nibble0Mask;
- uint b2 = (b & nibble1Mask) >> 4;
- str[strIx--] = hexDigit[b1];
- str[strIx--] = hexDigit[b2];
- }
- return new String(str);
- }
- /// <summary>
- /// Derives a hexademical string for an unsigned int value
- /// </summary>
- /// <param name="num">the unsigned int value</param>
- /// <returns>hex string for the unsigned int value</returns>
- public static String Int(uint num) {
- char[] str = new char[8];
- int strIx = 7;
- for (int i=0; i < iByteMask.Length; i++) {
- uint b = num & iByteMask[i];
- b >>= (i*8);
- uint b1 = b & nibble0Mask;
- uint b2 = (b & nibble1Mask) >> 4;
- str[strIx--] = hexDigit[b1];
- str[strIx--] = hexDigit[b2];
- }
- return new String(str);
- }
- /// <summary>
- /// Derives a hexademical string for a long value
- /// </summary>
- /// <param name="lnum">the long value</param>
- /// <returns>hex string for the long value</returns>
- public static String Long(long lnum) {
- ulong num = (ulong)lnum;
- return Long(num);
- }
- /// <summary>
- /// Derives a hexademical string for an unsigned long value
- /// </summary>
- /// <param name="num">the unsigned long value</param>
- /// <returns>hex string for the unsigned long value</returns>
- public static String Long(ulong num) {
- char[] str = new char[16];
- int strIx = 15;
- for (int i=0; i < lByteMask.Length; i++) {
- ulong b = num & lByteMask[i];
- b >>= (i*8);
- ulong b1 = b & nibble0Mask;
- ulong b2 = (b & nibble1Mask) >> 4;
- str[strIx--] = hexDigit[b1];
- str[strIx--] = hexDigit[b2];
- }
- return new String(str);
- }
- }
- /// <summary>
- /// Exception for features yet to be implemented
- /// </summary>
- public class NotYetImplementedException : System.Exception {
- /// <summary>
- /// constructor
- /// </summary>
- /// <param name="msg"></param>
- public NotYetImplementedException(string msg) : base(msg + " Not Yet Implemented") { }
- }
- /// <summary>
- /// Error in a type signature
- /// </summary>
- public class TypeSignatureException : System.Exception {
- /// <summary>
- /// constructor
- /// </summary>
- /// <param name="msg"></param>
- public TypeSignatureException(string msg) : base(msg) { }
- }
- /// <summary>
- /// Error with a CIL instruction
- /// </summary>
- public class InstructionException : System.Exception {
- IType iType;
- uint op;
- internal InstructionException(IType iType, uint op) {
- this.iType = iType;
- this.op = op;
- }
- internal string AddMethodName(string name) {
- string istr = " ";
- switch (iType) {
- case (IType.fieldOp) : istr += (FieldOp)op; break;
- case (IType.methOp) : istr += (MethodOp)op; break;
- case (IType.specialOp) : istr += (SpecialOp)op; break;
- case (IType.typeOp) : istr += (TypeOp)op; break;
- default : break;
- }
- return "NullPointer in instruction" + istr + " for method " + name;
- }
- }
- /// <summary>
- /// Error with descriptor types
- /// </summary>
- public class DescriptorException : System.Exception {
- /// <summary>
- /// exception
- /// </summary>
- /// <param name="msg"></param>
- public DescriptorException(string msg):
- base("Descriptor for " + msg + " already exists") { }
- /// <summary>
- /// exception
- /// </summary>
- public DescriptorException() :
- base("Descriptor is a Def when a Ref is required") { }
- }
- /// <summary>
- /// Error for invalid PE file
- /// </summary>
- public class PEFileException : System.Exception {
- /// <summary>
- /// PEFile exception constructor
- /// </summary>
- /// <param name="msg"></param>
- public PEFileException(string msg) : base("Error in PE File: " + msg) { }
- }
- /// <summary>
- /// When the maximum stack depth could not be found dynamically.
- /// </summary>
- public class CouldNotFindMaxStackDepth : System.Exception {
- /// <summary>
- /// Constructor
- /// </summary>
- public CouldNotFindMaxStackDepth() : base("Not able to find the maximum stack depth.") { }
- }
- /// <summary>
- /// When the stack depth is not valid for the current position.
- /// </summary>
- public class InvalidStackDepth : System.Exception {
- /// <summary>
- /// Constructor
- /// </summary>
- public InvalidStackDepth(string msg) : base("Invalid stack depth reached: " + msg) { }
- }
- /**************************************************************************/
- // Various Enumerations for PEFiles
- /// <summary>
- /// flags for the assembly (.corflags)
- /// </summary>
- public enum CorFlags {
- /// <summary>
- /// IL only
- /// </summary>
- CF_IL_ONLY = 1,
- /// <summary>
- /// 32 bits
- /// </summary>
- CF_32_BITREQUIRED = 2,
- /// <summary>
- /// strong name signed
- /// </summary>
- CF_STRONGNAMESIGNED = 8,
- /// <summary>
- /// track debug data
- /// </summary>
- CF_TRACKDEBUGDATA = 0x10000
- }
- /// <summary>
- /// subsystem for the assembly (.subsystem)
- /// </summary>
- public enum SubSystem {
- /// <summary>
- /// native subsystem
- /// </summary>
- Native = 1,
- /// <summary>
- /// gui app
- /// </summary>
- Windows_GUI = 2,
- /// <summary>
- /// console app
- /// </summary>
- Windows_CUI = 3,
- /// <summary>
- /// os2 console
- /// </summary>
- OS2_CUI = 5,
- /// <summary>
- /// posix console
- /// </summary>
- POSIX_CUI = 7,
- /// <summary>
- /// native windows
- /// </summary>
- Native_Windows = 8,
- /// <summary>
- /// CE gui
- /// </summary>
- Windows_CE_GUI = 9
- }
- /// <summary>
- /// Hash algorithms for the assembly
- /// </summary>
- public enum HashAlgorithmType {
- /// <summary>
- /// No hash algorithm
- /// </summary>
- None,
- /// <summary>
- /// SHA1
- /// </summary>
- SHA1 = 0x8004
- }
- /// <summary>
- /// Attributes for this assembly
- /// </summary>
- public enum AssemAttr {
- /// <summary>
- /// Public key assembly attribute
- /// </summary>
- PublicKey = 0x01,
- /// <summary>
- /// retargetable assembly
- /// </summary>
- Retargetable = 0x100,
- /// <summary>
- /// JIT tracking
- /// </summary>
- EnableJITCompileTracking = 0x8000,
- /// <summary>
- /// Disable JIT compile optimizer
- /// </summary>
- DisableJITCompileOptimizer = 0x4000}
- /// <summary>
- /// Method call conventions
- /// </summary>
- [FlagsAttribute]
- public enum CallConv {
- /// <summary>
- /// default cc
- /// </summary>
- Default,
- /// <summary>
- /// cdecl
- /// </summary>
- Cdecl,
- /// <summary>
- /// stdcall
- /// </summary>
- Stdcall,
- /// <summary>
- /// this call
- /// </summary>
- Thiscall,
- /// <summary>
- /// fast call
- /// </summary>
- Fastcall,
- /// <summary>
- /// var arg
- /// </summary>
- Vararg,
- /// <summary>
- /// generic
- /// </summary>
- Generic = 0x10,
- /// <summary>
- /// instance
- /// </summary>
- Instance = 0x20,
- /// <summary>
- /// explicit instance
- /// </summary>
- InstanceExplicit = 0x60 }
- /// <summary>
- /// Method Types for Events and Properties
- /// </summary>
- public enum MethodType {
- /// <summary>
- /// setter
- /// </summary>
- Setter = 0x01,
- /// <summary>
- /// getter
- /// </summary>
- Getter,
- /// <summary>
- /// other
- /// </summary>
- Other = 0x04,
- /// <summary>
- /// add on
- /// </summary>
- AddOn = 0x08,
- /// <summary>
- /// remove on
- /// </summary>
- RemoveOn = 0x10,
- /// <summary>
- /// Fire
- /// </summary>
- Fire = 0x20 }
- /// <summary>
- /// Type custom modifier
- /// </summary>
- public enum CustomModifier {
- /// <summary>
- /// mod req
- /// </summary>
- modreq = 0x1F,
- /// <summary>
- /// mod opt
- /// </summary>
- modopt };
- /// <summary>
- /// Attibutes for a class
- /// </summary>
- [FlagsAttribute]
- public enum TypeAttr {
- Private, Public, NestedPublic, NestedPrivate,
- NestedFamily, NestedAssembly, NestedFamAndAssem, NestedFamOrAssem,
- SequentialLayout, ExplicitLayout = 0x10, Interface = 0x20,
- Abstract = 0x80, PublicAbstract = 0x81, Sealed = 0x100,
- PublicSealed = 0x101, SpecialName = 0x400, RTSpecialName = 0x800,
- Import = 0x1000, Serializable = 0x2000, UnicodeClass = 0x10000,
- AutoClass = 0x20000, BeforeFieldInit = 0x100000 }
- /// <summary>
- /// Attributes for a field
- /// </summary>
- [FlagsAttribute]
- public enum FieldAttr {
- Default, Private, FamAndAssem, Assembly,
- Family, FamOrAssem, Public, Static = 0x10, PublicStatic = 0x16,
- Initonly = 0x20, Literal = 0x40, Notserialized = 0x80,
- SpecialName = 0x200, RTSpecialName = 0x400 }
- /// <summary>
- /// Attributes for a method
- /// </summary>
- [FlagsAttribute]
- public enum MethAttr {
- Default, Private, FamAndAssem, Assembly,
- Family, FamOrAssem, Public, Static = 0x0010, PublicStatic = 0x16,
- Final = 0x0020, PublicStaticFinal = 0x36, Virtual = 0x0040,
- PrivateVirtual, PublicVirtual = 0x0046, HideBySig = 0x0080,
- NewSlot = 0x0100, Abstract = 0x0400, SpecialName = 0x0800,
- RTSpecialName = 0x1000, SpecialRTSpecialName = 0x1800,
- RequireSecObject = 0x8000}
- /// <summary>
- /// Attributes for .pinvokeimpl method declarations
- /// </summary>
- [FlagsAttribute]
- public enum PInvokeAttr {
- ansi = 2, unicode = 4, autochar = 6,
- lasterr = 0x040, winapi = 0x100, cdecl = 0x200, stdcall = 0x300,
- thiscall = 0x400, fastcall = 0x500 }
- /// <summary>
- /// Implementation attributes for a method
- /// </summary>
- [FlagsAttribute]
- public enum ImplAttr {
- IL, Native, OPTIL, Runtime, Unmanaged,
- ForwardRef = 0x10, PreserveSig = 0x0080, InternalCall = 0x1000,
- Synchronised = 0x0020, Synchronized = 0x0020, NoInLining = 0x0008}
- /// <summary>
- /// Modes for a parameter
- /// </summary>
- [FlagsAttribute]
- public enum ParamAttr { Default, In, Out, Opt = 4 }
- /// <summary>
- /// Flags for a generic parameter
- /// </summary>
- [Flags]
- public enum GenericParamAttr {
- NonVariant,
- Covariant,
- Contravariant,
- ReferenceType = 0x4,
- RequireDefaultCtor = 0x10 }
- /// <summary>
- /// Which version of PE file to build
- /// </summary>
- public enum NetVersion {
- Everett, /* version 1.1.4322 */
- Whidbey40, /* version 2.0.40607 beta 1*/
- Whidbey41, /* version 2.0.41202 */
- Whidbey50, /* version 2.0.50215 beta2*/
- Version2 /* version 2.0.50727.0 */
- }
- /// <summary>
- /// CIL instructions
- /// </summary>
- public enum Op {
- nop, breakOp, ldarg_0, ldarg_1, ldarg_2, ldarg_3, ldloc_0, ldloc_1, ldloc_2,
- ldloc_3, stloc_0, stloc_1, stloc_2, stloc_3,
- ldnull = 0x14, ldc_i4_m1, ldc_i4_0, ldc_i4_1, ldc_i4_2, ldc_i4_3,
- ldc_i4_4, ldc_i4_5, ldc_i4_6, ldc_i4_7, ldc_i4_8, dup = 0x25, pop,
- ret = 0x2A, ldind_i1 = 0x46, ldind_u1, ldind_i2, ldind_u2, ldind_i4,
- ldind_u4, ldind_i8, ldind_i, ldind_r4, ldind_r8, ldind_ref, stind_ref,
- stind_i1, stind_i2, stind_i4, stind_i8, stind_r4, stind_r8, add, sub, mul,
- div, div_un, rem, rem_un, and, or, xor, shl, shr, shr_un, neg, not,
- conv_i1, conv_i2, conv_i4, conv_i8, conv_r4, conv_r8, conv_u4, conv_u8,
- conv_r_un = 0x76, throwOp = 0x7A, conv_ovf_i1_un = 0x82, conv_ovf_i2_un,
- conv_ovf_i4_un, conv_ovf_i8_un, conf_ovf_u1_un, conv_ovf_u2_un,
- conv_ovf_u4_un, conv_ovf_u8_un, conv_ovf_i_un, conv_ovf_u_un,
- ldlen = 0x8E, ldelem_i1 = 0x90, ldelem_u1, ldelem_i2, ldelem_u2,
- ldelem_i4, ldelem_u4, ldelem_i8, ldelem_i, ldelem_r4, ldelem_r8,
- ldelem_ref, stelem_i, stelem_i1, stelem_i2, stelem_i4, stelem_i8,
- stelem_r4, stelem_r8, stelem_ref, conv_ovf_i1 = 0xb3, conv_ovf_u1,
- conv_ovf_i2, conv_ovf_u2, conv_ovf_i4, conv_ovf_u4, conv_ovf_i8,
- conv_ovf_u8, ckfinite = 0xC3, conv_u2 = 0xD1, conv_u1, conv_i,
- conv_ovf_i, conv_ovf_u, add_ovf, add_ovf_un, mul_ovf, mul_ovf_un,
- sub_ovf, sub_ovf_un, endfinally, stind_i = 0xDF, conv_u,
- arglist = 0xFE00, ceq, cgt, cgt_un, clt, clt_un, localloc = 0xFE0F,
- endfilter = 0xFE11, volatile_ = 0xFE13, tail_, cpblk = 0xFE17, initblk,
- rethrow = 0xFE1A, refanytype = 0xFE1D, readOnly}
- /// <summary>
- /// CIL instructions requiring an integer parameter
- /// </summary>
- public enum IntOp {
- ldarg_s = 0x0E, ldarga_s, starg_s, ldloc_s, ldloca_s,
- stloc_s, ldc_i4_s = 0x1F, ldc_i4, ldarg = 0xFE09,
- ldarga, starg, ldloc, ldloca, stloc, unaligned = 0xFE12 }
- /// <summary>
- /// CIL instructions requiring a field parameter
- /// </summary>
- public enum FieldOp {
- ldfld = 0x7B, ldflda, stfld, ldsfld, ldsflda,
- stsfld, ldtoken = 0xD0 }
- /// <summary>
- /// CIL instructions requiring a method parameter
- /// </summary>
- public enum MethodOp {
- jmp = 0x27, call, callvirt = 0x6F, newobj = 0x73,
- ldtoken = 0xD0, ldftn = 0xFE06, ldvirtfn }
- /// <summary>
- /// CIL instructions requiring a type parameter
- /// </summary>
- public enum TypeOp {
- cpobj = 0x70, ldobj, castclass = 0x74, isinst,
- unbox = 0x79, stobj = 0x81, box = 0x8C, newarr,
- ldelema = 0x8F, ldelem_any = 0xA3, stelem_any, unbox_any,
- refanyval = 0xC2, mkrefany = 0xC6,
- ldtoken = 0xD0, initobj = 0xFE15, constrained, sizeOf = 0xFE1C }
- /// <summary>
- /// CIL branch instructions
- /// </summary>
- public enum BranchOp {
- br_s = 0x2B, brfalse_s, brtrue_s, beq_s, bge_s, bgt_s, ble_s,
- blt_s, bne_un_s, bge_un_s, bgt_un_s, ble_un_s, blt_un_s,
- br, brfalse, brtrue, beq, bge, bgt, ble, blt, bne_un, bge_un, bgt_un, ble_un, blt_un,
- leave = 0xDD, leave_s }
- public enum SpecialOp {
- ldc_i8 = 0x21, ldc_r4, ldc_r8, calli = 0x29,
- Switch = 0x45, ldstr = 0x72 }
- /// <summary>
- /// Index for all the tables in the meta data
- /// </summary>
- public enum MDTable {
- Module, TypeRef, TypeDef, Field = 0x04, Method = 0x06,
- Param = 0x08, InterfaceImpl, MemberRef, Constant, CustomAttribute,
- FieldMarshal, DeclSecurity, ClassLayout, FieldLayout, StandAloneSig,
- EventMap, Event = 0x14, PropertyMap, Property = 0x17, MethodSemantics,
- MethodImpl, ModuleRef, TypeSpec, ImplMap, FieldRVA, Assembly = 0x20,
- AssemblyProcessor, AssemblyOS, AssemblyRef, AssemblyRefProcessor,
- AssemblyRefOS, File, ExportedType, ManifestResource, NestedClass,
- GenericParam, MethodSpec, GenericParamConstraint, MaxMDTable }
- public enum NativeTypeIx {
- Void = 0x01, Boolean, I1, U1, I2, U2, I4, U4,
- I8, U8, R4, R8, SysChar, Variant, Currency, Ptr, Decimal, Date, BStr,
- LPStr, LPWStr, LPTStr, FixedSysString, ObjectRef, IUnknown, IDispatch,
- Struct, Intf, SafeArray, FixedArray, Int, UInt, NestedStruct, ByValStr,
- AnsiBStr, TBStr, VariantBool, Func, AsAny = 0x28, Array = 0x2A, LPStruct,
- CustomMarshaller, Error }
- public enum SafeArrayType {
- int16 = 2, int32, float32, float64,
- currency, date, bstr, dispatch, error, boolean, variant, unknown,
- Decimal, int8 = 16, uint8, uint16, uint32, Int = 22, UInt,
- record = 0x24,
- MAX = 0x50
- }
- internal enum CIx {
- TypeDefOrRef, HasConstant, HasCustomAttr, HasFieldMarshal,
- HasDeclSecurity, MemberRefParent, HasSemantics, MethodDefOrRef,
- MemberForwarded, Implementation, CustomAttributeType, ResolutionScope,
- TypeOrMethodDef, MaxCIx }
- internal enum MapType { eventMap, propertyMap, nestedClass }
- public enum ElementType : byte {
- End, Void, Boolean, Char, I1, U1, I2, U2, I4, U4,
- I8, U8, R4, R8, String, Ptr, ByRef, ValueType, Class, Var, Array, GenericInst,
- TypedByRef, I = 0x18, U, FnPtr = 0x1B, Object, SZArray, MVar, CmodReqd,
- CmodOpt, Internal, Modifier = 0x40, Sentinel, Pinned = 0x45, ClassType = 0x50 }
- public enum SecurityAction {
- Request = 0x01, Demand, Assert, Deny, PermitOnly,
- LinkDemand, InheritanceDemand, RequestMinimum, RequestOptional, RequestRefuse,
- PreJITGrant, PreJITDeny, NonCASDemand, NonCASLinkDemand, NonCASInheritanceDemand }
- internal enum IType {
- op, methOp, fieldOp, typeOp, specialOp, int8Op, uint8Op, uint16Op,
- int32Op, branchOp }
- /**************************************************************************/
- /// <summary>
- /// Abstract class to represent a row of the Meta Data Tables
- /// </summary>
- public abstract class TableRow {
- internal PEReader buffer;
- private uint row = 0;
- /// <summary>
- /// The index of the Meta Data Table containing this element
- /// </summary>
- protected MDTable tabIx;
- /*-------------------- Constructors ---------------------------------*/
- internal TableRow() { }
- internal TableRow(PEReader buff, uint ix, MDTable tableIx) {
- buffer = buff;
- row = ix;
- tabIx = tableIx;
- }
- /// <summary>
- /// The row number of this element in the Meta Data Table
- /// </summary>
- public uint Row {
- get { return row; }
- set { row = value; }
- }
- }
- /****************************************************/
- /// <summary>
- /// Base class for all Meta Data table elements
- /// </summary>
- public abstract class MetaDataElement : TableRow, IComparable {
- /// <summary>
- /// The list of custom attributes associated with this meta data element
- /// </summary>
- protected ArrayList customAttributes;
- protected bool done = false;
- protected bool sortTable = false;
- internal bool unresolved = false;
- /*-------------------- Constructors ---------------------------------*/
- internal MetaDataElement() { }
- /// <summary>
- /// Get any custom attributes associated with this meta data element
- /// </summary>
- /// <returns>Array of custom attribute descriptors</returns>
- public CustomAttribute[] GetCustomAttributes() {
- if (customAttributes == null) return new CustomAttribute[0];
- return (CustomAttribute[])customAttributes.ToArray(typeof(CustomAttribute));
- }
- /// <summary>
- /// Associate some custom attribute(s) with this meta data element
- /// </summary>
- /// <param name="cas">list of custom attributes</param>
- public void SetCustomAttributes(CustomAttribute[] cas) {
- if (cas == null)
- customAttributes = null;
- else
- customAttributes = new ArrayList(cas);
- }
- internal virtual bool isDef() { return false; }
- internal virtual void Resolve(PEReader buff) { }
- internal virtual void ResolveDetails(PEReader buff) { }
- internal virtual uint GetCodedIx(CIx code) { return 0; }
- internal bool NeedToSort() { return sortTable; }
- internal virtual uint SortKey() {
- throw new PEFileException("Trying to sort table of " + this);
- //return 0;
- }
- /// <summary>
- /// Add a custom attribute to this item
- /// </summary>
- /// <param name="ctorMeth">the constructor method for this attribute</param>
- /// <param name="val">the byte value of the parameters</param>
- public void AddCustomAttribute(Method ctorMeth, byte[] val) {
- if (customAttributes == null) {
- customAttributes = new ArrayList();
- }
- customAttributes.Add(new CustomAttribute(this,ctorMeth,val));
- }
- /// <summary>
- /// Add a custom attribute to this item
- /// </summary>
- /// <param name="ctorMeth">the constructor method for this attribute</param>
- /// <param name="cVals">the constant values of the parameters</param>
- public void AddCustomAttribute(Method ctorMeth, Constant[] cVals) {
- if (customAttributes == null) {
- customAttributes = new ArrayList();
- }
- customAttributes.Add(new CustomAttribute(this,ctorMeth,cVals));
- }
- /// <summary>
- /// Associate a custom attribute with this meta data element
- /// </summary>
- public void AddCustomAttribute(CustomAttribute ca) {
- if (customAttributes == null) {
- customAttributes = new ArrayList();
- }
- customAttributes.Add(ca);
- }
- internal uint Token() {
- if (Row == 0) throw new Exception("Meta data token is zero!!");
- return (((uint)tabIx << 24) | Row);
- }
- internal void BuildMDTables(MetaDataOut md) {
- if (done) return;
- done = true;
- if (Diag.DiagOn) Console.WriteLine("In BuildMDTables");
- BuildTables(md);
- if (customAttributes != null) {
- for (int i=0; i < customAttributes.Count; i++) {
- CustomAttribute ca = (CustomAttribute)customAttributes[i];
- ca.BuildTables(md);
- }
- }
- }
- internal virtual void BuildTables(MetaDataOut md) { }
- internal virtual void BuildSignatures(MetaDataOut md) {
- done = false;
- }
- internal virtual void BuildCILInfo(CILWriter output) { }
- internal virtual void AddToTable(MetaDataOut md) {
- md.AddToTable(tabIx,this);
- }
- internal virtual void Write(PEWriter output) { }
- internal virtual void Write(CILWriter output) {
- throw new Exception("CIL backend not yet fully implemented - " + GetType().ToString());
- }
- internal virtual string NameString() { return "NoName"; }
- internal void DescriptorError(MetaDataElement elem) {
- throw new DescriptorException(elem.NameString());
- }
- #region IComparable Members
- public int CompareTo(object obj) {
- uint otherKey = ((MetaDataElement)obj).SortKey();
- uint thisKey = SortKey();
- if (thisKey == otherKey) {
- if (this is GenericParam) {
- if (((GenericParam)this).Index < ((GenericParam)obj).Index)
- return -1;
- else
- return 1;
- }
- return 0;
- }
- if (thisKey < otherKey) return -1;
- return 1;
- }
- #endregion
- }
- /**************************************************************************/
- /// <summary>
- /// Layout information for a class (.class [sequential | explicit])
- /// </summary>
- internal class ClassLayout : MetaDataElement {
- ClassDef parent;
- ushort packSize = 0;
- uint classSize = 0;
- uint parentIx = 0;
- /*-------------------- Constructors ---------------------------------*/
- internal ClassLayout(int pack, int cSize, ClassDef par) {
- packSize = (ushort)pack;
- classSize = (uint)cSize;
- parent = par;
- tabIx = MDTable.ClassLayout;
- }
- internal ClassLayout(ushort pack, uint cSize, ClassDef par) {
- packSize = pack;
- classSize = cSize;
- parent = par;
- tabIx = MDTable.ClassLayout;
- }
- internal ClassLayout(PEReader buff) {
- packSize = buff.ReadUInt16();
- classSize = buff.ReadUInt32();
- parentIx = buff.GetIndex(MDTable.TypeDef);
- tabIx = MDTable.ClassLayout;
- }
- internal static ClassLayout FindLayout(PEReader buff, ClassDef paren, uint classIx) {
- buff.SetElementPosition(MDTable.ClassLayout,0);
- for (int i=0; i < buff.GetTableSize(MDTable.ClassLayout); i++) {
- ushort packSize = buff.ReadUInt16();
- uint classSize = buff.ReadUInt32();
- if (buff.GetIndex(MDTable.TypeDef) == classIx)
- return new ClassLayout(packSize,classSize,paren);
- }
- return null;
- }
- internal static void Read(PEReader buff, TableRow[] layouts) {
- for (int i=0; i < layouts.Length; i++ ) {
- layouts[i] = new ClassLayout(buff);
- }
- }
- internal override void Resolve(PEReader buff) {
- parent = (ClassDef)buff.GetElement(MDTable.TypeDef,parentIx);
- if (parent != null) parent.Layout = this;
- }
- /*------------------------- public set and get methods --------------------------*/
- public void SetPack(int pack) { packSize = (ushort)pack; }
- public int GetPack() { return (int)packSize; }
- public void SetSize(int size) { classSize = (uint)size; }
- public int GetSize() { return (int)classSize; }
- /*----------------------------- internal functions ------------------------------*/
- internal sealed override void BuildTables(MetaDataOut md) {
- md.AddToTable(tabIx,this);
- }
- internal static uint Size(MetaData md) {
- return 6 + md.TableIndexSize(MDTable.TypeDef);
- }
- internal sealed override void Write(PEWriter output) {
- output.Write(packSize);
- output.Write(classSize);
- output.WriteIndex(MDTable.TypeDef,parent.Row);
- }
- }
- /**************************************************************************/
- /// <summary>
- /// Summary description for ConstantElem.
- /// </summary>
- internal class ConstantElem : MetaDataElement {
- MetaDataElement parent;
- Constant cValue;
- uint valIx = 0, parentIx = 0;
- /*-------------------- Constructors ---------------------------------*/
- internal ConstantElem(MetaDataElement parent, Constant val) {
- this.parent = parent;
- cValue = val;
- sortTable = true;
- tabIx = MDTable.Constant;
- }
- internal ConstantElem(PEReader buff) {
- byte constType = buff.ReadByte();
- byte pad = buff.ReadByte();
- parentIx = buff.GetCodedIndex(CIx.HasConstant);
- //valIx = buff.GetBlobIx();
- cValue = buff.GetBlobConst(constType);
- sortTable = true;
- tabIx = MDTable.Constant;
- }
- internal override void Resolve(PEReader buff) {
- parent = buff.GetCodedElement(CIx.HasConstant,parentIx);
- if (parent != null) {
- if (parent is Param) ((Param)parent).AddDefaultValue(cValue);
- else if (parent is FieldDef) ((FieldDef)parent).AddValue(cValue);
- else ((Property)parent).AddInitValue(cValue);
- }
- }
- internal static void Read(PEReader buff, TableRow[] consts) {
- for (int i=0; i < consts.Length; i++)
- consts[i] = new ConstantElem(buff);
- }
- /*----------------------------- internal functions ------------------------------*/
- internal override uint SortKey() {
- return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasConstant])
- | parent.GetCodedIx(CIx.HasConstant);
- }
- internal sealed override void BuildTables(MetaDataOut md) {
- md.AddToTable(MDTable.Constant,this);
- valIx = cValue.GetBlobIndex(md);
- }
- internal static uint Size(MetaData md) {
- return 2 + md.CodedIndexSize(CIx.HasConstant) + md.BlobIndexSize();
- }
- internal sealed override void Write(PEWriter output) {
- output.Write(cValue.GetTypeIndex());
- output.Write((byte)0);
- output.WriteCodedIndex(CIx.HasConstant,parent);
- output.BlobIndex(valIx);
- }
- }
- /**************************************************************************/
- /// <summary>
- /// Descriptor for a Custom Attribute (.custom)
- /// </summary>
- public class CustomAttribute : MetaDataElement {
- internal static readonly ushort prolog = 0x0001;
- private static readonly int initSize = 5;
- MetaDataElement parent;
- Method type;
- uint valIx, parentIx, typeIx;
- Constant[] argVals, vals;
- public byte[] byteVal;
- ushort numNamed = 0;
- string[] names;
- bool[] isField;
- bool changed = false;
- /*-------------------- Constructors ---------------------------------*/
- internal CustomAttribute(MetaDataElement paren, Method constrType,
- Constant[] val) {
- parent = paren;
- type = constrType;
- argVals = val;
- changed = true;
- sortTable = true;
- tabIx = MDTable.CustomAttribute;
- }
- internal CustomAttribute(MetaDataElement paren, Method constrType,
- byte[] val) {
- parent = paren;
- type = constrType;
- tabIx = MDTable.CustomAttribute;
- byteVal = val;
- sortTable = true;
- changed = true;
- }
- internal CustomAttribute(PEReader buff) {
- parentIx = buff.GetCodedIndex(CIx.HasCustomAttr);
- typeIx = buff.GetCodedIndex(CIx.CustomAttributeType);
- valIx = buff.GetBlobIx();
- sortTable = true;
- tabIx = MDTable.CustomAttribute;
- }
- internal static void Read(PEReader buff, TableRow[] attrs) {
- for (int i=0; i < attrs.Length; i++) {
- attrs[i] = new CustomAttribute(buff);
- }
- }
- internal override void Resolve(PEReader buff) {
- parent = buff.GetCodedElement(CIx.HasCustomAttr,parentIx);
- if (parent == null) return;
- parent.AddCustomAttribute(this);
- type = (Method)buff.GetCodedElement(CIx.CustomAttributeType,typeIx);
- byteVal = buff.GetBlob(valIx);
- }
- /*------------------------- public set and get methods --------------------------*/
- public void AddFieldOrProp(string name, Constant val, bool isFld) {
- if ((byteVal != null) && !changed) DecodeCustomAttributeBlob();
- if (numNamed == 0) {
- names = new string[initSize];
- vals = new Constant[initSize];
- isField = new bool[initSize];
- } else if (numNamed >= names.Length) {
- string[] tmpNames = names;
- Constant[] tmpVals = vals;
- bool[] tmpField = isField;
- names = new String[names.Length + initSize];
- vals = new Constant[vals.Length + initSize];
- isField = new bool[isField.Length + initSize];
- for (int i = 0; i < numNamed; i++) {
- names[i] = tmpNames[i];
- vals[i] = tmpVals[i];
- isField[i] = tmpField[i];
- }
- }
- names[numNamed] = name;
- vals[numNamed] = val;
- isField[numNamed++] = isFld;
- changed = true;
- }
- public Constant[] Args {
- get {
- if (!changed && (byteVal != null)) {
- try {
- DecodeCustomAttributeBlob();
- } catch {
- }
- }
- return argVals;
- }
- set {
- argVals = value;
- changed = true;
- }
- }
- public string[] GetNames() {
- return names;
- }
- public bool[] GetIsField() {
- return isField;
- }
- public Constant[] GetNamedArgs() {
- return vals;
- }
- /*----------------------------- internal functions ------------------------------*/
- internal void DecodeCustomAttributeBlob() {
- MemoryStream caBlob = new MemoryStream(byteVal);
- BinaryReader blob = new BinaryReader(caBlob,System.Text.Encoding.UTF8);
- if (blob.ReadUInt16() != CustomAttribute.prolog) throw new PEFileException("Invalid Custom Attribute Blob");
- Type[] parTypes = type.GetParTypes();
- argVals = new Constant[parTypes.Length];
- for (int i=0; i < parTypes.Length; i++) {
- Type argType = parTypes[i];
- bool arrayConst = argType is Array;
- if (arrayConst) argType = ((ZeroBasedArray)(parTypes[i])).ElemType();
- bool boxed = argType is SystemClass;
- int eType = argType.GetTypeIndex();
- if (arrayConst) {
- Constant[] elems = new Constant[blob.ReadUInt32()];
- for (int j=0; j < elems.Length; j++) {
- if (boxed) {
- eType = blob.ReadByte();
- elems[j] = new BoxedSimpleConst((SimpleConstant)PEReader.ReadConst(eType,blob));
- } else {
- elems[j] = PEReader.ReadConst(eType,blob);
- }
- }
- argVals[i] = new ArrayConst(elems);
- } else if (boxed) {
- argVals[i] = new BoxedSimpleConst((SimpleConstant)PEReader.ReadConst(blob.ReadByte(),blob));
- } else {
- argVals[i] = PEReader.ReadConst(eType,blob);
- }
- }
- uint numNamed = 0;
- if (blob.BaseStream.Position != byteVal.Length)
- numNamed = blob.ReadUInt16();
- if (numNamed > 0) {
- names = new string[numNamed];
- vals = new Constant[numNamed];
- isField = new bool[numNamed];
- for (int i=0; i < numNamed; i++) {
- isField[i] = blob.ReadByte() == 0x53;
- int eType = blob.ReadByte();
- names[i] = blob.ReadString();
- vals[i] = PEReader.ReadConst(eType,blob);
- }
- }
- }
- internal void AddFieldOrProps(string[] names, Constant[] vals, bool[] isField) {
- this.names = names;
- this.vals = vals;
- this.isField = isField;
- numNamed = (ushort)names.Length;
- }
- internal void SetBytes(byte[] bytes) {
- this.byteVal = bytes;
- }
- internal Method GetCAType() {
- return type;
- }
- internal override uint SortKey() {
- return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasCustomAttr])
- | parent.GetCodedIx(CIx.HasCustomAttr);
- }
- internal sealed override void BuildTables(MetaDataOut md) {
- md.AddToTable(tabIx,this);
- type.BuildMDTables(md);
- // more adding to tables if data is not bytes
- if (changed || (byteVal == null)) {
- MemoryStream str = new MemoryStream();
- BinaryWriter bw = new BinaryWriter(str);
- bw.Write((ushort)1);
- if (argVals != null) {
- for (int i=0; i < argVals.Length; i++) {
- argVals[i].Write(bw);
- }
- }
- bw.Write(numNamed);
- for (int i=0; i < numNamed; i++) {
- if (isField[i]) bw.Write(Field.FieldTag);
- else bw.Write(Property.PropertyTag);
- bw.Write(vals[i].GetTypeIndex());
- bw.Write(names[i]); // check this is the right format!!!
- vals[i].Write(bw);
- }
- byteVal = str.ToArray();
- }
- valIx = md.AddToBlobHeap(byteVal);
- }
- internal static uint Size(MetaData md) {
- return md.CodedIndexSize(CIx.HasCustomAttr) + md.CodedIndexSize(CIx.CustomAttributeType) + md.BlobIndexSize();
- }
- internal sealed override void Write(PEWriter output) {
- output.WriteCodedIndex(CIx.HasCustomAttr,parent);
- output.WriteCodedIndex(CIx.CustomAttributeType,type);
- output.BlobIndex(valIx);
- }
- }
- /**************************************************************************/
- /// <summary>
- /// Descriptor for security permissions for a class or a method NOT YET IMPLEMENTED
- /// </summary>
- public class DeclSecurity : MetaDataElement {
- SecurityAction action;
- MetaDataElement parent;
- uint parentIx = 0, permissionIx;
- byte[] permissionSet;
- /*-------------------- Constructors ---------------------------------*/
- internal DeclSecurity(MetaDataElement paren, SecurityAction act, byte[] perSet) {
- parent = paren;
- action = act;
- permissionSet = perSet;
- sortTable = true;
- tabIx = MDTable.DeclSecurity;
- }
- internal DeclSecurity(PEReader buff) {
- action = (SecurityAction)buff.ReadUInt16();
- parentIx = buff.GetCodedIndex(CIx.HasDeclSecurity);
- permissionSet = buff.GetBlob();
- sortTable = true;
- tabIx = MDTable.DeclSecurity;
- }
- internal static void Read(PEReader buff, TableRow[] secs) {
- for (int i=0; i < secs.Length; i++)
- secs[i] = new DeclSecurity(buff);
- }
- internal static DeclSecurity FindSecurity(PEReader buff, MetaDataElement paren, uint codedParIx) {
- buff.SetElementPosition(MDTable.DeclSecurity,0);
- for (int i=0; i < buff.GetTableSize(MDTable.DeclSecurity); i++) {
- uint act = buff.ReadUInt16();
- if (buff.GetCodedIndex(CIx.HasDeclSecurity) == codedParIx)
- return new DeclSecurity(paren,(SecurityAction)act,buff.GetBlob());
- uint junk = buff.GetBlobIx();
- }
- return null;
- }
- internal override void Resolve(PEReader buff) {
- parent = buff.GetCodedElement(CIx.HasDeclSecurity,parentIx);
- if (parent != null) {
- if (parent is ClassDef) ((ClassDef)parent).AddSecurity(this);
- if (parent is Assembly) ((Assembly)parent).AddSecurity(this);
- if (parent is MethodDef) ((MethodDef)parent).AddSecurity(this);
- }
- }
- internal override uint SortKey() {
- return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasDeclSecurity])
- | parent.GetCodedIx(CIx.HasDeclSecurity);
- }
- internal sealed override void BuildTables(MetaDataOut md) {
- md.AddToTable(MDTable.DeclSecurity, this);
- permissionIx = md.AddToBlobHeap(permissionSet);
- }
- internal static uint Size(MetaData md) {
- return 2 + md.CodedIndexSize(CIx.HasDeclSecurity) + md.BlobIndexSize();
- }
- internal sealed override void Write(PEWriter output) {
- output.Write((UInt16)action); // or should this be 2 bytes??
- output.WriteCodedIndex(CIx.HasDeclSecurity,parent);
- output.BlobIndex(permissionIx);
- }
- }
- /**************************************************************************/
- /// <summary>
- /// Descriptor for a class defined in another module of THIS assembly
- /// and exported (.class extern)
- /// </summary>
- internal class ExternClass : MetaDataElement {
- MetaDataElement implementation;
- uint flags, typeDefId = 0;
- uint implIx = 0, nameIx = 0, nameSpaceIx = 0;
- string nameSpace, name;
- /*-------------------- Constructors ---------------------------------*/
- internal ExternClass(TypeAttr attr, string ns, string name, MetaDataElement paren) {
- flags = (uint)attr;
- nameSpace = ns;
- this.name = name;
- implementation = paren;
- tabIx = MDTable.ExportedType;
- }
- public ExternClass(PEReader buff) {
- flags = buff.ReadUInt32();
- typeDefId = buff.ReadUInt32();
- name = buff.GetString();
- nameSpace = buff.GetString();
- implIx = buff.GetCodedIndex(CIx.Implementation);
- tabIx = MDTable.ExportedType;
- }
- internal static void Read(PEReader buff, TableRow[] eClasses) {
- for (int i=0; i < eClasses.Length; i++)
- eClasses[i] = new ExternClass(buff);
- }
- internal static void GetClassRefs(PEReader buff, TableRow[] eClasses) {
- for (uint i=0; i < eClasses.Length; i++) {
- uint junk = buff.ReadUInt32();
- junk = buff.ReadUInt32();
- string name = buff.GetString();
- string nameSpace = buff.GetString();
- uint implIx = buff.GetCodedIndex(CIx.Implementation);
- eClasses[i] = new ClassRef(implIx,nameSpace,name);
- eClasses[i].Row = i+1;
- }
- }
- internal override void Resolve(PEReader buff) {
- implementation = buff.GetCodedElement(CIx.Implementation,implIx);
- while (implementation is ExternClass)
- implementation = ((ExternClass)implementation).implementation;
- ((ModuleFile)implementation).fileModule.AddExternClass(this);
- }
- internal string NameSpace() { return nameSpace; }
- internal string Name() { return name; }
- internal sealed override void BuildTables(MetaDataOut md) {
- md.AddToTable(MDTable.ExportedType,this);
- nameSpaceIx = md.AddToStringsHeap(nameSpace);
- nameIx = md.AddToStringsHeap(name);
- if (implementation is ModuleRef) {
- ModuleFile mFile = ((ModuleRef)implementation).modFile;
- mFile.BuildMDTables(md);
- implementation = mFile;
- }
- }
- internal static uint Size(MetaData md) {
- return 8 + 2* md.StringsIndexSize() + md.CodedIndexSize(CIx.Implementation);
- }
- internal sealed override void Write(PEWriter output) {
- output.Write(flags);
- output.Write(0);
- output.StringsIndex(nameIx);
- output.StringsIndex(nameSpaceIx);
- output.WriteCodedIndex(CIx.Implementation,implementation);
- }
- internal sealed override uint GetCodedIx(CIx code) {
- switch (code) {
- case (CIx.HasCustomAttr) : return 17;
- case (CIx.Implementation) : return 2;
- }
- return 0;
- }
- }
- /**************************************************************************/
- /// <summary>
- /// Base class for Event and Property descriptors
- /// </summary>
- public abstract class Feature : MetaDataElement {
- private static readonly int INITSIZE = 5;
- private static readonly ushort specialName = 0x200;
- private static readonly ushort rtsSpecialName = 0x400;
- private static readonly ushort noSpecialName = 0xFDFF;
- private static readonly ushort noRTSSpecialName = 0xFBFF;
- protected ClassDef parent;
- protected ushort flags = 0;
- protected string name;
- protected int tide = 0;
- protected uint nameIx;
- protected MethodSemantics[] methods = new MethodSemantics[INITSIZE];
- /*-------------------- Constructors ---------------------------------*/
- internal Feature(string name, ClassDef par) {
- parent = par;
- this.name = name;
- }
- internal Feature() { }
- internal static string[] GetFeatureNames(PEReader buff, MDTable tabIx, MDTable mapTabIx,
- ClassDef theClass, uint classIx) {
- buff.SetElementPosition(mapTabIx,0);
- uint start = 0, end = 0, i = 0;
- for (; (i < buff.GetTableSize(tabIx)) && (start == 0); i++) {
- if (buff.GetIndex(MDTable.TypeDef) == classIx) {
- start = buff.GetIndex(tabIx);
- }
- }
- if (start == 0) return null;
- if (i < buff.GetTableSize(mapTabIx)) {
- uint junk = buff.GetIndex(MDTable.TypeDef);
- end = buff.GetIndex(tabIx);
- } else
- end = buff.GetTableSize(tabIx);
- if (tabIx == MDTable.Event)
- theClass.eventIx = start;
- e…
Large files files are truncated, but you can click here to view the full file