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  }