github.com/lsg2020/gort@v0.0.0-20220515072951-7a7794baa036/gort_functions.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/proc" 10 ) 11 12 func (d *DwarfRT) ForeachFunc(f func(name string, pc uint64)) error { 13 if err := d.check(); err != nil { 14 return err 15 } 16 17 for _, function := range d.bi.Functions { 18 if function.Entry != 0 { 19 f(function.Name, function.Entry) 20 } 21 } 22 return nil 23 } 24 25 func (d *DwarfRT) FindFuncEntry(name string) (*proc.Function, error) { 26 if err := d.check(); err != nil { 27 return nil, err 28 } 29 30 f, err := d.findFunc(name) 31 if err != nil { 32 return nil, err 33 } 34 return f, nil 35 } 36 37 func (d *DwarfRT) FindFuncPc(name string) (uint64, error) { 38 if err := d.check(); err != nil { 39 return 0, err 40 } 41 42 f, err := d.findFunc(name) 43 if err != nil { 44 return 0, err 45 } 46 return f.Entry, nil 47 } 48 49 func (d *DwarfRT) FindFuncType(name string, variadic bool) (reflect.Type, error) { 50 if err := d.check(); err != nil { 51 return nil, err 52 } 53 54 f, err := d.findFunc(name) 55 if err != nil { 56 return nil, err 57 } 58 inTyps, outTyps, _, _, err := d.getFunctionArgTypes(f) 59 if err != nil { 60 return nil, err 61 } 62 63 ftyp := reflect.FuncOf(inTyps, outTyps, variadic) 64 return ftyp, nil 65 } 66 67 func (d *DwarfRT) FindFunc(name string, variadic bool) (reflect.Value, error) { 68 pc, err := d.FindFuncPc(name) 69 if err != nil { 70 return reflect.Value{}, err 71 } 72 ftyp, err := d.FindFuncType(name, variadic) 73 if err != nil { 74 return reflect.Value{}, err 75 } 76 77 newFunc := CreateFuncForCodePtr(ftyp, pc) 78 return newFunc, nil 79 } 80 81 func (d *DwarfRT) CallFunc(name string, variadic bool, args []reflect.Value) ([]reflect.Value, error) { 82 if err := d.check(); err != nil { 83 return nil, err 84 } 85 f, err := d.findFunc(name) 86 if err != nil { 87 return nil, err 88 } 89 90 inTyps, outTyps, inNames, _, err := d.getFunctionArgTypes(f) 91 if err != nil { 92 return nil, err 93 } 94 95 ftyp := reflect.FuncOf(inTyps, outTyps, variadic) 96 newFunc := CreateFuncForCodePtr(ftyp, f.Entry) 97 98 getInTyp := func(i int) (reflect.Type, string) { 99 if len(inTyps) <= 0 { 100 return nil, "" 101 } 102 if i < len(inTyps)-1 { 103 return inTyps[i], inNames[i] 104 } 105 if variadic { 106 return inTyps[len(inTyps)-1].Elem(), inNames[len(inNames)-1] 107 } 108 if i < len(inTyps) { 109 return inTyps[i], inNames[i] 110 } 111 return nil, "" 112 } 113 114 for i, arg := range args { 115 inTyp, inName := getInTyp(i) 116 if inTyp == nil { 117 return nil, fmt.Errorf("len mismatch %d", i) 118 } 119 120 if !arg.Type().AssignableTo(inTyp) { 121 return nil, fmt.Errorf("type mismatch %d:%s", i, inName) 122 } 123 } 124 125 out := newFunc.Call(args) 126 return out, nil 127 } 128 129 func (d *DwarfRT) findFunc(name string) (*proc.Function, error) { 130 for i := len(d.bi.Functions) - 1; i >= 0; i-- { 131 if d.bi.Functions[i].Name == name { 132 if d.bi.Functions[i].Entry != 0 { 133 return &(d.bi.Functions[i]), nil 134 } 135 return nil, ErrNotFound 136 } 137 } 138 return nil, ErrNotFound 139 } 140 141 func (d *DwarfRT) getFunctionArgTypes(f *proc.Function) ([]reflect.Type, []reflect.Type, []string, []string, error) { 142 rOffset := reflect.ValueOf(f).Elem().FieldByName("offset") 143 rCU := reflect.ValueOf(f).Elem().FieldByName("cu") 144 if !rOffset.IsValid() || !rCU.IsValid() { 145 return nil, nil, nil, nil, ErrNotSupport 146 } 147 rImage := rCU.Elem().FieldByName("image") 148 if !rImage.IsValid() { 149 return nil, nil, nil, nil, ErrNotSupport 150 } 151 rDwarf := rImage.Elem().FieldByName("dwarf") 152 if !rDwarf.IsValid() { 153 return nil, nil, nil, nil, ErrNotSupport 154 } 155 image := (*proc.Image)(unsafe.Pointer(rImage.Pointer())) 156 dwarfData := (*dwarf.Data)(unsafe.Pointer(rDwarf.Pointer())) 157 158 reader := image.DwarfReader() 159 reader.Seek(dwarf.Offset(rOffset.Uint())) 160 entry, err := reader.Next() 161 if err != nil || entry == nil || entry.Tag != dwarf.TagSubprogram { 162 return nil, nil, nil, nil, fmt.Errorf("get function arg types not found %s", f.Name) 163 } 164 name, ok := entry.Val(dwarf.AttrName).(string) 165 if !ok || f.Name != name { 166 return nil, nil, nil, nil, fmt.Errorf("get function arg types name err %s:%s", f.Name, name) 167 } 168 169 var inTyps []reflect.Type 170 var outTyps []reflect.Type 171 var inNames []string 172 var outNames []string 173 174 for { 175 child, err := reader.Next() 176 if err != nil { 177 return nil, nil, nil, nil, fmt.Errorf("get function arg types reader err %s:%s", f.Name, err.Error()) 178 } 179 if child == nil || child.Tag == 0 { 180 break 181 } 182 if child.Tag != dwarf.TagFormalParameter { 183 continue 184 } 185 186 dtyp, err := entryType(dwarfData, child) 187 if err != nil { 188 return nil, nil, nil, nil, fmt.Errorf("get function arg types type err %s:%s", f.Name, err.Error()) 189 } 190 dname := dwarfTypeName(dtyp) 191 rtyp, err := d.FindType(dname) 192 if err != nil { 193 return nil, nil, nil, nil, fmt.Errorf("get function arg types type err %s:%s", f.Name, err.Error()) 194 } 195 196 isret, _ := child.Val(dwarf.AttrVarParam).(bool) 197 if isret { 198 outTyps = append(outTyps, rtyp) 199 outNames = append(outNames, dname) 200 } else { 201 inTyps = append(inTyps, rtyp) 202 inNames = append(inNames, dname) 203 } 204 } 205 return inTyps, outTyps, inNames, outNames, nil 206 }