github.com/lsg2020/gort@v0.0.0-20220515072951-7a7794baa036/gort_types.go (about) 1 package gort 2 3 import ( 4 "debug/dwarf" 5 "fmt" 6 "reflect" 7 "unsafe" 8 9 "github.com/go-delve/delve/pkg/dwarf/godwarf" 10 "github.com/go-delve/delve/pkg/proc" 11 ) 12 13 func (d *DwarfRT) ForeachType(f func(name string)) error { 14 if err := d.check(); err != nil { 15 return err 16 } 17 18 types, err := d.bi.Types() 19 if err != nil { 20 return err 21 } 22 for _, name := range types { 23 f(name) 24 } 25 return nil 26 } 27 28 func (d *DwarfRT) FindType(name string) (reflect.Type, error) { 29 if err := d.check(); err != nil { 30 return nil, err 31 } 32 33 dwarfType, err := findType(d.bi, name) 34 if err != nil { 35 return nil, err 36 } 37 38 typeAddr, err := d.dwarfToRuntimeType(dwarfType, name) 39 if err != nil { 40 return nil, err 41 } 42 43 typ := reflect.TypeOf(*(*interface{})(unsafe.Pointer(&typeAddr))) 44 return typ, nil 45 } 46 47 func (d *DwarfRT) findImageType(img *proc.Image, name string) uint64 { 48 if d.imageCacheTypes == nil { 49 d.imageCacheTypes = make(map[*proc.Image]map[string]uint64) 50 } 51 cache, ok := d.imageCacheTypes[img] 52 if !ok { 53 cache = make(map[string]uint64) 54 d.imageCacheTypes[img] = cache 55 56 reader := img.DwarfReader() 57 md := imageToModuleData(d.bi, img, d.mds) 58 if md == nil { 59 return 0 60 } 61 62 rRuntimeTypes := reflect.ValueOf(img).Elem().FieldByName("runtimeTypeToDIE") 63 iter := rRuntimeTypes.MapRange() 64 for iter.Next() { 65 k := iter.Key() 66 v := iter.Value() 67 68 offset := v.FieldByName("offset").Uint() 69 reader.Seek(dwarf.Offset(offset)) 70 entry, err := reader.Next() 71 if err != nil || entry == nil { 72 continue 73 } 74 entryName, ok := entry.Val(dwarf.AttrName).(string) 75 if !ok { 76 continue 77 } 78 if k.Uint() == 0 { 79 continue 80 } 81 82 typeAddr := md.types + k.Uint() 83 if typeAddr < md.types || typeAddr >= md.etypes { 84 cache[entryName] = k.Uint() 85 } else { 86 cache[entryName] = typeAddr 87 } 88 } 89 } 90 91 return cache[name] 92 } 93 94 func (d *DwarfRT) dwarfToRuntimeType(typ godwarf.Type, name string) (typeAddr uint64, err error) { 95 bi := d.bi 96 mds := d.mds 97 98 if typ.Common().Index >= len(bi.Images) { 99 return 0, fmt.Errorf("could not find image for type %s", name) 100 } 101 img := bi.Images[typ.Common().Index] 102 rdr := img.DwarfReader() 103 rdr.Seek(typ.Common().Offset) 104 e, err := rdr.Next() 105 if err != nil { 106 return 0, fmt.Errorf("could not find dwarf entry for type:%s err:%s", name, err) 107 } 108 entryName, ok := e.Val(dwarf.AttrName).(string) 109 if !ok || entryName != name { 110 return 0, fmt.Errorf("could not find name for type:%s entry:%s", name, entryName) 111 } 112 off, ok := e.Val(godwarf.AttrGoRuntimeType).(uint64) 113 if !ok || off == 0 { 114 for i, img := range bi.Images { 115 if i == 0 { 116 continue 117 } 118 addr := d.findImageType(img, name) 119 if addr != 0 { 120 return addr, nil 121 } 122 } 123 return 0, fmt.Errorf("could not find runtime type for type:%s", name) 124 } 125 126 md := imageToModuleData(bi, img, mds) 127 if md == nil { 128 return 0, fmt.Errorf("could not find module data for type %s", name) 129 } 130 131 typeAddr = md.types + off 132 if typeAddr < md.types || typeAddr >= md.etypes { 133 return off, nil 134 } 135 return typeAddr, nil 136 }