github.com/pkujhd/goloader@v0.0.0-20240411034752-1a28096bd7bd/registerInExe.go (about) 1 package goloader 2 3 import ( 4 "cmd/objfile/objfile" 5 "debug/elf" 6 "debug/gosym" 7 "debug/macho" 8 "debug/pe" 9 "encoding/binary" 10 "fmt" 11 "reflect" 12 "runtime" 13 "unsafe" 14 ) 15 16 type typedata struct { 17 data []byte 18 saddr uintptr 19 naddr uintptr 20 byteOrder binary.ByteOrder 21 adapted map[int32]int32 22 } 23 24 func (td *typedata) adaptPtr(dataOff int) uintptr { 25 ptr := uintptr(td.byteOrder.Uint64(td.data[dataOff:])) 26 if PtrSize == Uint32Size { 27 ptr = uintptr(td.byteOrder.Uint32(td.data[dataOff:])) 28 } 29 putAddress(td.byteOrder, td.data[dataOff:], uint64(ptr+td.naddr-td.saddr)) 30 return ptr + td.naddr - td.saddr 31 } 32 33 func (td *typedata) adaptType(tl int32) { 34 if _, ok := td.adapted[tl]; ok { 35 return 36 } 37 td.adapted[tl] = tl 38 t := (*_type)(adduintptr(td.naddr, int(tl))) 39 switch t.Kind() { 40 case reflect.Array, reflect.Ptr, reflect.Chan, reflect.Slice: 41 //Element 42 addr := td.adaptPtr(int(tl) + _typeSize) 43 td.adaptType(int32(addr - td.naddr)) 44 case reflect.Func: 45 f := (*funcType)(unsafe.Pointer(t)) 46 inOutCount := f.inCount + f.outCount&(1<<15-1) 47 uadd := funcTypeSize 48 if f.tflag&tflagUncommon != 0 { 49 uadd += uncommonTypeSize 50 } 51 uadd += int(tl) 52 for i := 0; i < int(inOutCount); i++ { 53 addr := td.adaptPtr(int(uadd + i*PtrSize)) 54 td.adaptType(int32(addr - td.naddr)) 55 } 56 case reflect.Interface: 57 //pkgPath 58 td.adaptPtr(int(tl + int32(_typeSize))) 59 //imethod slice.Data 60 td.adaptPtr(int(tl + int32(_typeSize+PtrSize))) 61 case reflect.Map: 62 //Key 63 addr := td.adaptPtr(int(tl) + _typeSize) 64 td.adaptType(int32(addr - td.naddr)) 65 //Elem 66 addr = td.adaptPtr(int(tl) + _typeSize + PtrSize) 67 td.adaptType(int32(addr - td.naddr)) 68 //Bucket 69 addr = td.adaptPtr(int(tl) + _typeSize + PtrSize + PtrSize) 70 td.adaptType(int32(addr - td.naddr)) 71 case reflect.Struct: 72 //PkgPath 73 td.adaptPtr(int(tl + int32(_typeSize))) 74 s := (*sliceHeader)(unsafe.Pointer(&td.data[tl+int32(_typeSize+PtrSize)])) 75 for i := 0; i < s.Len; i++ { 76 //Filed Name 77 off := s.Data - td.saddr + +uintptr(3*i)*PtrSize 78 td.adaptPtr(int(off)) 79 //Field Type 80 addr := td.adaptPtr(int(off + PtrSize)) 81 td.adaptType(int32(addr - td.naddr)) 82 } 83 s.Data = s.Data + td.naddr - td.saddr 84 case reflect.Bool, 85 reflect.Int, reflect.Uint, 86 reflect.Int64, reflect.Uint64, 87 reflect.Int32, reflect.Uint32, 88 reflect.Int16, reflect.Uint16, 89 reflect.Int8, reflect.Uint8, 90 reflect.Float64, reflect.Float32, 91 reflect.Complex64, reflect.Complex128, 92 reflect.String, reflect.UnsafePointer, 93 reflect.Uintptr: 94 //noting todo 95 default: 96 panic(fmt.Errorf("not deal reflect type:%s", t.Kind())) 97 } 98 } 99 100 func registerTypesInMacho(path string, symPtr map[string]uintptr) error { 101 machoFile, _ := macho.Open(path) 102 typeLinkSect := machoFile.Section("__typelink") 103 typeLinkSectData, err := typeLinkSect.Data() 104 if err != nil { 105 return err 106 } 107 roDataSect := machoFile.Section("__rodata") 108 roDataSectData, err := roDataSect.Data() 109 if err != nil { 110 return err 111 } 112 113 byteOrder := machoFile.ByteOrder 114 typelinks := *ptr2uint32slice(uintptr(unsafe.Pointer(&typeLinkSectData[0])), len(typeLinkSectData)/Uint32Size) 115 _registerTypesInExe(symPtr, byteOrder, typelinks, roDataSectData, uintptr(roDataSect.Addr)) 116 return nil 117 } 118 119 func registerTypesInElf(path string, symPtr map[string]uintptr) error { 120 elfFile, _ := elf.Open(path) 121 typeLinkSect := elfFile.Section(".typelink") 122 typeLinkSectData, err := typeLinkSect.Data() 123 if err != nil { 124 return err 125 } 126 roDataSect := elfFile.Section(".rodata") 127 roDataSectData, err := roDataSect.Data() 128 if err != nil { 129 return err 130 } 131 132 byteOrder := elfFile.ByteOrder 133 typelinks := *ptr2uint32slice(uintptr(unsafe.Pointer(&typeLinkSectData[0])), len(typeLinkSectData)/Uint32Size) 134 _registerTypesInExe(symPtr, byteOrder, typelinks, roDataSectData, uintptr(roDataSect.Addr)) 135 return nil 136 } 137 138 func registerTypesInPE(path string, symPtr map[string]uintptr) error { 139 peFile, _ := pe.Open(path) 140 getSymbolInPe := func(symbols []*pe.Symbol, symbolName string) *pe.Symbol { 141 for _, sym := range symbols { 142 if sym.Name == symbolName { 143 return sym 144 } 145 } 146 return nil 147 } 148 typelinkSym := getSymbolInPe(peFile.Symbols, "runtime.typelink") 149 moduledataSym := getSymbolInPe(peFile.Symbols, "runtime.firstmoduledata") 150 151 roDataSect := peFile.Section(".rdata") 152 roDataSectData, err := roDataSect.Data() 153 if err != nil { 154 return err 155 } 156 157 dataSect := peFile.Section(".data") 158 dataSectData, err := dataSect.Data() 159 if err != nil { 160 return err 161 } 162 163 md := (*moduledata)(unsafe.Pointer(&dataSectData[moduledataSym.Value])) 164 typelinks := *ptr2uint32slice(uintptr(unsafe.Pointer(&roDataSectData[typelinkSym.Value])), len(md.typelinks)) 165 166 getImageBase := func(peFile *pe.File) uintptr { 167 _, pe64 := peFile.OptionalHeader.(*pe.OptionalHeader64) 168 if pe64 { 169 return uintptr(peFile.OptionalHeader.(*pe.OptionalHeader64).ImageBase) 170 } else { 171 return uintptr(peFile.OptionalHeader.(*pe.OptionalHeader32).ImageBase) 172 } 173 } 174 _registerTypesInExe(symPtr, binary.LittleEndian, typelinks, roDataSectData, uintptr(roDataSect.VirtualAddress)+getImageBase(peFile)) 175 return nil 176 } 177 178 func _registerTypesInExe(symPtr map[string]uintptr, byteOrder binary.ByteOrder, typelinks []int32, data []byte, addr uintptr) { 179 md := &moduledata{typelinks: typelinks} 180 md.types = uintptr(unsafe.Pointer(&data[0])) 181 md.etypes = md.types + uintptr(len(data)) 182 183 td := typedata{ 184 data: data, 185 saddr: addr, 186 naddr: md.types, 187 byteOrder: byteOrder, 188 adapted: make(map[int32]int32), 189 } 190 modulesLock.Lock() 191 addModule(md) 192 modulesLock.Unlock() 193 for _, tl := range md.typelinks { 194 td.adaptType(tl) 195 } 196 for _, tl := range md.typelinks { 197 registerType((*_type)(adduintptr(md.types, int(tl))), symPtr) 198 } 199 modulesLock.Lock() 200 removeModule(md) 201 modulesLock.Unlock() 202 } 203 204 func registerTypesInExe(symPtr map[string]uintptr, path string) error { 205 f, err := objfile.Open(path) 206 if err != nil { 207 return err 208 } 209 defer f.Close() 210 pcLineTable, err := f.PCLineTable() 211 if err != nil { 212 return err 213 } 214 for _, f := range pcLineTable.(*gosym.Table).Funcs { 215 symPtr[f.Name] = uintptr(f.Entry) 216 } 217 218 switch runtime.GOOS { 219 case "linux", "android": 220 return registerTypesInElf(path, symPtr) 221 case "darwin": 222 return registerTypesInMacho(path, symPtr) 223 case "windows": 224 return registerTypesInPE(path, symPtr) 225 default: 226 panic(fmt.Errorf("unsupported platform:%s", runtime.GOOS)) 227 } 228 }