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 }