github.com/undoio/delve@v1.9.0/pkg/proc/types.go (about) 1 package proc 2 3 import ( 4 "bytes" 5 "debug/dwarf" 6 "errors" 7 "fmt" 8 "go/constant" 9 "reflect" 10 "strings" 11 12 "github.com/undoio/delve/pkg/dwarf/godwarf" 13 "github.com/undoio/delve/pkg/dwarf/reader" 14 "github.com/undoio/delve/pkg/goversion" 15 ) 16 17 // The kind field in runtime._type is a reflect.Kind value plus 18 // some extra flags defined here. 19 // See equivalent declaration in $GOROOT/src/reflect/type.go 20 const ( 21 kindDirectIface = 1 << 5 // +rtype kindDirectIface 22 kindGCProg = 1 << 6 // +rtype kindGCProg 23 kindNoPointers = 1 << 7 24 kindMask = (1 << 5) - 1 // +rtype kindMask 25 ) 26 27 // Value of tflag field in runtime._type. 28 // See $GOROOT/reflect/type.go for a description of these flags. 29 const ( 30 tflagUncommon = 1 << 0 31 tflagExtraStar = 1 << 1 32 tflagNamed = 1 << 2 33 ) 34 35 // These constants contain the names of the fields of runtime.interfacetype 36 // and runtime.imethod. 37 // runtime.interfacetype.mhdr is a slice of runtime.imethod describing the 38 // methods of the interface. 39 const ( 40 imethodFieldName = "name" 41 imethodFieldItyp = "ityp" 42 interfacetypeFieldMhdr = "mhdr" 43 ) 44 45 type runtimeTypeDIE struct { 46 offset dwarf.Offset 47 kind int64 48 } 49 50 func pointerTo(typ godwarf.Type, arch *Arch) godwarf.Type { 51 return &godwarf.PtrType{ 52 CommonType: godwarf.CommonType{ 53 ByteSize: int64(arch.PtrSize()), 54 Name: "*" + typ.Common().Name, 55 ReflectKind: reflect.Ptr, 56 Offset: 0, 57 }, 58 Type: typ, 59 } 60 } 61 62 type functionsDebugInfoByEntry []Function 63 64 func (v functionsDebugInfoByEntry) Len() int { return len(v) } 65 func (v functionsDebugInfoByEntry) Less(i, j int) bool { return v[i].Entry < v[j].Entry } 66 func (v functionsDebugInfoByEntry) Swap(i, j int) { v[i], v[j] = v[j], v[i] } 67 68 type compileUnitsByOffset []*compileUnit 69 70 func (v compileUnitsByOffset) Len() int { return len(v) } 71 func (v compileUnitsByOffset) Less(i int, j int) bool { return v[i].offset < v[j].offset } 72 func (v compileUnitsByOffset) Swap(i int, j int) { v[i], v[j] = v[j], v[i] } 73 74 type packageVarsByAddr []packageVar 75 76 func (v packageVarsByAddr) Len() int { return len(v) } 77 func (v packageVarsByAddr) Less(i int, j int) bool { return v[i].addr < v[j].addr } 78 func (v packageVarsByAddr) Swap(i int, j int) { v[i], v[j] = v[j], v[i] } 79 80 type loadDebugInfoMapsContext struct { 81 ardr *reader.Reader 82 abstractOriginTable map[dwarf.Offset]int 83 knownPackageVars map[string]struct{} 84 offsetToVersion map[dwarf.Offset]uint8 85 } 86 87 func newLoadDebugInfoMapsContext(bi *BinaryInfo, image *Image, offsetToVersion map[dwarf.Offset]uint8) *loadDebugInfoMapsContext { 88 ctxt := &loadDebugInfoMapsContext{} 89 90 ctxt.ardr = image.DwarfReader() 91 ctxt.abstractOriginTable = make(map[dwarf.Offset]int) 92 ctxt.offsetToVersion = offsetToVersion 93 94 ctxt.knownPackageVars = map[string]struct{}{} 95 for _, v := range bi.packageVars { 96 ctxt.knownPackageVars[v.name] = struct{}{} 97 } 98 99 return ctxt 100 } 101 102 func (ctxt *loadDebugInfoMapsContext) lookupAbstractOrigin(bi *BinaryInfo, off dwarf.Offset) int { 103 r, ok := ctxt.abstractOriginTable[off] 104 if !ok { 105 bi.Functions = append(bi.Functions, Function{}) 106 r = len(bi.Functions) - 1 107 bi.Functions[r].offset = off 108 ctxt.abstractOriginTable[off] = r 109 } 110 return r 111 } 112 113 // runtimeTypeToDIE returns the DIE corresponding to the runtime._type. 114 // This is done in three different ways depending on the version of go. 115 // - Before go1.7 the type name is retrieved directly from the runtime._type 116 // and looked up in debug_info 117 // - After go1.7 the runtime._type struct is read recursively to reconstruct 118 // the name of the type, and then the type's name is used to look up 119 // debug_info 120 // - After go1.11 the runtimeTypeToDIE map is used to look up the address of 121 // the type and map it drectly to a DIE. 122 func runtimeTypeToDIE(_type *Variable, dataAddr uint64) (typ godwarf.Type, kind int64, err error) { 123 bi := _type.bi 124 125 _type = _type.maybeDereference() 126 127 // go 1.11 implementation: use extended attribute in debug_info 128 129 mds, err := loadModuleData(bi, _type.mem) 130 if err != nil { 131 return nil, 0, fmt.Errorf("error loading module data: %v", err) 132 } 133 134 md := findModuleDataForType(bi, mds, _type.Addr, _type.mem) 135 if md != nil { 136 so := bi.moduleDataToImage(md) 137 if so != nil { 138 if rtdie, ok := so.runtimeTypeToDIE[uint64(_type.Addr-md.types)]; ok { 139 typ, err := godwarf.ReadType(so.dwarf, so.index, rtdie.offset, so.typeCache) 140 if err != nil { 141 return nil, 0, fmt.Errorf("invalid interface type: %v", err) 142 } 143 if rtdie.kind == -1 { 144 if kindField := _type.loadFieldNamed("kind"); kindField != nil && kindField.Value != nil { 145 rtdie.kind, _ = constant.Int64Val(kindField.Value) 146 } 147 } 148 return typ, rtdie.kind, nil 149 } 150 } 151 } 152 153 // go1.7 to go1.10 implementation: convert runtime._type structs to type names 154 155 if goversion.ProducerAfterOrEqual(_type.bi.Producer(), 1, 17) { 156 // Go 1.17 changed the encoding of names in runtime._type breaking the 157 // code below, but the codepath above, using runtimeTypeToDIE should be 158 // enough. 159 // The change happened in commit 287025925f66f90ad9b30aea2e533928026a8376 160 // reviewed in https://go-review.googlesource.com/c/go/+/318249 161 return nil, 0, fmt.Errorf("could not resolve interface type") 162 } 163 164 typename, kind, err := nameOfRuntimeType(mds, _type) 165 if err != nil { 166 return nil, 0, fmt.Errorf("invalid interface type: %v", err) 167 } 168 169 typ, err = bi.findType(typename) 170 if err != nil { 171 return nil, 0, fmt.Errorf("interface type %q not found for %#x: %v", typename, dataAddr, err) 172 } 173 174 return typ, kind, nil 175 } 176 177 // resolveParametricType returns the real type of t if t is a parametric 178 // type, by reading the correct dictionary entry. 179 func resolveParametricType(tgt *Target, bi *BinaryInfo, mem MemoryReadWriter, t godwarf.Type, dictAddr uint64) (godwarf.Type, error) { 180 ptyp, _ := t.(*godwarf.ParametricType) 181 if ptyp == nil { 182 return t, nil 183 } 184 if dictAddr == 0 { 185 return ptyp.TypedefType.Type, errors.New("parametric type without a dictionary") 186 } 187 rtypeAddr, err := readUintRaw(mem, dictAddr+uint64(ptyp.DictIndex*int64(bi.Arch.PtrSize())), int64(bi.Arch.PtrSize())) 188 if err != nil { 189 return ptyp.TypedefType.Type, err 190 } 191 runtimeType, err := bi.findType("runtime._type") 192 if err != nil { 193 return ptyp.TypedefType.Type, err 194 } 195 _type := newVariable("", rtypeAddr, runtimeType, bi, mem) 196 197 typ, _, err := runtimeTypeToDIE(_type, 0) 198 if err != nil { 199 return ptyp.TypedefType.Type, err 200 } 201 202 return typ, nil 203 } 204 205 type nameOfRuntimeTypeEntry struct { 206 typename string 207 kind int64 208 } 209 210 // Returns the type name of the type described in _type. 211 // _type is a non-loaded Variable pointing to runtime._type struct in the target. 212 // The returned string is in the format that's used in DWARF data 213 func nameOfRuntimeType(mds []moduleData, _type *Variable) (typename string, kind int64, err error) { 214 if e, ok := _type.bi.nameOfRuntimeType[_type.Addr]; ok { 215 return e.typename, e.kind, nil 216 } 217 218 var tflag int64 219 220 if tflagField := _type.loadFieldNamed("tflag"); tflagField != nil && tflagField.Value != nil { 221 tflag, _ = constant.Int64Val(tflagField.Value) 222 } 223 if kindField := _type.loadFieldNamed("kind"); kindField != nil && kindField.Value != nil { 224 kind, _ = constant.Int64Val(kindField.Value) 225 } 226 227 // Named types are defined by a 'type' expression, everything else 228 // (for example pointers to named types) are not considered named. 229 if tflag&tflagNamed != 0 { 230 typename, err = nameOfNamedRuntimeType(mds, _type, kind, tflag) 231 if err == nil { 232 _type.bi.nameOfRuntimeType[_type.Addr] = nameOfRuntimeTypeEntry{typename: typename, kind: kind} 233 } 234 return typename, kind, err 235 } 236 237 typename, err = nameOfUnnamedRuntimeType(mds, _type, kind, tflag) 238 if err == nil { 239 _type.bi.nameOfRuntimeType[_type.Addr] = nameOfRuntimeTypeEntry{typename: typename, kind: kind} 240 } 241 return typename, kind, err 242 } 243 244 // The layout of a runtime._type struct is as follows: 245 // 246 // <runtime._type><kind specific struct fields><runtime.uncommontype> 247 // 248 // with the 'uncommon type struct' being optional 249 // 250 // For named types first we extract the type name from the 'str' 251 // field in the runtime._type struct. 252 // Then we prepend the package path from the runtime.uncommontype 253 // struct, when it exists. 254 // 255 // To find out the memory address of the runtime.uncommontype struct 256 // we first cast the Variable pointing to the runtime._type struct 257 // to a struct specific to the type's kind (for example, if the type 258 // being described is a slice type the variable will be specialized 259 // to a runtime.slicetype). 260 func nameOfNamedRuntimeType(mds []moduleData, _type *Variable, kind, tflag int64) (typename string, err error) { 261 var strOff int64 262 if strField := _type.loadFieldNamed("str"); strField != nil && strField.Value != nil { 263 strOff, _ = constant.Int64Val(strField.Value) 264 } else { 265 return "", errors.New("could not find str field") 266 } 267 268 // The following code is adapted from reflect.(*rtype).Name. 269 // For a description of how memory is organized for type names read 270 // the comment to 'type name struct' in $GOROOT/src/reflect/type.go 271 272 typename, _, _, err = resolveNameOff(_type.bi, mds, _type.Addr, uint64(strOff), _type.mem) 273 if err != nil { 274 return "", err 275 } 276 277 if tflag&tflagExtraStar != 0 { 278 typename = typename[1:] 279 } 280 281 if i := strings.Index(typename, "."); i >= 0 { 282 typename = typename[i+1:] 283 } else { 284 return typename, nil 285 } 286 287 // The following code is adapted from reflect.(*rtype).PkgPath in 288 // $GOROOT/src/reflect/type.go 289 290 _type, err = specificRuntimeType(_type, kind) 291 if err != nil { 292 return "", err 293 } 294 295 if ut := uncommon(_type, tflag); ut != nil { 296 if pkgPathField := ut.loadFieldNamed("pkgpath"); pkgPathField != nil && pkgPathField.Value != nil { 297 pkgPathOff, _ := constant.Int64Val(pkgPathField.Value) 298 pkgPath, _, _, err := resolveNameOff(_type.bi, mds, _type.Addr, uint64(pkgPathOff), _type.mem) 299 if err != nil { 300 return "", err 301 } 302 if slash := strings.LastIndex(pkgPath, "/"); slash >= 0 { 303 fixedName := strings.Replace(pkgPath[slash+1:], ".", "%2e", -1) 304 if fixedName != pkgPath[slash+1:] { 305 pkgPath = pkgPath[:slash+1] + fixedName 306 } 307 } 308 typename = pkgPath + "." + typename 309 } 310 } 311 312 return typename, nil 313 } 314 315 func nameOfUnnamedRuntimeType(mds []moduleData, _type *Variable, kind, tflag int64) (string, error) { 316 _type, err := specificRuntimeType(_type, kind) 317 if err != nil { 318 return "", err 319 } 320 321 // The types referred to here are defined in $GOROOT/src/runtime/type.go 322 switch reflect.Kind(kind & kindMask) { 323 case reflect.Array: 324 var len int64 325 if lenField := _type.loadFieldNamed("len"); lenField != nil && lenField.Value != nil { 326 len, _ = constant.Int64Val(lenField.Value) 327 } 328 elemname, err := fieldToType(mds, _type, "elem") 329 if err != nil { 330 return "", err 331 } 332 return fmt.Sprintf("[%d]%s", len, elemname), nil 333 case reflect.Chan: 334 elemname, err := fieldToType(mds, _type, "elem") 335 if err != nil { 336 return "", err 337 } 338 return "chan " + elemname, nil 339 case reflect.Func: 340 return nameOfFuncRuntimeType(mds, _type, tflag, true) 341 case reflect.Interface: 342 return nameOfInterfaceRuntimeType(mds, _type, kind, tflag) 343 case reflect.Map: 344 keyname, err := fieldToType(mds, _type, "key") 345 if err != nil { 346 return "", err 347 } 348 elemname, err := fieldToType(mds, _type, "elem") 349 if err != nil { 350 return "", err 351 } 352 return "map[" + keyname + "]" + elemname, nil 353 case reflect.Ptr: 354 elemname, err := fieldToType(mds, _type, "elem") 355 if err != nil { 356 return "", err 357 } 358 return "*" + elemname, nil 359 case reflect.Slice: 360 elemname, err := fieldToType(mds, _type, "elem") 361 if err != nil { 362 return "", err 363 } 364 return "[]" + elemname, nil 365 case reflect.Struct: 366 return nameOfStructRuntimeType(mds, _type, kind, tflag) 367 default: 368 return nameOfNamedRuntimeType(mds, _type, kind, tflag) 369 } 370 } 371 372 // Returns the expression describing an anonymous function type. 373 // A runtime.functype is followed by a runtime.uncommontype 374 // (optional) and then by an array of pointers to runtime._type, 375 // one for each input and output argument. 376 func nameOfFuncRuntimeType(mds []moduleData, _type *Variable, tflag int64, anonymous bool) (string, error) { 377 rtyp, err := _type.bi.findType("runtime._type") 378 if err != nil { 379 return "", err 380 } 381 prtyp := pointerTo(rtyp, _type.bi.Arch) 382 383 uadd := _type.RealType.Common().ByteSize 384 if ut := uncommon(_type, tflag); ut != nil { 385 uadd += ut.RealType.Common().ByteSize 386 } 387 388 var inCount, outCount int64 389 if inCountField := _type.loadFieldNamed("inCount"); inCountField != nil && inCountField.Value != nil { 390 inCount, _ = constant.Int64Val(inCountField.Value) 391 } 392 if outCountField := _type.loadFieldNamed("outCount"); outCountField != nil && outCountField.Value != nil { 393 outCount, _ = constant.Int64Val(outCountField.Value) 394 // only the lowest 15 bits of outCount are used, rest are flags 395 outCount = outCount & (1<<15 - 1) 396 } 397 398 cursortyp := _type.newVariable("", _type.Addr+uint64(uadd), prtyp, _type.mem) 399 var buf bytes.Buffer 400 if anonymous { 401 buf.WriteString("func(") 402 } else { 403 buf.WriteString("(") 404 } 405 406 for i := int64(0); i < inCount; i++ { 407 argtype := cursortyp.maybeDereference() 408 cursortyp.Addr += uint64(_type.bi.Arch.PtrSize()) 409 argtypename, _, err := nameOfRuntimeType(mds, argtype) 410 if err != nil { 411 return "", err 412 } 413 buf.WriteString(argtypename) 414 if i != inCount-1 { 415 buf.WriteString(", ") 416 } 417 } 418 buf.WriteString(")") 419 420 switch outCount { 421 case 0: 422 // nothing to do 423 case 1: 424 buf.WriteString(" ") 425 argtype := cursortyp.maybeDereference() 426 argtypename, _, err := nameOfRuntimeType(mds, argtype) 427 if err != nil { 428 return "", err 429 } 430 buf.WriteString(argtypename) 431 default: 432 buf.WriteString(" (") 433 for i := int64(0); i < outCount; i++ { 434 argtype := cursortyp.maybeDereference() 435 cursortyp.Addr += uint64(_type.bi.Arch.PtrSize()) 436 argtypename, _, err := nameOfRuntimeType(mds, argtype) 437 if err != nil { 438 return "", err 439 } 440 buf.WriteString(argtypename) 441 if i != inCount-1 { 442 buf.WriteString(", ") 443 } 444 } 445 buf.WriteString(")") 446 } 447 return buf.String(), nil 448 } 449 450 func nameOfInterfaceRuntimeType(mds []moduleData, _type *Variable, kind, tflag int64) (string, error) { 451 var buf bytes.Buffer 452 buf.WriteString("interface {") 453 454 methods, _ := _type.structMember(interfacetypeFieldMhdr) 455 methods.loadArrayValues(0, LoadConfig{false, 1, 0, 4096, -1, 0}) 456 if methods.Unreadable != nil { 457 return "", nil 458 } 459 460 if len(methods.Children) == 0 { 461 buf.WriteString("}") 462 return buf.String(), nil 463 } 464 buf.WriteString(" ") 465 466 for i, im := range methods.Children { 467 var methodname, methodtype string 468 for i := range im.Children { 469 switch im.Children[i].Name { 470 case imethodFieldName: 471 nameoff, _ := constant.Int64Val(im.Children[i].Value) 472 var err error 473 methodname, _, _, err = resolveNameOff(_type.bi, mds, _type.Addr, uint64(nameoff), _type.mem) 474 if err != nil { 475 return "", err 476 } 477 478 case imethodFieldItyp: 479 typeoff, _ := constant.Int64Val(im.Children[i].Value) 480 typ, err := resolveTypeOff(_type.bi, mds, _type.Addr, uint64(typeoff), _type.mem) 481 if err != nil { 482 return "", err 483 } 484 typ, err = specificRuntimeType(typ, int64(reflect.Func)) 485 if err != nil { 486 return "", err 487 } 488 var tflag int64 489 if tflagField := typ.loadFieldNamed("tflag"); tflagField != nil && tflagField.Value != nil { 490 tflag, _ = constant.Int64Val(tflagField.Value) 491 } 492 methodtype, err = nameOfFuncRuntimeType(mds, typ, tflag, false) 493 if err != nil { 494 return "", err 495 } 496 } 497 } 498 499 buf.WriteString(methodname) 500 buf.WriteString(methodtype) 501 502 if i != len(methods.Children)-1 { 503 buf.WriteString("; ") 504 } else { 505 buf.WriteString(" }") 506 } 507 } 508 return buf.String(), nil 509 } 510 511 func nameOfStructRuntimeType(mds []moduleData, _type *Variable, kind, tflag int64) (string, error) { 512 var buf bytes.Buffer 513 buf.WriteString("struct {") 514 515 fields, _ := _type.structMember("fields") 516 fields.loadArrayValues(0, LoadConfig{false, 2, 0, 4096, -1, 0}) 517 if fields.Unreadable != nil { 518 return "", fields.Unreadable 519 } 520 521 if len(fields.Children) == 0 { 522 buf.WriteString("}") 523 return buf.String(), nil 524 } 525 buf.WriteString(" ") 526 527 for i, field := range fields.Children { 528 var fieldname, fieldtypename string 529 var typeField *Variable 530 isembed := false 531 for i := range field.Children { 532 switch field.Children[i].Name { 533 case "name": 534 var nameoff int64 535 switch field.Children[i].Kind { 536 case reflect.Struct: 537 nameoff = int64(field.Children[i].fieldVariable("bytes").Children[0].Addr) 538 default: 539 nameoff, _ = constant.Int64Val(field.Children[i].Value) 540 } 541 542 var err error 543 fieldname, _, _, err = loadName(_type.bi, uint64(nameoff), _type.mem) 544 if err != nil { 545 return "", err 546 } 547 548 case "typ": 549 typeField = field.Children[i].maybeDereference() 550 var err error 551 fieldtypename, _, err = nameOfRuntimeType(mds, typeField) 552 if err != nil { 553 return "", err 554 } 555 556 case "offsetAnon": 557 // The offsetAnon field of runtime.structfield combines the offset of 558 // the struct field from the base address of the struct with a flag 559 // determining whether the field is anonymous (i.e. an embedded struct). 560 // 561 // offsetAnon = (offset<<1) | (anonFlag) 562 // 563 // Here we are only interested in the anonymous flag. 564 offsetAnon, _ := constant.Int64Val(field.Children[i].Value) 565 isembed = offsetAnon%2 != 0 566 } 567 } 568 569 // fieldname will be the empty string for anonymous fields 570 if fieldname != "" && !isembed { 571 buf.WriteString(fieldname) 572 buf.WriteString(" ") 573 } 574 buf.WriteString(fieldtypename) 575 if i != len(fields.Children)-1 { 576 buf.WriteString("; ") 577 } else { 578 buf.WriteString(" }") 579 } 580 } 581 582 return buf.String(), nil 583 } 584 585 func fieldToType(mds []moduleData, _type *Variable, fieldName string) (string, error) { 586 typeField, err := _type.structMember(fieldName) 587 if err != nil { 588 return "", err 589 } 590 typeField = typeField.maybeDereference() 591 typename, _, err := nameOfRuntimeType(mds, typeField) 592 return typename, err 593 } 594 595 func specificRuntimeType(_type *Variable, kind int64) (*Variable, error) { 596 typ, err := typeForKind(kind, _type.bi) 597 if err != nil { 598 return nil, err 599 } 600 if typ == nil { 601 return _type, nil 602 } 603 604 return _type.newVariable(_type.Name, _type.Addr, typ, _type.mem), nil 605 } 606 607 // See reflect.(*rtype).uncommon in $GOROOT/src/reflect/type.go 608 func uncommon(_type *Variable, tflag int64) *Variable { 609 if tflag&tflagUncommon == 0 { 610 return nil 611 } 612 613 typ, err := _type.bi.findType("runtime.uncommontype") 614 if err != nil { 615 return nil 616 } 617 618 return _type.newVariable(_type.Name, _type.Addr+uint64(_type.RealType.Size()), typ, _type.mem) 619 } 620 621 var kindToRuntimeTypeName = map[reflect.Kind]string{ 622 reflect.Array: "runtime.arraytype", 623 reflect.Chan: "runtime.chantype", 624 reflect.Func: "runtime.functype", 625 reflect.Interface: "runtime.interfacetype", 626 reflect.Map: "runtime.maptype", 627 reflect.Ptr: "runtime.ptrtype", 628 reflect.Slice: "runtime.slicetype", 629 reflect.Struct: "runtime.structtype", 630 } 631 632 // typeForKind returns a *dwarf.StructType describing the specialization of 633 // runtime._type for the specified type kind. For example if kind is 634 // reflect.ArrayType it will return runtime.arraytype 635 func typeForKind(kind int64, bi *BinaryInfo) (*godwarf.StructType, error) { 636 typename, ok := kindToRuntimeTypeName[reflect.Kind(kind&kindMask)] 637 if !ok { 638 return nil, nil 639 } 640 typ, err := bi.findType(typename) 641 if err != nil { 642 return nil, err 643 } 644 typ = resolveTypedef(typ) 645 return typ.(*godwarf.StructType), nil 646 } 647 648 func dwarfToRuntimeType(bi *BinaryInfo, mem MemoryReadWriter, typ godwarf.Type) (typeAddr uint64, typeKind uint64, found bool, err error) { 649 so := bi.typeToImage(typ) 650 rdr := so.DwarfReader() 651 rdr.Seek(typ.Common().Offset) 652 e, err := rdr.Next() 653 if err != nil { 654 return 0, 0, false, err 655 } 656 off, ok := e.Val(godwarf.AttrGoRuntimeType).(uint64) 657 if !ok { 658 return 0, 0, false, nil 659 } 660 661 mds, err := loadModuleData(bi, mem) 662 if err != nil { 663 return 0, 0, false, err 664 } 665 666 md := bi.imageToModuleData(so, mds) 667 if md == nil { 668 if so.index > 0 { 669 return 0, 0, false, fmt.Errorf("could not find module data for type %s (shared object: %q)", typ, so.Path) 670 } else { 671 return 0, 0, false, fmt.Errorf("could not find module data for type %s", typ) 672 } 673 } 674 675 typeAddr = uint64(md.types) + off 676 677 rtyp, err := bi.findType("runtime._type") 678 if err != nil { 679 return 0, 0, false, err 680 } 681 _type := newVariable("", typeAddr, rtyp, bi, mem) 682 kindv := _type.loadFieldNamed("kind") 683 if kindv.Unreadable != nil || kindv.Kind != reflect.Uint { 684 return 0, 0, false, fmt.Errorf("unreadable interface type: %v", kindv.Unreadable) 685 } 686 typeKind, _ = constant.Uint64Val(kindv.Value) 687 return typeAddr, typeKind, true, nil 688 }