github.com/Rookout/GoSDK@v0.1.48/pkg/services/safe_hook_validator/safe_hook_validator.go (about) 1 package safe_hook_validator 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/Rookout/GoSDK/pkg/services/callstack" 8 ) 9 10 type FunctionType int 11 12 const ( 13 FunctionType0 FunctionType = iota 14 FunctionType1 15 FunctionType2 16 ) 17 18 func (f FunctionType) String() string { 19 switch f { 20 case FunctionType0: 21 return "Type0" 22 case FunctionType1: 23 return "Type1" 24 case FunctionType2: 25 return "Type2" 26 default: 27 return "Illegal" 28 } 29 } 30 31 type ValidationErrorFlags int 32 33 const ( 34 NoError ValidationErrorFlags = 0 35 IllegalPcValue ValidationErrorFlags = 1 << (iota - 1) 36 PcInDangerZoneEntry 37 PcInDangerZoneAfterEntry 38 PcInFunction 39 DeepStackDidntResolveAllPc 40 ) 41 42 func (f ValidationErrorFlags) String() string { 43 if f == NoError { 44 return "No error" 45 } 46 msgs := make([]string, 0) 47 if f&IllegalPcValue != 0 { 48 f ^= IllegalPcValue 49 msgs = append(msgs, "Had PC in function entry which is illegal!") 50 } 51 if f&PcInDangerZoneEntry != 0 { 52 f ^= PcInDangerZoneEntry 53 msgs = append(msgs, "Had PC at function entry+1. Not sure if dangerous or not!") 54 } 55 if f&PcInDangerZoneAfterEntry != 0 { 56 f ^= PcInDangerZoneAfterEntry 57 msgs = append(msgs, "Had PC in the danger zone!") 58 } 59 if f&PcInFunction != 0 { 60 f ^= PcInFunction 61 msgs = append(msgs, "Had PC in the function!") 62 } 63 if f&DeepStackDidntResolveAllPc != 0 { 64 f ^= DeepStackDidntResolveAllPc 65 msgs = append(msgs, "Failed to retrieve an entire stack trace, possible PC in function!") 66 } 67 if f != 0 { 68 msgs = append(msgs, "Illegal validation result!") 69 } 70 return strings.Join(msgs, " | ") 71 } 72 73 type AddressRange struct { 74 Start uintptr 75 End uintptr 76 } 77 78 79 80 type ValidatorFactory interface { 81 GetValidator(funcType FunctionType, functionRange, dangerRange AddressRange) (Validator, error) 82 } 83 84 type Validator interface { 85 Validate(buffer callstack.IStackTraceBuffer) ValidationErrorFlags 86 } 87 88 type ValidatorFactoryImpl struct { 89 } 90 91 func (v *ValidatorFactoryImpl) GetValidator(funcType FunctionType, functionRange, dangerRange AddressRange) (Validator, error) { 92 switch funcType { 93 case FunctionType0: 94 if dangerRange.Start != functionRange.Start+1 { 95 return nil, fmt.Errorf("danger zone should start after the first byte of the function") 96 } 97 return &type0Validator{ 98 functionRange: functionRange, 99 dangerRange: dangerRange, 100 }, nil 101 case FunctionType1: 102 return &type1Validator{ 103 functionRange: functionRange, 104 }, nil 105 case FunctionType2: 106 return &type2Validator{}, nil 107 } 108 return nil, fmt.Errorf("illegal function type! Got %d=%s", int(funcType), funcType.String()) 109 } 110 111 type type0Validator struct { 112 functionRange AddressRange 113 dangerRange AddressRange 114 } 115 116 type type1Validator struct { 117 functionRange AddressRange 118 } 119 120 type type2Validator struct { 121 } 122 123 func (r *AddressRange) contains(pc uintptr) bool { 124 return (r.Start <= pc) && (pc < r.End) 125 } 126 127 func (v *type0Validator) Validate(buffer callstack.IStackTraceBuffer) ValidationErrorFlags { 128 ret := NoError 129 totalGoroutines := buffer.Size() 130 for gr := 0; gr < totalGoroutines; gr++ { 131 depth, _ := buffer.GetDepth(gr) 132 for d := 0; d < depth; d++ { 133 pc := buffer.GetPC(gr, d) 134 if pc == v.functionRange.Start { 135 ret |= IllegalPcValue 136 } else if pc == v.dangerRange.Start { 137 ret |= PcInDangerZoneEntry 138 } else if v.dangerRange.contains(pc) { 139 ret |= PcInDangerZoneAfterEntry 140 } 141 } 142 } 143 return ret 144 } 145 146 func (v *type1Validator) Validate(buffer callstack.IStackTraceBuffer) ValidationErrorFlags { 147 ret := NoError 148 totalGoroutines := buffer.Size() 149 for gr := 0; gr < totalGoroutines; gr++ { 150 depth, allFrames := buffer.GetDepth(gr) 151 if !allFrames { 152 ret |= DeepStackDidntResolveAllPc 153 } 154 for d := 0; d < depth; d++ { 155 pc := buffer.GetPC(gr, d) 156 if pc == v.functionRange.Start { 157 ret |= IllegalPcValue 158 } else if v.functionRange.contains(pc) { 159 ret |= PcInFunction 160 } 161 } 162 } 163 return ret 164 } 165 166 func (v *type2Validator) Validate(buffer callstack.IStackTraceBuffer) ValidationErrorFlags { 167 168 return NoError 169 }