Safe Haskell | None |
---|

This internal module implements the CallGraph and the CallGraphSCC traversal together because the traversal depends on CallGraph internals. They are meant to be used through their respective interfaces, but this internal module is accessible in case their APIs are insufficient to do something a user might want. These internals are not stable.

- data CallGraph = forall pta . PointsToAnalysis pta => CallGraph CG pta
- type CG = Gr CallNode CallEdge
- data CallEdge
- data CallNode
- = DefinedFunction Function
- | ExtFunction ExternalFunction
- | UnknownFunction

- callGraph :: PointsToAnalysis a => Module -> a -> [Function] -> CallGraph
- callGraphRepr :: CallGraph -> CG
- callValueTargets :: CallGraph -> Value -> [Value]
- callSiteTargets :: CallGraph -> Instruction -> [Value]
- callGraphFunctions :: CallGraph -> [Function]
- functionCallees :: CallGraph -> Function -> [Value]
- allFunctionCallees :: CallGraph -> Function -> [Value]
- functionCallers :: CallGraph -> Function -> [Value]
- allFunctionCallers :: CallGraph -> Function -> [Value]
- data ComposableAnalysis compSumm funcLike
- callGraphSCCTraversal :: FuncLike funcLike => CallGraph -> ([funcLike] -> summary -> summary) -> summary -> summary
- parallelCallGraphSCCTraversal :: (NFData summary, Monoid summary, FuncLike funcLike) => CallGraph -> ([funcLike] -> summary -> summary) -> summary -> summary
- callGraphAnalysis :: (FuncLike funcLike, Eq summary) => (funcLike -> summary -> summary) -> [funcLike] -> summary -> summary
- callGraphAnalysisM :: (FuncLike funcLike, Eq summary, Monad m) => (m summary -> summary) -> (funcLike -> summary -> m summary) -> [funcLike] -> summary -> summary
- callGraphComposeAnalysis :: (FuncLike funcLike, Monoid compSumm, Eq compSumm) => [ComposableAnalysis compSumm funcLike] -> [funcLike] -> compSumm -> compSumm
- composableAnalysis :: (NFData summary, Monoid summary, Eq summary, FuncLike funcLike) => (funcLike -> summary -> summary) -> Lens' compSumm summary -> ComposableAnalysis compSumm funcLike
- composableDependencyAnalysis :: (NFData summary, Monoid summary, Eq summary, FuncLike funcLike) => (deps -> funcLike -> summary -> summary) -> Lens' compSumm summary -> Getter compSumm deps -> ComposableAnalysis compSumm funcLike
- composableAnalysisM :: (NFData summary, Monoid summary, Eq summary, Monad m, FuncLike funcLike) => (m summary -> summary) -> (funcLike -> summary -> m summary) -> Lens' compSumm summary -> ComposableAnalysis compSumm funcLike
- composableDependencyAnalysisM :: (NFData summary, Monoid summary, Eq summary, Monad m, FuncLike funcLike) => (m summary -> summary) -> (deps -> funcLike -> summary -> m summary) -> Lens' compSumm summary -> Getter compSumm deps -> ComposableAnalysis compSumm funcLike

# Types

An opaque wrapper for the callgraph. The nodes are functions and the edges are calls between them.

forall pta . PointsToAnalysis pta => CallGraph CG pta |

DirectCall | A static call to a known function |

IndirectCall | A possible call to a known function through a function pointer |

UnknownCall | A possible call to an unknown function through a function pointer |

The nodes are actually a wrapper type:

DefinedFunction Function | An actual function defined in this |

ExtFunction ExternalFunction | An externally-defined function with a declaration
in the |

UnknownFunction | A function called indirectly that may not have
any definition or declaration within the |

# Constructor

:: PointsToAnalysis a | |

=> Module | |

-> a | A points-to analysis (to resolve function pointers) |

-> [Function] | The entry points to the |

-> CallGraph |

Build a call graph for the given `Module`

using a pre-computed
points-to analysis. The String parameter identifies the program
entry point.

FIXME: `entryPoint`

is not respected.

FIXME: Function pointers can be bitcasted - be sure to respect those when adding indirect edges.

# Accessors

callGraphRepr :: CallGraph -> CGSource

Convert the CallGraph to a graph ADT that can be traversed, manipulated, or easily displayed with graphviz.

For now, this representation is not guaranteed to remain stable.

callValueTargets :: CallGraph -> Value -> [Value]Source

Given the value called by a Call or Invoke instruction, return all of the possible Functions or ExternalFunctions that it could be.

callSiteTargets :: CallGraph -> Instruction -> [Value]Source

Given a Call or Invoke instruction, return the list of possible callees. All returned Values will be either Functions or ExternalFunctions.

Passing a non-call/invoke instruction will trigger a noisy pattern matching failure.

callGraphFunctions :: CallGraph -> [Function]Source

Get all of the functions defined in this module from the CallGraph

functionCallees :: CallGraph -> Function -> [Value]Source

allFunctionCallees :: CallGraph -> Function -> [Value]Source

functionCallers :: CallGraph -> Function -> [Value]Source

allFunctionCallers :: CallGraph -> Function -> [Value]Source

# CallGraphSCC Traversal

data ComposableAnalysis compSumm funcLike Source

An abstract representation of a composable analysis. Construct
these with the smart constructors `composableAnalysis`

,
`composableDependencyAnalysis`

, `composableAnalysisM`

, and
`composableDependencyAnalysisM`

.

Use `callGraphComposeAnalysis`

to convert a list of these into a
summary function for use with the call graph traversals.

:: FuncLike funcLike | |

=> CallGraph | The callgraph |

-> ([funcLike] -> summary -> summary) | A function to process a strongly-connected component |

-> summary | An initial summary value |

-> summary |

Traverse the callgraph bottom-up with an accumulator function.

callGraphSCCTraversal cg f seed

This example applies the folding function `f`

over each
strongly-connected component in the callgraph bottom-up with a
starting `seed`

. Each strongly-connected component is processed as
a unit. The final accumulated value (based on `seed`

) is returned.

The function `f`

is responsible for approximating the analysis
value for the SCC in whatever way makes sense for the analysis.

parallelCallGraphSCCTraversal :: (NFData summary, Monoid summary, FuncLike funcLike) => CallGraph -> ([funcLike] -> summary -> summary) -> summary -> summarySource

Just like `callGraphSCCTraversal`

, except strongly-connected
components are analyzed in parallel. Each component is analyzed as
soon as possible after its dependencies have been analyzed.

# Adaptors

callGraphAnalysis :: (FuncLike funcLike, Eq summary) => (funcLike -> summary -> summary) -> [funcLike] -> summary -> summarySource

Make a call-graph SCC summary function from a pure summary function. The function is applied to each function in the SCC in an arbitrary order. It returns the resulting summary obtained by repeated evaluation until a fixed-point is reached.

:: (FuncLike funcLike, Eq summary, Monad m) | |

=> (m summary -> summary) | A function to unwrap a monadic result from the summary |

-> (funcLike -> summary -> m summary) | Summary function |

-> [funcLike] -> summary -> summary |

Make a call-graph SCC summary function from a basic monadic summary function and a function to evaluate the function in its monad and unwrap the monadic value.

The monadic equivalent of `callGraphAnalysis`

.

callGraphComposeAnalysis :: (FuncLike funcLike, Monoid compSumm, Eq compSumm) => [ComposableAnalysis compSumm funcLike] -> [funcLike] -> compSumm -> compSummSource

Compose a list of analyses into a pure summary function for use in a callGraphSCCTraversal. The advantage of using a composable analysis is that it only traverses the call graph once. At each SCC, all analyses are applied until their fixed-point is reached.

This makes it easier to share intermediate values (like CFGs) between analyses without having to recompute them or store them on the side.

The input analyses are processed *in order* (left-to-right). This means that analyses with dependencies should come *after* the analyses they depend on in the list. This is not currently statically enforced - your dependency summaries will just be missing information you might have expected if you get the order wrong.

composableAnalysis :: (NFData summary, Monoid summary, Eq summary, FuncLike funcLike) => (funcLike -> summary -> summary) -> Lens' compSumm summary -> ComposableAnalysis compSumm funcLikeSource

Create a pure composable analysis from a summary function and a Lens that accesses the summary for this function (given the composite summary). The lens is used to access the current state of this analysis and to update the state for this analysis after it is run.

composableDependencyAnalysis :: (NFData summary, Monoid summary, Eq summary, FuncLike funcLike) => (deps -> funcLike -> summary -> summary) -> Lens' compSumm summary -> Getter compSumm deps -> ComposableAnalysis compSumm funcLikeSource

Like `composableAnalysis`

, but with an extra lens that is used to
extract *dependency* information from the composite summary, which
is then fed into this summary function.

The intended use is that some analysis will have a dependency on an earlier analysis summary. The lens is used to extract the relevant part of the composite summary. A dependency on multiple earlier analysis summaries can be expressed by providing a lens that extracts a *tuple* containing all relevant analyses.

composableAnalysisM :: (NFData summary, Monoid summary, Eq summary, Monad m, FuncLike funcLike) => (m summary -> summary) -> (funcLike -> summary -> m summary) -> Lens' compSumm summary -> ComposableAnalysis compSumm funcLikeSource

A monadic version of `composableAnalysis`

. The first argument
here is a function to unwrap a monadic value (something like
runIdentity or runReader).

composableDependencyAnalysisM :: (NFData summary, Monoid summary, Eq summary, Monad m, FuncLike funcLike) => (m summary -> summary) -> (deps -> funcLike -> summary -> m summary) -> Lens' compSumm summary -> Getter compSumm deps -> ComposableAnalysis compSumm funcLikeSource

A monadic version of `composableDependencyAnalysis`

.