Module: PEdump::CLR

Defined in:
lib/pedump/clr.rb,
lib/pedump/clr/signature.rb,
lib/pedump/clr/readytorun.rb

Defined Under Namespace

Modules: DynTableMethods Classes: FieldSig, MetadataHeader, MetadataStreamHeader, MetadataTableStreamHeader, MethodDefSig, MethodRefSig, PropertySig, READYTORUN_CORE_HEADER, READYTORUN_HEADER, READYTORUN_SECTION, Signature, StandAloneMethodSig, StringsHash, TablesHash, TypeSpecBlob

Constant Summary collapse

CustomAttributeType =
[:not_used, :not_used, :MethodDef, :MemberRef, :not_used]
HasConstant =
[:Field, :Param, :Property]
HasCustomAttribute =

XXX not checked thoroughly

[:MethodDef, :Field, :TypeRef, :TypeDef, :Param, :InterfaceImpl, :MemberRef, :Module, :DeclSecurity, :Property, :Event, :StandAloneSig, :ModuleRef, :TypeSpec, :Assembly, :AssemblyRef, :File, :ExportedType, :ManifestResource, :GenericParam, :GenericParamConstraint, :MethodSpec]
HasDeclSecurity =
[:TypeDef, :MethodDef, :Assembly]
HasFieldMarshal =
[:Field, :Param]
HasSemantics =
[:Event, :Property]
Implementation =
[:File, :AssemblyRef, :ExportedType]
MemberForwarded =
[:Field, :MethodDef]
MemberRefParent =
[:TypeDef, :TypeRef, :ModuleRef, :MethodDef, :TypeSpec]
MethodDefOrRef =
[:MethodDef, :MemberRef]
ResolutionScope =
[:Module, :ModuleRef, :AssemblyRef, :TypeRef]
TypeDefOrRef =
[:TypeDef, :TypeRef, :TypeSpec]
TypeOrMethodDef =
[:TypeDef, :MethodDef]
TableDefs =
{
  # undocumented?
  FieldPtr: { Field: :Field },
  MethodPtr: { Method: :MethodDef },
  ParamPtr: { Param: :Param },
  EventPtr: { Event: :Event },
  PropertyPtr: { Property: :Property },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.30-module_0x00.md
  Module: {
    Generation: 2,       # a 2-byte value, reserved, shall be zero)
    Name:       :string, # an index into the String heap
    Mvid:       :guid,   # an index into the Guid heap
    EncId:      :guid,   # an index into the Guid heap; reserved, shall be zero
    EncBaseId:  :guid,   # an index into the Guid heap; reserved, shall be zero
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.38-typeref-0x01.md
  TypeRef: {
    ResolutionScope: ResolutionScope,
    TypeName:        :string,
    TypeNamespace:   :string,
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.37-typedef-0x02.md
  TypeDef: {
    Flags:           4,        # a 4-byte bitmask of TypeAttributes
    TypeName:        :string,
    TypeNamespace:   :string,
    Extends:         TypeDefOrRef,
    FieldList:       :Field,
    MethodList:      :MethodDef,
  },
  
  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.15-field-0x04.md
  Field: {
    Flags:           2,        # a 2-byte bitmask of FieldAttributes
    Name:            :string,
    Signature:       :blob,
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.26-methoddef-0x06.md
  MethodDef: {
    RVA:             4,        # a 4-byte constant
    ImplFlags:       2,        # a 2-byte bitmask of MethodImplAttributes
    Flags:           2,        # a 2-byte bitmask of MethodAttributes
    Name:            :string,
    Signature:       :blob,
    ParamList:       :Param,
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.33-param-0x08.md
  Param: {
    Flags:           2,        # a 2-byte bitmask of ParamAttributes
    Sequence:        2,        # a 2-byte constant
    Name:            :string,
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.23-interfaceimpl-0x09.md
  InterfaceImpl: {
    Class:           :TypeDef,
    Interface:       TypeDefOrRef,
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.25-memberref-0x0a.md
  MemberRef: {
    Class:           MemberRefParent,
    Name:            :string,
    Signature:       :blob,
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.9-constant-0x0b.md
  Constant: {
    Type:            2,        # a 1-byte constant, followed by a 1-byte padding zero
    Parent:          HasConstant,
    Value:           :blob,
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.10-customattribute-0x0c.md
  CustomAttribute: {
    Parent:          HasCustomAttribute,
    Type:            CustomAttributeType,
    Value:           :blob,
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.17-fieldmarshal-0x0d.md
  FieldMarshal: {
    Parent:          HasFieldMarshal,
    NativeType:      :blob,
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.11-declsecurity-0x0e.md
  DeclSecurity: {
    Action:          2,        # a 2-byte constant
    Parent:          HasDeclSecurity,
    PermissionSet:   :blob,
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.8-classlayout-0x0f.md
  ClassLayout: {
    PackingSize:     2,        # a 2-byte constant
    ClassSize:       4,        # a 4-byte constant
    Parent:          :TypeDef,
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.16-fieldlayout-0x10.md
  FieldLayout: {
    Offset:          4,        # a 4-byte constant
    Field:           :Field,
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.36-standalonesig-0x11.md
  StandAloneSig: {
    Signature:       :blob,
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.12-eventmap-0x12.md
  EventMap: {
    Parent:          :TypeDef,
    EventList:       :Event,
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.13-event-0x14.md
  Event: {
    EventFlags:      2,        # a 2-byte bitmask of EventAttributes
    Name:            :string,
    EventType:       TypeDefOrRef,
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.35-propertymap-0x15.md
  PropertyMap: {
    Parent:          :TypeDef,
    PropertyList:    :Property,
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.34-property-0x17.md
  Property: {
    Flags:           2,        # a 2-byte bitmask of PropertyAttributes
    Name:            :string,
    Type:            :blob,
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.28-methodsemantics-0x18.md
  MethodSemantics: {
    Semantics:       2,        # a 2-byte bitmask of MethodSemanticsAttributes
    Method:          :MethodDef,
    Association:     HasSemantics,
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.27-methodimpl-0x19.md
  MethodImpl: {
    Class:             :TypeDef,
    MethodBody:        MethodDefOrRef,
    MethodDeclaration: MethodDefOrRef,
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.31-moduleref-0x1a.md
  ModuleRef: {
    Name:            :string,
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.39-typespec-0x1b.md
  TypeSpec: {
    Signature:       :blob,
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.22-implmap-0x1c.md
  ImplMap: {
    MappingFlags:    2,        # a 2-byte bitmask of PInvokeAttributes
    MemberForwarded: MemberForwarded,
    ImportName:      :string,
    ImportScope:     :ModuleRef,
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.18-fieldrva-0x1d.md
  FieldRVA: {
    RVA:             4,        # a 4-byte constant
    Field:           :Field,
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.2-assembly-0x20.md
  Assembly: {
    HashAlgId:       4,        # a 4-byte constant
    MajorVersion:    2,        # a 2-byte constant
    MinorVersion:    2,        # a 2-byte constant
    BuildNumber:     2,        # a 2-byte constant
    RevisionNumber:  2,        # a 2-byte constant
    Flags:           4,        # a 4-byte bitmask of AssemblyFlags
    PublicKey:       :blob,
    Name:            :string,
    Culture:         :string,
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.4-assemblyprocessor-0x21.md
  AssemblyProcessor: {
    Processor:       4,        # a 4-byte constant
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.3-assemblyos-0x22.md
  AssemblyOS: {
    OSPlatformId:    4,        # a 4-byte constant
    OSMajorVersion:  4,        # a 4-byte constant
    OSMinorVersion:  4,        # a 4-byte constant
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.5-assemblyref-0x23.md
  AssemblyRef: {
    MajorVersion:     2,        # a 2-byte constant
    MinorVersion:     2,        # a 2-byte constant
    BuildNumber:      2,        # a 2-byte constant
    RevisionNumber:   2,        # a 2-byte constant
    Flags:            4,        # a 4-byte bitmask of AssemblyFlags
    PublicKeyOrToken: :blob,
    Name:             :string,
    Culture:          :string,
    HashValue:        :blob,
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.7-assemblyrefprocessor-0x24.md
  AssemblyRefProcessor: {
    Processor:       4,        # a 4-byte constant
    AssemblyRef:     :AssemblyRef,
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.6-assemblyrefos-0x25.md
  AssemblyRefOS: {
    OSPlatformId:    4,        # a 4-byte constant
    OSMajorVersion:  4,        # a 4-byte constant
    OSMinorVersion:  4,        # a 4-byte constant
    AssemblyRef:     :AssemblyRef,
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.19-file-0x26.md
  File: {
    Flags:           4,        # a 4-byte bitmask of FileAttributes
    Name:            :string,
    HashValue:       :blob,
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.24-manifestresource-0x28.md
  ManifestResource: {
    Offset:          4,        # a 4-byte constant
    Flags:           4,        # a 4-byte bitmask of ManifestResourceAttributes
    Name:            :string,
    Implementation:  Implementation,
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.32-nestedclass-0x29.md
  NestedClass: {
    NestedClass:     :TypeDef,
    EnclosingClass:  :TypeDef,
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.20-genericparam-0x2a.md
  GenericParam: {
    Number:          2,        # a 2-byte constant
    Flags:           2,        # a 2-byte bitmask of GenericParamAttributes
    Owner:           TypeOrMethodDef,
    Name:            :string,
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.29-methodspec-0x2b.md
  MethodSpec: {
    Method:          MethodDefOrRef,
    Instantiation:   :blob,
  },

  # https://github.com/stakx/ecma-335/blob/master/docs/ii.22.21-genericparamconstraint-0x2c.md
  GenericParamConstraint: {
    Owner:           :GenericParam,
    Constraint:      TypeDefOrRef,
  }
}

Class Method Summary collapse

Class Method Details

._create_dynamic_class(fields, hdr, name: nil) ⇒ Object



525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
# File 'lib/pedump/clr.rb', line 525

def self._create_dynamic_class fields, hdr, name: nil
  table_idx_bits = {}
  string_keys = []

  decl = fields.map do |k,v|
    case v
    when 2
      'S'
    when 4
      'V'
    when :blob
      hdr.HeapSizes & MetadataTableStreamHeader::HEAP_SIZES_MANY_BLOBS != 0 ? 'V' : 'S'
    when :guid
      hdr.HeapSizes & MetadataTableStreamHeader::HEAP_SIZES_MANY_GUIDS != 0 ? 'V' : 'S'
    when :string
      string_keys << k
      hdr.HeapSizes & MetadataTableStreamHeader::HEAP_SIZES_MANY_STRINGS != 0 ? 'V' : 'S'
    when Array
      # pointer to table i out of n possible tables
      n = v.size
      table_idx_bits[k] = bits_for_table_idx = Math.log2(n).ceil
      max_rows = 2**(16 - bits_for_table_idx)
      v.each{ |table_id| raise "Unknown table: #{table_id}" unless table_id == :not_used || hdr.known_table?(table_id) }
      v.any?{ |table_id| hdr.sizes_hash[table_id].to_i >= max_rows } ? 'V' : 'S'
    when Symbol
      raise "Unknown table: #{v}" unless hdr.known_table?(v)
      hdr.sizes_hash[v].to_i < 2**16 ? 'S' : 'V'
    else
      raise "Unknown field type #{v.inspect}"
    end
  end.join

  IOStruct.new(decl, *fields.keys, inspect_name_override: name).tap do |klass|
    klass.const_set(:STRING_KEYS, string_keys)
    klass.include(DynTableMethods)
    fields.each do |k,v|
      case v
      when Array
        # define 'decode_...' method
        idx_bits = table_idx_bits[k]
        table_id_mask = (1 << idx_bits) - 1
        klass.instance_eval do
          define_method("decode_#{k}") do
            val = self[k]
            table_id = val & table_id_mask
            table_key = v[table_id]
            val >>= idx_bits
            [table_key, val]
          end
        end
      end
    end
  end
end