// runPTA runs the pointer analysis of the selected SSA value or address. func runPTA(conf *pointer.Config, v ssa.Value, isAddr bool) (ptrs []pointerResult, err error) { T := v.Type() if isAddr { conf.AddIndirectQuery(v) T = deref(T) } else { conf.AddQuery(v) } ptares := ptrAnalysis(conf) var ptr pointer.Pointer if isAddr { ptr = ptares.IndirectQueries[v] } else { ptr = ptares.Queries[v] } if ptr == (pointer.Pointer{}) { return nil, fmt.Errorf("pointer analysis did not find expression (dead code?)") } pts := ptr.PointsTo() if pointer.CanHaveDynamicTypes(T) { // Show concrete types for interface/reflect.Value expression. if concs := pts.DynamicTypes(); concs.Len() > 0 { concs.Iterate(func(conc types.Type, pta interface{}) { labels := pta.(pointer.PointsToSet).Labels() sort.Sort(byPosAndString(labels)) // to ensure determinism ptrs = append(ptrs, pointerResult{conc, labels}) }) } } else { // Show labels for other expressions. labels := pts.Labels() sort.Sort(byPosAndString(labels)) // to ensure determinism ptrs = append(ptrs, pointerResult{T, labels}) } sort.Sort(byTypeString(ptrs)) // to ensure determinism return ptrs, nil }
func findCallees(conf *pointer.Config, site ssa.CallInstruction) ([]*ssa.Function, error) { // Avoid running the pointer analysis for static calls. if callee := site.Common().StaticCallee(); callee != nil { switch callee.String() { case "runtime.SetFinalizer", "(reflect.Value).Call": // The PTA treats calls to these intrinsics as dynamic. // TODO(adonovan): avoid reliance on PTA internals. default: return []*ssa.Function{callee}, nil // singleton } } // Dynamic call: use pointer analysis. conf.BuildCallGraph = true cg := ptrAnalysis(conf).CallGraph cg.DeleteSyntheticNodes() // Find all call edges from the site. n := cg.Nodes[site.Parent()] if n == nil { return nil, fmt.Errorf("this call site is unreachable in this analysis") } calleesMap := make(map[*ssa.Function]bool) for _, edge := range n.Out { if edge.Site == site { calleesMap[edge.Callee.Func] = true } } // De-duplicate and sort. funcs := make([]*ssa.Function, 0, len(calleesMap)) for f := range calleesMap { funcs = append(funcs, f) } sort.Sort(byFuncPos(funcs)) return funcs, nil }