Skip to content

Commit e5e20ba

Browse files
fabianbs96mxHuberfabianbs
authored
Fix Type-based Call-Graphs with Multiple Inheritance (#776)
* replaced llvm-14 with llvm-15 in relevant files * some changes * more efficient call-graph * String-nbased vtable getter + CG-test with dbg info * minor in CG * annotation fix + test fix * removed bitcasts and fixed tests * Fix Annotation.cpp + TaintConfigTest * Quick-fix LLVMTypeHierarchyTest * fix one IIA test * Fix StringtestCpp for generalized LCA * first half of tests fixed * fixed first half of tests * fixed all but one test in IDEInstInteractionAnalysisTest * fixed all but two tests * Fix IIAFlowFact equality * Re-add getVFTableGlobal * fixed some newly failed tests * trade soundness for precision in LLVMAliasSet * ci.yml update * Revert "fixed some newly failed tests" * pre-commit hook * Two Tests + xtaint09 test fix for pipeline * Basic Opaque Pointer Impl, bugged * switching to DebugInfoFinder * re-add the quick-fix for LLVMTypeHierarchy * OpaquePtr type mapping, missing subroutines * Introducing a pass to save ptr types * Revert "Introducing a pass to save ptr types" This reverts commit 2a91b6d. * moving phasar to DIBasedTypeHierarchy * full switch to DIBasedTypeHierarchy + Test fixes * fixed PathTracingTest * dtaresolver deprecated and test fixes * Fixed OTFTest * trimmed trailing whitespace * minor fixes * readded TypeToDIType map for RTAResolver * pre-commit clang-format fix * pre-commit clang-format llvmbasedicfg.cpp * moved RTAResolver to DITypes * implemented review suggestions * Log error if trying to instantiate DTAResolver + minor * Add breaking changes * Also compare gep type in IIA EqualGEPDescriptor * Expose getDILocation() * expose getSrcCodeFromIR for DebugLocation + minor * Remove some unused includes * Make TaintConfigData compatible with C++20 * Compatibility with opaque pointers * Allow setting the LLVM version from higher-level projects * Getting rid of UB in CHAResolver * Start adding more sophisticated type extraction (WIP) * Handle function calls in getVarTypeFromIR * better fallback handling for getDebugLocation, etc * Better IntraMonoSolver dump * minor * improve intra mono dump * minor * expose getNonPureVirtualVFTEntry as namespace-scope function + fix build with LLVM 14 * Fix RTA resolver * Add missing include * Fix solveIFDSProblem + cherry-pick fix of DIBasedTypeHierarchy::buildTypeGraph * Potential fix, needs testing * Look into the right VTable, when resolving a virtual call * pre-commit * some cleanup --------- Co-authored-by: mxHuber <[email protected]> Co-authored-by: Fabian Schiebel <[email protected]>
1 parent 6352566 commit e5e20ba

28 files changed

+557
-147
lines changed

include/phasar/PhasarLLVM/ControlFlow/LLVMVFTableProvider.h

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,13 @@
1111
#define PHASAR_PHASARLLVM_CONTROLFLOW_LLVMVFTABLEPROVIDER_H
1212

1313
#include "phasar/PhasarLLVM/TypeHierarchy/LLVMVFTable.h"
14+
#include "phasar/Utils/HashUtils.h"
1415

16+
#include "llvm/ADT/DenseSet.h"
1517
#include "llvm/ADT/StringMap.h"
18+
#include "llvm/IR/DebugInfoMetadata.h"
1619

20+
#include <cstdint>
1721
#include <unordered_map>
1822

1923
namespace llvm {
@@ -37,8 +41,19 @@ class LLVMVFTableProvider {
3741
explicit LLVMVFTableProvider(const LLVMProjectIRDB &IRDB);
3842

3943
[[nodiscard]] bool hasVFTable(const llvm::DIType *Type) const;
40-
[[nodiscard]] const LLVMVFTable *
41-
getVFTableOrNull(const llvm::DIType *Type) const;
44+
[[nodiscard]] const LLVMVFTable *getVFTableOrNull(const llvm::DIType *Type,
45+
uint32_t Index = 0) const;
46+
47+
[[nodiscard]] const llvm::SmallDenseSet<uint32_t> &
48+
getVTableIndexInHierarchy(const llvm::DIType *DerivedType,
49+
const llvm::DIType *BaseType) const;
50+
51+
/// Supercedes DIBasedTypeHierarchy::removeVTablePrefix
52+
[[nodiscard]] static llvm::StringRef
53+
removeVTablePrefix(llvm::StringRef GlobName) noexcept;
54+
55+
/// Supercedes DIBasedTypeHierarchy::isVTable
56+
[[nodiscard]] static bool isVTable(llvm::StringRef MangledVarName);
4257

4358
[[nodiscard]] const llvm::GlobalVariable *
4459
getVFTableGlobal(const llvm::DIType *Type) const;
@@ -48,7 +63,13 @@ class LLVMVFTableProvider {
4863

4964
private:
5065
llvm::StringMap<const llvm::GlobalVariable *> ClearNameTVMap;
51-
std::unordered_map<const llvm::DIType *, LLVMVFTable> TypeVFTMap;
66+
std::unordered_map<std::pair<const llvm::DIType *, uint32_t>, LLVMVFTable,
67+
PairHash>
68+
TypeVFTMap;
69+
std::unordered_map<
70+
const llvm::DIType *,
71+
llvm::SmallDenseMap<const llvm::DIType *, llvm::SmallDenseSet<uint32_t>>>
72+
BasesOfVirt;
5273
};
5374
} // namespace psr
5475

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ class CHAResolver : public Resolver {
3838
// dtor in CHAResolver.cpp
3939
~CHAResolver() override;
4040

41-
FunctionSetTy resolveVirtualCall(const llvm::CallBase *CallSite) override;
41+
void resolveVirtualCall(FunctionSetTy &PossibleTargets,
42+
const llvm::CallBase *CallSite) override;
4243

4344
[[nodiscard]] std::string str() const override;
4445

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@ class NOResolver final : public Resolver {
2525

2626
~NOResolver() override = default;
2727

28-
FunctionSetTy resolveVirtualCall(const llvm::CallBase *CallSite) override;
28+
void resolveVirtualCall(FunctionSetTy &PossibleTargets,
29+
const llvm::CallBase *CallSite) override;
2930

30-
FunctionSetTy resolveFunctionPointer(const llvm::CallBase *CallSite) override;
31+
void resolveFunctionPointer(FunctionSetTy &PossibleTargets,
32+
const llvm::CallBase *CallSite) override;
3133

3234
[[nodiscard]] std::string str() const override;
3335

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,11 @@ class OTFResolver : public Resolver {
4848
void handlePossibleTargets(const llvm::CallBase *CallSite,
4949
FunctionSetTy &CalleeTargets) override;
5050

51-
FunctionSetTy resolveVirtualCall(const llvm::CallBase *CallSite) override;
51+
void resolveVirtualCall(FunctionSetTy &PossibleTargets,
52+
const llvm::CallBase *CallSite) override;
5253

53-
FunctionSetTy resolveFunctionPointer(const llvm::CallBase *CallSite) override;
54+
void resolveFunctionPointer(FunctionSetTy &PossibleTargets,
55+
const llvm::CallBase *CallSite) override;
5456

5557
static std::set<const llvm::Type *>
5658
getReachableTypes(const LLVMAliasInfo::AliasSetTy &Values);

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ class RTAResolver : public CHAResolver {
3838

3939
~RTAResolver() override = default;
4040

41-
FunctionSetTy resolveVirtualCall(const llvm::CallBase *CallSite) override;
41+
void resolveVirtualCall(FunctionSetTy &PossibleTargets,
42+
const llvm::CallBase *CallSite) override;
4243

4344
[[nodiscard]] std::string str() const override;
4445

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

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,9 @@ getReceiverType(const llvm::CallBase *CallSite);
5252

5353
/// Assuming that `CallSite` is a virtual call, where `Idx` is retrieved through
5454
/// `getVFTIndex()` and `T` through `getReceiverType()`
55-
[[nodiscard]] const llvm::Function *
56-
getNonPureVirtualVFTEntry(const llvm::DIType *T, unsigned Idx,
57-
const llvm::CallBase *CallSite,
58-
const psr::LLVMVFTableProvider &VTP);
55+
[[nodiscard]] const llvm::Function *getNonPureVirtualVFTEntry(
56+
const llvm::DIType *T, unsigned Idx, const llvm::CallBase *CallSite,
57+
const psr::LLVMVFTableProvider &VTP, const llvm::DIType *ReceiverType);
5958

6059
[[nodiscard]] std::string getReceiverTypeName(const llvm::CallBase *CallSite);
6160

@@ -79,11 +78,12 @@ class Resolver {
7978

8079
const llvm::Function *
8180
getNonPureVirtualVFTEntry(const llvm::DIType *T, unsigned Idx,
82-
const llvm::CallBase *CallSite) {
81+
const llvm::CallBase *CallSite,
82+
const llvm::DIType *ReceiverType) {
8383
if (!VTP) {
8484
return nullptr;
8585
}
86-
return psr::getNonPureVirtualVFTEntry(T, Idx, CallSite, *VTP);
86+
return psr::getNonPureVirtualVFTEntry(T, Idx, CallSite, *VTP, ReceiverType);
8787
}
8888

8989
public:
@@ -103,12 +103,6 @@ class Resolver {
103103
[[nodiscard]] FunctionSetTy
104104
resolveIndirectCall(const llvm::CallBase *CallSite);
105105

106-
[[nodiscard]] virtual FunctionSetTy
107-
resolveVirtualCall(const llvm::CallBase *CallSite) = 0;
108-
109-
[[nodiscard]] virtual FunctionSetTy
110-
resolveFunctionPointer(const llvm::CallBase *CallSite);
111-
112106
virtual void otherInst(const llvm::Instruction *Inst);
113107

114108
[[nodiscard]] virtual std::string str() const = 0;
@@ -126,6 +120,13 @@ class Resolver {
126120
const LLVMVFTableProvider *VTP,
127121
const DIBasedTypeHierarchy *TH,
128122
LLVMAliasInfoRef PT = nullptr);
123+
124+
protected:
125+
virtual void resolveVirtualCall(FunctionSetTy &PossibleTargets,
126+
const llvm::CallBase *CallSite) = 0;
127+
128+
virtual void resolveFunctionPointer(FunctionSetTy &PossibleTargets,
129+
const llvm::CallBase *CallSite);
129130
};
130131
} // namespace psr
131132

include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@ class DIBasedTypeHierarchy
5858
const DIBasedTypeHierarchyData &SerializedData);
5959
~DIBasedTypeHierarchy() override = default;
6060

61+
[[deprecated("Use LLVMVFTableProvider::isVTable() instead")]]
6162
static bool isVTable(llvm::StringRef VarName);
63+
[[deprecated("Use LLVMVFTableProvider::removeVTablePrefix() instead")]]
6264
static std::string removeVTablePrefix(llvm::StringRef VarName);
6365

6466
[[nodiscard]] bool hasType(ClassType Type) const override {

include/phasar/PhasarLLVM/TypeHierarchy/LLVMVFTable.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,26 +73,26 @@ class LLVMVFTable : public VFTable<const llvm::Function *> {
7373

7474
void printAsJson(llvm::raw_ostream &OS) const override;
7575

76-
[[nodiscard]] std::vector<const llvm::Function *>::iterator begin() {
76+
[[nodiscard]] std::vector<const llvm::Function *>::iterator begin() noexcept {
7777
return VFT.begin();
7878
}
7979

8080
[[nodiscard]] std::vector<const llvm::Function *>::const_iterator
81-
begin() const {
81+
begin() const noexcept {
8282
return VFT.begin();
8383
};
8484

85-
[[nodiscard]] std::vector<const llvm::Function *>::iterator end() {
85+
[[nodiscard]] std::vector<const llvm::Function *>::iterator end() noexcept {
8686
return VFT.end();
8787
};
8888

8989
[[nodiscard]] std::vector<const llvm::Function *>::const_iterator
90-
end() const {
90+
end() const noexcept {
9191
return VFT.end();
9292
};
9393

9494
[[nodiscard]] static std::vector<const llvm::Function *>
95-
getVFVectorFromIRVTable(const llvm::ConstantStruct &);
95+
getVFVectorFromIRVTable(const llvm::ConstantStruct &VT, uint32_t Index = 0);
9696
};
9797

9898
} // namespace psr

include/phasar/PhasarLLVM/Utils/LLVMIRToSrc.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ class Value;
3333
class GlobalVariable;
3434
class Module;
3535
class DIFile;
36-
class DIType;
3736
class DILocation;
3837
} // namespace llvm
3938

include/phasar/Utils/DefaultValue.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,26 @@ getDefaultValue() noexcept(std::is_nothrow_default_constructible_v<T>) {
4040
}
4141
}
4242

43+
namespace detail {
44+
struct DefaultCast {
45+
template <typename To,
46+
typename = std::enable_if_t<CanEfficientlyPassByValue<To>>>
47+
operator To() && {
48+
return psr::getDefaultValue<To>();
49+
}
50+
51+
template <typename To,
52+
typename = std::enable_if_t<!CanEfficientlyPassByValue<To>>>
53+
operator const To &() && {
54+
return psr::getDefaultValue<To>();
55+
}
56+
};
57+
} // namespace detail
58+
59+
/// Provides a value that automatically converts to (a const-ref to) the
60+
/// default-constructed object of the expected receiver type.
61+
static constexpr detail::DefaultCast default_value() noexcept { return {}; }
62+
4363
} // namespace psr
4464

4565
#endif // PHASAR_UTILS_DEFAULTVALUE_H

0 commit comments

Comments
 (0)