gitlab.com/Raven-IO/raven-delve@v1.22.4/pkg/proc/types.go (about) 1 package proc 2 3 import ( 4 "debug/dwarf" 5 "errors" 6 "fmt" 7 "go/constant" 8 "reflect" 9 10 "gitlab.com/Raven-IO/raven-delve/pkg/dwarf/godwarf" 11 "gitlab.com/Raven-IO/raven-delve/pkg/dwarf/reader" 12 ) 13 14 // The kind field in runtime._type is a reflect.Kind value plus 15 // some extra flags defined here. 16 // See equivalent declaration in $GOROOT/src/reflect/type.go 17 const ( 18 kindDirectIface = 1 << 5 // +rtype kindDirectIface|internal/abi.KindDirectIface 19 kindGCProg = 1 << 6 // +rtype kindGCProg|internal/abi.KindGCProg 20 kindNoPointers = 1 << 7 21 kindMask = (1 << 5) - 1 // +rtype kindMask|internal/abi.KindMask 22 ) 23 24 type runtimeTypeDIE struct { 25 offset dwarf.Offset 26 kind int64 27 } 28 29 func pointerTo(typ godwarf.Type, arch *Arch) godwarf.Type { 30 return &godwarf.PtrType{ 31 CommonType: godwarf.CommonType{ 32 ByteSize: int64(arch.PtrSize()), 33 Name: "*" + typ.Common().Name, 34 ReflectKind: reflect.Ptr, 35 Offset: 0, 36 }, 37 Type: typ, 38 } 39 } 40 41 type functionsDebugInfoByEntry []Function 42 43 func (v functionsDebugInfoByEntry) Len() int { return len(v) } 44 func (v functionsDebugInfoByEntry) Less(i, j int) bool { return v[i].Entry < v[j].Entry } 45 func (v functionsDebugInfoByEntry) Swap(i, j int) { v[i], v[j] = v[j], v[i] } 46 47 type compileUnitsByOffset []*compileUnit 48 49 func (v compileUnitsByOffset) Len() int { return len(v) } 50 func (v compileUnitsByOffset) Less(i int, j int) bool { return v[i].offset < v[j].offset } 51 func (v compileUnitsByOffset) Swap(i int, j int) { v[i], v[j] = v[j], v[i] } 52 53 type packageVarsByAddr []packageVar 54 55 func (v packageVarsByAddr) Len() int { return len(v) } 56 func (v packageVarsByAddr) Less(i int, j int) bool { return v[i].addr < v[j].addr } 57 func (v packageVarsByAddr) Swap(i int, j int) { v[i], v[j] = v[j], v[i] } 58 59 type loadDebugInfoMapsContext struct { 60 ardr *reader.Reader 61 abstractOriginTable map[dwarf.Offset]int 62 knownPackageVars map[string]struct{} 63 offsetToVersion map[dwarf.Offset]uint8 64 } 65 66 func newLoadDebugInfoMapsContext(bi *BinaryInfo, image *Image, offsetToVersion map[dwarf.Offset]uint8) *loadDebugInfoMapsContext { 67 ctxt := &loadDebugInfoMapsContext{} 68 69 ctxt.ardr = image.DwarfReader() 70 ctxt.abstractOriginTable = make(map[dwarf.Offset]int) 71 ctxt.offsetToVersion = offsetToVersion 72 73 ctxt.knownPackageVars = map[string]struct{}{} 74 for _, v := range bi.packageVars { 75 ctxt.knownPackageVars[v.name] = struct{}{} 76 } 77 78 return ctxt 79 } 80 81 func (ctxt *loadDebugInfoMapsContext) lookupAbstractOrigin(bi *BinaryInfo, off dwarf.Offset) int { 82 r, ok := ctxt.abstractOriginTable[off] 83 if !ok { 84 bi.Functions = append(bi.Functions, Function{}) 85 r = len(bi.Functions) - 1 86 bi.Functions[r].offset = off 87 ctxt.abstractOriginTable[off] = r 88 } 89 return r 90 } 91 92 // runtimeTypeToDIE returns the DIE corresponding to the runtime._type. 93 // This is done in three different ways depending on the version of go. 94 // - Before go1.7 the type name is retrieved directly from the runtime._type 95 // and looked up in debug_info 96 // - After go1.7 the runtime._type struct is read recursively to reconstruct 97 // the name of the type, and then the type's name is used to look up 98 // debug_info 99 // - After go1.11 the runtimeTypeToDIE map is used to look up the address of 100 // the type and map it directly to a DIE. 101 func runtimeTypeToDIE(_type *Variable, dataAddr uint64) (typ godwarf.Type, kind int64, err error) { 102 bi := _type.bi 103 104 _type = _type.maybeDereference() 105 106 // go 1.11 implementation: use extended attribute in debug_info 107 108 mds, err := loadModuleData(bi, _type.mem) 109 if err != nil { 110 return nil, 0, fmt.Errorf("error loading module data: %v", err) 111 } 112 113 md := findModuleDataForType(bi, mds, _type.Addr, _type.mem) 114 if md != nil { 115 so := bi.moduleDataToImage(md) 116 if so != nil { 117 if rtdie, ok := so.runtimeTypeToDIE[_type.Addr-md.types]; ok { 118 typ, err := godwarf.ReadType(so.dwarf, so.index, rtdie.offset, so.typeCache) 119 if err != nil { 120 return nil, 0, fmt.Errorf("invalid interface type: %v", err) 121 } 122 if rtdie.kind == -1 { 123 if kindField := _type.loadFieldNamed("kind"); kindField != nil && kindField.Value != nil { 124 rtdie.kind, _ = constant.Int64Val(kindField.Value) 125 } else if kindField := _type.loadFieldNamed("Kind_"); kindField != nil && kindField.Value != nil { 126 rtdie.kind, _ = constant.Int64Val(kindField.Value) 127 } 128 } 129 return typ, rtdie.kind, nil 130 } 131 } 132 } 133 134 return nil, 0, fmt.Errorf("could not resolve interface type") 135 } 136 137 // resolveParametricType returns the real type of t if t is a parametric 138 // type, by reading the correct dictionary entry. 139 func resolveParametricType(bi *BinaryInfo, mem MemoryReadWriter, t godwarf.Type, dictAddr uint64) (godwarf.Type, error) { 140 ptyp, _ := t.(*godwarf.ParametricType) 141 if ptyp == nil { 142 return t, nil 143 } 144 if dictAddr == 0 { 145 return ptyp.TypedefType.Type, errors.New("parametric type without a dictionary") 146 } 147 rtypeAddr, err := readUintRaw(mem, dictAddr+uint64(ptyp.DictIndex*int64(bi.Arch.PtrSize())), int64(bi.Arch.PtrSize())) 148 if err != nil { 149 return ptyp.TypedefType.Type, err 150 } 151 runtimeType, err := bi.findType(bi.runtimeTypeTypename()) 152 if err != nil { 153 return ptyp.TypedefType.Type, err 154 } 155 _type := newVariable("", rtypeAddr, runtimeType, bi, mem) 156 157 typ, _, err := runtimeTypeToDIE(_type, 0) 158 if err != nil { 159 return ptyp.TypedefType.Type, err 160 } 161 162 return typ, nil 163 } 164 165 func dwarfToRuntimeType(bi *BinaryInfo, mem MemoryReadWriter, typ godwarf.Type) (typeAddr uint64, typeKind uint64, found bool, err error) { 166 so := bi.typeToImage(typ) 167 rdr := so.DwarfReader() 168 rdr.Seek(typ.Common().Offset) 169 e, err := rdr.Next() 170 if err != nil { 171 return 0, 0, false, err 172 } 173 off, ok := e.Val(godwarf.AttrGoRuntimeType).(uint64) 174 if !ok { 175 return 0, 0, false, nil 176 } 177 178 mds, err := loadModuleData(bi, mem) 179 if err != nil { 180 return 0, 0, false, err 181 } 182 183 md := bi.imageToModuleData(so, mds) 184 if md == nil { 185 if so.index > 0 { 186 return 0, 0, false, fmt.Errorf("could not find module data for type %s (shared object: %q)", typ, so.Path) 187 } else { 188 return 0, 0, false, fmt.Errorf("could not find module data for type %s", typ) 189 } 190 } 191 192 typeAddr = md.types + off 193 194 rtyp, err := bi.findType(bi.runtimeTypeTypename()) 195 if err != nil { 196 return 0, 0, false, err 197 } 198 _type := newVariable("", typeAddr, rtyp, bi, mem) 199 kindv := _type.loadFieldNamed("kind") 200 if kindv == nil || kindv.Unreadable != nil || kindv.Kind != reflect.Uint { 201 kindv = _type.loadFieldNamed("Kind_") 202 } 203 if kindv == nil || kindv.Unreadable != nil || kindv.Kind != reflect.Uint { 204 return 0, 0, false, fmt.Errorf("unreadable interface type: %v", kindv.Unreadable) 205 } 206 typeKind, _ = constant.Uint64Val(kindv.Value) 207 return typeAddr, typeKind, true, nil 208 }