Skip to content

Commit b07f56a

Browse files
fabianbs96fabianbsboehmsebMMory
authored
Path Tracing (#640)
* Add explicit ExplodedSuperGraph and a version of the IDESolver that fills it with content. TODO: Add PathSensitivityManager + unittests * Add more TODOs * Add GraphTraits * Add pathsDagTo (not tested yet) * Add Z3 submodule * Set Z3 version * Add Z3-related stuff (WIP) * Added now basic functionality for path sensitivity (compiles, but not tested yet) * Implement LLVMPathConstraints * Add unittest for PathTracking (C/C++ test files are still missing) and resolve a lot of compilation errors * Make a lot of the unittests work (still not completed) * Fix Config propagation * Finally, fix all unittests * minor * redirect z3 submodule * Checkout the right z3 branch * bump z3 * add bulk dag-generation (not tested yet) * Some more fixes * Add filters to PSM * Better integrate filter into PSM * minor * Improve on reverseDAG * minor improvements in reverseDAG * Bump z3 * Fix depdendency issue with utils->config * Fix bugs indiced by reverse merging from development + bump z3 * Make Z3 optional * Workaround weird cmake behavior * Fix seeds in exploded supergraph * Add forward minimize graph * Add one Test for forward minimize DAG * Fix in createEquivalentGraphFrom * Fix filterOutUnreachableNodes * Fix: DFAMinimizer edge comparison * Fix compilation on ubuntu22 * Improve createEquivalentGraphFrom * Resolve errors due to merging * Fix z3 dependency * Fix UAF when copying an ExplicitESG * Get rid of NodeRef::DSI * Fix compile error due to merge * minor * More const in Table * Give the PathTracing Filters more power * Fix null error * Fix Path Tracing with chaotic edge saving due to new Worklist structure in IDESolver * Some cleanup * pre-commit * Apply some review comments * Write ESG to temp file instead of hard-coded file * minor * pre-commitIDESolver.h * pre-commit Utilities.h * trailing whitespace IDESolver.h * Fix errors due to merge * Integrate free-functions NToString and DToString into ExplicitESG * Adapt invariants due to chaotic solving (worklist vs recursion) * Add LLVMSSA version of pathsDagTo as temporary solution until f-IDESolverStrategy is merged * minor * Use system z3 * Find z3 from psr installation * Assert size overflow * Enable Z3 in CI * fix naming issue --------- Co-authored-by: Fabian Benedikt Schiebel <fabianbs@mail.uni-paderborn.de> Co-authored-by: Sebastian Böhm <boehmseb@cs.uni-saarland.de> Co-authored-by: Martin Mory <mmo@mail.upb.de>
1 parent 1e9f3b7 commit b07f56a

62 files changed

Lines changed: 5090 additions & 91 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.clang-tidy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ Checks: '-*,
3131
modernize-*,
3232
-modernize-use-trailing-return-type,
3333
performance-*,
34-
clang-analyzer-*,
34+
clang-analyzer-*
3535
'
3636

3737
FormatStyle: LLVM

.github/workflows/ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ jobs:
6565
-DCMAKE_BUILD_TYPE=${{ matrix.build }} \
6666
-DBUILD_SWIFT_TESTS=ON \
6767
-DPHASAR_DEBUG_LIBDEPS=ON \
68+
-DPHASAR_USE_Z3=ON \
6869
${{ matrix.flags }} \
6970
-G Ninja
7071
cmake --build .

CMakeLists.txt

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
cmake_minimum_required (VERSION 3.9)
1+
cmake_minimum_required (VERSION 3.14)
22

33
# Avoid IPO/LTO Warnings:
44
cmake_policy(SET CMP0069 NEW)
@@ -150,6 +150,8 @@ option(PHASAR_BUILD_UNITTESTS "Build all tests (default is ON)" ON)
150150

151151
option(PHASAR_BUILD_OPENSSL_TS_UNITTESTS "Build OPENSSL typestate tests (require OpenSSL, default is OFF)" OFF)
152152

153+
option(PHASAR_USE_Z3 "Build the phasar_llvm_pathsensitivity library with Z3 support for constraint solving (default is OFF)" OFF)
154+
153155
option(PHASAR_BUILD_IR "Build IR test code (default is ON)" ON)
154156

155157
option(PHASAR_ENABLE_CLANG_TIDY_DURING_BUILD "Run clang-tidy during build (default is OFF)" OFF)
@@ -259,11 +261,13 @@ add_subdirectory(external/json)
259261
# The following workaround may collapse or become unnecessary once the issue is
260262
# changed or fixed in nlohmann_json_schema_validator.
261263

262-
#Override option of nlohmann_json_schema_validator to not build its tests
264+
# Override option of nlohmann_json_schema_validator to not build its tests
263265
set(BUILD_TESTS OFF CACHE BOOL "Build json-schema-validator-tests")
264266

265267
if (PHASAR_IN_TREE)
266268
set_property(GLOBAL APPEND PROPERTY LLVM_EXPORTS nlohmann_json_schema_validator)
269+
270+
set (PHASAR_USE_Z3 OFF)
267271
endif()
268272

269273
# Json Schema Validator
@@ -337,6 +341,21 @@ if(NOT LLVM_ENABLE_RTTI AND NOT PHASAR_IN_TREE)
337341
message(FATAL_ERROR "PhASAR requires a LLVM version that is built with RTTI")
338342
endif()
339343

344+
# Z3 Solver
345+
if(PHASAR_USE_Z3)
346+
# This z3-version is the same version LLVM requires; however, we cannot just use Z3 via the LLVM interface
347+
# as it lacks some functionality (such as z3::expr::simplify()) that we require
348+
find_package(Z3 4.7.1 REQUIRED)
349+
350+
if(NOT TARGET z3)
351+
add_library(z3 IMPORTED SHARED)
352+
set_property(TARGET z3 PROPERTY
353+
IMPORTED_LOCATION ${Z3_LIBRARIES})
354+
set_property(TARGET z3 PROPERTY
355+
INTERFACE_INCLUDE_DIRECTORIES ${Z3_INCLUDE_DIR})
356+
endif()
357+
endif(PHASAR_USE_Z3)
358+
340359
# Clang
341360
option(BUILD_PHASAR_CLANG "Build the phasar_clang library (default is ON)" ON)
342361

Config.cmake.in

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ find_package(LLVM 14 REQUIRED CONFIG)
1313

1414
set(PHASAR_USE_LLVM_FAT_LIB @USE_LLVM_FAT_LIB@)
1515
set(PHASAR_BUILD_DYNLIB @PHASAR_BUILD_DYNLIB@)
16+
set(PHASAR_USE_Z3 @PHASAR_USE_Z3@)
17+
18+
if (PHASAR_USE_Z3)
19+
find_dependency(Z3)
20+
endif()
1621

1722
set(PHASAR_COMPONENTS
1823
utils

include/phasar/DataFlow.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "phasar/DataFlow/IfdsIde/Solver/IDESolver.h"
2525
#include "phasar/DataFlow/IfdsIde/Solver/IFDSSolver.h"
2626
#include "phasar/DataFlow/IfdsIde/Solver/JumpFunctions.h"
27+
#include "phasar/DataFlow/IfdsIde/Solver/PathAwareIDESolver.h"
2728
#include "phasar/DataFlow/IfdsIde/Solver/PathEdge.h"
2829
#include "phasar/DataFlow/IfdsIde/SolverResults.h"
2930
#include "phasar/DataFlow/IfdsIde/SpecialSummaries.h"
@@ -32,5 +33,7 @@
3233
#include "phasar/DataFlow/Mono/IntraMonoProblem.h"
3334
#include "phasar/DataFlow/Mono/Solver/InterMonoSolver.h"
3435
#include "phasar/DataFlow/Mono/Solver/IntraMonoSolver.h"
36+
#include "phasar/DataFlow/PathSensitivity/PathSensitivityConfig.h"
37+
#include "phasar/DataFlow/PathSensitivity/PathSensitivityManager.h"
3538

3639
#endif // PHASAR_DATAFLOW_H
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/******************************************************************************
2+
* Copyright (c) 2022 Philipp Schubert.
3+
* All rights reserved. This program and the accompanying materials are made
4+
* available under the terms of LICENSE.txt.
5+
*
6+
* Contributors:
7+
* Fabian Schiebel and others
8+
*****************************************************************************/
9+
10+
#ifndef PHASAR_DATAFLOW_IFDSIDE_SOLVER_ESGEDGEKIND_H
11+
#define PHASAR_DATAFLOW_IFDSIDE_SOLVER_ESGEDGEKIND_H
12+
13+
namespace psr {
14+
enum class ESGEdgeKind { Normal, Call, CallToRet, SkipUnknownFn, Ret, Summary };
15+
16+
constexpr bool isInterProc(ESGEdgeKind Kind) noexcept {
17+
return Kind == ESGEdgeKind::Call || Kind == ESGEdgeKind::Ret;
18+
}
19+
20+
} // namespace psr
21+
22+
#endif // PHASAR_DATAFLOW_IFDSIDE_SOLVER_ESGEDGEKIND_H

include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "phasar/DataFlow/IfdsIde/IDETabulationProblem.h"
2727
#include "phasar/DataFlow/IfdsIde/IFDSTabulationProblem.h"
2828
#include "phasar/DataFlow/IfdsIde/InitialSeeds.h"
29+
#include "phasar/DataFlow/IfdsIde/Solver/ESGEdgeKind.h"
2930
#include "phasar/DataFlow/IfdsIde/Solver/FlowEdgeFunctionCache.h"
3031
#include "phasar/DataFlow/IfdsIde/Solver/IDESolverAPIMixin.h"
3132
#include "phasar/DataFlow/IfdsIde/Solver/JumpFunctions.h"
@@ -297,20 +298,25 @@ class IDESolver
297298
}
298299
});
299300

301+
bool HasNoCalleeInformation = true;
302+
300303
// for each possible callee
301304
for (f_t SCalledProcN : Callees) { // still line 14
302305
// check if a special summary for the called procedure exists
303306
FlowFunctionPtrType SpecialSum =
304307
CachedFlowEdgeFunctions.getSummaryFlowFunction(n, SCalledProcN);
308+
305309
// if a special summary is available, treat this as a normal flow
306310
// and use the summary flow and edge functions
311+
307312
if (SpecialSum) {
313+
HasNoCalleeInformation = false;
308314
PHASAR_LOG_LEVEL(DEBUG, "Found and process special summary");
309315
for (n_t ReturnSiteN : ReturnSiteNs) {
310316
container_type Res = computeSummaryFlowFunction(SpecialSum, d1, d2);
311317
INC_COUNTER("SpecialSummary-FF Application", 1, Full);
312318
ADD_TO_HISTOGRAM("Data-flow facts", Res.size(), 1, Full);
313-
saveEdges(n, ReturnSiteN, d2, Res, false);
319+
saveEdges(n, ReturnSiteN, d2, Res, ESGEdgeKind::Summary);
314320
for (d_t d3 : Res) {
315321
EdgeFunction<l_t> SumEdgFnE =
316322
CachedFlowEdgeFunctions.getSummaryEdgeFunction(n, d2,
@@ -341,7 +347,8 @@ class IDESolver
341347
}
342348
// if startPointsOf is empty, the called function is a declaration
343349
for (n_t SP : StartPointsOf) {
344-
saveEdges(n, SP, d2, Res, true);
350+
HasNoCalleeInformation = false;
351+
saveEdges(n, SP, d2, Res, ESGEdgeKind::Call);
345352
// for each result node of the call-flow function
346353
for (d_t d3 : Res) {
347354
using TableCell = typename Table<n_t, d_t, EdgeFunction<l_t>>::Cell;
@@ -382,7 +389,7 @@ class IDESolver
382389
RetFunction, d3, d4, n, Container{d2});
383390
ADD_TO_HISTOGRAM("Data-flow facts", ReturnedFacts.size(), 1,
384391
Full);
385-
saveEdges(eP, RetSiteN, d4, ReturnedFacts, true);
392+
saveEdges(eP, RetSiteN, d4, ReturnedFacts, ESGEdgeKind::Ret);
386393
// for each target value of the function
387394
for (d_t d5 : ReturnedFacts) {
388395
// update the caller-side summary function
@@ -439,7 +446,9 @@ class IDESolver
439446
container_type ReturnFacts =
440447
computeCallToReturnFlowFunction(CallToReturnFF, d1, d2);
441448
ADD_TO_HISTOGRAM("Data-flow facts", ReturnFacts.size(), 1, Full);
442-
saveEdges(n, ReturnSiteN, d2, ReturnFacts, false);
449+
saveEdges(n, ReturnSiteN, d2, ReturnFacts,
450+
HasNoCalleeInformation ? ESGEdgeKind::SkipUnknownFn
451+
: ESGEdgeKind::CallToRet);
443452
for (d_t d3 : ReturnFacts) {
444453
EdgeFunction<l_t> EdgeFnE =
445454
CachedFlowEdgeFunctions.getCallToRetEdgeFunction(n, d2, ReturnSiteN,
@@ -478,7 +487,7 @@ class IDESolver
478487
INC_COUNTER("FF Queries", 1, Full);
479488
const container_type Res = computeNormalFlowFunction(FlowFunc, d1, d2);
480489
ADD_TO_HISTOGRAM("Data-flow facts", Res.size(), 1, Full);
481-
saveEdges(n, nPrime, d2, Res, false);
490+
saveEdges(n, nPrime, d2, Res, ESGEdgeKind::Normal);
482491
for (d_t d3 : Res) {
483492
EdgeFunction<l_t> g =
484493
CachedFlowEdgeFunctions.getNormalEdgeFunction(n, d2, nPrime, d3);
@@ -690,12 +699,12 @@ class IDESolver
690699
}
691700

692701
virtual void saveEdges(n_t SourceNode, n_t SinkStmt, d_t SourceVal,
693-
const container_type &DestVals, bool InterP) {
702+
const container_type &DestVals, ESGEdgeKind Kind) {
694703
if (!SolverConfig.recordEdges()) {
695704
return;
696705
}
697706
Table<n_t, n_t, std::map<d_t, container_type>> &TgtMap =
698-
(InterP) ? ComputedInterPathEdges : ComputedIntraPathEdges;
707+
(isInterProc(Kind)) ? ComputedInterPathEdges : ComputedIntraPathEdges;
699708
TgtMap.get(SourceNode, SinkStmt)[SourceVal].insert(DestVals.begin(),
700709
DestVals.end());
701710
}
@@ -833,7 +842,7 @@ class IDESolver
833842
const container_type Targets =
834843
computeReturnFlowFunction(RetFunction, d1, d2, c, Entry.second);
835844
ADD_TO_HISTOGRAM("Data-flow facts", Targets.size(), 1, Full);
836-
saveEdges(n, RetSiteC, d2, Targets, true);
845+
saveEdges(n, RetSiteC, d2, Targets, ESGEdgeKind::Ret);
837846
// for each target value at the return site
838847
// line 23
839848
for (d_t d5 : Targets) {
@@ -902,7 +911,7 @@ class IDESolver
902911
const container_type Targets = computeReturnFlowFunction(
903912
RetFunction, d1, d2, Caller, Container{ZeroValue});
904913
ADD_TO_HISTOGRAM("Data-flow facts", Targets.size(), 1, Full);
905-
saveEdges(n, RetSiteC, d2, Targets, true);
914+
saveEdges(n, RetSiteC, d2, Targets, ESGEdgeKind::Ret);
906915
for (d_t d5 : Targets) {
907916
EdgeFunction<l_t> f5 =
908917
CachedFlowEdgeFunctions.getReturnEdgeFunction(
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/******************************************************************************
2+
* Copyright (c) 2022 Philipp Schubert.
3+
* All rights reserved. This program and the accompanying materials are made
4+
* available under the terms of LICENSE.txt.
5+
*
6+
* Contributors:
7+
* Fabian Schiebel and others
8+
*****************************************************************************/
9+
10+
#ifndef PHASAR_DATAFLOW_IFDSIDE_SOLVER_PATHAWAREIDESOLVER_H
11+
#define PHASAR_DATAFLOW_IFDSIDE_SOLVER_PATHAWAREIDESOLVER_H
12+
13+
#include "phasar/DataFlow/IfdsIde/IDETabulationProblem.h"
14+
#include "phasar/DataFlow/IfdsIde/Solver/ESGEdgeKind.h"
15+
#include "phasar/DataFlow/IfdsIde/Solver/IDESolver.h"
16+
#include "phasar/DataFlow/PathSensitivity/ExplodedSuperGraph.h"
17+
#include "phasar/Utils/Logger.h"
18+
19+
namespace psr {
20+
template <typename AnalysisDomainTy,
21+
typename Container = std::set<typename AnalysisDomainTy::d_t>>
22+
class PathAwareIDESolver : public IDESolver<AnalysisDomainTy, Container> {
23+
using base_t = IDESolver<AnalysisDomainTy, Container>;
24+
25+
public:
26+
using domain_t = AnalysisDomainTy;
27+
using n_t = typename base_t::n_t;
28+
using d_t = typename base_t::d_t;
29+
using i_t = typename base_t::i_t;
30+
using container_type = typename base_t::container_type;
31+
32+
explicit PathAwareIDESolver(
33+
IDETabulationProblem<domain_t, container_type> &Problem, const i_t *ICF)
34+
: base_t(Problem, ICF), ESG(Problem.getZeroValue()) {
35+
36+
if (Problem.getIFDSIDESolverConfig().autoAddZero()) {
37+
PHASAR_LOG_LEVEL(
38+
WARNING,
39+
"The PathAwareIDESolver is initialized with the option 'autoAddZero' "
40+
"being set. This might degrade the quality of the computed paths!");
41+
}
42+
}
43+
44+
[[nodiscard]] const ExplodedSuperGraph<domain_t> &
45+
getExplicitESG() const &noexcept {
46+
return ESG;
47+
}
48+
49+
[[nodiscard]] ExplodedSuperGraph<domain_t> &&getExplicitESG() &&noexcept {
50+
return std::move(ESG);
51+
}
52+
53+
private:
54+
void saveEdges(n_t Curr, n_t Succ, d_t CurrNode,
55+
const container_type &SuccNodes, ESGEdgeKind Kind) override {
56+
ESG.saveEdges(std::move(Curr), std::move(CurrNode), std::move(Succ),
57+
SuccNodes, Kind);
58+
}
59+
60+
ExplodedSuperGraph<domain_t> ESG;
61+
};
62+
63+
template <typename ProblemTy>
64+
PathAwareIDESolver(ProblemTy &)
65+
-> PathAwareIDESolver<typename ProblemTy::ProblemAnalysisDomain>;
66+
67+
} // namespace psr
68+
69+
#endif // PHASAR_DATAFLOW_IFDSIDE_SOLVER_PATHAWAREIDESOLVER_H

include/phasar/DataFlow/IfdsIde/SolverResults.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ class OwningSolverResults
232232
[[nodiscard]] operator SolverResults<N, D, L>() const &noexcept {
233233
return get();
234234
}
235+
235236
operator SolverResults<N, D, L>() && = delete;
236237

237238
private:

0 commit comments

Comments
 (0)