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 }