github.com/pkujhd/goloader@v0.0.0-20240411034752-1a28096bd7bd/register.go (about) 1 package goloader 2 3 import ( 4 "cmd/objfile/objfile" 5 "fmt" 6 "os" 7 "reflect" 8 "strings" 9 "unsafe" 10 11 "github.com/pkujhd/goloader/constants" 12 ) 13 14 // !IMPORTANT: only init firstmodule type, avoid load multiple objs but unload non-sequence errors 15 func typelinksRegister(symPtr map[string]uintptr) { 16 md := firstmoduledata 17 for _, tl := range md.typelinks { 18 t := (*_type)(adduintptr(md.types, int(tl))) 19 if md.typemap != nil { 20 t = (*_type)(adduintptr(md.typemap[typeOff(tl)], 0)) 21 } 22 registerType(t, symPtr) 23 } 24 //register function 25 for _, f := range md.ftab { 26 if int(f.funcoff) < len(md.pclntable) { 27 _func := (*_func)(unsafe.Pointer(&(md.pclntable[f.funcoff]))) 28 name := getfuncname(_func, &md) 29 if name != EmptyString { 30 if _, ok := symPtr[name]; !ok { 31 symPtr[name] = getfuncentry(_func, md.text) 32 } 33 } 34 } 35 } 36 } 37 38 func registerType(t *_type, symPtr map[string]uintptr) { 39 if t.Kind() == reflect.Invalid { 40 panic("Unexpected invalid kind during registration!") 41 } 42 43 name := constants.TypePrefix + resolveTypeName(t) 44 if _, ok := symPtr[name]; ok { 45 return 46 } 47 symPtr[name] = uintptr(unsafe.Pointer(t)) 48 49 switch t.Kind() { 50 case reflect.Ptr, reflect.Chan, reflect.Array, reflect.Slice: 51 registerType(rtypeOf(t.Elem()), symPtr) 52 case reflect.Func: 53 for i := 0; i < t.NumIn(); i++ { 54 registerType(rtypeOf(t.In(i)), symPtr) 55 } 56 for i := 0; i < t.NumOut(); i++ { 57 registerType(rtypeOf(t.Out(i)), symPtr) 58 } 59 case reflect.Struct: 60 for i := 0; i < t.NumField(); i++ { 61 registerType(rtypeOf(t.Field(i).Type), symPtr) 62 } 63 case reflect.Map: 64 registerType(rtypeOf(t.Key()), symPtr) 65 registerType(rtypeOf(t.Elem()), symPtr) 66 case reflect.Bool, 67 reflect.Int, reflect.Uint, 68 reflect.Int64, reflect.Uint64, 69 reflect.Int32, reflect.Uint32, 70 reflect.Int16, reflect.Uint16, 71 reflect.Int8, reflect.Uint8, 72 reflect.Float64, reflect.Float32, 73 reflect.Complex64, reflect.Complex128, 74 reflect.String, reflect.UnsafePointer, 75 reflect.Uintptr, 76 reflect.Interface: 77 // Nothing to do 78 default: 79 panic(fmt.Sprintf("typelinksregister found unexpected type (kind %s): ", t.Kind())) 80 } 81 } 82 83 func RegSymbolWithSo(symPtr map[string]uintptr, path string) error { 84 typelinksRegister(symPtr) 85 return regSymbol(symPtr, path) 86 } 87 88 func RegSymbolWithPath(symPtr map[string]uintptr, path string) error { 89 //register types and functions in exe file, the address of symbol not used for relocateaaa, just 90 //for builder check reachable 91 err := registerTypesInExe(symPtr, path) 92 if err != nil { 93 return err 94 } 95 return regSymbol(symPtr, path) 96 } 97 98 func RegSymbol(symPtr map[string]uintptr) error { 99 path, err := os.Executable() 100 if err != nil { 101 return err 102 } 103 typelinksRegister(symPtr) 104 return regSymbol(symPtr, path) 105 } 106 107 func regSymbol(symPtr map[string]uintptr, path string) error { 108 f, err := objfile.Open(path) 109 if err != nil { 110 return err 111 } 112 defer f.Close() 113 114 syms, err := f.Symbols() 115 for _, sym := range syms { 116 if sym.Name == OsStdout { 117 symPtr[sym.Name] = uintptr(sym.Addr) 118 } 119 } 120 //Address space layout randomization(ASLR) 121 //golang 1.15 symbol address has offset, before 1.15 offset is 0 122 addroff := int64(uintptr(unsafe.Pointer(&os.Stdout))) - int64(symPtr[OsStdout]) 123 for _, sym := range syms { 124 code := strings.ToUpper(string(sym.Code)) 125 if code == "B" || code == "D" { 126 symPtr[sym.Name] = uintptr(int64(sym.Addr) + addroff) 127 } 128 if strings.HasPrefix(sym.Name, constants.ItabPrefix) { 129 symPtr[sym.Name] = uintptr(int64(sym.Addr) + addroff) 130 } 131 } 132 return nil 133 }