Skip to content

Commit 1e857b1

Browse files
authored
Call-Graph Improvements (#785)
* minor fix in CHA and RTA resolvers * Several small improvements for call-graph resolving * Fix out-of-bounds access in getVarTypeFromIR() * Add address-taken functions caching in base resolver * Some cleanup in resolvers * pre-commit * Fix bug in the overloads of buildLLVMBasedCallGraph() that takes a CallGraphAnalysisType
1 parent 0024a53 commit 1e857b1

File tree

10 files changed

+194
-138
lines changed

10 files changed

+194
-138
lines changed

include/phasar/PhasarLLVM/ControlFlow/Resolver/CHAResolver.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,6 @@
2020
#include "phasar/PhasarLLVM/ControlFlow/Resolver/Resolver.h"
2121
#include "phasar/Utils/MaybeUniquePtr.h"
2222

23-
namespace llvm {
24-
class CallBase;
25-
} // namespace llvm
26-
2723
namespace psr {
2824
class DIBasedTypeHierarchy;
2925

include/phasar/PhasarLLVM/ControlFlow/Resolver/NOResolver.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,6 @@
1212

1313
#include "phasar/PhasarLLVM/ControlFlow/Resolver/Resolver.h"
1414

15-
namespace llvm {
16-
class CallBase;
17-
} // namespace llvm
18-
1915
namespace psr {
2016

2117
/// \brief A resolver that doesn't resolve indirect- and virtual calls

include/phasar/PhasarLLVM/ControlFlow/Resolver/OTFResolver.h

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,8 @@
2020
#include "phasar/PhasarLLVM/ControlFlow/Resolver/Resolver.h"
2121
#include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h"
2222

23-
#include <set>
24-
#include <string>
25-
#include <utility>
26-
#include <vector>
27-
28-
namespace llvm {
29-
class CallBase;
30-
class Function;
31-
class Type;
32-
class Value;
33-
} // namespace llvm
34-
3523
namespace psr {
3624

37-
class DIBasedTypeHierarchy;
38-
3925
/// \brief A resolver that uses alias information to resolve indirect and
4026
/// virtual calls
4127
class OTFResolver : public Resolver {
@@ -54,18 +40,11 @@ class OTFResolver : public Resolver {
5440
void resolveFunctionPointer(FunctionSetTy &PossibleTargets,
5541
const llvm::CallBase *CallSite) override;
5642

57-
static std::set<const llvm::Type *>
58-
getReachableTypes(const LLVMAliasInfo::AliasSetTy &Values);
59-
60-
static std::vector<std::pair<const llvm::Value *, const llvm::Value *>>
61-
getActualFormalPointerPairs(const llvm::CallBase *CallSite,
62-
const llvm::Function *CalleeTarget);
63-
6443
[[nodiscard]] std::string str() const override;
6544

6645
[[nodiscard]] bool
6746
mutatesHelperAnalysisInformation() const noexcept override {
68-
return true;
47+
return !PT.isInterProcedural();
6948
}
7049

7150
protected:

include/phasar/PhasarLLVM/ControlFlow/Resolver/RTAResolver.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,10 @@
2222
#include <vector>
2323

2424
namespace llvm {
25-
class CallBase;
2625
class DICompositeType;
2726
} // namespace llvm
2827

2928
namespace psr {
30-
class DIBasedTypeHierarchy;
3129

3230
/// \brief A resolver that performs Rapid Type Analysis to resolve calls
3331
/// to C++ virtual functions. Requires debug information.

include/phasar/PhasarLLVM/ControlFlow/Resolver/Resolver.h

Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h"
2121

2222
#include "llvm/ADT/DenseSet.h"
23+
#include "llvm/ADT/SmallVector.h"
2324
#include "llvm/IR/DerivedTypes.h"
2425

2526
#include <memory>
@@ -44,6 +45,10 @@ enum class CallGraphAnalysisType;
4445
[[nodiscard]] std::optional<unsigned>
4546
getVFTIndex(const llvm::CallBase *CallSite);
4647

48+
/// Similar to getVFTIndex(), but also returns a pointer to the vtable
49+
[[nodiscard]] std::optional<std::pair<const llvm::Value *, uint64_t>>
50+
getVFTIndexAndVT(const llvm::CallBase *CallSite);
51+
4752
/// Assuming that `CallSite` is a call to a non-static member function,
4853
/// retrieves the type of the receiver. Returns nullptr, if the receiver-type
4954
/// could not be extracted
@@ -67,43 +72,40 @@ getReceiverType(const llvm::CallBase *CallSite);
6772
[[nodiscard]] bool isVirtualCall(const llvm::Instruction *Inst,
6873
const LLVMVFTableProvider &VTP);
6974

75+
/// A variant of F->hasAddressTaken() that is better suited for our use cases.
76+
///
77+
/// Especially, it filteres out global aliases.
78+
[[nodiscard]] bool isAddressTakenFunction(const llvm::Function *F);
79+
7080
/// \brief A base class for call-target resolvers. Used to build call graphs.
7181
///
7282
/// Create a specific resolver by making a new class, inheriting this resolver
7383
/// class and implementing the virtual functions as needed.
7484
class Resolver {
75-
protected:
76-
const LLVMProjectIRDB *IRDB;
77-
const LLVMVFTableProvider *VTP;
78-
79-
const llvm::Function *
80-
getNonPureVirtualVFTEntry(const llvm::DIType *T, unsigned Idx,
81-
const llvm::CallBase *CallSite,
82-
const llvm::DIType *ReceiverType) {
83-
if (!VTP) {
84-
return nullptr;
85-
}
86-
return psr::getNonPureVirtualVFTEntry(T, Idx, CallSite, *VTP, ReceiverType);
87-
}
88-
8985
public:
9086
using FunctionSetTy = llvm::SmallDenseSet<const llvm::Function *, 4>;
9187

9288
Resolver(const LLVMProjectIRDB *IRDB, const LLVMVFTableProvider *VTP);
9389

9490
virtual ~Resolver() = default;
9591

96-
virtual void preCall(const llvm::Instruction *Inst);
92+
[[deprecated("With the removal of DTAResolver, this is not used "
93+
"anymore")]] virtual void
94+
preCall(const llvm::Instruction *Inst);
9795

9896
virtual void handlePossibleTargets(const llvm::CallBase *CallSite,
9997
FunctionSetTy &PossibleTargets);
10098

101-
virtual void postCall(const llvm::Instruction *Inst);
99+
[[deprecated("With the removal of DTAResolver, this is not used "
100+
"anymore")]] virtual void
101+
postCall(const llvm::Instruction *Inst);
102102

103103
[[nodiscard]] FunctionSetTy
104104
resolveIndirectCall(const llvm::CallBase *CallSite);
105105

106-
virtual void otherInst(const llvm::Instruction *Inst);
106+
[[deprecated("With the removal of DTAResolver, this is not used "
107+
"anymore")]] virtual void
108+
otherInst(const llvm::Instruction *Inst);
107109

108110
[[nodiscard]] virtual std::string str() const = 0;
109111

@@ -115,11 +117,30 @@ class Resolver {
115117
// Conservatively returns true. Override if possible
116118
return true;
117119
}
118-
static std::unique_ptr<Resolver> create(CallGraphAnalysisType Ty,
119-
const LLVMProjectIRDB *IRDB,
120-
const LLVMVFTableProvider *VTP,
121-
const DIBasedTypeHierarchy *TH,
122-
LLVMAliasInfoRef PT = nullptr);
120+
121+
[[nodiscard]] llvm::ArrayRef<const llvm::Function *>
122+
getAddressTakenFunctions();
123+
124+
[[nodiscard]] static std::unique_ptr<Resolver>
125+
create(CallGraphAnalysisType Ty, const LLVMProjectIRDB *IRDB,
126+
const LLVMVFTableProvider *VTP, const DIBasedTypeHierarchy *TH,
127+
LLVMAliasInfoRef PT = nullptr);
128+
129+
protected:
130+
const llvm::Function *
131+
getNonPureVirtualVFTEntry(const llvm::DIType *T, unsigned Idx,
132+
const llvm::CallBase *CallSite,
133+
const llvm::DIType *ReceiverType) {
134+
if (!VTP) {
135+
return nullptr;
136+
}
137+
return psr::getNonPureVirtualVFTEntry(T, Idx, CallSite, *VTP, ReceiverType);
138+
}
139+
140+
const LLVMProjectIRDB *IRDB{};
141+
const LLVMVFTableProvider *VTP{};
142+
std::optional<llvm::SmallVector<const llvm::Function *, 0>>
143+
AddressTakenFunctions{};
123144

124145
protected:
125146
virtual void resolveVirtualCall(FunctionSetTy &PossibleTargets,

lib/PhasarLLVM/ControlFlow/LLVMBasedCallGraphBuilder.cpp

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -153,13 +153,9 @@ bool Builder::processFunction(const llvm::Function *F) {
153153
for (const auto &I : llvm::instructions(F)) {
154154
const auto *CS = llvm::dyn_cast<llvm::CallBase>(&I);
155155
if (!CS) {
156-
Res->otherInst(&I);
157156
continue;
158157
}
159158

160-
Res->preCall(&I);
161-
scope_exit PostCall = [&] { Res->postCall(&I); };
162-
163159
FixpointReached &=
164160
fillPossibleTargets(PossibleTargets, *Res, CS, IndirectCalls);
165161

@@ -203,9 +199,6 @@ bool Builder::constructDynamicCall(const llvm::Instruction *CS) {
203199
"Looking into dynamic call-site: ");
204200
PHASAR_LOG_LEVEL_CAT(DEBUG, "LLVMBasedICFG", " " << llvmIRToString(CS));
205201

206-
Res->preCall(CallSite);
207-
scope_exit PostCall = [&] { Res->postCall(CallSite); };
208-
209202
// call the resolve routine
210203

211204
auto PossibleTargets = Res->resolveIndirectCall(CallSite);
@@ -275,7 +268,7 @@ auto psr::buildLLVMBasedCallGraph(
275268
PT = PTOwn.asRef();
276269
}
277270

278-
auto Res = Resolver::create(CGType, &IRDB, &VTP, &TH);
271+
auto Res = Resolver::create(CGType, &IRDB, &VTP, &TH, PT);
279272
return buildLLVMBasedCallGraph(IRDB, *Res, EntryPoints, S);
280273
}
281274

lib/PhasarLLVM/ControlFlow/Resolver/CHAResolver.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,10 @@
2121
#include "phasar/PhasarLLVM/Utils/LLVMShorthands.h"
2222
#include "phasar/Utils/Logger.h"
2323

24-
#include "llvm/IR/Constants.h"
25-
#include "llvm/IR/DerivedTypes.h"
2624
#include "llvm/IR/Function.h"
27-
#include "llvm/IR/Instruction.h"
28-
#include "llvm/IR/Module.h"
2925

3026
#include <memory>
3127

32-
using namespace std;
3328
using namespace psr;
3429

3530
CHAResolver::CHAResolver(const LLVMProjectIRDB *IRDB,

lib/PhasarLLVM/ControlFlow/Resolver/NOResolver.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,8 @@
1616

1717
#include "phasar/PhasarLLVM/ControlFlow/Resolver/NOResolver.h"
1818

19-
#include <set>
20-
2119
using namespace psr;
2220

23-
namespace psr {
24-
2521
NOResolver::NOResolver(const LLVMProjectIRDB *IRDB,
2622
const LLVMVFTableProvider *VTP)
2723
: Resolver(IRDB, VTP) {}
@@ -33,5 +29,3 @@ void NOResolver::resolveFunctionPointer(FunctionSetTy & /*PossibleTargets*/,
3329
const llvm::CallBase * /*CallSite*/) {}
3430

3531
std::string NOResolver::str() const { return "NOResolver"; }
36-
37-
} // namespace psr

0 commit comments

Comments
 (0)