Skip to content

Commit 17491f6

Browse files
authored
Alias Iterator (#783)
* Add AliasIterator * Add alias() check as optional member to AliasIterator * Integrate AliasIterator into Default[IFDS/IDE]AliasAwareFlowFunctions * Some restructure * Add PointsToIterator and integrate it with SVFBasedPointsToInfo * Integrate reachableAllocationSites with PointsToIterator * Add boilerplate + some comments * Start adding SVFAliasInfo for SVF-DDA(WIP) * Fill missing functions for SVFAliasInfoImpl * minor * Fix FilteredLLVMAliasSet * Fix example * Fix some bugs in aliasiterator and pointstoiterator * minor fix * Remove AliasIterator::alias as it is probably not needed and makes the API more complex and harder to adopt * Add FilteredLLVMAliasIterator * Implement FilteredLLVMAliasSet in terms of FilteredLLVMAliasIterator * Add CachedLLVMAliasIterator and implement FilteredLLVMAliasSet in terms of it * Make AliasIterator more convenient to use by reducing the requirement of typedefs v_t and n_t * Attempt to fix install in CI Apparently, cmake does not like relative paths on the commandline anymore... * Add find_package_message to Config.cmake.in * minor
1 parent a5c611a commit 17491f6

Some content is hidden

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

43 files changed

+1858
-571
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ jobs:
7373
shell: bash
7474
run: |
7575
cmake -DCMAKE_INSTALL_PREFIX=./INSTALL -P ./build/cmake_install.cmake
76+
PHASAR_ROOT_DIR=$(pwd)
7677
cd ./examples/how-to
77-
cmake -S . -B build -Dphasar_ROOT=../../INSTALL
78+
cmake -S . -B build -Dphasar_ROOT="$PHASAR_ROOT_DIR/INSTALL"
7879
cmake --build ./build --target run_sample_programs

Config.cmake.in

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,17 +54,30 @@ include("${CMAKE_CURRENT_LIST_DIR}/PhasarExports.cmake")
5454

5555
foreach(component ${phasar_FIND_COMPONENTS})
5656
if(NOT ${component} IN_LIST PHASAR_COMPONENTS)
57-
set(phasar_FOUND false)
57+
set(phasar_FOUND FALSE)
5858
set(phasar_NOT_FOUND_MESSAGE "Unsupported component: ${component}. Valid components are: ${PHASAR_COMPONENTS}")
5959
endif()
6060

6161
list(APPEND PHASAR_NEEDED_LIBS phasar::${component})
6262
endforeach()
6363

64-
if (NOT DEFINED phasar_FOUND OR phasar_FOUND EQUAL TRUE)
64+
if (NOT DEFINED phasar_FOUND)
65+
set(phasar_FOUND TRUE)
66+
endif()
67+
68+
include(FindPackageHandleStandardArgs)
69+
70+
if (phasar_FOUND)
6571
if (NOT phasar_FIND_COMPONENTS)
6672
list(APPEND PHASAR_NEEDED_LIBS phasar::phasar)
6773
# Default target
6874
add_library(phasar ALIAS phasar::phasar)
6975
endif()
76+
77+
find_package_message(phasar
78+
"Found phasar: ${PHASAR_LIBRARY_DIR} (found version \"${PHASAR_VERSION}\")"
79+
"[${PHASAR_LIBRARY_DIR}][${PHASAR_INCLUDE_DIR}]"
80+
)
81+
else()
82+
message(STATUS "Could NOT find phasar")
7083
endif()

examples/how-to/07-write-ifds-analysis/simple.cpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77

88
namespace {
99

10-
void populateWithMayAliases(psr::LLVMAliasInfoRef AS,
11-
std::set<const llvm::Value *> &Facts);
10+
void populateWithMayAliases(psr::LLVMAliasIteratorRef AS,
11+
std::set<const llvm::Value *> &Facts,
12+
const llvm::Instruction *At);
1213

1314
/// To create a custom IFDS analysis, we must create a subclass of the
1415
/// IFDSTabulationProblem.
@@ -23,7 +24,7 @@ class ExampleTaintAnalysis : public psr::DefaultAliasAwareIFDSProblem {
2324
/// The last parameter of the base-ctor denotes the special zero-value of the
2425
/// IFDS problem. We use LLVMZeroValue for this.
2526
explicit ExampleTaintAnalysis(const psr::LLVMProjectIRDB *IRDB,
26-
psr::LLVMAliasInfoRef AS,
27+
psr::LLVMAliasIteratorRef AS,
2728
const psr::LLVMTaintConfig *Config,
2829
std::vector<std::string> EntryPoints)
2930
: psr::DefaultAliasAwareIFDSProblem(IRDB, AS, std::move(EntryPoints),
@@ -63,8 +64,8 @@ class ExampleTaintAnalysis : public psr::DefaultAliasAwareIFDSProblem {
6364
}
6465

6566
// Since our analysis is alias-aware, we must handle aliasing here:
66-
populateWithMayAliases(getAliasInfo(), Gen);
67-
populateWithMayAliases(getAliasInfo(), Leak);
67+
populateWithMayAliases(getAliasInfo(), Gen, CallSite);
68+
populateWithMayAliases(getAliasInfo(), Leak, CallSite);
6869

6970
// We have special behavior to communicate to the analysis solver, so create
7071
// a flow-function that captures this behavior:
@@ -101,12 +102,12 @@ class ExampleTaintAnalysis : public psr::DefaultAliasAwareIFDSProblem {
101102
};
102103

103104
// For all given facts, we add their aliases:
104-
void populateWithMayAliases(psr::LLVMAliasInfoRef AS,
105-
std::set<const llvm::Value *> &Facts) {
105+
void populateWithMayAliases(psr::LLVMAliasIteratorRef AS,
106+
std::set<const llvm::Value *> &Facts,
107+
const llvm::Instruction *At) {
106108
auto Tmp = Facts;
107109
for (const auto *Fact : Facts) {
108-
auto Aliases = AS.getAliasSet(Fact);
109-
Tmp.insert(Aliases->begin(), Aliases->end());
110+
AS.forallAliasesOf(Fact, At, [&](const auto *Alias) { Tmp.insert(Alias); });
110111
}
111112

112113
Facts = std::move(Tmp);

include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultAliasAwareIDEProblem.h

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,13 @@ class IDEAliasAwareDefaultFlowFunctionsImpl
3636

3737
using IDENoAliasDefaultFlowFunctionsImpl::isFunctionModeled;
3838

39-
[[nodiscard]] constexpr LLVMAliasInfoRef getAliasInfo() const noexcept {
39+
[[nodiscard]] constexpr LLVMAliasIteratorRef getAliasInfo() const noexcept {
4040
return AS;
4141
}
4242

43-
constexpr IDEAliasAwareDefaultFlowFunctionsImpl(LLVMAliasInfoRef AS) noexcept
44-
: AS(AS) {
45-
assert(AS && "You must provide an alias information handle!");
46-
}
43+
constexpr IDEAliasAwareDefaultFlowFunctionsImpl(
44+
LLVMAliasIteratorRef AS) noexcept
45+
: AS(AS) {}
4746

4847
[[nodiscard]] FlowFunctionPtrType getNormalFlowFunctionImpl(n_t Curr,
4948
n_t /*Succ*/);
@@ -54,8 +53,8 @@ class IDEAliasAwareDefaultFlowFunctionsImpl
5453
using IDENoAliasDefaultFlowFunctionsImpl::getCallFlowFunctionImpl;
5554
using IDENoAliasDefaultFlowFunctionsImpl::getCallToRetFlowFunctionImpl;
5655

57-
protected:
58-
LLVMAliasInfoRef AS;
56+
private:
57+
LLVMAliasIteratorRef AS;
5958
};
6059
} // namespace detail
6160

@@ -78,7 +77,7 @@ class DefaultAliasAwareIDEProblem
7877
/// \note It is useful to use an instance of FilteredAliasSet for the alias
7978
/// information to lower suprious aliases
8079
explicit DefaultAliasAwareIDEProblem(
81-
const ProjectIRDBBase<db_t> *IRDB, LLVMAliasInfoRef AS,
80+
const ProjectIRDBBase<db_t> *IRDB, LLVMAliasIteratorRef AS,
8281
std::vector<std::string> EntryPoints,
8382
std::optional<d_t>
8483
ZeroValue) noexcept(std::is_nothrow_move_constructible_v<d_t>)
@@ -125,7 +124,7 @@ class DefaultAliasAwareIFDSProblem
125124
/// \note It is useful to use an instance of FilteredAliasSet for the alias
126125
/// information to lower suprious aliases
127126
explicit DefaultAliasAwareIFDSProblem(
128-
const ProjectIRDBBase<db_t> *IRDB, LLVMAliasInfoRef AS,
127+
const ProjectIRDBBase<db_t> *IRDB, LLVMAliasIteratorRef AS,
129128
std::vector<std::string> EntryPoints,
130129
d_t ZeroValue) noexcept(std::is_nothrow_move_constructible_v<d_t>)
131130
: IFDSTabulationProblem(IRDB, std::move(EntryPoints), ZeroValue),

include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultNoAliasIDEProblem.h"
1414
#include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h"
15+
#include "phasar/PhasarLLVM/Pointer/LLVMPointsToInfo.h"
1516

1617
// Forward declaration of types for which we only use its pointer or ref type
1718
namespace llvm {
@@ -34,15 +35,14 @@ class IDEReachableAllocationSitesDefaultFlowFunctionsImpl
3435

3536
using IDENoAliasDefaultFlowFunctionsImpl::isFunctionModeled;
3637

37-
[[nodiscard]] constexpr LLVMAliasInfoRef getAliasInfo() const noexcept {
38+
[[nodiscard]] constexpr LLVMPointsToIteratorRef
39+
getPointsToInfo() const noexcept {
3840
return AS;
3941
}
4042

4143
constexpr IDEReachableAllocationSitesDefaultFlowFunctionsImpl(
42-
LLVMAliasInfoRef AS) noexcept
43-
: AS(AS) {
44-
assert(AS && "You must provide an alias information handle!");
45-
}
44+
LLVMPointsToIteratorRef AS) noexcept
45+
: AS(AS) {}
4646

4747
[[nodiscard]] FlowFunctionPtrType getNormalFlowFunctionImpl(n_t Curr,
4848
n_t /*Succ*/);
@@ -56,7 +56,7 @@ class IDEReachableAllocationSitesDefaultFlowFunctionsImpl
5656
using IDENoAliasDefaultFlowFunctionsImpl::getCallToRetFlowFunctionImpl;
5757

5858
protected:
59-
LLVMAliasInfoRef AS;
59+
LLVMPointsToIteratorRef AS;
6060
};
6161
} // namespace detail
6262

@@ -77,7 +77,7 @@ class DefaultReachableAllocationSitesIDEProblem
7777
/// \note It is useful to use an instance of FilteredAliasSet for the alias
7878
/// information to lower suprious aliases
7979
explicit DefaultReachableAllocationSitesIDEProblem(
80-
const ProjectIRDBBase<db_t> *IRDB, LLVMAliasInfoRef AS,
80+
const ProjectIRDBBase<db_t> *IRDB, LLVMPointsToIteratorRef AS,
8181
std::vector<std::string> EntryPoints,
8282
std::optional<d_t>
8383
ZeroValue) noexcept(std::is_nothrow_move_constructible_v<d_t>)
@@ -125,7 +125,7 @@ class DefaultReachableAllocationSitesIFDSProblem
125125
/// \note It is useful to use an instance of FilteredAliasSet for the alias
126126
/// information to lower suprious aliases
127127
explicit DefaultReachableAllocationSitesIFDSProblem(
128-
const ProjectIRDBBase<db_t> *IRDB, LLVMAliasInfoRef AS,
128+
const ProjectIRDBBase<db_t> *IRDB, LLVMPointsToIteratorRef AS,
129129
std::vector<std::string> EntryPoints,
130130
d_t ZeroValue) noexcept(std::is_nothrow_move_constructible_v<d_t>)
131131
: IFDSTabulationProblem(IRDB, std::move(EntryPoints), ZeroValue),

include/phasar/PhasarLLVM/Pointer.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,15 @@
1010
#ifndef PHASAR_PHASARLLVM_POINTER_H
1111
#define PHASAR_PHASARLLVM_POINTER_H
1212

13+
#include "phasar/Config/phasar-config.h" // for PHASAR_USE_SVF
1314
#include "phasar/PhasarLLVM/Pointer/AliasAnalysisView.h"
1415
#include "phasar/PhasarLLVM/Pointer/FilteredLLVMAliasSet.h"
1516
#include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h"
1617
#include "phasar/PhasarLLVM/Pointer/LLVMAliasSet.h"
1718
#include "phasar/PhasarLLVM/Pointer/LLVMPointsToUtils.h"
1819

20+
#ifdef PHASAR_USE_SVF
21+
#include "phasar/PhasarLLVM/Pointer/SVF/SVFPointsToSet.h"
22+
#endif
23+
1924
#endif // PHASAR_PHASARLLVM_POINTER_H
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/******************************************************************************
2+
* Copyright (c) 2025 Fabian Schiebel.
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_PHASARLLVM_POINTER_CACHEDLLVMALIASITERATOR_H
11+
#define PHASAR_PHASARLLVM_POINTER_CACHEDLLVMALIASITERATOR_H
12+
13+
#include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h"
14+
#include "phasar/Pointer/AliasAnalysisType.h"
15+
#include "phasar/Pointer/AliasInfoTraits.h"
16+
#include "phasar/Pointer/AliasSetOwner.h"
17+
18+
#include "llvm/IR/Function.h"
19+
20+
namespace psr {
21+
22+
class CachedLLVMAliasIterator;
23+
24+
template <>
25+
struct AliasInfoTraits<CachedLLVMAliasIterator>
26+
: DefaultAATraits<const llvm::Value *, const llvm::Instruction *> {};
27+
28+
/// \brief A wrapper over a LLVMAliasIteratorRef that adds caching to make it
29+
/// conform to the LLVMAliasInfoRef interface
30+
///
31+
/// \note Currently assumes that the underlying alias information is
32+
/// flow-insensitive and the granularity of different alias-information per
33+
/// instruction is actually at function-level
34+
class CachedLLVMAliasIterator {
35+
public:
36+
using alias_traits_t = AliasInfoTraits<CachedLLVMAliasIterator>;
37+
using n_t = alias_traits_t::n_t;
38+
using v_t = alias_traits_t::v_t;
39+
using AliasSetTy = alias_traits_t::AliasSetTy;
40+
using AliasSetPtrTy = alias_traits_t::AliasSetPtrTy;
41+
using AllocationSiteSetPtrTy = alias_traits_t::AllocationSiteSetPtrTy;
42+
43+
CachedLLVMAliasIterator(LLVMAliasIteratorRef AS) noexcept;
44+
45+
// --- API Functions:
46+
47+
[[nodiscard]] inline bool isInterProcedural() const noexcept {
48+
return false; // No idea, so be conservative here
49+
};
50+
51+
[[nodiscard]] AliasAnalysisType getAliasAnalysisType() const noexcept {
52+
return AliasAnalysisType::Invalid; // No idea
53+
}
54+
55+
[[nodiscard]] AliasResult alias(const llvm::Value *V1, const llvm::Value *V2,
56+
const llvm::Instruction *I);
57+
58+
[[nodiscard]] AliasSetPtrTy getAliasSet(const llvm::Value *V,
59+
const llvm::Instruction *I);
60+
61+
[[nodiscard]] AllocationSiteSetPtrTy
62+
getReachableAllocationSites(const llvm::Value *V, bool IntraProcOnly = false,
63+
const llvm::Instruction *I = nullptr);
64+
65+
// Checks if PotentialValue is in the reachable allocation sites of V.
66+
[[nodiscard]] bool isInReachableAllocationSites(
67+
const llvm::Value *V, const llvm::Value *PotentialValue,
68+
bool IntraProcOnly = false, const llvm::Instruction *I = nullptr);
69+
70+
void mergeWith(const CachedLLVMAliasIterator & /*OtherPTI*/) {
71+
llvm::report_fatal_error("Not Supported");
72+
}
73+
74+
void introduceAlias(const llvm::Value * /*V1*/, const llvm::Value * /*V2*/,
75+
const llvm::Instruction * /*I*/ = nullptr,
76+
AliasResult /*Kind*/ = AliasResult::MustAlias) {
77+
llvm::report_fatal_error("Not Supported");
78+
}
79+
80+
void print(llvm::raw_ostream &OS = llvm::outs()) const;
81+
82+
[[nodiscard]] nlohmann::json getAsJson() const;
83+
84+
void printAsJson(llvm::raw_ostream &OS = llvm::outs()) const;
85+
86+
[[nodiscard]] AnalysisProperties getAnalysisProperties() const noexcept {
87+
return AnalysisProperties::None;
88+
}
89+
90+
[[nodiscard]] LLVMAliasIteratorRef getUnderlying() const noexcept {
91+
return AS;
92+
}
93+
94+
private:
95+
struct ReachableAllocationSitesKey {
96+
llvm::PointerIntPair<const llvm::Function *, 1, bool> FunAndIntraProcOnly;
97+
v_t Value{};
98+
};
99+
100+
struct ReachableAllocationSitesKeyDMI {
101+
inline static ReachableAllocationSitesKey getEmptyKey() noexcept {
102+
return {{}, llvm::DenseMapInfo<v_t>::getEmptyKey()};
103+
}
104+
inline static ReachableAllocationSitesKey getTombstoneKey() noexcept {
105+
return {{}, llvm::DenseMapInfo<v_t>::getTombstoneKey()};
106+
}
107+
inline static auto getHashValue(ReachableAllocationSitesKey Key) noexcept {
108+
return llvm::hash_combine(Key.FunAndIntraProcOnly.getOpaqueValue(),
109+
Key.Value);
110+
}
111+
inline static bool isEqual(ReachableAllocationSitesKey Key1,
112+
ReachableAllocationSitesKey Key2) noexcept {
113+
return Key1.FunAndIntraProcOnly == Key2.FunAndIntraProcOnly &&
114+
Key1.Value == Key2.Value;
115+
}
116+
};
117+
118+
LLVMAliasIteratorRef AS;
119+
AliasSetOwner<AliasSetTy>::memory_resource_type MRes;
120+
AliasSetOwner<AliasSetTy> Owner;
121+
llvm::DenseMap<std::pair<const llvm::Function *, v_t>, AliasSetPtrTy>
122+
AliasSetMap;
123+
llvm::DenseMap<ReachableAllocationSitesKey, std::unique_ptr<AliasSetTy>,
124+
ReachableAllocationSitesKeyDMI>
125+
ReachableAllocationSitesMap;
126+
};
127+
} // namespace psr
128+
129+
#endif // PHASAR_PHASARLLVM_POINTER_CACHEDALIASITERATOR_H
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/******************************************************************************
2+
* Copyright (c) 2025 Fabian Schiebel.
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_PHASARLLVM_POINTER_FILTEREDLLVMALIASITERATOR_H
11+
#define PHASAR_PHASARLLVM_POINTER_FILTEREDLLVMALIASITERATOR_H
12+
13+
#include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h"
14+
15+
#include "llvm/ADT/STLFunctionalExtras.h"
16+
17+
namespace psr {
18+
class FilteredLLVMAliasIterator {
19+
public:
20+
using n_t = const llvm::Instruction *;
21+
using v_t = const llvm::Value *;
22+
23+
constexpr FilteredLLVMAliasIterator(LLVMAliasIteratorRef Underlying) noexcept
24+
: Underlying(Underlying) {}
25+
26+
void forallAliasesOf(const llvm::Value *V, const llvm::Function *Fun,
27+
llvm::function_ref<void(const llvm::Value *)> WithAlias);
28+
void forallAliasesOf(const llvm::Value *V, const llvm::Instruction *At,
29+
llvm::function_ref<void(const llvm::Value *)> WithAlias);
30+
31+
[[nodiscard]] LLVMAliasIteratorRef getUnderlying() const noexcept {
32+
return Underlying;
33+
}
34+
35+
private:
36+
LLVMAliasIteratorRef Underlying;
37+
};
38+
} // namespace psr
39+
40+
#endif // PHASAR_PHASARLLVM_POINTER_FILTEREDLLVMALIASITERATOR_H

0 commit comments

Comments
 (0)