github.com/Rookout/GoSDK@v0.1.48/pkg/services/instrumentation/module/module_patcher1.18.go (about) 1 //go:build go1.18 && !go1.21 2 // +build go1.18,!go1.21 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 []uint32 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) funcDataOffset(table uint8) uint32 { 29 p := uintptr(unsafe.Pointer(&m.origFunction.nfuncdata)) + unsafe.Sizeof(m.origFunction.nfuncdata) + uintptr(m.origFunction.npcdata)*4 + uintptr(table)*4 30 return *(*uint32)(unsafe.Pointer(p)) 31 } 32 33 func (m *moduleDataPatcher) buildFunc(pcspOffset uint32, pcfileOffset uint32, pclnOffset uint32) _func { 34 return _func{ 35 entryoff: 0, 36 nameoff: m.origFunction.nameoff, 37 38 args: m.origFunction.args, 39 deferreturn: m.getDeferreturn(), 40 41 pcsp: pcspOffset, 42 pcfile: pcfileOffset, 43 pcln: pclnOffset, 44 npcdata: uint32(len(m.info.pcDataTables)), 45 cuOffset: m.origFunction.cuOffset, 46 funcID: m.origFunction.funcID, 47 flag: m.origFunction.flag, 48 nfuncdata: uint8(len(m.info.funcDataOffsets)), 49 } 50 } 51 52 func (m *moduleDataPatcher) buildPCFile(patcher *PCDataPatcher) error { 53 newPCFile, _, err := patcher.CreatePCFile(decodePCDataEntries(m.getPCDataTable(uintptr(m.origFunction.pcfile)))) 54 if err != nil { 55 return err 56 } 57 newPCFileBytes, err := encodePCDataEntries(newPCFile) 58 if _, ok := os.LookupEnv("ROOKOUT_DEV_DEBUG"); ok { 59 dumpPCData(m.getPCDataTable(uintptr(m.origFunction.pcfile)), "Old pcfile") 60 dumpPCData(newPCFileBytes, "New pcfile") 61 } 62 63 m.info.pcFile = newPCFileBytes 64 return nil 65 } 66 67 68 func (m *moduleDataPatcher) createPCHeader() { 69 m.pcHeader.nfunc = len(m.origModule.ftab) 70 m.pcHeader.nfiles = (uint)(len(m.origModule.filetab)) 71 m.pcHeader.textStart = m.newFuncEntryAddress 72 } 73 74 75 func (m *moduleDataPatcher) getModuleData() (moduledata, error) { 76 return moduledata{ 77 pcHeader: &m.pcHeader, 78 funcnametab: m.origModule.funcnametab, 79 filetab: m.origModule.filetab, 80 cutab: m.origModule.cutab, 81 ftab: m.ftab, 82 pctab: m.newPclntable, 83 pclntable: m.newPclntable, 84 findfunctab: uintptr(unsafe.Pointer(m.findFuncBucketTable)), 85 minpc: m.newFuncEntryAddress, 86 maxpc: m.newFuncEndAddress, 87 text: m.newFuncEntryAddress, 88 etext: m.newFuncEndAddress, 89 noptrdata: m.origModule.noptrdata, 90 enoptrdata: m.origModule.enoptrdata, 91 data: m.origModule.data, 92 edata: m.origModule.edata, 93 bss: m.origModule.bss, 94 ebss: m.origModule.ebss, 95 noptrbss: m.origModule.noptrbss, 96 enoptrbss: m.origModule.enoptrbss, 97 end: m.origModule.end, 98 gcdata: m.origModule.gcdata, 99 gcbss: m.origModule.gcbss, 100 types: m.origModule.types, 101 etypes: m.origModule.etypes, 102 gofunc: m.origModule.gofunc, 103 rodata: m.origModule.noptrdata, 104 105 modulename: m.name, 106 107 hasmain: 0, 108 109 gcdatamask: m.origModule.gcdatamask, 110 gcbssmask: m.origModule.gcbssmask, 111 112 typemap: m.origModule.typemap, 113 114 bad: false, 115 116 next: nil, 117 }, nil 118 } 119 120 func (m *moduleDataPatcher) isPCDataStartValid(pcDataStart uint32) bool { 121 return int(pcDataStart) < len(m.origModule.pctab) 122 } 123 124 func (m *moduleDataPatcher) newFuncTab(funcOff uintptr, entry uintptr) functab { 125 entryOff := entry - m.newFuncEntryAddress 126 return functab{funcoff: uint32(funcOff), entryoff: uint32(entryOff)} 127 } 128 129 func (m *moduleDataPatcher) createPclnTable() rookoutErrors.RookoutError { 130 131 m.newPclntable = make([]byte, 1) 132 133 pcDataOffsets := make([]uint32, len(m.info.pcDataTables)) 134 for i, table := range m.info.pcDataTables { 135 if table == nil { 136 continue 137 } 138 pcDataOffsets[i] = uint32(len(m.newPclntable)) 139 m.writeObjectToPclnTable(unsafe.Pointer(&table[0]), len(table)) 140 } 141 142 pcspOffset := uint32(len(m.newPclntable)) 143 m.writeBytesToPclnTable(m.info.pcsp) 144 pcfileOffset := uint32(len(m.newPclntable)) 145 m.writeBytesToPclnTable(m.info.pcFile) 146 pclnOffset := uint32(len(m.newPclntable)) 147 m.writeBytesToPclnTable(m.info.pcLine) 148 149 f := m.buildFunc(pcspOffset, pcfileOffset, pclnOffset) 150 m.funcOffset = uintptr(len(m.newPclntable)) 151 152 m.writeObjectToPclnTable(unsafe.Pointer(&f), int(unsafe.Offsetof(f.nfuncdata)+unsafe.Sizeof(f.nfuncdata))) 153 154 if len(pcDataOffsets) > 0 { 155 m.writeObjectToPclnTable(unsafe.Pointer(&pcDataOffsets[0]), len(pcDataOffsets)*4) 156 } 157 158 if len(m.info.funcDataOffsets) > 0 { 159 m.writeObjectToPclnTable(unsafe.Pointer(&m.info.funcDataOffsets[0]), len(m.info.funcDataOffsets)*4) 160 } 161 162 return nil 163 }