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  }