Empc: Effective Path Prioritization for Symbolic Execution
- PATH is a technique for guiding symbolic execution by computing minimum path covers to achieve comprehensive and non-redundant code coverage.
- It transforms cyclic control-flow into acyclic subproblems using virtual node techniques and recombines covers for global efficiency.
- Empc integrates online scheduling with lightweight dependence analysis in KLEE to prune infeasible paths and reduce resource usage significantly.
Searching arXiv for the target paper and a few closely related symbolic-execution references. Searching arXiv for “Empc Effective Path Prioritization for Symbolic Execution with Path Cover”. Empc is a path prioritization technique for symbolic execution that reframes path selection as a minimum path cover problem on the inter-procedural control-flow graph rather than a ranking problem over exponentially many execution paths. Implemented on top of KLEE, it targets the path explosion problem by computing a small set of paths whose union covers all code regions of the tested program, then guiding symbolic execution toward those paths while adapting to run-time infeasibility through lightweight program-dependence analysis. The method is presented in “Empc: Effective Path Prioritization for Symbolic Execution with Path Cover” (Yao et al., 6 May 2025).
1. Path explosion and the change in prioritization objective
Symbolic execution explores program behaviors by treating program inputs as symbolic variables and symbolically tracking the path constraints that arise at conditional branches. Each branch causes the executor to fork states and explore both branch outcomes when feasible. If a program has branching points with average branching factor , the number of syntactic paths scales as approximately ; in practice, the number of states and paths to reason about can grow exponentially with program size. This path explosion produces severe CPU and memory pressure, saturates SMT solvers, and limits coverage on large, real-world programs (Yao et al., 6 May 2025).
Existing engines mitigate this behavior with path prioritization heuristics. KLEE includes breadth-first search, random-path, and non-uniform random search variants; other work prioritizes closest uncovered branches, favors minimally explored subpaths, chooses pending-feasible paths, or uses concrete constraint guidance. Empc’s central criticism is that these methods rank paths using static rules or heuristics that may not generalize across diverse programs and path structures, and that their selection logic is not anchored in a global objective of code coverage with minimum redundancy (Yao et al., 6 May 2025).
Empc therefore changes the unit of prioritization. Rather than scoring among exponentially many paths, it computes a small set of paths whose union covers the whole code. This suggests a shift from local branch preference to global coverage structure. The minimum path cover objective itself belongs to a broader graph-theoretic family of path cover and path partition problems (Fernau et al., 2022), but Empc specializes that objective to symbolic execution over program control-flow graphs (Yao et al., 6 May 2025).
2. Minimum path cover on the inter-procedural control-flow graph
Empc models the program CFG as a directed graph , where is the set of basic blocks and is the set of directed control-flow edges. A directed path in is a sequence with . A path cover 0 is a set of directed paths whose union of vertices covers all nodes:
1
The typical path-cover constraint is vertex-disjointness among paths, so each vertex belongs to exactly one path. The minimum path cover (MPC) is any path cover 2 of minimum cardinality:
3
On DAGs, MPC admits a classic reduction to maximum bipartite matching. Empc constructs the DAG’s bipartite transform 4 by duplicating every vertex 5 into two copies 6 and 7, then adding an edge 8 whenever 9 reaches 0 in the DAG, including direct edges. If 1 is a maximum matching in 2, then the MPC size satisfies
3
Empc computes maximum matchings with Hopcroft–Karp in 4, with reachability obtained by transitive closure or another indexing method; the paper quotes 5, 6, for reachability precomputation (Yao et al., 6 May 2025).
This formulation is the algorithmic core of Empc’s reduction in search space. Instead of considering all syntactic paths, symbolic execution is steered toward the chains in one or more MPCs. The cover preserves coverage potential because every basic block belongs to at least one selected chain, while the minimum-cardinality objective suppresses redundant path exploration (Yao et al., 6 May 2025).
3. Decomposing cyclic control flow into acyclic subproblems
General inter-procedural CFGs contain cycles from loops and call/return structure, and MPC on cyclic digraphs is NP-hard. Empc handles this by transforming the iCFG into acyclic subproblems and then recombining the resulting covers (Yao et al., 6 May 2025).
For caller–callee cycles, Empc adds a virtual return node as successor to all returns in the callee, then splits the graph into a one-entry-one-exit callee subgraph 7 and a transformed graph 8 in which the callee body is removed and the callee entry and exit are merged into a single virtual vertex. MPCs are computed separately on 9 and 0, then spliced using
1
where 2 is the maximum number of paths in 3 that go through the merged vertex. This equality preserves minimum cover cardinality when the callee is reintroduced (Yao et al., 6 May 2025).
For loop cycles, Empc removes back edges, introduces a virtual representation for the loop body, and splits the graph into a loop subgraph with one entry and multiple exits, plus a transformed acyclic graph in which the loop entry is replaced by a virtual vertex connected to the exits. It then uses the same recombination form,
4
with 5 defined by the maximum number of transformed paths that traverse the loop-exit edges. Repeated loop iterations are not unrolled in the static cover; they are handled at run time by selecting successive paths from the loop subgraph’s MPC until exhausted, then steering to an exit (Yao et al., 6 May 2025).
These transformations create tractable acyclic analysis units while maintaining a formal minimality guarantee under recombination. This is one of Empc’s main distinguishing features: it does not merely prune paths heuristically, but reduces cyclic control flow to acyclic units on which the MPC objective is computationally accessible (Yao et al., 6 May 2025).
4. Multiple MPCs and online scheduling in KLEE
A single maximum matching need not be unique, and different maximum matchings induce different MPCs. Empc treats this non-uniqueness as a source of diversity. It enumerates multiple maximum matchings in the bipartite graph using Uno’s algorithm, which exchanges edges along even-length alternating cycles and paths in the symmetric difference of matchings. To keep preprocessing tractable, it relies on two practical measures: decomposition into many small subgraphs and a cap on the number of MPCs per large subgraph (Yao et al., 6 May 2025).
At run time, Empc integrates as a KLEE searcher through the state update and state selection interfaces. For each subgraph it maintains a group of precomputed MPCs. When KLEE forks states at a branch, Empc compares each candidate state’s current subpath against the cover paths in the relevant MPC group. It selects a state whose subpath matches some path in at least one MPC, then prunes MPCs that no longer match the taken prefix, while ensuring that at least one MPC remains active (Yao et al., 6 May 2025).
This online pruning preserves diversity while incorporating feasibility feedback. No explicit solver caching or pending-constraint mechanism is added; the performance gain comes from structured path-space pruning. The paper’s interpretation is that by restricting exploration to a small number of chains that cover the code, Empc reduces state multiplicity and SMT load, which in turn improves throughput and memory behavior (Yao et al., 6 May 2025).
5. Infeasible paths, dependence guidance, and implementation
Because MPCs are computed from CFG structure rather than semantic feasibility, some selected paths may be infeasible under actual path constraints. Empc addresses this with lightweight dependence analysis. If a branch condition at 6 uses variable 7, Empc maps 8 to a predecessor block that last defines 9 without intervening redefinitions. It also records potential dependence when whether 0 is defined depends on a prior branch. When an MPC-guided path becomes infeasible, Empc locates the last unvisited block on that path, traces back to an ancestor with dependence on the failing branch, and resumes from states reaching that ancestor, including previously ignored states whose subpaths did not match the current MPC group (Yao et al., 6 May 2025).
The analysis is deliberately lightweight. Nested or multilevel pointer flows and indirect calls are not analyzed, which reduces overhead but can miss some dependence relations. The paper cites an average increase of approximately 1 in internal basic-block coverage attributable to this dependence guidance in comparison with a fallback strategy that uses depth-first search for infeasible paths (Yao et al., 6 May 2025).
Implementation is on top of KLEE 3.1 and LLVM 13.0.0. Empc parses LLVM IR, builds the iCFG, identifies call and loop structures, performs the virtual-node transformations for cyclic regions, computes reachability and bipartite transforms, and implements Hopcroft–Karp and maximum-matching enumeration from scratch. Dependence analysis uses LLVM def-use chains and BFS over instructions and basic blocks. The system stores, per subgraph, sets of MPCs and lightweight path-prefix matchers; it makes no changes to the program IR, and indirect calls are not modeled in detail (Yao et al., 6 May 2025).
6. Empirical results
The evaluation covers 12 real-world open-source programs from calculators, text tools, binary utilities, image/video processing, and networking, including bc, tic, make, bison, readelf, strip-new, nasm, tiffinfo, jasper, transicc, flvmeta, and curl. Experiments run on a 128-core Xeon machine, with each KLEE instance limited to 1 core and 32 GB RAM. Each run lasts 10 hours and is repeated 10 times. Comparisons include KLEE baselines—bfs, dfs, random-state, random-path, and several nurs variants—and three prior strategies: sgs, Learch, and cgs (Yao et al., 6 May 2025).
Because Learch and cgs require older KLEE/LLVM versions, coverage is reported in two groups: internal basic block coverage against KLEE baselines on all 12 programs, and external line coverage via gcov against KLEE baselines plus sgs/Learch/cgs on 8 compatible programs (Yao et al., 6 May 2025).
| Metric | Empc result | Comparison |
|---|---|---|
| Basic-block coverage | 19,853 | 19.6% more than bfs at 16,602 |
| Line coverage | 17,634 | 24.4% more than cgs at 14,173 |
| Security violations | 70 | 24 more than the second-best baseline |
| Unique violations | 15 | Missed by all others |
| Peak heap reduction | up to 93.5% | On flvmeta |
| Symbolic-state reduction | up to 88.6% | On jasper |
| Preprocessing time | often tens of seconds | at most ~400 s on strip-new |
| Searcher overhead | average ~12% | under ~400 s total for 8 of 12 programs |
Empc also finds 24 more security violations than KLEE’s best search strategy and reduces KLEE’s peak heap memory usage by up to 93.5% (Yao et al., 6 May 2025). These results support the paper’s claim that MPC guidance improves not only coverage but also bug-finding yield and resource efficiency. A plausible implication is that the reduction in state count permits deeper exploration within a fixed time budget.
7. Limitations, practical scope, and future work
Empc’s limitations are closely tied to its abstraction boundary. In programs where most syntactic paths are infeasible, CFG-only covers can mislead. The dependence analysis mitigates this but remains shallow: no deep pointer analysis is performed, indirect calls are not modeled in detail, and extraordinary loops with multiple headers are not handled, although the paper reports such loops as rare, approximately 0.3% in the benchmarks (Yao et al., 6 May 2025).
Enumeration of all maximum matchings can also become expensive on very large bipartite graphs. Empc addresses this through decomposition and by capping the number of MPCs per subgraph, but this is an approximation that trades diversity against preprocessing cost. Some complex programs, such as nasm and transicc, incur higher graph-level bookkeeping overhead during search, even though the coverage and memory benefits remain (Yao et al., 6 May 2025).
The paper positions Empc as especially effective when broader code coverage is needed under tight resource budgets, and when KLEE’s default strategies saturate memory or stall in hot regions. It recommends enabling dependence fallback by default, capping the number of MPCs only for very large subgraphs, and running on KLEE 3.1 with LLVM 13 without IR modification (Yao et al., 6 May 2025).
Future directions include adaptive MPC recomputation using dynamic feedback, richer inter-procedural points-to and indirect-call handling, more precise loop modeling, and cross-engine or fuzzing integration. These proposals suggest that Empc’s cover-driven prioritization may be extensible beyond KLEE, but the current results are confined to the implemented KLEE-based searcher and its benchmark regime (Yao et al., 6 May 2025).