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  }