Documentation
¶
Overview ¶
Package lang contains functions to help manipulate different objects representing elements of the Go language and the ssa.
Package lang provides functions to operate on the SSA representation of a program. It provides an interface to implement visitors for SSA instructions.
Index ¶
- Variables
- func CallGraphReachable(cg *callgraph.Graph, excludeMain bool, excludeInit bool) map[*ssa.Function]bool
- func CanType(v ssa.Value) (res bool)
- func FindImplementationMethod(prog *ssa.Program, tp types.Type, iface types.Type, methodName string) (method *ssa.Function, pointerRequired bool)
- func FindTypeByName(prog *ssa.Program, pkg string, tpName string) types.Type
- func FnReadsFrom(fn *ssa.Function, val ssa.Value) bool
- func FnWritesTo(fn *ssa.Function, val ssa.Value) bool
- func GetArgs(instr ssa.CallInstruction) []ssa.Value
- func GetPackageOfType(tp types.Type) *types.Package
- func HasPathTo(b1 *ssa.BasicBlock, b2 *ssa.BasicBlock, ...) bool
- func InstrMethodKey(instr ssa.CallInstruction) fn.Optional[string]
- func InstrSwitch(visitor InstrOp, instr ssa.Instruction)
- func IsAnyType(tp types.Type) bool
- func IsChannelEnclosingType(t types.Type) bool
- func IsErrorType(t types.Type) bool
- func IsExternal(function *ssa.Function) bool
- func IsNillableType(t types.Type) bool
- func IsPredicateFunctionType(f *types.Signature) bool
- func IsReturningFunctionType(typ types.Type) bool
- func IsStaticallyDefinedLocal(v ssa.Value) bool
- func IsValueReturningCall(value ssa.Value) bool
- func IterateInstructions(function *ssa.Function, f func(index int, instruction ssa.Instruction))
- func IterateValues(function *ssa.Function, f func(index int, value ssa.Value))
- func LastInstr(block *ssa.BasicBlock) ssa.Instruction
- func LastInstrIsReturn(block *ssa.BasicBlock) bool
- func MatchExtract(x ssa.Value) ssa.Value
- func MatchLoadField(x ssa.Value) ssa.Value
- func MatchNegation(x ssa.Value) ssa.Value
- func MatchNilCheck(v ssa.Value) (ssa.Value, bool)
- func NewBinOp(op token.Token, x, y dst.Expr) *dst.BinaryExpr
- func NewFalse() *dst.BasicLit
- func NewFloat32(value float32) *dst.BasicLit
- func NewFloat64(value float64) *dst.BasicLit
- func NewInt(value int) *dst.BasicLit
- func NewNil() dst.Expr
- func NewPanic(args ...dst.Expr) *dst.CallExpr
- func NewString(value string) *dst.BasicLit
- func NewTypeExpr(t types.Type) (dst.Expr, error)
- func NewUnOp(op token.Token, x dst.Expr) *dst.UnaryExpr
- func PackageNameFromFunction(f *ssa.Function) string
- func PackageTypeFromFunction(f *ssa.Function) *types.Package
- func RunAllPaths(op PathSensitiveInstrOp, function *ssa.Function)
- func RunDFS(op InstrOp, function *ssa.Function)
- func RunForwardIterative(op IterativeAnalysis, function *ssa.Function)
- func SafeFunctionPos(function *ssa.Function) fn.Optional[token.Position]
- func TryTupleIndexType(v types.Type, i int) types.Type
- func ValuesWithSameData(v1 ssa.Value, v2 ssa.Value) bool
- func ZeroValueExpr(typ types.Type) (dst.Expr, error)
- type BlockPath
- type BlockTree
- type CalleeInfo
- type CalleeType
- type CallgraphAnalysisMode
- type Expression
- type FuncInfo
- func (f *FuncInfo) ClosestEnclosingScope(n dst.Node) *types.Scope
- func (f *FuncInfo) FreshNameAt(n dst.Node, prefix string, i int) string
- func (f *FuncInfo) FunctionScope() *types.Scope
- func (f *FuncInfo) NameExistsAt(n dst.Node, name string) bool
- func (f *FuncInfo) NewName(n dst.Node, prefix string) (*types.Scope, string)
- type InstrOp
- type IterativeAnalysis
- type NodeTree
- type PathSensitiveInstrOp
- type ValueOp
Constants ¶
This section is empty.
Variables ¶
var DummyPos = token.Position{
Filename: "unknown",
Offset: -1,
Line: -1,
Column: -1,
}
DummyPos is a dummy position returned to indicate that no position could be found. Can also be used when generating code, and the generated code has no position.
Functions ¶
func CallGraphReachable ¶
func CallGraphReachable(cg *callgraph.Graph, excludeMain bool, excludeInit bool) map[*ssa.Function]bool
CallGraphReachable returns a map where each entry is a reachable function
func CanType ¶
CanType checks some properties to ensure calling the Type() method on the value won't cause a segfault. This seems to be a problem in the SSA.
func FindImplementationMethod ¶
func FindImplementationMethod(prog *ssa.Program, tp types.Type, iface types.Type, methodName string) (method *ssa.Function, pointerRequired bool)
FindImplementationMethod looks up the ssa.Function for a reciever value of type tp when called for the given interface type and method name. This could require adding a pointer indirection if the given tp is e.g. a struct type, so the function also returns a boolean indicating if this is necessary.
func FindTypeByName ¶
FindTypeByName finds the given type from the given package, if it exists. Otherwise, returns nil
func FnReadsFrom ¶
FnReadsFrom returns true if an instruction in fn reads from val.
func FnWritesTo ¶
FnWritesTo returns true if an instruction in fn writes to val.
func GetArgs ¶
func GetArgs(instr ssa.CallInstruction) []ssa.Value
GetArgs returns the arguments of a function call including the receiver when the function called is a method. More precisely, it returns instr.Common().Args, but prepends instr.Common().Value if the call is "invoke" mode.
func GetPackageOfType ¶
GetPackageOfType finds the type.Package for a type. Does not require any ssa.* objects
func HasPathTo ¶
func HasPathTo(b1 *ssa.BasicBlock, b2 *ssa.BasicBlock, mem map[*ssa.BasicBlock]map[*ssa.BasicBlock]bool) bool
HasPathTo returns true if there is a control-flow path from b1 to b2. Use mem to amortize cost. If mem is nil, then the algorithm runs without memoization, and no map is allocated.
func InstrMethodKey ¶
func InstrMethodKey(instr ssa.CallInstruction) fn.Optional[string]
InstrMethodKey return a method key (as used in the analyzer state for indexing interface methods) if the instruction calls a method from an interface Returns an optional value TODO: this may not be idiomatic but I'm testing this "Optional" implementation
func InstrSwitch ¶
func InstrSwitch(visitor InstrOp, instr ssa.Instruction)
InstrSwitch is mainly a map from the different instructions to the methods of the visitor.
func IsChannelEnclosingType ¶
IsChannelEnclosingType return true if the type is a pointer to channel, a channel, or a data structure containing a channel
func IsErrorType ¶
IsErrorType returns true if t is the error type
func IsExternal ¶
IsExternal returns true if function is external (in ssa, when Blocks is nil)
func IsNillableType ¶
IsNillableType returns true if t is a type that can have the nil value.
func IsPredicateFunctionType ¶
IsPredicateFunctionType returns true if f is a function that can be interpreted as a predicate A function is a predicate if its last argument is either a boolean or an error.
func IsReturningFunctionType ¶
IsReturningFunctionType returns true if typ is the type of a function that returns values
func IsStaticallyDefinedLocal ¶
IsStaticallyDefinedLocal returns true if the value is statically defined, i.e. its value is entirely defined at compile time. This is the case for: - constants - slices of constants This does not analyze whether the value v is mutated; this function is useful in conjunction with the dataflow analyzes for example, which would track all dataflows to the values being analyzed. For values of nodes that do not have any other incoming edges, this function is sound: the dataflow analysis indirectly guarantees no data is flowing from a parameter of the function, or from being written to by another function being called in the function body.
TODO: make this function usable outside of dataflow analysis
func IsValueReturningCall ¶
IsValueReturningCall returns true if value is a call that returns some value
func IterateInstructions ¶
func IterateInstructions(function *ssa.Function, f func(index int, instruction ssa.Instruction))
IterateInstructions iterates through all the instructions in the function, in no specific order. It ignores the order in which blocks should be executed, but always starts with the first block.
func IterateValues ¶
IterateValues applies f to every value in the function. It might apply f several times to the same value if the value is from an instruction, the index of the instruction in the block will be provided, otherwise a value of -1 indicating the value is not in an instruction is given to the function.
func LastInstr ¶
func LastInstr(block *ssa.BasicBlock) ssa.Instruction
LastInstr returns the last instruction in a block. There is always a last instruction for a reachable block. Returns nil for an empty block (a block can be empty if it is non-reachable)
func LastInstrIsReturn ¶
func LastInstrIsReturn(block *ssa.BasicBlock) bool
LastInstrIsReturn returns true when the last instruction of the block is a return instruction
func MatchExtract ¶
MatchExtract is a proxy for matching a *ssa.Extract. It returns a non-nil value if x is some tuple-extraction value i.e. if x is extract y #0 for some y, then y is returned, otherwise nil
func MatchLoadField ¶
MatchLoadField matches instruction sequence: y = &z.Field x = *y and returns (z,true) if x is given as argument
func MatchNegation ¶
MatchNegation returns a non-nil ssa. value if x is the negation of some value y, in which case y is returned.
func MatchNilCheck ¶
MatchNilCheck returns a non-nil ssa value if x is a nil check, i.e. an instruction of the form 'y == nil' or 'y != nil' for some y
The returned ssa value is the value being checked against. The boolean is true if the check is a check of the form 'y == nil' and false if 'y != nil'
func NewFloat32 ¶
NewFloat32 returns a new AST structure that represents the float32 value
func NewFloat64 ¶
NewFloat64 returns a new AST structure that represents the float64 value
func NewTypeExpr ¶
NewTypeExpr returns an AST expression that represents the type t.
For example, the expression that represents a types.Struct will be of the form struct{...}.
For an integer, the expression is an identifier 'int'
func PackageNameFromFunction ¶
PackageNameFromFunction returns the best possible package name for a ssa.Function If the Function has a package, use that. If the function doesn't have a package, check if it's a method and use the package associated with its object If none of those are true, it must be an error, so try to extract the package name from the various error formats.
func PackageTypeFromFunction ¶
PackageTypeFromFunction returns the package associated with a function If the function has a package, return that. If the function is a method, return the package of its object
func RunAllPaths ¶
func RunAllPaths(op PathSensitiveInstrOp, function *ssa.Function)
RunAllPaths tries every possible simple path in the function and runs the instruction operation calling NewPath every time a new path from the initial Block is taken, and NewBlock every time a new Block in a path is entered. The operation op should implement the functionality to keep track of path information, either at the Block level or at the operation level.
func RunDFS ¶
RunDFS visits the blocks in the function in a depth-first search, running the instruction operation on every instruction in each Block.
func RunForwardIterative ¶
func RunForwardIterative(op IterativeAnalysis, function *ssa.Function)
RunForwardIterative visits the blocks in the function. At each Block visited, it queues the successors of the Block if the information for the Block has changed after visiting each of its instructions. All reachable blocks of the function will be visited if the call to ChangedOnBlock is true after each first visit to a given Block (the IterativeAnalysis structure must keep track of previously visited blocks, and ensure termination)
func SafeFunctionPos ¶
SafeFunctionPos returns the position of the function without panicking
func TryTupleIndexType ¶
TryTupleIndexType extract the type of element i in tuple type, or returns the type if it's not a tuple type
func ValuesWithSameData ¶
ValuesWithSameData defines when values v1 and v2 refer to the same data. WARNING: This function is incomplete, and encodes only the necessary information for validators. You should modify as much as you need.
Types ¶
type BlockPath ¶
type BlockPath struct {
// contains filtered or unexported fields
}
A BlockPath is a simple list of blocks
func (*BlockPath) ToBlocks ¶
func (b *BlockPath) ToBlocks() []*ssa.BasicBlock
ToBlocks turns a pointer-based list into a slice
type BlockTree ¶
type BlockTree struct { Block *ssa.BasicBlock Parent *BlockTree Children []*BlockTree }
BlockTree is a tree of ssa.BasicBlock
func (*BlockTree) AddChild ¶
func (t *BlockTree) AddChild(block *ssa.BasicBlock) *BlockTree
AddChild adds a child to t and returns pointer to that child
func (*BlockTree) CountPathOccurrences ¶
func (t *BlockTree) CountPathOccurrences(block *ssa.BasicBlock) int
CountPathOccurrences count how many times Block is encountered on the path to the root
func (*BlockTree) PathToLeaf ¶
PathToLeaf returns the path from the root to the receiver
type CalleeInfo ¶
type CalleeInfo struct { Callee *ssa.Function Type CalleeType }
CalleeInfo decorates a function with some CalleeType that records how the dataflow information of the function can be resolved or how the callee's identity was determined
type CalleeType ¶
type CalleeType int
A CalleeType gives information about how the callee was resolved
const ( // Static indicates the callee is a statically defined function Static CalleeType = 1 << iota // CallGraph indicates the callee is a function obtained from the call graph CallGraph // InterfaceContract indicates the callee is obtained from an interface contract (one particular instance // of an interface method to stand for all methods) InterfaceContract // InterfaceMethod indicates the calle is an interface method InterfaceMethod )
func (CalleeType) Code ¶
func (t CalleeType) Code() string
Code returns a short string representation of the type of callee
type CallgraphAnalysisMode ¶
type CallgraphAnalysisMode uint64
CallgraphAnalysisMode is either PointerAnalysis, StaticAnalysis, ClassHierarchyAnalysis, RapidTypeAnalysis or VariableTypeAnalysis for calling ComputeCallGraph
const ( // PointerAnalysis is over-approximating (slow) PointerAnalysis CallgraphAnalysisMode = iota // StaticAnalysis is under-approximating (fast) StaticAnalysis // ClassHierarchyAnalysis is a coarse over-approximation (fast) ClassHierarchyAnalysis // RapidTypeAnalysis TODO: review RapidTypeAnalysis // VariableTypeAnalysis TODO: review VariableTypeAnalysis )
func (CallgraphAnalysisMode) ComputeCallgraph ¶
ComputeCallgraph computes the call graph of prog using the provided mode.
type Expression ¶
An Expression can be used to manipulate expression for symbolic execution. TODO: implementations
type FuncInfo ¶
type FuncInfo struct { // Package is the package where the function is declared Package *decorator.Package // Decorator is the decorator object that contains also the maps from dst to ast objects Decorator *decorator.Decorator // File if the file where the function is declared File *dst.File // NodeMap stores parent information for the ast NodeMap map[dst.Node]*NodeTree // Decl is the function declaration in the ast Decl *dst.FuncDecl }
FuncInfo contains information about a function declaration in the ast.
func (*FuncInfo) ClosestEnclosingScope ¶
ClosestEnclosingScope returns the closest scope to the node n.
For example, in :
func f(..) { if(b) { node1 } else { node2 } node 3 }
the closest scope for node1 is the then-branch scope, for node2 the else-branch scope and for node3 the function scope
func (*FuncInfo) FreshNameAt ¶
FreshNameAt returns a fresh identifier at node n. The identifier will be of the form `prefix(NUM)` where NUM is empty or some integer. For example, FreshNameAt(n,"s", 0) may return "s", "s0" or "s1".
func (*FuncInfo) FunctionScope ¶
FunctionScope returns the scope of the function
func (*FuncInfo) NameExistsAt ¶
NameExistsAt checks whether name is a declared identifier at node n
func (*FuncInfo) NewName ¶
NewName returns a new identifier that is a fresh name at node n. If successful, the scope should be non-nil and addition of the identifier in the program should be done by adding the identifier to the scope returned (if the intention is to declare the identifier next to n).
type InstrOp ¶
type InstrOp interface { DoDebugRef(*ssa.DebugRef) DoUnOp(*ssa.UnOp) DoBinOp(*ssa.BinOp) DoCall(*ssa.Call) DoChangeInterface(*ssa.ChangeInterface) DoChangeType(*ssa.ChangeType) DoConvert(*ssa.Convert) DoSliceArrayToPointer(*ssa.SliceToArrayPointer) DoMakeInterface(*ssa.MakeInterface) DoExtract(*ssa.Extract) DoSlice(*ssa.Slice) DoReturn(*ssa.Return) DoRunDefers(*ssa.RunDefers) DoPanic(*ssa.Panic) DoSend(*ssa.Send) DoStore(*ssa.Store) DoIf(*ssa.If) DoJump(*ssa.Jump) DoDefer(*ssa.Defer) DoGo(*ssa.Go) DoMakeChan(*ssa.MakeChan) DoAlloc(*ssa.Alloc) DoMakeSlice(*ssa.MakeSlice) DoMakeMap(*ssa.MakeMap) DoRange(*ssa.Range) DoNext(*ssa.Next) DoFieldAddr(*ssa.FieldAddr) DoField(*ssa.Field) DoIndexAddr(*ssa.IndexAddr) DoIndex(*ssa.Index) DoLookup(*ssa.Lookup) DoMapUpdate(*ssa.MapUpdate) DoTypeAssert(*ssa.TypeAssert) DoMakeClosure(*ssa.MakeClosure) DoPhi(*ssa.Phi) DoSelect(*ssa.Select) }
An InstrOp must implement methods for ALL possible SSA instructions
type IterativeAnalysis ¶
type IterativeAnalysis interface { InstrOp Pre(instruction ssa.Instruction) Post(instruction ssa.Instruction) NewBlock(block *ssa.BasicBlock) ChangedOnEndBlock() bool // ChangedOnEndBlock returns a boolean signaling the information has changed. }
IterativeAnalysis is an iterative analysis that extends an InstrOp with a function executed each time a new Block is visited, and a function that queries the analysis once the Block has been visited to check whether the analysis information has changed.
type PathSensitiveInstrOp ¶
type PathSensitiveInstrOp interface { InstrOp NewPath() // Called when a new path is inspected. EndPath() // Called when a path ended. NewBlock(*ssa.BasicBlock) // Called when a new Block is entered on a path. }
PathSensitiveInstrOp is an InstrOp with additional functionality to indicate that the operation is running on a different path
type ValueOp ¶
type ValueOp interface { DoFunction(*ssa.Function) DoFreeVar(*ssa.FreeVar) DoParameter(*ssa.Parameter) DoConst(*ssa.Const) DoGlobal(*ssa.Global) DoBuiltin(*ssa.Builtin) DoAlloc(*ssa.Alloc) DoPhi(*ssa.Phi) DoCall(*ssa.Call) DoBinOp(*ssa.BinOp) DoUnOp(*ssa.UnOp) DoChangeType(*ssa.ChangeType) DoSliceToArrayPointer(*ssa.SliceToArrayPointer) DoMakeInterface(*ssa.MakeInterface) DoMakeClosure(*ssa.MakeClosure) DoMakeMap(*ssa.MakeMap) DoMakeChan(*ssa.MakeChan) DoMakeSlice(*ssa.MakeSlice) DoSlice(*ssa.Slice) DoFieldAddr(*ssa.FieldAddr) DoField(*ssa.Field) DoIndexAddr(*ssa.IndexAddr) DoIndex(*ssa.Index) DoLookup(*ssa.Lookup) DoSelect(*ssa.Select) DoRange(*ssa.Range) DoNext(*ssa.Next) DoTypeAssert(*ssa.TypeAssert) DoExtract(*ssa.Extract) }
A ValueOp contains the methods necessary to implement an exhaustive switch on ssa.Value