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