github.com/saferwall/pe@v1.5.2/dotnet_helper.go (about)

     1  // Copyright 2018 Saferwall. All rights reserved.
     2  // Use of this source code is governed by Apache v2 license
     3  // license that can be found in the LICENSE file.
     4  
     5  package pe
     6  
     7  const (
     8  	// these are intentionally made so they do not collide with StringStream, GUIDStream, and BlobStream
     9  	// they are used only for the getCodedIndexSize function
    10  	idxStringStream = iota + 100
    11  	idxGUIDStream
    12  	idxBlobStream
    13  )
    14  
    15  type codedidx struct {
    16  	tagbits uint8
    17  	idx     []int
    18  }
    19  
    20  var (
    21  	idxTypeDefOrRef        = codedidx{tagbits: 2, idx: []int{TypeDef, TypeRef, TypeSpec}}
    22  	idxResolutionScope     = codedidx{tagbits: 2, idx: []int{Module, ModuleRef, AssemblyRef, TypeRef}}
    23  	idxMemberRefParent     = codedidx{tagbits: 3, idx: []int{TypeDef, TypeRef, ModuleRef, MethodDef, TypeSpec}}
    24  	idxHasConstant         = codedidx{tagbits: 2, idx: []int{Field, Param, Property}}
    25  	idxHasCustomAttributes = codedidx{tagbits: 5, idx: []int{Field, TypeRef, TypeDef, Param, InterfaceImpl, MemberRef, Module, Property, Event, StandAloneSig, ModuleRef, TypeSpec, Assembly, AssemblyRef, FileMD, ExportedType, ManifestResource}}
    26  	idxCustomAttributeType = codedidx{tagbits: 3, idx: []int{MethodDef, MemberRef}}
    27  	idxHasFieldMarshall    = codedidx{tagbits: 1, idx: []int{Field, Param}}
    28  	idxHasDeclSecurity     = codedidx{tagbits: 2, idx: []int{TypeDef, MethodDef, Assembly}}
    29  	idxHasSemantics        = codedidx{tagbits: 1, idx: []int{Event, Property}}
    30  	idxMethodDefOrRef      = codedidx{tagbits: 1, idx: []int{MethodDef, MemberRef}}
    31  	idxMemberForwarded     = codedidx{tagbits: 1, idx: []int{Field, MethodDef}}
    32  	idxImplementation      = codedidx{tagbits: 2, idx: []int{AssemblyRef, ExportedType}}
    33  	idxTypeOrMethodDef     = codedidx{tagbits: 1, idx: []int{TypeDef, MethodDef}}
    34  
    35  	idxField        = codedidx{tagbits: 0, idx: []int{Field}}
    36  	idxMethodDef    = codedidx{tagbits: 0, idx: []int{MethodDef}}
    37  	idxParam        = codedidx{tagbits: 0, idx: []int{Param}}
    38  	idxTypeDef      = codedidx{tagbits: 0, idx: []int{TypeDef}}
    39  	idxEvent        = codedidx{tagbits: 0, idx: []int{Event}}
    40  	idxProperty     = codedidx{tagbits: 0, idx: []int{Property}}
    41  	idxModuleRef    = codedidx{tagbits: 0, idx: []int{ModuleRef}}
    42  	idxGenericParam = codedidx{tagbits: 0, idx: []int{GenericParam}}
    43  
    44  	idxString = codedidx{tagbits: 0, idx: []int{idxStringStream}}
    45  	idxBlob   = codedidx{tagbits: 0, idx: []int{idxBlobStream}}
    46  	idxGUID   = codedidx{tagbits: 0, idx: []int{idxGUIDStream}}
    47  )
    48  
    49  func (pe *File) getCodedIndexSize(tagbits uint32, idx ...int) uint32 {
    50  	// special case String/GUID/Blob streams
    51  	switch idx[0] {
    52  	case int(idxStringStream):
    53  		return uint32(pe.GetMetadataStreamIndexSize(StringStream))
    54  	case int(idxGUIDStream):
    55  		return uint32(pe.GetMetadataStreamIndexSize(GUIDStream))
    56  	case int(idxBlobStream):
    57  		return uint32(pe.GetMetadataStreamIndexSize(BlobStream))
    58  	}
    59  
    60  	// now deal with coded indices or single table
    61  	var maxIndex16 uint32 = 1 << (16 - tagbits)
    62  	var maxColumnCount uint32
    63  	for _, tblidx := range idx {
    64  		tbl, ok := pe.CLR.MetadataTables[tblidx]
    65  		if ok {
    66  			if tbl.CountCols > maxColumnCount {
    67  				maxColumnCount = tbl.CountCols
    68  			}
    69  		}
    70  	}
    71  	if maxColumnCount > maxIndex16 {
    72  		return 4
    73  	}
    74  	return 2
    75  }
    76  
    77  func (pe *File) readFromMetadataStream(cidx codedidx, off uint32, out *uint32) (uint32, error) {
    78  	indexSize := pe.getCodedIndexSize(uint32(cidx.tagbits), cidx.idx...)
    79  	var data uint32
    80  	var err error
    81  	switch indexSize {
    82  	case 2:
    83  		d, err := pe.ReadUint16(off)
    84  		if err != nil {
    85  			return 0, err
    86  		}
    87  		data = uint32(d)
    88  	case 4:
    89  		data, err = pe.ReadUint32(off)
    90  		if err != nil {
    91  			return 0, err
    92  		}
    93  	}
    94  
    95  	*out = data
    96  	return uint32(indexSize), nil
    97  }