gitlab.com/Raven-IO/raven-delve@v1.22.4/pkg/dwarf/reader/variables.go (about) 1 package reader 2 3 import ( 4 "debug/dwarf" 5 6 "gitlab.com/Raven-IO/raven-delve/pkg/dwarf/godwarf" 7 ) 8 9 type Variable struct { 10 *godwarf.Tree 11 // Depth represents the depth of the lexical block in which this variable 12 // was declared, relative to a root scope (e.g. a function) passed to 13 // Variables(). The depth is used to figure out if a variable is shadowed at 14 // a particular pc by another one with the same name declared in an inner 15 // block. 16 Depth int 17 } 18 19 // VariablesFlags specifies some configuration flags for the Variables function. 20 type VariablesFlags uint8 21 22 const ( 23 VariablesOnlyVisible VariablesFlags = 1 << iota 24 VariablesSkipInlinedSubroutines 25 VariablesTrustDeclLine 26 VariablesNoDeclLineCheck 27 VariablesOnlyCaptured 28 ) 29 30 // Variables returns a list of variables contained inside 'root'. 31 // 32 // If the VariablesOnlyVisible flag is set, only variables visible at 'pc' will be 33 // returned. If the VariablesSkipInlinedSubroutines is set, variables from 34 // inlined subroutines will be skipped. 35 func Variables(root *godwarf.Tree, pc uint64, line int, flags VariablesFlags) []Variable { 36 return variablesInternal(nil, root, 0, pc, line, flags) 37 } 38 39 // variablesInternal appends to 'v' variables from 'root'. The function calls 40 // itself with an incremented scope for all sub-blocks in 'root'. 41 func variablesInternal(v []Variable, root *godwarf.Tree, depth int, pc uint64, line int, flags VariablesFlags) []Variable { 42 switch root.Tag { 43 case dwarf.TagInlinedSubroutine: 44 if flags&VariablesSkipInlinedSubroutines != 0 { 45 return v 46 } 47 fallthrough 48 case dwarf.TagLexDwarfBlock, dwarf.TagSubprogram: 49 // Recurse into blocks and functions, if the respective block contains 50 // pc (or if we don't care about visibility). 51 if (flags&VariablesOnlyVisible == 0) || root.ContainsPC(pc) { 52 for _, child := range root.Children { 53 v = variablesInternal(v, child, depth+1, pc, line, flags) 54 } 55 } 56 return v 57 default: 58 // Variables are considered to be visible starting on the line after the 59 // line they are declared on. Function arguments are an exception - the line 60 // they are declared on does not matter; they are considered to be 61 // visible throughout the function. 62 declLine, varHasDeclLine := root.Val(dwarf.AttrDeclLine).(int64) 63 checkDeclLine := 64 root.Tag != dwarf.TagFormalParameter && // var is not a function argument 65 varHasDeclLine && // we know the DeclLine 66 (flags&VariablesNoDeclLineCheck == 0) // we were not explicitly instructed to ignore DeclLine 67 68 varVisible := !checkDeclLine || (line >= int(declLine)+1) // +1 because visibility starts on the line after DeclLine 69 if varVisible { 70 return append(v, Variable{root, depth}) 71 } 72 return v 73 } 74 }