github.com/Rookout/GoSDK@v0.1.48/pkg/services/instrumentation/module/module_patcher1.15.go (about) 1 //go:build go1.15 && !go1.16 2 // +build go1.15,!go1.16 3 4 package module 5 6 import ( 7 "unsafe" 8 9 "github.com/Rookout/GoSDK/pkg/rookoutErrors" 10 ) 11 12 type pclntableInfo struct { 13 pcDataTables [][]byte 14 funcDataOffsets []unsafe.Pointer 15 pcLine []byte 16 pcFile []byte 17 pcsp []byte 18 files map[int32][]byte 19 } 20 21 func (m *moduleDataPatcher) getPCDataTable(offset uintptr) []byte { 22 if offset == 0 { 23 return nil 24 } 25 return m.origModule.pclntable[offset:] 26 } 27 28 29 func (m *moduleDataPatcher) getModuleData() (moduledata, error) { 30 return moduledata{ 31 filetab: m.filetab, 32 ftab: m.ftab, 33 pclntable: m.newPclntable, 34 findfunctab: uintptr(unsafe.Pointer(m.findFuncBucketTable)), 35 minpc: m.newFuncEntryAddress, 36 maxpc: m.newFuncEndAddress, 37 text: m.newFuncEntryAddress, 38 etext: m.newFuncEndAddress, 39 noptrdata: m.origModule.noptrdata, 40 enoptrdata: m.origModule.enoptrdata, 41 data: m.origModule.data, 42 edata: m.origModule.edata, 43 bss: m.origModule.bss, 44 ebss: m.origModule.ebss, 45 noptrbss: m.origModule.noptrbss, 46 enoptrbss: m.origModule.enoptrbss, 47 end: m.origModule.end, 48 gcdata: m.origModule.gcdata, 49 gcbss: m.origModule.gcbss, 50 types: m.origModule.types, 51 etypes: m.origModule.etypes, 52 53 modulename: m.name, 54 55 hasmain: 0, 56 57 gcdatamask: m.origModule.gcdatamask, 58 gcbssmask: m.origModule.gcbssmask, 59 60 typemap: m.origModule.typemap, 61 62 bad: false, 63 64 next: nil, 65 }, nil 66 } 67 68 const ptrSize = 8 69 70 func (m *moduleDataPatcher) createPCHeader() error { 71 return nil 72 } 73 74 func (m *moduleDataPatcher) funcDataOffset(tableIndex uint8) unsafe.Pointer { 75 return funcdata(*m.origFunction, tableIndex) 76 } 77 78 func (m *moduleDataPatcher) buildFunc(funcnameOffset int32, pcspOffset int32, pcfileOffset int32, pclnOffset int32) _func { 79 return _func{ 80 entry: m.newFuncEntryAddress, 81 nameoff: funcnameOffset, 82 83 args: m.origFunction.args, 84 deferreturn: m.getDeferreturn(), 85 86 pcsp: pcspOffset, 87 pcfile: pcfileOffset, 88 pcln: pclnOffset, 89 npcdata: int32(len(m.info.pcDataTables)), 90 funcID: m.origFunction.funcID, 91 nfuncdata: m.origFunction.nfuncdata, 92 } 93 } 94 95 func (m *moduleDataPatcher) isPCDataStartValid(pcDataStart uint32) bool { 96 return int(pcDataStart) < len(m.origModule.pclntable) 97 } 98 99 func (m *moduleDataPatcher) newFuncTab(funcOff uintptr, entry uintptr) functab { 100 return functab{funcoff: funcOff, entry: entry} 101 } 102 103 func (m *moduleDataPatcher) buildPCFile(patcher *PCDataPatcher) error { 104 pcFile, oldFilenosToNew, err := patcher.CreatePCFile(decodePCDataEntries(m.getPCDataTable(uintptr(m.origFunction.pcfile)))) 105 106 m.info.files = make(map[int32][]byte) 107 for oldFileno, newFileno := range oldFilenosToNew { 108 m.info.files[newFileno] = []byte(funcfile(*m.origFunction, oldFileno)) 109 } 110 111 pcFileBytes, err := encodePCDataEntries(pcFile) 112 if err != nil { 113 return err 114 } 115 m.info.pcFile = pcFileBytes 116 return nil 117 } 118 119 func (m *moduleDataPatcher) createPclnTable() rookoutErrors.RookoutError { 120 m.filetab = make([]uint32, len(m.info.files)) 121 for fileno, filename := range m.info.files { 122 m.filetab[fileno] = uint32(len(m.newPclntable)) 123 m.writeBytesToPclnTable(append(filename, 0)) 124 } 125 126 127 if len(m.newPclntable) == 0 { 128 m.newPclntable = append(m.newPclntable, 0) 129 } 130 131 funcnameOffset := int32(len(m.newPclntable)) 132 m.writeBytesToPclnTable(append([]byte(m.funcName), 0)) 133 134 pcDataOffsets := make([]uint32, len(m.info.pcDataTables)) 135 for i, table := range m.info.pcDataTables { 136 if table == nil { 137 continue 138 } 139 pcDataOffsets[i] = uint32(len(m.newPclntable)) 140 m.writeBytesToPclnTable(table) 141 } 142 143 pcspOffset := int32(len(m.newPclntable)) 144 m.writeBytesToPclnTable(m.info.pcsp) 145 pclnOffset := int32(len(m.newPclntable)) 146 m.writeBytesToPclnTable(m.info.pcLine) 147 pcfileOffset := int32(len(m.newPclntable)) 148 m.writeBytesToPclnTable(m.info.pcFile) 149 150 f := m.buildFunc(funcnameOffset, pcspOffset, pcfileOffset, pclnOffset) 151 m.funcOffset = uintptr(len(m.newPclntable)) 152 153 m.writeObjectToPclnTable(unsafe.Pointer(&f), int(unsafe.Offsetof(f.nfuncdata)+unsafe.Sizeof(f.nfuncdata))) 154 155 if len(pcDataOffsets) > 0 { 156 m.writeObjectToPclnTable(unsafe.Pointer(&pcDataOffsets[0]), len(pcDataOffsets)*4) 157 } 158 159 if len(m.info.funcDataOffsets) > 0 { 160 161 if len(pcDataOffsets)%2 != 0 { 162 m.writeBytesToPclnTable(make([]byte, 4)) 163 } 164 m.writeObjectToPclnTable(unsafe.Pointer(&m.info.funcDataOffsets[0]), len(m.info.funcDataOffsets)*ptrSize) 165 } 166 167 return m.alignPclntable() 168 } 169 170 171 func (m *moduleDataPatcher) alignPclntable() rookoutErrors.RookoutError { 172 if uintptr(unsafe.Pointer(&m.newPclntable[m.funcOffset]))&4 == 0 { 173 return nil 174 } 175 176 pclntable := m.newPclntable 177 m.newPclntable = make([]byte, uintptr(len(pclntable))+4) 178 alignment := uintptr(unsafe.Pointer(&m.newPclntable[m.funcOffset])) & 4 179 for i := uintptr(0); i < m.funcOffset; i++ { 180 m.newPclntable[i] = pclntable[i] 181 } 182 for i := m.funcOffset; i < uintptr(len(pclntable)); i++ { 183 m.newPclntable[i+alignment] = pclntable[i] 184 } 185 m.funcOffset += alignment 186 187 if uintptr(unsafe.Pointer(&m.newPclntable[m.funcOffset]))&4 != 0 { 188 return rookoutErrors.NewFailedToAlignFunc( 189 uintptr(unsafe.Pointer(&m.newPclntable[m.funcOffset])), 190 uintptr(unsafe.Pointer(&m.newPclntable[0])), 191 m.funcOffset) 192 } 193 194 return nil 195 }