github.com/Rookout/GoSDK@v0.1.48/pkg/services/instrumentation/function_creator.go (about)

     1  package instrumentation
     2  
     3  import (
     4  	"github.com/Rookout/GoSDK/pkg/augs"
     5  	"github.com/Rookout/GoSDK/pkg/logger"
     6  	"github.com/Rookout/GoSDK/pkg/rookoutErrors"
     7  	"github.com/Rookout/GoSDK/pkg/services/assembler"
     8  	"github.com/Rookout/GoSDK/pkg/services/collection/variable"
     9  	"github.com/Rookout/GoSDK/pkg/services/instrumentation/binary_info"
    10  	"github.com/Rookout/GoSDK/pkg/services/instrumentation/hooker"
    11  	"github.com/Rookout/GoSDK/pkg/services/instrumentation/hooker/prologue"
    12  	"github.com/Rookout/GoSDK/pkg/services/instrumentation/module"
    13  )
    14  
    15  type functionCreator struct {
    16  	trampolineManager *trampolineManager
    17  	hooker            hooker.Hooker
    18  	filename          string
    19  	lineno            int
    20  	biFunction        *binary_info.Function
    21  	binaryInfo        *binary_info.BinaryInfo
    22  }
    23  
    24  func NewFunction(function *binary_info.Function, filename string, lineno int, binaryInfo *binary_info.BinaryInfo, hooker hooker.Hooker, trampolineManager *trampolineManager) (*augs.Function, rookoutErrors.RookoutError) {
    25  	functionCreator := &functionCreator{
    26  		trampolineManager: trampolineManager,
    27  		hooker:            hooker,
    28  		biFunction:        function,
    29  		filename:          filename,
    30  		lineno:            lineno,
    31  		binaryInfo:        binaryInfo,
    32  	}
    33  	return functionCreator.createFunction()
    34  }
    35  
    36  func (f *functionCreator) createFunction() (*augs.Function, rookoutErrors.RookoutError) {
    37  	finalTrampolinePointer, middleTrampolineAddress, err := f.trampolineManager.getTrampolineAddress()
    38  	if err != nil {
    39  		return nil, err
    40  	}
    41  	stackFrameSize := module.FindFuncMaxSPDelta(f.biFunction.Entry)
    42  	function := augs.NewFunction(f.biFunction.Entry, f.biFunction.End, stackFrameSize, middleTrampolineAddress, finalTrampolinePointer)
    43  	function.FunctionCopyStateID, function.Prologue, err = f.getPrologue(function)
    44  	if err != nil {
    45  		return nil, err
    46  	}
    47  
    48  	return function, nil
    49  }
    50  
    51  func (f *functionCreator) getPrologue(function *augs.Function) (int, []byte, rookoutErrors.RookoutError) {
    52  	functionCopyStateID, functionCopyEntry, err := f.createFunctionCopy(function)
    53  	if err != nil {
    54  		return -1, nil, err
    55  	}
    56  
    57  	getRegsUsed := func() ([]assembler.Reg, rookoutErrors.RookoutError) {
    58  		variableLocators, err := variable.GetVariableLocators(function.Entry, f.lineno, f.biFunction, f.binaryInfo)
    59  		if err != nil {
    60  			return nil, rookoutErrors.NewFailedToGetVariableLocators(f.filename, f.lineno, err)
    61  		}
    62  
    63  		var regsUsed []assembler.Reg
    64  		regsUsedMap := make(map[assembler.Reg]struct{})
    65  		for _, locator := range variableLocators {
    66  			regs, err := locator.GetRegsUsed()
    67  			if err != nil {
    68  				logger.Logger().WithError(err).Warningf("Failed to get regs used by variable %s", locator.VariableName)
    69  			}
    70  
    71  			
    72  			for _, reg := range regs {
    73  				if _, ok := regsUsedMap[reg]; !ok {
    74  					regsUsedMap[reg] = struct{}{}
    75  					regsUsed = append(regsUsed, reg)
    76  				}
    77  			}
    78  		}
    79  		return regsUsed, nil
    80  	}
    81  
    82  	prologueGenerator, err := prologue.NewGenerator(uintptr(f.biFunction.Entry), uintptr(f.biFunction.End), int(function.StackFrameSize), functionCopyEntry, getRegsUsed)
    83  	if err != nil {
    84  		return -1, nil, err
    85  	}
    86  	p, err := prologueGenerator.Generate()
    87  	return functionCopyStateID, p, err
    88  }
    89  
    90  func (f *functionCreator) createFunctionCopy(function *augs.Function) (int, uintptr, rookoutErrors.RookoutError) {
    91  	runner, err := f.hooker.StartCopyingFunction(function)
    92  	if err != nil {
    93  		return -1, 0, rookoutErrors.NewFailedToStartCopyingFunction(err)
    94  	}
    95  	addressMappings, offsetMappings, err := runner.GetAddressMapping()
    96  	if err != nil {
    97  		return -1, 0, rookoutErrors.NewFailedToGetAddressMapping(f.filename, f.lineno, err)
    98  	}
    99  
   100  	
   101  	
   102  	
   103  	if err = module.PatchModuleData(addressMappings, offsetMappings, runner.ID()); err != nil {
   104  		return -1, 0, rookoutErrors.NewFailedToPatchModule(f.filename, f.lineno, err)
   105  	}
   106  
   107  	return runner.ID(), addressMappings[0].NewAddress, nil
   108  }