github.com/Rookout/GoSDK@v0.1.48/pkg/services/collection/collection_service.go (about) 1 package collection 2 3 import ( 4 "errors" 5 "fmt" 6 7 "github.com/Rookout/GoSDK/pkg/config" 8 "github.com/Rookout/GoSDK/pkg/rookoutErrors" 9 "github.com/Rookout/GoSDK/pkg/services/collection/registers" 10 "github.com/Rookout/GoSDK/pkg/services/collection/variable" 11 ) 12 13 type Stackframe struct { 14 File string `json:"file"` 15 Line int `json:"line"` 16 Function string `json:"function,omitempty"` 17 } 18 19 type CollectionService struct { 20 21 variables []*variable.Variable 22 StackTraceElements []Stackframe 23 variableLocators []*variable.VariableLocator 24 variablesCache *variable.VariablesCache 25 dictVariableLocator *variable.VariableLocator 26 shouldLoadDictVariable bool 27 dictAddr uint64 28 regs registers.Registers 29 pointerSize int 30 goid int 31 } 32 33 const goDictionaryName = ".dict" 34 35 func NewCollectionService(regs registers.Registers, pointerSize int, stackTraceElements []Stackframe, variableLocators []*variable.VariableLocator, goid int) (*CollectionService, rookoutErrors.RookoutError) { 36 c := &CollectionService{ 37 StackTraceElements: stackTraceElements, 38 regs: regs, 39 shouldLoadDictVariable: false, 40 pointerSize: pointerSize, 41 goid: goid, 42 variablesCache: variable.NewVariablesCache(), 43 } 44 45 for _, variableLocator := range variableLocators { 46 if variableLocator.VariableName == goDictionaryName { 47 c.dictVariableLocator = variableLocator 48 c.shouldLoadDictVariable = true 49 } else { 50 c.variableLocators = append(c.variableLocators, variableLocator) 51 } 52 } 53 54 return c, nil 55 } 56 57 func (c *CollectionService) GetFrame() *Stackframe { 58 return &c.StackTraceElements[0] 59 } 60 61 func (c *CollectionService) loadDictVariable(config config.ObjectDumpConfig) { 62 if c.shouldLoadDictVariable { 63 dictVar := c.dictVariableLocator.Locate(c.regs, 0, c.variablesCache, config) 64 dictAddr := dictVar.Addr 65 66 c.dictAddr = uint64(dictAddr) 67 c.shouldLoadDictVariable = false 68 } 69 } 70 71 func (c *CollectionService) GetVariables(config config.ObjectDumpConfig) []*variable.Variable { 72 c.loadDictVariable(config) 73 74 var variables []*variable.Variable 75 for _, varLocator := range c.variableLocators { 76 variables = append(variables, c.locateAndLoadVariable(varLocator, config)) 77 } 78 79 return variables 80 } 81 82 func (c *CollectionService) GetVariable(name string, config config.ObjectDumpConfig) (*variable.Variable, error) { 83 c.loadDictVariable(config) 84 85 for _, varLocator := range c.variableLocators { 86 if varLocator.VariableName == name || varLocator.VariableName == "&"+name { 87 return c.locateAndLoadVariable(varLocator, config), nil 88 } 89 } 90 return nil, errors.New("variable not found") 91 } 92 93 func (c *CollectionService) locateAndLoadVariable(varLocator *variable.VariableLocator, objectDumpConfig config.ObjectDumpConfig) (v *variable.Variable) { 94 v = varLocator.Locate(c.regs, c.dictAddr, c.variablesCache, objectDumpConfig) 95 if name := v.Name; len(name) > 1 && name[0] == '&' { 96 v = v.MaybeDereference() 97 if v.Addr == 0 && v.Unreadable == nil { 98 v.Unreadable = fmt.Errorf("no address for escaped variable") 99 } 100 v.Name = name[1:] 101 } 102 103 if v.ObjectDumpConfig.ShouldTailor { 104 v.UpdateObjectDumpConfig(config.TailorObjectDumpConfig(v.Kind, int(v.Len))) 105 } 106 107 v.LoadValue() 108 c.variables = append(c.variables, v) 109 return v 110 } 111 112 func (c *CollectionService) Close() error { 113 for _, v := range c.variables { 114 _ = v.Close() 115 } 116 117 return nil 118 } 119 120 func (c *CollectionService) GoroutineID() int { 121 return c.goid 122 }